moved PEM parsing functionality to its own plugin
This commit is contained in:
parent
5672eae131
commit
160f4c225d
17
configure.in
17
configure.in
|
@ -287,6 +287,17 @@ AC_ARG_ENABLE(
|
|||
pubkey=true
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
[pem],
|
||||
AS_HELP_STRING([--disable-pem],[disable PEM decoding plugin. (default is NO).]),
|
||||
[if test x$enableval = xyes; then
|
||||
pem=true
|
||||
else
|
||||
pem=false
|
||||
fi],
|
||||
pem=true
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
[hmac],
|
||||
AS_HELP_STRING([--disable-hmac],[disable HMAC crypto implementation plugin. (default is NO).]),
|
||||
|
@ -1181,6 +1192,10 @@ if test x$pubkey = xtrue; then
|
|||
libstrongswan_plugins=${libstrongswan_plugins}" pubkey"
|
||||
pluto_plugins=${pluto_plugins}" pubkey"
|
||||
fi
|
||||
if test x$pem = xtrue; then
|
||||
libstrongswan_plugins=${libstrongswan_plugins}" pem"
|
||||
pluto_plugins=${pluto_plugins}" pem"
|
||||
fi
|
||||
if test x$mysql = xtrue; then
|
||||
libstrongswan_plugins=${libstrongswan_plugins}" mysql"
|
||||
fi
|
||||
|
@ -1237,6 +1252,7 @@ AM_CONDITIONAL(USE_GMP, test x$gmp = xtrue)
|
|||
AM_CONDITIONAL(USE_RANDOM, test x$random = xtrue)
|
||||
AM_CONDITIONAL(USE_X509, test x$x509 = xtrue)
|
||||
AM_CONDITIONAL(USE_PUBKEY, test x$pubkey = xtrue)
|
||||
AM_CONDITIONAL(USE_PEM, test x$pem = xtrue)
|
||||
AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue)
|
||||
AM_CONDITIONAL(USE_XCBC, test x$xcbc = xtrue)
|
||||
AM_CONDITIONAL(USE_MYSQL, test x$mysql = xtrue)
|
||||
|
@ -1331,6 +1347,7 @@ AC_OUTPUT(
|
|||
src/libstrongswan/plugins/xcbc/Makefile
|
||||
src/libstrongswan/plugins/x509/Makefile
|
||||
src/libstrongswan/plugins/pubkey/Makefile
|
||||
src/libstrongswan/plugins/pem/Makefile
|
||||
src/libstrongswan/plugins/curl/Makefile
|
||||
src/libstrongswan/plugins/ldap/Makefile
|
||||
src/libstrongswan/plugins/mysql/Makefile
|
||||
|
|
|
@ -162,6 +162,10 @@ if USE_PUBKEY
|
|||
SUBDIRS += plugins/pubkey
|
||||
endif
|
||||
|
||||
if USE_PEM
|
||||
SUBDIRS += plugins/pem
|
||||
endif
|
||||
|
||||
if USE_CURL
|
||||
SUBDIRS += plugins/curl
|
||||
endif
|
||||
|
|
|
@ -19,9 +19,11 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
|
|||
"BUILD_FROM_FILE",
|
||||
"BUILD_AGENT_SOCKET",
|
||||
"BUILD_BLOB_ASN1_DER",
|
||||
"BUILD_BLOB_ASN1_PEM",
|
||||
"BUILD_BLOB_PEM",
|
||||
"BUILD_BLOB_PGP",
|
||||
"BUILD_BLOB_RFC_3110",
|
||||
"BUILD_PASSPHRASE",
|
||||
"BUILD_PASSPHRASE_CALLBACK",
|
||||
"BUILD_KEY_SIZE",
|
||||
"BUILD_SIGNING_KEY",
|
||||
"BUILD_SIGNING_CERT",
|
||||
|
|
|
@ -44,12 +44,18 @@ enum builder_part_t {
|
|||
BUILD_AGENT_SOCKET,
|
||||
/** DER encoded ASN.1 blob, chunk_t */
|
||||
BUILD_BLOB_ASN1_DER,
|
||||
/** PEM encoded ASN.1 blob, null terminated char* */
|
||||
BUILD_BLOB_ASN1_PEM,
|
||||
/** PEM encoded ASN.1/PGP blob, chunk_t */
|
||||
BUILD_BLOB_PEM,
|
||||
/** OpenPGP key blob, chunk_t */
|
||||
BUILD_BLOB_PGP,
|
||||
/** RFC 3110 DNS public key blob, chunk_t */
|
||||
BUILD_BLOB_RFC_3110,
|
||||
/** passphrase for e.g. PEM decryption, chunk_t */
|
||||
BUILD_PASSPHRASE,
|
||||
/** passphrase callback, chunk_t(*fn)(void *user, int try), void *user.
|
||||
* The callback is invoked until the returned passphrase is accepted, or
|
||||
* a zero-length passphrase is returned. Try starts at 1. */
|
||||
BUILD_PASSPHRASE_CALLBACK,
|
||||
/** key size in bits, as used for key generation, u_int */
|
||||
BUILD_KEY_SIZE,
|
||||
/** private key to use for signing, private_key_t* */
|
||||
|
|
|
@ -142,7 +142,7 @@ static void* create(private_credential_factory_t *this, credential_type_t type,
|
|||
builder_t *builder;
|
||||
builder_part_t part;
|
||||
va_list args;
|
||||
void* construct = NULL;
|
||||
void* construct = NULL, *fn, *data;
|
||||
|
||||
enumerator = create_builder_enumerator(this, type, subtype);
|
||||
while (enumerator->enumerate(enumerator, &builder))
|
||||
|
@ -155,9 +155,11 @@ static void* create(private_credential_factory_t *this, credential_type_t type,
|
|||
{
|
||||
case BUILD_END:
|
||||
break;
|
||||
case BUILD_BLOB_PEM:
|
||||
case BUILD_BLOB_ASN1_DER:
|
||||
case BUILD_BLOB_PGP:
|
||||
case BUILD_BLOB_RFC_3110:
|
||||
case BUILD_PASSPHRASE:
|
||||
case BUILD_SERIAL:
|
||||
builder->add(builder, part, va_arg(args, chunk_t));
|
||||
continue;
|
||||
|
@ -171,7 +173,6 @@ static void* create(private_credential_factory_t *this, credential_type_t type,
|
|||
case BUILD_NOT_AFTER_TIME:
|
||||
builder->add(builder, part, va_arg(args, time_t));
|
||||
continue;
|
||||
case BUILD_BLOB_ASN1_PEM:
|
||||
case BUILD_FROM_FILE:
|
||||
case BUILD_AGENT_SOCKET:
|
||||
case BUILD_SIGNING_KEY:
|
||||
|
@ -188,6 +189,11 @@ static void* create(private_credential_factory_t *this, credential_type_t type,
|
|||
case BUILD_SMARTCARD_PIN:
|
||||
builder->add(builder, part, va_arg(args, void*));
|
||||
continue;
|
||||
case BUILD_PASSPHRASE_CALLBACK:
|
||||
fn = va_arg(args, void*);
|
||||
data = va_arg(args, void*);
|
||||
builder->add(builder, part, fn, data);
|
||||
continue;
|
||||
/* no default to get a compiler warning */
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan
|
||||
|
||||
AM_CFLAGS = -rdynamic
|
||||
|
||||
plugin_LTLIBRARIES = libstrongswan-pem.la
|
||||
|
||||
libstrongswan_pem_la_SOURCES = pem_plugin.h pem_plugin.c \
|
||||
pem_builder.c pem_builder.h
|
||||
|
||||
libstrongswan_pem_la_LDFLAGS = -module -avoid-version
|
||||
|
|
@ -0,0 +1,490 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Martin Willi
|
||||
* Copyright (C) 2001-2008 Andreas Steffen
|
||||
* 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 "pem_builder.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <library.h>
|
||||
#include <utils/lexparser.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <crypto/crypters/crypter.h>
|
||||
|
||||
#define PKCS5_SALT_LEN 8 /* bytes */
|
||||
|
||||
typedef struct private_builder_t private_builder_t;
|
||||
|
||||
/**
|
||||
* Builder implementation for PEM decoding
|
||||
*/
|
||||
struct private_builder_t {
|
||||
/** implements the builder interface */
|
||||
builder_t public;
|
||||
/** credential type we are building */
|
||||
credential_type_t type;
|
||||
/** subtype (keytype, certtype) of the credential we build */
|
||||
int subtype;
|
||||
/** PEM encoding of the credential */
|
||||
chunk_t pem;
|
||||
/** PEM decryption passphrase, if given */
|
||||
chunk_t passphrase;
|
||||
/** supplied callback to read passphrase */
|
||||
chunk_t (*cb)(void *data, int try);
|
||||
/** user data to callback */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* check the presence of a pattern in a character string, skip if found
|
||||
*/
|
||||
static bool present(char* pattern, chunk_t* ch)
|
||||
{
|
||||
u_int len = strlen(pattern);
|
||||
|
||||
if (ch->len >= len && strneq(ch->ptr, pattern, len))
|
||||
{
|
||||
*ch = chunk_skip(*ch, len);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* find a boundary of the form -----tag name-----
|
||||
*/
|
||||
static bool find_boundary(char* tag, chunk_t *line)
|
||||
{
|
||||
chunk_t name = chunk_empty;
|
||||
|
||||
if (!present("-----", line) ||
|
||||
!present(tag, line) ||
|
||||
*line->ptr != ' ')
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*line = chunk_skip(*line, 1);
|
||||
|
||||
/* extract name */
|
||||
name.ptr = line->ptr;
|
||||
while (line->len > 0)
|
||||
{
|
||||
if (present("-----", line))
|
||||
{
|
||||
DBG2(" -----%s %.*s-----", tag, (int)name.len, name.ptr);
|
||||
return TRUE;
|
||||
}
|
||||
line->ptr++; line->len--; name.len++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* decrypts a passphrase protected encrypted data block
|
||||
*/
|
||||
static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
|
||||
size_t key_size, chunk_t iv, chunk_t passphrase)
|
||||
{
|
||||
hasher_t *hasher;
|
||||
crypter_t *crypter;
|
||||
chunk_t salt = { iv.ptr, PKCS5_SALT_LEN };
|
||||
chunk_t hash;
|
||||
chunk_t decrypted;
|
||||
chunk_t key = {alloca(key_size), key_size};
|
||||
u_int8_t padding, *last_padding_pos, *first_padding_pos;
|
||||
|
||||
/* build key from passphrase and IV */
|
||||
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
||||
if (hasher == NULL)
|
||||
{
|
||||
DBG1(" MD5 hash algorithm not available");
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
hash.len = hasher->get_hash_size(hasher);
|
||||
hash.ptr = alloca(hash.len);
|
||||
hasher->get_hash(hasher, passphrase, NULL);
|
||||
hasher->get_hash(hasher, salt, hash.ptr);
|
||||
memcpy(key.ptr, hash.ptr, hash.len);
|
||||
|
||||
if (key.len > hash.len)
|
||||
{
|
||||
hasher->get_hash(hasher, hash, NULL);
|
||||
hasher->get_hash(hasher, passphrase, NULL);
|
||||
hasher->get_hash(hasher, salt, hash.ptr);
|
||||
memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len);
|
||||
}
|
||||
hasher->destroy(hasher);
|
||||
|
||||
/* decrypt blob */
|
||||
crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
|
||||
if (crypter == NULL)
|
||||
{
|
||||
DBG1(" %N encryption algorithm not available",
|
||||
encryption_algorithm_names, alg);
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
crypter->set_key(crypter, key);
|
||||
|
||||
if (iv.len != crypter->get_block_size(crypter) ||
|
||||
blob->len % iv.len)
|
||||
{
|
||||
crypter->destroy(crypter);
|
||||
DBG1(" data size is not multiple of block size");
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
crypter->decrypt(crypter, *blob, iv, &decrypted);
|
||||
crypter->destroy(crypter);
|
||||
memcpy(blob->ptr, decrypted.ptr, blob->len);
|
||||
chunk_free(&decrypted);
|
||||
|
||||
/* determine amount of padding */
|
||||
last_padding_pos = blob->ptr + blob->len - 1;
|
||||
padding = *last_padding_pos;
|
||||
if (padding > blob->len)
|
||||
{
|
||||
first_padding_pos = blob->ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
first_padding_pos = last_padding_pos - padding;
|
||||
}
|
||||
/* check the padding pattern */
|
||||
while (--last_padding_pos > first_padding_pos)
|
||||
{
|
||||
if (*last_padding_pos != padding)
|
||||
{
|
||||
DBG1(" invalid passphrase");
|
||||
return INVALID_ARG;
|
||||
}
|
||||
}
|
||||
/* remove padding */
|
||||
blob->len -= padding;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a PEM encoded file into its binary form (RFC 1421, RFC 934)
|
||||
*/
|
||||
status_t pem_to_bin(chunk_t *blob, private_builder_t *this, bool *pgp)
|
||||
{
|
||||
typedef enum {
|
||||
PEM_PRE = 0,
|
||||
PEM_MSG = 1,
|
||||
PEM_HEADER = 2,
|
||||
PEM_BODY = 3,
|
||||
PEM_POST = 4,
|
||||
PEM_ABORT = 5
|
||||
} state_t;
|
||||
|
||||
encryption_algorithm_t alg = ENCR_UNDEFINED;
|
||||
size_t key_size = 0;
|
||||
bool encrypted = FALSE;
|
||||
state_t state = PEM_PRE;
|
||||
chunk_t src = *blob;
|
||||
chunk_t dst = *blob;
|
||||
chunk_t line = chunk_empty;
|
||||
chunk_t iv = chunk_empty;
|
||||
chunk_t passphrase;
|
||||
int try = 0;
|
||||
u_char iv_buf[HASH_SIZE_MD5];
|
||||
|
||||
dst.len = 0;
|
||||
iv.ptr = iv_buf;
|
||||
iv.len = 0;
|
||||
|
||||
while (fetchline(&src, &line))
|
||||
{
|
||||
if (state == PEM_PRE)
|
||||
{
|
||||
if (find_boundary("BEGIN", &line))
|
||||
{
|
||||
state = PEM_MSG;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (find_boundary("END", &line))
|
||||
{
|
||||
state = PEM_POST;
|
||||
break;
|
||||
}
|
||||
if (state == PEM_MSG)
|
||||
{
|
||||
state = PEM_HEADER;
|
||||
if (memchr(line.ptr, ':', line.len) == NULL)
|
||||
{
|
||||
state = PEM_BODY;
|
||||
}
|
||||
}
|
||||
if (state == PEM_HEADER)
|
||||
{
|
||||
err_t ugh = NULL;
|
||||
chunk_t name = chunk_empty;
|
||||
chunk_t value = chunk_empty;
|
||||
|
||||
/* an empty line separates HEADER and BODY */
|
||||
if (line.len == 0)
|
||||
{
|
||||
state = PEM_BODY;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we are looking for a parameter: value pair */
|
||||
DBG2(" %.*s", (int)line.len, line.ptr);
|
||||
ugh = extract_parameter_value(&name, &value, &line);
|
||||
if (ugh != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (match("Proc-Type", &name) && *value.ptr == '4')
|
||||
{
|
||||
encrypted = TRUE;
|
||||
}
|
||||
else if (match("DEK-Info", &name))
|
||||
{
|
||||
chunk_t dek;
|
||||
|
||||
if (!extract_token(&dek, ',', &value))
|
||||
{
|
||||
dek = value;
|
||||
}
|
||||
if (match("DES-EDE3-CBC", &dek))
|
||||
{
|
||||
alg = ENCR_3DES;
|
||||
key_size = 24;
|
||||
}
|
||||
else if (match("AES-128-CBC", &dek))
|
||||
{
|
||||
alg = ENCR_AES_CBC;
|
||||
key_size = 16;
|
||||
}
|
||||
else if (match("AES-192-CBC", &dek))
|
||||
{
|
||||
alg = ENCR_AES_CBC;
|
||||
key_size = 24;
|
||||
}
|
||||
else if (match("AES-256-CBC", &dek))
|
||||
{
|
||||
alg = ENCR_AES_CBC;
|
||||
key_size = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(" encryption algorithm '%.s' not supported",
|
||||
dek.len, dek.ptr);
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
eat_whitespace(&value);
|
||||
iv = chunk_from_hex(value, iv.ptr);
|
||||
}
|
||||
}
|
||||
else /* state is PEM_BODY */
|
||||
{
|
||||
chunk_t data;
|
||||
|
||||
/* remove any trailing whitespace */
|
||||
if (!extract_token(&data ,' ', &line))
|
||||
{
|
||||
data = line;
|
||||
}
|
||||
|
||||
/* check for PGP armor checksum */
|
||||
if (*data.ptr == '=')
|
||||
{
|
||||
*pgp = TRUE;
|
||||
data.ptr++;
|
||||
data.len--;
|
||||
DBG2(" armor checksum: %.*s", (int)data.len, data.ptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (blob->len - dst.len < data.len / 4 * 3)
|
||||
{
|
||||
state = PEM_ABORT;
|
||||
}
|
||||
data = chunk_from_base64(data, dst.ptr);
|
||||
|
||||
dst.ptr += data.len;
|
||||
dst.len += data.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* set length to size of binary blob */
|
||||
blob->len = dst.len;
|
||||
|
||||
if (state != PEM_POST)
|
||||
{
|
||||
DBG1(" file coded in unknown format, discarded");
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
if (!encrypted)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
if (!this->cb)
|
||||
{
|
||||
DBG1(" missing passphrase");
|
||||
return INVALID_ARG;
|
||||
}
|
||||
while (TRUE)
|
||||
{
|
||||
passphrase = this->cb(this->data, ++try);
|
||||
if (!passphrase.len || !passphrase.ptr)
|
||||
{
|
||||
return INVALID_ARG;
|
||||
}
|
||||
switch (pem_decrypt(blob, alg, key_size, iv, passphrase))
|
||||
{
|
||||
case INVALID_ARG:
|
||||
/* bad passphrase, retry */
|
||||
continue;
|
||||
case SUCCESS:
|
||||
return SUCCESS;
|
||||
default:
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of builder_t.build
|
||||
*/
|
||||
static void *build(private_builder_t *this)
|
||||
{
|
||||
bool pgp = FALSE;
|
||||
void *cred = NULL;
|
||||
chunk_t blob;
|
||||
builder_part_t part = BUILD_BLOB_ASN1_DER;
|
||||
|
||||
if (!this->pem.ptr)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
blob = chunk_clone(this->pem);
|
||||
if (pem_to_bin(&blob, this, &pgp) == SUCCESS)
|
||||
{
|
||||
if (pgp)
|
||||
{
|
||||
part = BUILD_BLOB_PGP;
|
||||
}
|
||||
cred = lib->creds->create(lib->creds, this->type, this->subtype,
|
||||
part, blob, BUILD_END);
|
||||
}
|
||||
chunk_clear(&blob);
|
||||
free(this);
|
||||
return cred;
|
||||
}
|
||||
|
||||
/**
|
||||
* passphrase callback to use if passphrase given
|
||||
*/
|
||||
static chunk_t given_passphrase_cb(chunk_t *passphrase, int try)
|
||||
{
|
||||
if (try > 1)
|
||||
{ /* try only once for given passphrases */
|
||||
return chunk_empty;
|
||||
}
|
||||
return *passphrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of builder_t.add
|
||||
*/
|
||||
static void add(private_builder_t *this, builder_part_t part, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
switch (part)
|
||||
{
|
||||
case BUILD_BLOB_PEM:
|
||||
va_start(args, part);
|
||||
this->pem = va_arg(args, chunk_t);
|
||||
va_end(args);
|
||||
break;
|
||||
case BUILD_PASSPHRASE:
|
||||
va_start(args, part);
|
||||
this->passphrase = va_arg(args, chunk_t);
|
||||
va_end(args);
|
||||
if (this->passphrase.len && this->passphrase.ptr)
|
||||
{
|
||||
this->cb = (void*)given_passphrase_cb;
|
||||
this->data = &this->passphrase;
|
||||
}
|
||||
break;
|
||||
case BUILD_PASSPHRASE_CALLBACK:
|
||||
va_start(args, part);
|
||||
this->cb = va_arg(args, chunk_t(*)(void*,int));
|
||||
this->data = va_arg(args, void*);
|
||||
va_end(args);
|
||||
break;
|
||||
default:
|
||||
builder_cancel(&this->public);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic PEM builder.
|
||||
*/
|
||||
static builder_t *pem_builder(credential_type_t type, int subtype)
|
||||
{
|
||||
private_builder_t *this = malloc_thing(private_builder_t);
|
||||
|
||||
this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
|
||||
this->public.build = (void*(*)(builder_t *this))build;
|
||||
|
||||
this->type = type;
|
||||
this->subtype = subtype;
|
||||
this->pem = chunk_empty;
|
||||
this->passphrase = chunk_empty;
|
||||
this->cb = NULL;
|
||||
this->data = NULL;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private key PEM builder.
|
||||
*/
|
||||
builder_t *private_key_pem_builder(key_type_t type)
|
||||
{
|
||||
return pem_builder(CRED_PRIVATE_KEY, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public key PEM builder.
|
||||
*/
|
||||
builder_t *public_key_pem_builder(key_type_t type)
|
||||
{
|
||||
return pem_builder(CRED_PUBLIC_KEY, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Certificate PEM builder.
|
||||
*/
|
||||
builder_t *certificate_pem_builder(certificate_type_t type)
|
||||
{
|
||||
return pem_builder(CRED_CERTIFICATE, type);
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 pem_builder pem_builder
|
||||
* @{ @ingroup pem_p
|
||||
*/
|
||||
|
||||
#ifndef PEM_PRIVATE_KEY_H_
|
||||
#define PEM_PRIVATE_KEY_H_
|
||||
|
||||
#include <credentials/certificates/certificate.h>
|
||||
#include <credentials/credential_factory.h>
|
||||
|
||||
/**
|
||||
* Builder for PEM encoded private keys of all kind.
|
||||
*
|
||||
* @param type type of the key
|
||||
* @return builder instance
|
||||
*/
|
||||
builder_t *private_key_pem_builder(key_type_t type);
|
||||
|
||||
/**
|
||||
* Builder for PEM encoded public keys of all kind.
|
||||
*
|
||||
* @param type type of the key
|
||||
* @return builder instance
|
||||
*/
|
||||
builder_t *public_key_pem_builder(key_type_t type);
|
||||
|
||||
/**
|
||||
* Builder for PEM encoded certificates of all kind.
|
||||
*
|
||||
* @param type type of the key
|
||||
* @return builder instance
|
||||
*/
|
||||
builder_t *certificate_pem_builder(certificate_type_t type);
|
||||
|
||||
#endif /** PEM_PRIVATE_KEY_H_ @}*/
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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 "pem_plugin.h"
|
||||
|
||||
#include <library.h>
|
||||
#include "pem_builder.h"
|
||||
|
||||
typedef struct private_pem_plugin_t private_pem_plugin_t;
|
||||
|
||||
/**
|
||||
* private data of pem_plugin
|
||||
*/
|
||||
struct private_pem_plugin_t {
|
||||
|
||||
/**
|
||||
* public functions
|
||||
*/
|
||||
pem_plugin_t public;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of pem_plugin_t.pemtroy
|
||||
*/
|
||||
static void destroy(private_pem_plugin_t *this)
|
||||
{
|
||||
lib->creds->remove_builder(lib->creds,
|
||||
(builder_constructor_t)private_key_pem_builder);
|
||||
lib->creds->remove_builder(lib->creds,
|
||||
(builder_constructor_t)public_key_pem_builder);
|
||||
lib->creds->remove_builder(lib->creds,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* see header file
|
||||
*/
|
||||
plugin_t *plugin_create()
|
||||
{
|
||||
private_pem_plugin_t *this = malloc_thing(private_pem_plugin_t);
|
||||
|
||||
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
|
||||
|
||||
/* register private key PEM decoding builders */
|
||||
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
|
||||
(builder_constructor_t)private_key_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
|
||||
(builder_constructor_t)private_key_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
|
||||
(builder_constructor_t)private_key_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_DSA,
|
||||
(builder_constructor_t)private_key_pem_builder);
|
||||
|
||||
/* register public key PEM decoding builders */
|
||||
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
|
||||
(builder_constructor_t)public_key_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
|
||||
(builder_constructor_t)public_key_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
|
||||
(builder_constructor_t)public_key_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_DSA,
|
||||
(builder_constructor_t)public_key_pem_builder);
|
||||
|
||||
/* register certificate PEM decoding builders */
|
||||
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_ANY,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PGP,
|
||||
(builder_constructor_t)certificate_pem_builder);
|
||||
|
||||
return &this->public.plugin;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 pem_p pem
|
||||
* @ingroup plugins
|
||||
*
|
||||
* @defgroup pem_plugin pem_plugin
|
||||
* @{ @ingroup pem_p
|
||||
*/
|
||||
|
||||
#ifndef PEM_PLUGIN_H_
|
||||
#define PEM_PLUGIN_H_
|
||||
|
||||
#include <plugins/plugin.h>
|
||||
|
||||
typedef struct pem_plugin_t pem_plugin_t;
|
||||
|
||||
/**
|
||||
* Plugin providing support to load credentials in PEM format
|
||||
*/
|
||||
struct pem_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
*/
|
||||
plugin_t plugin;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a pem_plugin instance.
|
||||
*/
|
||||
plugin_t *plugin_create();
|
||||
|
||||
#endif /** PEM_PLUGIN_H_ @}*/
|
|
@ -137,14 +137,13 @@ static void add(private_builder_t *this, builder_part_t part, ...)
|
|||
va_end(args);
|
||||
return;
|
||||
}
|
||||
case BUILD_BLOB_ASN1_PEM:
|
||||
case BUILD_BLOB_PEM:
|
||||
{
|
||||
bool pgp;
|
||||
char *pem;
|
||||
|
||||
|
||||
va_start(args, part);
|
||||
pem = va_arg(args, char *);
|
||||
blob = chunk_clone(chunk_create(pem, strlen(pem)));
|
||||
blob = va_arg(args, chunk_t);
|
||||
blob = chunk_clone(blob);
|
||||
if (pem_to_bin(&blob, chunk_empty, &pgp) == SUCCESS)
|
||||
{
|
||||
this->key = pubkey_public_key_load(chunk_clone(blob));
|
||||
|
|
|
@ -122,15 +122,18 @@ static bool parse_public_key(private_peer_controller_t *this,
|
|||
{
|
||||
public_key_t *public;
|
||||
identification_t *id;
|
||||
chunk_t blob;
|
||||
|
||||
if (!public_key || *public_key == '\0')
|
||||
{
|
||||
request->setf(request, "error=Public key is missing.");
|
||||
return FALSE;
|
||||
}
|
||||
blob = chunk_clone(chunk_create(public_key, strlen(public_key)));
|
||||
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
|
||||
BUILD_BLOB_ASN1_PEM, public_key,
|
||||
BUILD_BLOB_PEM, blob,
|
||||
BUILD_END);
|
||||
chunk_free(&blob);
|
||||
if (!public)
|
||||
{
|
||||
request->setf(request, "error=Parsing public key failed.");
|
||||
|
|
Loading…
Reference in New Issue