aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstrongswan/plugins/pgp/Makefile.am1
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_builder.c198
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_utils.c178
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_utils.h130
4 files changed, 334 insertions, 173 deletions
diff --git a/src/libstrongswan/plugins/pgp/Makefile.am b/src/libstrongswan/plugins/pgp/Makefile.am
index 3eb3992ec..6cbc09ed3 100644
--- a/src/libstrongswan/plugins/pgp/Makefile.am
+++ b/src/libstrongswan/plugins/pgp/Makefile.am
@@ -6,6 +6,7 @@ AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libstrongswan-pgp.la
libstrongswan_pgp_la_SOURCES = pgp_plugin.h pgp_plugin.c \
+ pgp_utils.h pgp_utils.c \
pgp_encoder.h pgp_encoder.c \
pgp_builder.h pgp_builder.c
diff --git a/src/libstrongswan/plugins/pgp/pgp_builder.c b/src/libstrongswan/plugins/pgp/pgp_builder.c
index 5147237c7..d262d18ff 100644
--- a/src/libstrongswan/plugins/pgp/pgp_builder.c
+++ b/src/libstrongswan/plugins/pgp/pgp_builder.c
@@ -15,141 +15,12 @@
*/
#include "pgp_builder.h"
+#include "pgp_utils.h"
#include <enum.h>
#include <debug.h>
#include <credentials/keys/private_key.h>
-typedef enum pgp_pubkey_alg_t pgp_pubkey_alg_t;
-typedef enum pgp_sym_alg_t pgp_sym_alg_t;
-
-/**
- * OpenPGP public key algorithms as defined in section 9.1 of RFC 4880
- */
-enum pgp_pubkey_alg_t {
- PGP_PUBKEY_ALG_RSA = 1,
- PGP_PUBKEY_ALG_RSA_ENC_ONLY = 2,
- PGP_PUBKEY_ALG_RSA_SIGN_ONLY = 3,
- PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY = 16,
- PGP_PUBKEY_ALG_DSA = 17,
- PGP_PUBKEY_ALG_ECC = 18,
- PGP_PUBKEY_ALG_ECDSA = 19,
- PGP_PUBKEY_ALG_ELGAMAL = 20,
- PGP_PUBKEY_ALG_DIFFIE_HELLMAN = 21,
-};
-
-/**
- * OpenPGP symmetric key algorithms as defined in section 9.2 of RFC 4880
- */
-enum pgp_sym_alg_t {
- PGP_SYM_ALG_PLAIN = 0,
- PGP_SYM_ALG_IDEA = 1,
- PGP_SYM_ALG_3DES = 2,
- PGP_SYM_ALG_CAST5 = 3,
- PGP_SYM_ALG_BLOWFISH = 4,
- PGP_SYM_ALG_SAFER = 5,
- PGP_SYM_ALG_DES = 6,
- PGP_SYM_ALG_AES_128 = 7,
- PGP_SYM_ALG_AES_192 = 8,
- PGP_SYM_ALG_AES_256 = 9,
- PGP_SYM_ALG_TWOFISH = 10
-};
-
-ENUM_BEGIN(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_RSA, PGP_PUBKEY_ALG_RSA_SIGN_ONLY,
- "RSA",
- "RSA_ENC_ONLY",
- "RSA_SIGN_ONLY"
-);
-ENUM_NEXT(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY, PGP_PUBKEY_ALG_DIFFIE_HELLMAN, PGP_PUBKEY_ALG_RSA_SIGN_ONLY,
- "ELGAMAL_ENC_ONLY",
- "DSA",
- "ECC",
- "ECDSA",
- "ELGAMAL",
- "DIFFIE_HELLMAN"
-);
-ENUM_END(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_DIFFIE_HELLMAN);
-
-ENUM(pgp_sym_alg_names, PGP_SYM_ALG_PLAIN, PGP_SYM_ALG_TWOFISH,
- "PLAINTEXT",
- "IDEA",
- "3DES",
- "CAST5",
- "BLOWFISH",
- "SAFER",
- "DES",
- "AES_128",
- "AES_192",
- "AES_256",
- "TWOFISH"
-);
-
-/**
- * Read a PGP scalar of bytes length, advance blob
- */
-static bool read_scalar(chunk_t *blob, size_t bytes, u_int32_t *scalar)
-{
- u_int32_t res = 0;
-
- if (bytes > blob->len)
- {
- DBG1("PGP data too short to read %d byte scalar", bytes);
- return FALSE;
- }
- while (bytes-- > 0)
- {
- res = 256 * res + blob->ptr[0];
- *blob = chunk_skip(*blob, 1);
- }
- *scalar = res;
- return TRUE;
-}
-
-/**
- * Read length of an PGP old packet length encoding
- */
-static bool old_packet_length(chunk_t *blob, u_int32_t *length)
-{
- /* bits 0 and 1 define the packet length type */
- u_char type;
-
- if (!blob->len)
- {
- return FALSE;
- }
- type = 0x03 & blob->ptr[0];
- *blob = chunk_skip(*blob, 1);
-
- if (type > 2)
- {
- return FALSE;
- }
- return read_scalar(blob, type == 0 ? 1 : type * 2, length);
-}
-
-/**
- * Read a PGP MPI, advance blob
- */
-static bool read_mpi(chunk_t *blob, chunk_t *mpi)
-{
- u_int32_t bits, bytes;
-
- if (!read_scalar(blob, 2, &bits))
- {
- DBG1("PGP data too short to read MPI length");
- return FALSE;
- }
- bytes = (bits + 7) / 8;
- if (bytes > blob->len)
- {
- DBG1("PGP data too short to read %d byte MPI", bytes);
- return FALSE;
- }
- *mpi = chunk_create(blob->ptr, bytes);
- *blob = chunk_skip(*blob, bytes);
- return TRUE;
-}
-
/**
* Load a generic public key from a PGP packet
*/
@@ -158,7 +29,7 @@ static public_key_t *parse_public_key(chunk_t blob)
u_int32_t alg;
public_key_t *key;
- if (!read_scalar(&blob, 1, &alg))
+ if (!pgp_read_scalar(&blob, 1, &alg))
{
return NULL;
}
@@ -187,7 +58,7 @@ static public_key_t *parse_rsa_public_key(chunk_t blob)
for (i = 0; i < 2; i++)
{
- if (!read_mpi(&blob, &mpi[i]))
+ if (!pgp_read_mpi(&blob, &mpi[i]))
{
return NULL;
}
@@ -208,12 +79,12 @@ static private_key_t *parse_rsa_private_key(chunk_t blob)
for (i = 0; i < 2; i++)
{
- if (!read_mpi(&blob, &mpi[i]))
+ if (!pgp_read_mpi(&blob, &mpi[i]))
{
return NULL;
}
}
- if (!read_scalar(&blob, 1, &s2k))
+ if (!pgp_read_scalar(&blob, 1, &s2k))
{
return NULL;
}
@@ -230,7 +101,7 @@ static private_key_t *parse_rsa_private_key(chunk_t blob)
for (i = 2; i < 6; i++)
{
- if (!read_mpi(&blob, &mpi[i]))
+ if (!pgp_read_mpi(&blob, &mpi[i]))
{
return NULL;
}
@@ -270,56 +141,37 @@ static bool decrypt_not_allowed(private_key_t *this,
static private_key_t *parse_private_key(chunk_t blob)
{
chunk_t packet;
- u_char tag, type;
- u_int32_t len, version, created, days, alg;
+ pgp_packet_tag_t tag;
+ u_int32_t version, created, days, alg;
private_key_t *key;
- tag = blob.ptr[0];
-
- /* bit 7 must be set */
- if (!(tag & 0x80))
- {
- DBG1("invalid packet tag");
- return NULL;
- }
- /* bit 6 set defines new packet format */
- if (tag & 0x40)
- {
- DBG1("new PGP packet format not supported");
- return NULL;
- }
-
- type = (tag & 0x3C) >> 2;
- if (!old_packet_length(&blob, &len) || len > blob.len)
+ if (!pgp_read_packet(&blob, &packet, &tag))
{
- DBG1("invalid packet length");
return NULL;
}
- packet.len = len;
- packet.ptr = blob.ptr;
- blob = chunk_skip(blob, len);
-
- if (!read_scalar(&packet, 1, &version))
+ if (!pgp_read_scalar(&packet, 1, &version))
{
- return NULL;
+ return FALSE;
}
- if (version < 3 || version > 4)
+ switch (version)
{
- DBG1("OpenPGP packet version V%d not supported", version);
- return NULL;
+ case 3:
+ if (!pgp_read_scalar(&packet, 2, &days))
+ {
+ return NULL;
+ }
+ break;
+ case 4:
+ break;
+ default:
+ DBG1("PGP packet version V%d not supported", version);
+ return FALSE;
}
- if (!read_scalar(&packet, 4, &created))
+ if (!pgp_read_scalar(&packet, 4, &created))
{
return NULL;
}
- if (version == 3)
- {
- if (!read_scalar(&packet, 2, &days))
- {
- return NULL;
- }
- }
- if (!read_scalar(&packet, 1, &alg))
+ if (!pgp_read_scalar(&packet, 1, &alg))
{
return NULL;
}
diff --git a/src/libstrongswan/plugins/pgp/pgp_utils.c b/src/libstrongswan/plugins/pgp/pgp_utils.c
new file mode 100644
index 000000000..b55896f74
--- /dev/null
+++ b/src/libstrongswan/plugins/pgp/pgp_utils.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pgp_utils.h"
+
+#include <debug.h>
+
+ENUM_BEGIN(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_RSA, PGP_PUBKEY_ALG_RSA_SIGN_ONLY,
+ "RSA",
+ "RSA_ENC_ONLY",
+ "RSA_SIGN_ONLY"
+);
+ENUM_NEXT(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY, PGP_PUBKEY_ALG_DIFFIE_HELLMAN, PGP_PUBKEY_ALG_RSA_SIGN_ONLY,
+ "ELGAMAL_ENC_ONLY",
+ "DSA",
+ "ECC",
+ "ECDSA",
+ "ELGAMAL",
+ "DIFFIE_HELLMAN"
+);
+ENUM_END(pgp_pubkey_alg_names, PGP_PUBKEY_ALG_DIFFIE_HELLMAN);
+
+ENUM(pgp_sym_alg_names, PGP_SYM_ALG_PLAIN, PGP_SYM_ALG_TWOFISH,
+ "PLAINTEXT",
+ "IDEA",
+ "3DES",
+ "CAST5",
+ "BLOWFISH",
+ "SAFER",
+ "DES",
+ "AES_128",
+ "AES_192",
+ "AES_256",
+ "TWOFISH"
+);
+
+ENUM_BEGIN(pgp_packet_tag_names, PGP_PKT_RESERVED, PGP_PKT_PUBLIC_SUBKEY,
+ "Reserved",
+ "Public-Key Encrypted Session Key Packet",
+ "Signature Packet",
+ "Symmetric-Key Encrypted Session Key Packet",
+ "One-Pass Signature Packet",
+ "Secret Key Packet",
+ "Public Key Packet",
+ "Secret Subkey Packet",
+ "Compressed Data Packet",
+ "Symmetrically Encrypted Data Packet",
+ "Marker Packet",
+ "Literal Data Packet",
+ "Trust Packet",
+ "User ID Packet",
+ "Public Subkey Packet"
+);
+ENUM_NEXT(pgp_packet_tag_names, PGP_PKT_USER_ATTRIBUTE, PGP_PKT_MOD_DETECT_CODE, PGP_PKT_PUBLIC_SUBKEY,
+ "User Attribute Packet",
+ "Sym. Encrypted and Integrity Protected Data Packet",
+ "Modification Detection Code Packet"
+);
+ENUM_END(pgp_packet_tag_names, PGP_PKT_MOD_DETECT_CODE);
+
+/**
+ * Read a PGP scalar of bytes length, advance blob
+ */
+bool pgp_read_scalar(chunk_t *blob, size_t bytes, u_int32_t *scalar)
+{
+ u_int32_t res = 0;
+
+ if (bytes > blob->len)
+ {
+ DBG1("PGP data too short to read %d byte scalar", bytes);
+ return FALSE;
+ }
+ while (bytes-- > 0)
+ {
+ res = 256 * res + blob->ptr[0];
+ *blob = chunk_skip(*blob, 1);
+ }
+ *scalar = res;
+ return TRUE;
+}
+
+/**
+ * Read a PGP MPI, advance blob
+ */
+bool pgp_read_mpi(chunk_t *blob, chunk_t *mpi)
+{
+ u_int32_t bits, bytes;
+
+ if (!pgp_read_scalar(blob, 2, &bits))
+ {
+ DBG1("PGP data too short to read MPI length");
+ return FALSE;
+ }
+ bytes = (bits + 7) / 8;
+ if (bytes > blob->len)
+ {
+ DBG1("PGP data too short to read %d byte MPI", bytes);
+ return FALSE;
+ }
+ *mpi = chunk_create(blob->ptr, bytes);
+ *blob = chunk_skip(*blob, bytes);
+ return TRUE;
+}
+
+/**
+ * Read length of an PGP old packet length encoding
+ */
+static bool pgp_old_packet_length(chunk_t *blob, u_int32_t *length)
+{
+ /* bits 0 and 1 define the packet length type */
+ u_char type;
+
+ if (!blob->len)
+ {
+ return FALSE;
+ }
+ type = 0x03 & blob->ptr[0];
+ *blob = chunk_skip(*blob, 1);
+
+ if (type > 2)
+ {
+ return FALSE;
+ }
+ return pgp_read_scalar(blob, type == 0 ? 1 : type * 2, length);
+}
+
+/**
+ * See header.
+ */
+bool pgp_read_packet(chunk_t *blob, chunk_t *data, pgp_packet_tag_t *tag)
+{
+ u_int32_t len;
+ u_char t;
+
+ if (!blob->len)
+ {
+ DBG1("missing input");
+ return FALSE;
+ }
+ t = blob->ptr[0];
+
+ /* bit 7 must be set */
+ if (!(t & 0x80))
+ {
+ DBG1("invalid packet tag");
+ return FALSE;
+ }
+ /* bit 6 set defines new packet format */
+ if (t & 0x40)
+ {
+ DBG1("new PGP packet format not supported");
+ return FALSE;
+ }
+
+ t = (t & 0x3C) >> 2;
+ if (!pgp_old_packet_length(blob, &len) || len > blob->len)
+ {
+ DBG1("invalid packet length");
+ return FALSE;
+ }
+ *data = chunk_create(blob->ptr, len);
+ *blob = chunk_skip(*blob, len);
+ *tag = t;
+ return TRUE;
+}
+
diff --git a/src/libstrongswan/plugins/pgp/pgp_utils.h b/src/libstrongswan/plugins/pgp/pgp_utils.h
new file mode 100644
index 000000000..93c51c44b
--- /dev/null
+++ b/src/libstrongswan/plugins/pgp/pgp_utils.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup pgp_utils pgp_utils
+ * @{ @ingroup pgp
+ */
+
+#ifndef PGP_UTILS_H_
+#define PGP_UTILS_H_
+
+#include <library.h>
+
+typedef enum pgp_pubkey_alg_t pgp_pubkey_alg_t;
+typedef enum pgp_sym_alg_t pgp_sym_alg_t;
+typedef enum pgp_packet_tag_t pgp_packet_tag_t;
+
+/**
+ * OpenPGP public key algorithms as defined in section 9.1 of RFC 4880
+ */
+enum pgp_pubkey_alg_t {
+ PGP_PUBKEY_ALG_RSA = 1,
+ PGP_PUBKEY_ALG_RSA_ENC_ONLY = 2,
+ PGP_PUBKEY_ALG_RSA_SIGN_ONLY = 3,
+ PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY = 16,
+ PGP_PUBKEY_ALG_DSA = 17,
+ PGP_PUBKEY_ALG_ECC = 18,
+ PGP_PUBKEY_ALG_ECDSA = 19,
+ PGP_PUBKEY_ALG_ELGAMAL = 20,
+ PGP_PUBKEY_ALG_DIFFIE_HELLMAN = 21,
+};
+
+/**
+ * Enum names of pgp_pubkey_alg_t
+ */
+extern enum_name_t *pgp_pubkey_alg_names;
+
+/**
+ * OpenPGP symmetric key algorithms as defined in section 9.2 of RFC 4880
+ */
+enum pgp_sym_alg_t {
+ PGP_SYM_ALG_PLAIN = 0,
+ PGP_SYM_ALG_IDEA = 1,
+ PGP_SYM_ALG_3DES = 2,
+ PGP_SYM_ALG_CAST5 = 3,
+ PGP_SYM_ALG_BLOWFISH = 4,
+ PGP_SYM_ALG_SAFER = 5,
+ PGP_SYM_ALG_DES = 6,
+ PGP_SYM_ALG_AES_128 = 7,
+ PGP_SYM_ALG_AES_192 = 8,
+ PGP_SYM_ALG_AES_256 = 9,
+ PGP_SYM_ALG_TWOFISH = 10
+};
+
+/**
+ * Enum names of pgp_sym_alg_t
+ */
+extern enum_name_t *pgp_sym_alg_names;
+
+/**
+ * OpenPGP packet tags as defined in section 4.3 of RFC 4880
+ */
+enum pgp_packet_tag_t {
+ PGP_PKT_RESERVED = 0,
+ PGP_PKT_PUBKEY_ENC_SESSION_KEY = 1,
+ PGP_PKT_SIGNATURE = 2,
+ PGP_PKT_SYMKEY_ENC_SESSION_KEY = 3,
+ PGP_PKT_ONE_PASS_SIGNATURE_PKT = 4,
+ PGP_PKT_SECRET_KEY = 5,
+ PGP_PKT_PUBLIC_KEY = 6,
+ PGP_PKT_SECRET_SUBKEY = 7,
+ PGP_PKT_COMPRESSED_DATA = 8,
+ PGP_PKT_SYMKEY_ENC_DATA = 9,
+ PGP_PKT_MARKER = 10,
+ PGP_PKT_LITERAL_DATA = 11,
+ PGP_PKT_TRUST = 12,
+ PGP_PKT_USER_ID = 13,
+ PGP_PKT_PUBLIC_SUBKEY = 14,
+ PGP_PKT_USER_ATTRIBUTE = 17,
+ PGP_PKT_SYM_ENC_INT_PROT_DATA = 18,
+ PGP_PKT_MOD_DETECT_CODE = 19
+};
+
+/**
+ * Enum names of pgp_packet_tag_t
+ */
+extern enum_name_t *pgp_packet_tag_names;
+
+/**
+ * Parse a PGP encoded MPI.
+ *
+ * @param blob blob to read from, gets advanced
+ * @param mpi parsed MPI value
+ * @return TRUE if MPI parsed successfully
+ */
+bool pgp_read_mpi(chunk_t *blob, chunk_t *mpi);
+
+/**
+ * Parse a PGP encoded Scalar.
+ *
+ * @param blob blob to read from, gets advanced
+ * @param bytes number of bytes the scalar uses for encoding
+ * @param scalar resultin scalar
+ * @return TRUE if scalar parsed successfully
+ */
+bool pgp_read_scalar(chunk_t *blob, size_t bytes, u_int32_t *scalar);
+
+/**
+ * Parse a PGP packet.
+ *
+ * @param blob blob to read from, gets advanced
+ * @param data contained packet data
+ * @param tag tag of the parsed PGP packet
+ * @return TRUE if packet parsed successfully
+ */
+bool pgp_read_packet(chunk_t *blob, chunk_t *data, pgp_packet_tag_t *tag);
+
+#endif /* PGP_UTILS_ @}*/