aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2009-08-28 17:23:58 +0200
committerMartin Willi <martin@strongswan.org>2009-08-28 17:23:58 +0200
commit4593ef51fddee237dca08faafdd004ada18ef841 (patch)
treec8d3523386313198a098aeb74b698640a04a9236 /src/libstrongswan
parentcaf1af1d9ff37c9684dc72d453769d9d51deb879 (diff)
downloadstrongswan-4593ef51fddee237dca08faafdd004ada18ef841.tar.bz2
strongswan-4593ef51fddee237dca08faafdd004ada18ef841.tar.xz
implemented PGP Secret-Key Packet parsing
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_builder.c157
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_builder.h4
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_plugin.c2
3 files changed, 156 insertions, 7 deletions
diff --git a/src/libstrongswan/plugins/pgp/pgp_builder.c b/src/libstrongswan/plugins/pgp/pgp_builder.c
index 5e500396a..37dd1518b 100644
--- a/src/libstrongswan/plugins/pgp/pgp_builder.c
+++ b/src/libstrongswan/plugins/pgp/pgp_builder.c
@@ -106,6 +106,28 @@ static bool read_scalar(chunk_t *blob, size_t bytes, u_int32_t *scalar)
}
/**
+ * 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)
@@ -120,7 +142,7 @@ static bool read_mpi(chunk_t *blob, chunk_t *mpi)
bytes = (bits + 7) / 8;
if (bytes > blob->len)
{
- DBG1("PGP data too short to %d byte MPI", bytes);
+ DBG1("PGP data too short to read %d byte MPI", bytes);
return FALSE;
}
*mpi = chunk_create(blob->ptr, bytes);
@@ -213,6 +235,7 @@ static private_key_t *parse_rsa_private_key(chunk_t blob)
return NULL;
}
}
+
/* PGP has uses p < q, but we use p > q */
return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
BUILD_RSA_MODULUS, mpi[0], BUILD_RSA_PUB_EXP, mpi[1],
@@ -221,6 +244,120 @@ static private_key_t *parse_rsa_private_key(chunk_t blob)
BUILD_END);
}
+/**
+ * Implementation of private_key_t.sign for encryption-only keys
+ */
+static bool sign_not_allowed(private_key_t *this, signature_scheme_t scheme,
+ chunk_t data, chunk_t *signature)
+{
+ DBG1("signing failed - decryption only key");
+ return FALSE;
+}
+
+/**
+ * Implementation of private_key_t.decrypt for signature-only keys
+ */
+static bool decrypt_not_allowed(private_key_t *this,
+ chunk_t crypto, chunk_t *plain)
+{
+ DBG1("decryption failed - signature only key");
+ return FALSE;
+}
+
+/**
+ * Load a generic private key from a PGP packet
+ */
+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;
+ 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)
+ {
+ DBG1("invalid packet length");
+ return NULL;
+ }
+ packet.len = len;
+ packet.ptr = blob.ptr;
+ blob = chunk_skip(blob, len);
+
+ if (!read_scalar(&packet, 1, &version))
+ {
+ return NULL;
+ }
+ if (version < 3 || version > 4)
+ {
+ DBG1("OpenPGP packet version V%d not supported", version);
+ return NULL;
+ }
+ if (!read_scalar(&packet, 4, &created))
+ {
+ return NULL;
+ }
+ if (version == 3)
+ {
+ if (!read_scalar(&packet, 2, &days))
+ {
+ return NULL;
+ }
+ }
+ if (!read_scalar(&packet, 1, &alg))
+ {
+ return NULL;
+ }
+ switch (alg)
+ {
+ case PGP_PUBKEY_ALG_RSA:
+ POS;
+ return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_PGP, packet, BUILD_END);
+ case PGP_PUBKEY_ALG_RSA_ENC_ONLY:
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_PGP, packet, BUILD_END);
+ if (key)
+ {
+ key->sign = sign_not_allowed;
+ }
+ return key;
+ case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_PGP, packet, BUILD_END);
+ if (key)
+ {
+ key->decrypt = decrypt_not_allowed;
+ }
+ return key;
+ case PGP_PUBKEY_ALG_ECDSA:
+ return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
+ BUILD_BLOB_PGP, packet, BUILD_END);
+ case PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY:
+ case PGP_PUBKEY_ALG_DSA:
+ case PGP_PUBKEY_ALG_ECC:
+ case PGP_PUBKEY_ALG_ELGAMAL:
+ case PGP_PUBKEY_ALG_DIFFIE_HELLMAN:
+ default:
+ return NULL;
+ }
+}
+
typedef struct private_builder_t private_builder_t;
/**
@@ -266,7 +403,7 @@ static void add_public(private_builder_t *this, builder_part_t part, ...)
switch (part)
{
- case BUILD_BLOB_PEM:
+ case BUILD_BLOB_PGP:
{
va_start(args, part);
this->blob = va_arg(args, chunk_t);
@@ -306,9 +443,19 @@ builder_t *pgp_public_key_builder(key_type_t type)
*/
static private_key_t *build_private(private_builder_t *this)
{
- private_key_t *key;
+ private_key_t *key = NULL;
- key = parse_rsa_private_key(this->blob);
+ switch (this->type)
+ {
+ case KEY_ANY:
+ key = parse_private_key(this->blob);
+ break;
+ case KEY_RSA:
+ key = parse_rsa_private_key(this->blob);
+ break;
+ default:
+ break;
+ }
free(this);
return key;
}
@@ -342,7 +489,7 @@ builder_t *pgp_private_key_builder(key_type_t type)
{
private_builder_t *this;
- if (type != KEY_RSA)
+ if (type != KEY_ANY && type != KEY_RSA)
{
return NULL;
}
diff --git a/src/libstrongswan/plugins/pgp/pgp_builder.h b/src/libstrongswan/plugins/pgp/pgp_builder.h
index 739456e03..4968d7caa 100644
--- a/src/libstrongswan/plugins/pgp/pgp_builder.h
+++ b/src/libstrongswan/plugins/pgp/pgp_builder.h
@@ -32,9 +32,9 @@
builder_t *pgp_public_key_builder(key_type_t type);
/**
- * Create the builder for a RSA private key using PGP decoding.
+ * Create the builder for a generic or RSA private key using PGP decoding.
*
- * @param type type of the key, KEY_RSA
+ * @param type type of the key, either KEY_ANY or KEY_RSA
* @return builder instance
*/
builder_t *pgp_private_key_builder(key_type_t type);
diff --git a/src/libstrongswan/plugins/pgp/pgp_plugin.c b/src/libstrongswan/plugins/pgp/pgp_plugin.c
index d31666b59..98f5c3356 100644
--- a/src/libstrongswan/plugins/pgp/pgp_plugin.c
+++ b/src/libstrongswan/plugins/pgp/pgp_plugin.c
@@ -60,6 +60,8 @@ plugin_t *plugin_create()
(builder_constructor_t)pgp_public_key_builder);
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
(builder_constructor_t)pgp_public_key_builder);
+ lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
+ (builder_constructor_t)pgp_private_key_builder);
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
(builder_constructor_t)pgp_private_key_builder);