merged the modularization branch (credentials) back to trunk

This commit is contained in:
Martin Willi
2008-03-13 14:14:44 +00:00
parent 2df655134c
commit 552cc11b1f
495 changed files with 30378 additions and 23843 deletions
+81 -34
View File
@@ -9,43 +9,37 @@ else
endif
libstrongswan_la_SOURCES += \
credential_store.h \
library.c library.h \
chunk.c chunk.h \
debug.c debug.h \
enum.c enum.h \
settings.h settings.c \
printf_hook.c printf_hook.h \
asn1/asn1.c asn1/asn1.h \
asn1/oid.c asn1/oid.h \
asn1/pem.c asn1/pem.h \
asn1/ttodata.c asn1/ttodata.h \
crypto/ac.c crypto/ac.h \
crypto/ca.c crypto/ca.h \
crypto/certinfo.c crypto/certinfo.h \
crypto/crl.c crypto/crl.h \
crypto/crypters/crypter.c crypto/crypters/crypter.h \
crypto/crypters/aes_cbc_crypter.c crypto/crypters/aes_cbc_crypter.h \
crypto/crypters/des_crypter.c crypto/crypters/des_crypter.h \
crypto/diffie_hellman.c crypto/diffie_hellman.h \
crypto/hashers/hasher.h crypto/hashers/hasher.c \
crypto/hashers/sha1_hasher.c crypto/hashers/sha1_hasher.h \
crypto/hashers/sha2_hasher.c crypto/hashers/sha2_hasher.h \
crypto/hashers/md5_hasher.c crypto/hashers/md5_hasher.h \
crypto/hmac.c crypto/hmac.h \
crypto/ietf_attr_list.c crypto/ietf_attr_list.h \
crypto/ocsp.c crypto/ocsp.h \
crypto/pkcs7.c crypto/pkcs7.h \
crypto/pkcs9.c crypto/pkcs9.h \
crypto/prfs/fips_prf.c crypto/prfs/fips_prf.h \
crypto/prfs/hmac_prf.c crypto/prfs/hmac_prf.h \
crypto/prfs/prf.c crypto/prfs/prf.h \
crypto/prf_plus.h crypto/prf_plus.c \
crypto/rsa/rsa_private_key.c crypto/rsa/rsa_private_key.h \
crypto/rsa/rsa_public_key.h crypto/rsa/rsa_public_key.c \
crypto/signers/hmac_signer.c crypto/signers/hmac_signer.h \
crypto/signers/signer.c crypto/signers/signer.h \
crypto/x509.c crypto/x509.h \
utils/fetcher.c utils/fetcher.h \
crypto/diffie_hellman.c crypto/diffie_hellman.h \
crypto/crypto_factory.c crypto/crypto_factory.h \
credentials/credential_factory.c credentials/credential_factory.h \
credentials/builder.c credentials/builder.h \
credentials/keys/private_key.c credentials/keys/private_key.h \
credentials/keys/public_key.c credentials/keys/public_key.h \
credentials/keys/shared_key.c credentials/keys/shared_key.h \
credentials/certificates/certificate.c credentials/certificates/certificate.h \
credentials/certificates/x509.h credentials/certificates/x509.c \
credentials/certificates/crl.h credentials/certificates/crl.c \
credentials/certificates/ocsp_request.h credentials/certificates/ocsp_request.c \
credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
database/database.h database/database_factory.h database/database_factory.c \
utils.h utils.c \
utils/host.c utils/host.h \
utils/identification.c utils/identification.h \
utils/iterator.h \
@@ -54,28 +48,22 @@ utils/lexparser.c utils/lexparser.h \
utils/linked_list.c utils/linked_list.h \
utils/enumerator.c utils/enumerator.h \
utils/optionsfrom.c utils/optionsfrom.h \
utils/randomizer.c utils/randomizer.h
utils/randomizer.c utils/randomizer.h \
utils/mutex.c utils/mutex.h \
plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h
if USE_INTEGRITY_TEST
libstrongswan_la_SOURCES += \
fips/fips_canister_end.c
endif
libstrongswan_la_LIBADD = -lgmp -lpthread
libstrongswan_la_LIBADD = -lpthread -ldl
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS =
if USE_LEAK_DETECTIVE
libstrongswan_la_LIBADD += -ldl
AM_CFLAGS = -DLEAK_DETECTIVE
endif
if USE_LIBCURL
libstrongswan_la_LIBADD += -lcurl
endif
if USE_LIBLDAP
libstrongswan_la_LIBADD += -lldap -llber
AM_CFLAGS += -DLEAK_DETECTIVE
endif
EXTRA_DIST = asn1/oid.txt asn1/oid.pl
@@ -88,6 +76,65 @@ asn1/oid.c : asn1/oid.txt asn1/oid.pl
asn1/oid.h : asn1/oid.txt asn1/oid.pl
cd asn1 && $(PERL) oid.pl
# build plugins with their own Makefile
#######################################
SUBDIRS =
if USE_AES
SUBDIRS += plugins/aes
endif
if USE_DES
SUBDIRS += plugins/des
endif
if USE_MD5
SUBDIRS += plugins/md5
endif
if USE_SHA1
SUBDIRS += plugins/sha1
endif
if USE_SHA2
SUBDIRS += plugins/sha2
endif
if USE_FIPS_PRF
SUBDIRS += plugins/fips_prf
endif
if USE_GMP
SUBDIRS += plugins/gmp
endif
if USE_HMAC
SUBDIRS += plugins/hmac
endif
if USE_X509
SUBDIRS += plugins/x509
endif
if USE_CURL
SUBDIRS += plugins/curl
endif
if USE_LDAP
SUBDIRS += plugins/ldap
endif
if USE_MYSQL
SUBDIRS += plugins/mysql
endif
if USE_SQLITE
SUBDIRS += plugins/sqlite
endif
if USE_INTEGRITY_TEST
# build fips_signer which in turn builds fips_signature.h
#########################################################
+1 -23
View File
@@ -1,14 +1,6 @@
/**
* @file asn1.c
*
* @brief Simple ASN.1 parser
*
*/
/*
* Copyright (C) 2006 Martin Will
* Copyright (C) 2000-2008 Andreas Steffen
*
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -21,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
#include <stdio.h>
@@ -833,20 +825,6 @@ chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
return construct;
}
/**
* convert a MP integer into a DER coded ASN.1 object
*/
chunk_t asn1_integer_from_mpz(const mpz_t value)
{
size_t bits = mpz_sizeinbase(value, 2); /* size in bits */
chunk_t n;
n.len = 1 + bits / 8; /* size in bytes */
n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, value);
return asn1_wrap(ASN1_INTEGER, "m", n);
}
/**
* ASN.1 definition of time
*/
+10 -17
View File
@@ -1,10 +1,3 @@
/**
* @file asn1.h
*
* @brief Simple ASN.1 parser
*
*/
/*
* Copyright (C) 2006 Martin Will
* Copyright (C) 2000-2008 Andreas Steffen
@@ -21,11 +14,16 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
/**
* @defgroup asn1 asn1
* @{ @ingroup asn1
*/
#ifndef _ASN1_H
#define _ASN1_H
#ifndef ASN1_H_
#define ASN1_H_
#include <stdarg.h>
#include <gmp.h>
@@ -35,9 +33,7 @@
/**
* @brief Definition of some primitive ASN1 types
*
* @ingroup asn1
* Definition of some primitive ASN1 types
*/
typedef enum {
ASN1_EOC = 0x00,
@@ -87,7 +83,6 @@ typedef enum {
} asn1_t;
/* Definition of ASN1 flags */
#define ASN1_NONE 0x00
#define ASN1_DEF 0x01
#define ASN1_OPT 0x02
@@ -100,7 +95,6 @@ typedef enum {
#define ASN1_INVALID_LENGTH 0xffffffff
/* definition of an ASN.1 object */
typedef struct {
u_int level;
const u_char *name;
@@ -141,9 +135,8 @@ extern bool is_asn1(chunk_t blob);
extern void code_asn1_length(size_t length, chunk_t *code);
extern u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen);
extern chunk_t asn1_integer_from_mpz(const mpz_t value);
extern chunk_t asn1_simple_object(asn1_t tag, chunk_t content);
extern chunk_t asn1_bitstring(const char *mode, chunk_t content);
extern chunk_t asn1_wrap(asn1_t type, const char *mode, ...);
#endif /* _ASN1_H */
#endif /* ASN1_H_ @}*/
+13 -7
View File
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
#include <stdio.h>
@@ -95,10 +95,16 @@ static err_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_s
u_int8_t padding, *last_padding_pos, *first_padding_pos;
if (passphrase == NULL || passphrase->len == 0)
{
return "missing passphrase";
}
/* build key from passphrase and IV */
hasher = hasher_create(HASH_MD5);
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
if (hasher == NULL)
{
return "MD5 hasher not supported";
}
hash.len = hasher->get_hash_size(hasher);
hash.ptr = alloca(hash.len);
hasher->get_hash(hasher, *passphrase, NULL);
@@ -115,7 +121,7 @@ static err_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_s
hasher->destroy(hasher);
/* decrypt blob */
crypter = crypter_create(alg, key_size);
crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
crypter->set_key(crypter, key);
if (crypter->decrypt(crypter, *blob, *iv, &decrypted) != SUCCESS)
{
@@ -310,8 +316,8 @@ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
/* load a coded key or certificate file with autodetection
* of binary DER or base64 PEM ASN.1 formats and armored PGP format
*/
bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
const char *type, chunk_t *blob, bool *pgp)
bool pem_asn1_load_file(char *filename, chunk_t *passphrase,
chunk_t *blob, bool *pgp)
{
err_t ugh = NULL;
@@ -326,7 +332,7 @@ bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
blob->ptr = malloc(blob->len);
bytes = fread(blob->ptr, 1, blob->len, fd);
fclose(fd);
DBG1(" loading %s file '%s' (%d bytes)", type, filename, bytes);
DBG2(" loading '%s' (%d bytes)", filename, bytes);
*pgp = FALSE;
@@ -364,7 +370,7 @@ bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
}
else
{
DBG1(" could not open %s file '%s'", type, filename);
DBG1(" reading file '%s' failed", filename);
}
return FALSE;
}
+3 -3
View File
@@ -21,7 +21,7 @@
err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp);
bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
const char *type, chunk_t *blob, bool *pgp);
bool pem_asn1_load_file(char *filename, chunk_t *passphrase,
chunk_t *blob, bool *pgp);
#endif /*PEM_H_*/
#endif /*PEM_H_ @} */
+10 -8
View File
@@ -11,6 +11,8 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
* $Id$
*/
#include "ttodata.h"
@@ -34,7 +36,7 @@ static const char *badch(const char *, int, char *, size_t);
#define BADOFF(code) (BADCH0-(code))
/**
* @brief convert text to data, with verbose error reports
* convert text to data, with verbose error reports
*
* If some of this looks slightly odd, it's because it has changed
* repeatedly (from the original atodata()) without a major rewrite.
@@ -197,7 +199,7 @@ const char *ttodatav(const char *src, size_t srclen, int base, char *dst, size_t
}
/**
* @brief ttodata - convert text to data
* ttodata - convert text to data
*
* @param src
* @param srclen 0 means apply strlen()
@@ -214,7 +216,7 @@ const char *ttodata(const char *src, size_t srclen, int base, char *dst, size_t
}
/**
* @brief atodata - convert ASCII to data
* atodata - convert ASCII to data
*
* backward-compatibility interface
*
@@ -234,7 +236,7 @@ size_t atodata(const char *src, size_t srclen, char *dst, size_t dstlen)
}
/**
* @brief atobytes - convert ASCII to data bytes
* atobytes - convert ASCII to data bytes
*
* another backward-compatibility interface
*/
@@ -244,7 +246,7 @@ const char *atobytes(const char *src, size_t srclen, char *dst, size_t dstlen, s
}
/**
* @brief unhex - convert two ASCII hex digits to byte
* unhex - convert two ASCII hex digits to byte
*
* @param src known to be full length
* @param dstnumber of result bytes, or error code
@@ -290,7 +292,7 @@ static int unhex(const char *src, char *dst, size_t dstlen)
}
/**
* @brief unb64 - convert four ASCII base64 digits to three bytes
* unb64 - convert four ASCII base64 digits to three bytes
*
* Note that a base64 digit group is padded out with '=' if it represents
* less than three bytes: one byte is dd==, two is ddd=, three is dddd.
@@ -368,7 +370,7 @@ static int unb64(const char *src, char *dst, size_t dstlen)
}
/**
* @brief untext - convert one ASCII character to byte
* untext - convert one ASCII character to byte
*
* @param src known to be full length
* @param dst
@@ -386,7 +388,7 @@ static int untext(const char *src, char *dst, size_t dstlen)
}
/**
* @brief badch - produce a nice complaint about an unknown character
* badch - produce a nice complaint about an unknown character
*
* If the compiler complains that the array bigenough[] has a negative
* size, that means the TTODATAV_BUF constant has been set too small.
+1 -1
View File
@@ -25,4 +25,4 @@
err_t ttodata(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed);
#endif /* TTODATA_H_ */
#endif /* TTODATA_H_ @} */
+23 -74
View File
@@ -1,10 +1,3 @@
/**
* @file chunk.c
*
* @brief Pointer/lenght abstraction and its functions.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,8 @@
* 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.
*
* $Id$
*/
#include <stdio.h>
@@ -356,82 +351,22 @@ bool chunk_equals_or_null(chunk_t a, chunk_t b)
return a.len == b.len && memeq(a.ptr, b.ptr, a.len);
}
/**
* Number of bytes per line to dump raw data
*/
#define BYTES_PER_LINE 16
/**
* output handler in printf() for byte ranges
*/
static int print_bytes(FILE *stream, const struct printf_info *info,
const void *const *args)
{
char *bytes = *((void**)(args[0]));
int len = *((size_t*)(args[1]));
char buffer[BYTES_PER_LINE * 3];
char ascii_buffer[BYTES_PER_LINE + 1];
char *buffer_pos = buffer;
char *bytes_pos = bytes;
char *bytes_roof = bytes + len;
int line_start = 0;
int i = 0;
int written = 0;
written += fprintf(stream, "=> %d bytes @ %p", len, bytes);
while (bytes_pos < bytes_roof)
{
*buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
*buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
ascii_buffer[i++] =
(*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
{
int padding = 3 * (BYTES_PER_LINE - i);
int written;
while (padding--)
{
*buffer_pos++ = ' ';
}
*buffer_pos++ = '\0';
ascii_buffer[i] = '\0';
written += fprintf(stream, "\n%4d: %s %s",
line_start, buffer, ascii_buffer);
buffer_pos = buffer;
line_start += BYTES_PER_LINE;
i = 0;
}
else
{
*buffer_pos++ = ' ';
}
}
return written;
}
/**
* output handler in printf() for chunks
*/
static int print_chunk(FILE *stream, const struct printf_info *info,
static int chunk_print(FILE *stream, const struct printf_info *info,
const void *const *args)
{
chunk_t *chunk = *((chunk_t**)(args[0]));
bool first = TRUE;
chunk_t copy = *chunk;
int written = 0;
printf_hook_functions_t mem = mem_get_printf_hooks();
if (!info->alt)
{
const void *new_args[] = {&chunk->ptr, &chunk->len};
return print_bytes(stream, info, new_args);
return mem.print(stream, info, new_args);
}
while (copy.len > 0)
@@ -451,10 +386,24 @@ static int print_chunk(FILE *stream, const struct printf_info *info,
}
/**
* register printf() handlers
* arginfo handler for printf() mem ranges
*/
static void __attribute__ ((constructor))print_register()
static int chunk_arginfo(const struct printf_info *info, size_t n, int *argtypes)
{
register_printf_function(PRINTF_CHUNK, print_chunk, arginfo_ptr);
register_printf_function(PRINTF_BYTES, print_bytes, arginfo_ptr_int);
if (n > 0)
{
argtypes[0] = PA_POINTER;
}
return 1;
}
/**
* return printf hook functions for a chunk
*/
printf_hook_functions_t chunk_get_printf_hooks()
{
printf_hook_functions_t hooks = {chunk_print, chunk_arginfo};
return hooks;
}
+20 -11
View File
@@ -1,12 +1,5 @@
/**
* @file chunk.h
*
* @brief Pointer/length abstraction and its functions.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -19,6 +12,13 @@
* 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.
*
* $Id$
*/
/**
* @defgroup chunk chunk
* @{ @ingroup libstrongswan
*/
#ifndef CHUNK_H_
@@ -26,8 +26,7 @@
#include <string.h>
#include <stdarg.h>
#include <library.h>
#include <sys/types.h>
typedef struct chunk_t chunk_t;
@@ -41,6 +40,8 @@ struct chunk_t {
size_t len;
};
#include <library.h>
/**
* A { NULL, 0 }-chunk handy for initialization.
*/
@@ -161,4 +162,12 @@ bool chunk_equals(chunk_t a, chunk_t b);
*/
bool chunk_equals_or_null(chunk_t a, chunk_t b);
#endif /* CHUNK_H_ */
/**
* Get printf hooks for a chunk.
*
* Arguments are:
* chunk_t *chunk
*/
printf_hook_functions_t chunk_get_printf_hooks();
#endif /* CHUNK_H_ @}*/
-330
View File
@@ -1,330 +0,0 @@
/**
* @file credential_store.h
*
* @brief Interface credential_store_t.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* 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.
*/
#ifndef CREDENTIAL_STORE_H_
#define CREDENTIAL_STORE_H_
typedef struct credential_store_t credential_store_t;
#include <library.h>
#include <crypto/x509.h>
#include <crypto/ca.h>
#include <crypto/rsa/rsa_private_key.h>
#include <crypto/rsa/rsa_public_key.h>
#include <utils/identification.h>
/**
* @brief The interface for a credential_store backend.
*
* @b Constructors:
* - stroke_create()
*
* @ingroup config
*/
struct credential_store_t {
/**
* @brief Returns the secret shared by two specific IDs.
*
* The returned chunk must be destroyed by the caller after usage.
*
* @param this calling object
* @param my_id my ID identifiying the secret.
* @param other_id peer ID identifying the secret.
* @param[out] secret the pre-shared secret will be written there.
* @return
* - NOT_FOUND if no preshared secrets for specific ID could be found
* - SUCCESS
*
*/
status_t (*get_shared_key) (credential_store_t *this, identification_t *my_id,
identification_t *other_id, chunk_t *shared_key);
/**
* @brief Returns the EAP secret for two specified IDs.
*
* The returned chunk must be destroyed by the caller after usage.
*
* @param this calling object
* @param my_id my ID identifiying the secret.
* @param other_id peer ID identifying the secret.
* @param[out] eap_key the EAP secret will be written here
* @return
* - NOT_FOUND if no preshared secrets for specific ID could be found
* - SUCCESS
*
*/
status_t (*get_eap_key) (credential_store_t *this, identification_t *my_id,
identification_t *other_id, chunk_t *eap_key);
/**
* @brief Returns the RSA public key of a specific ID.
*
* @param this calling object
* @param id identification_t object identifiying the key.
* @return public key, or NULL if not found
*/
rsa_public_key_t* (*get_rsa_public_key) (credential_store_t *this, identification_t *id);
/**
* @brief Is there a matching RSA private key belonging to an RSA public key?
*
* @param this calling object
* @param pubkey public key
* @return TRUE if matching private key was found
*/
bool (*has_rsa_private_key) (credential_store_t *this, rsa_public_key_t *pubkey);
/**
* @brief Returns the certificate of a specific ID.
*
* @param this calling object
* @param id identification_t object identifiying the cert.
* @return certificate, or NULL if not found
*/
x509_t* (*get_certificate) (credential_store_t *this, identification_t *id);
/**
* @brief Returns the auth certificate of a specific subject distinguished name.
*
* @param this calling object
* @param auth_flags set of allowed authority types
* @param id identification_t object identifiying the cacert.
* @return certificate, or NULL if not found
*/
x509_t* (*get_auth_certificate) (credential_store_t *this, u_int auth_flags, identification_t *id);
/**
* @brief Returns the ca certificate of a specific keyID.
*
* @param this calling object
* @param keyid identification_t object identifiying the cacert.
* @return certificate, or NULL if not found
*/
x509_t* (*get_ca_certificate_by_keyid) (credential_store_t *this, chunk_t keyid);
/**
* @brief Returns the issuing ca of a given certificate.
*
* @param this calling object
* @param cert certificate for which issuer ca info is required
* @return ca info, or NULL if not found
*/
ca_info_t* (*get_issuer) (credential_store_t *this, x509_t* cert);
/**
* @brief RSA private key belonging to an RSA public key
*
*
* @param this calling object
* @param pubkey public key used to find the matching private key
* @param hash_algorithm hash algorithm to be used for signature
* @param data data block to be signed
* @param signature signature to be returned
* @return status of the signature process - SUCCESS if successful
*/
status_t (*rsa_signature) (credential_store_t *this, rsa_public_key_t *pubkey, hash_algorithm_t hash_algorithm,
chunk_t data, chunk_t *signature);
/**
* @brief Verify an RSA signature given the ID of the signer
*
* @param this calling object
* @param hash hash value to be verified.
* @param sig signature to be verified.
* @param id identification_t object identifiying the signer.
* @param issuer_p issuer of the signer's certificate (if not self-signed).
* @return status of the verification - SUCCESS if successful
*/
status_t (*verify_signature) (credential_store_t *this, chunk_t hash, chunk_t sig, identification_t *id,
ca_info_t **issuer_p);
/**
* @brief Verify an X.509 certificate up to trust anchor without any status checks
*
* @param this calling object
* @param label label characterizing the certificate to be verified
* @param cert certificate to be verified
* @return TRUE if trusted
*/
bool (*is_trusted) (credential_store_t *this, const char *label, x509_t *cert);
/**
* @brief Verify an X.509 certificate up to trust anchor including status checks
*
* @param this calling object
* @param cert certificate to be verified
* @param found found a certificate copy in the credential store
* @return TRUE if valid, trusted, and current status is good
*/
bool (*verify) (credential_store_t *this, x509_t *cert, bool *found);
/**
* @brief If an end certificate does not already exists in the credential store then add it.
*
* @param this calling object
* @param cert certificate to be added
* @return pointer to the added or already existing certificate
*/
x509_t* (*add_end_certificate) (credential_store_t *this, x509_t *cert);
/**
* @brief If an authority certificate does not already exists in the credential store then add it.
*
* @param this calling object
* @param cert authority certificate to be added
* @param auth_flag authority flags to add to the certificate
* @return pointer to the added or already existing certificate
*/
x509_t* (*add_auth_certificate) (credential_store_t *this, x509_t *cert, u_int auth_flag);
/**
* @brief If a ca info record does not already exists in the credential store then add it.
*
* @param this calling object
* @param ca_info ca info record to be added
* @return pointer to the added or already existing ca_info_t record
*/
ca_info_t* (*add_ca_info) (credential_store_t *this, ca_info_t *ca_info);
/**
* @brief Release a ca info record with a given name.
*
* @param this calling object
* @param name name of the ca info record to be released
* @return
* - SUCCESS, or
* - NOT_FOUND
*/
status_t (*release_ca_info) (credential_store_t *this, const char *name);
/**
* @brief Create an iterator over all end certificates.
*
* @param this calling object
* @return iterator
*/
iterator_t* (*create_cert_iterator) (credential_store_t *this);
/**
* @brief Create an iterator over all authority certificates.
*
* @param this calling object
* @return iterator
*/
iterator_t* (*create_auth_cert_iterator) (credential_store_t *this);
/**
* @brief Create an iterator over all CA info records
*
* @param this calling object
* @return iterator
*/
iterator_t* (*create_cainfo_iterator) (credential_store_t *this);
/**
* @brief Create an iterator over all attribute certificates.
*
* @param this calling object
* @return iterator
*/
iterator_t* (*create_acert_iterator) (credential_store_t *this);
/**
* @brief Loads ca certificates from a default directory.
*
* Certificates in both DER and PEM format are accepted
*
* @param this calling object
*/
void (*load_ca_certificates) (credential_store_t *this);
/**
* @brief Loads authorization authority certificates from a default directory.
*
* Certificates in both DER and PEM format are accepted
*
* @param this calling object
*/
void (*load_aa_certificates) (credential_store_t *this);
/**
* @brief Loads attribute certificates from a default directory.
*
* Certificates in both DER and PEM format are accepted
*
* @param this calling object
*/
void (*load_attr_certificates) (credential_store_t *this);
/**
* @brief Loads ocsp certificates from a default directory.
*
* Certificates in both DER and PEM format are accepted
*
* @param this calling object
*/
void (*load_ocsp_certificates) (credential_store_t *this);
/**
* @brief Loads CRLs from a default directory.
*
* Certificates in both DER and PEM format are accepted
*
* @param this calling object
* @param path directory to load crls from
*/
void (*load_crls) (credential_store_t *this);
/**
* @brief Loads secrets in ipsec.secrets
*
* RSA private key files can be either in DER or PEM format
* Optional encryption with a passphrase supported
*
* @param this calling object
* @param reload are the secrets to be reloaded
*/
void (*load_secrets) (credential_store_t *this, bool reload);
/**
* @brief Destroys a credential_store_t object.
*
* @param this calling object
*/
void (*destroy) (credential_store_t *this);
};
/**
* @brief Creates a credential_store_t instance.
*
* @param strict enforce a strict crl policy
* @return credential store instance.
*
* @ingroup config
*/
credential_store_t *credential_store_create(bool strict);
#endif /*CREDENTIAL_STORE_H_*/
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2008 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 "builder.h"
ENUM(builder_part_names, BUILD_BLOB_ASN1_DER, BUILD_END,
"BUILD_BLOB_ASN1_DER",
"BUILD_KEY_SIZE",
"BUILD_SIGNING_KEY",
"BUILD_SIGNING_CERT",
"BUILD_PUBLIC_KEY",
"BUILD_SUBJECT",
"BUILD_SUBJECT_ALTNAME",
"BUILD_ISSUER",
"BUILD_ISSUER_ALTNAME",
"BUILD_CA_CERT",
"BUILD_CERT",
"BUILD_END",
);
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2008 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 builder builder
* @{ @ingroup credentials
*/
#ifndef BUILDER_H_
#define BUILDER_H_
typedef struct builder_t builder_t;
typedef enum builder_part_t builder_part_t;
/**
* Constructor function which creates a new builder instance.
*
* @param subtype constructor specific subtype, e.g. certificate_type_t
* @return builder to construct a instance of type
*/
typedef builder_t* (*builder_constructor_t)(int subtype);
#include <library.h>
/**
* Parts to build credentials from.
*/
enum builder_part_t {
/** DER encoded ASN1 blob, argument is a chunk_t */
BUILD_BLOB_ASN1_DER,
/** key size in bits, as used for key generation, as u_int */
BUILD_KEY_SIZE,
/** private key to use for signing, private_key_t* */
BUILD_SIGNING_KEY,
/** certificate used for signing, certificate_t* */
BUILD_SIGNING_CERT,
/** public key to include, public_key_t* */
BUILD_PUBLIC_KEY,
/** subject for e.g. certificates, identification_t* */
BUILD_SUBJECT,
/** additional subject name, identification_t* */
BUILD_SUBJECT_ALTNAME,
/** issuer for e.g. certificates, identification_t* */
BUILD_ISSUER,
/** additional issuer name, identification_t* */
BUILD_ISSUER_ALTNAME,
/** a CA certificate, certificate_t* */
BUILD_CA_CERT,
/** a certificcate, certificate_t* */
BUILD_CERT,
/** end of variable argument builder list */
BUILD_END,
};
/**
* enum names for build_part_t
*/
extern enum_name_t *builder_part_names;
/**
* Credential construction API.
*
* The builder allows the construction of credentials in a generic and
* flexible way.
*/
struct builder_t {
/**
* Add a part to the construct.
*
* Any added parts get owned by the builder/construct, so clone/refcount
* them if needed.
*
* @param part kind of part
* @param ... part specific variable argument
*/
void (*add)(builder_t *this, builder_part_t part, ...);
/**
* Build the construct with all supplied parts.
*
* Once build() is called, the builder gets destroyed.
*
* @return specific interface, as requested with constructor.
*/
void* (*build)(builder_t *this);
};
#endif /* BUILDER_H_ @}*/
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2007 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.
*
* $Id$
*/
#include "certificate.h"
#include <credentials/certificates/x509.h>
ENUM(certificate_type_names, CERT_ANY, CERT_PGP,
"ANY",
"X509",
"X509_CRL",
"X509_OCSP_REQUEST",
"X509_OCSP_RESPONSE",
"X509_AC",
"X509_CHAIN",
"TRUSTED_PUBKEY",
"PGP",
);
ENUM(cert_validation_names, VALIDATION_GOOD, VALIDATION_SKIPPED,
"GOOD",
"REVOKED",
"FAILED",
"SKIPPED",
);
@@ -0,0 +1,190 @@
/*
* Copyright (C) 2007-2008 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 certificate certificate
* @{ @ingroup certificates
*/
#ifndef CERTIFICATE_H_
#define CERTIFICATE_H_
typedef struct certificate_t certificate_t;
typedef enum certificate_type_t certificate_type_t;
typedef enum cert_validation_t cert_validation_t;
#include <library.h>
#include <utils/identification.h>
#include <credentials/keys/public_key.h>
/**
* Kind of a certificate_t
*/
enum certificate_type_t {
/** just any certificate */
CERT_ANY,
/** X.509 certificate */
CERT_X509,
/** X.509 certificate revocation list */
CERT_X509_CRL,
/** X.509 online certificate status protocol request */
CERT_X509_OCSP_REQUEST,
/** X.509 online certificate status protocol response */
CERT_X509_OCSP_RESPONSE,
/** X.509 attribute certificate */
CERT_X509_AC,
/** trusted, preinstalled public key */
CERT_TRUSTED_PUBKEY,
/** PGP certificate */
CERT_PGP,
};
/**
* Enum names for certificate_type_t
*/
extern enum_name_t *certificate_type_names;
/**
* Result of a certificate validation.
*/
enum cert_validation_t {
/** certificate has been validated successfully */
VALIDATION_GOOD,
/** validation failed, certificate is revoked */
VALIDATION_REVOKED,
/* ocsp status is unknown or crl is stale */
VALIDATION_UNKNOWN,
/** validation process failed due to an error */
VALIDATION_FAILED,
/** validation has been skipped (no cdps available) */
VALIDATION_SKIPPED,
};
/**
* Enum names for cert_validation_t
*/
extern enum_name_t *cert_validation_names;
/**
* An abstract certificate.
*
* A certificate designs a subject-issuer relationship. It may have an
* associated public key.
*/
struct certificate_t {
/**
* Get the type of the certificate.
*
* @return certifcate type
*/
certificate_type_t (*get_type)(certificate_t *this);
/**
* Get the primary subject to which this certificate belongs.
*
* @return subject identity
*/
identification_t* (*get_subject)(certificate_t *this);
/**
* Check if certificate contains a subject ID.
*
* A certificate may contain additional subject identifiers, which are
* not returned by get_subject (e.g. subjectAltNames)
*
* @param subject subject identity
* @return matching value of best match
*/
id_match_t (*has_subject)(certificate_t *this, identification_t *subject);
/**
* Get the issuer which signed this certificate.
*
* @return issuer identity
*/
identification_t* (*get_issuer)(certificate_t *this);
/**
* Check if certificate contains an issuer ID.
*
* A certificate may contain additional issuer identifiers, which are
* not returned by get_issuer (e.g. issuerAltNames)
*
* @param subject isser identity
* @return matching value of best match
*/
id_match_t (*has_issuer)(certificate_t *this, identification_t *issuer);
/**
* Check if this certificate is issued by a specific issuer.
*
* As signature verification is computional expensive, it is optional
* and may be skipped. While this is not sufficient for verification
* purposes, it is to e.g. find matching certificates.
*
* @param issuer issuer's certificate
* @param checksig TRUE to verify signature, FALSE to compare issuer only
* @return TRUE if certificate issued by issuer and trusted
*/
bool (*issued_by)(certificate_t *this, certificate_t *issuer, bool checksig);
/**
* Get the public key associated to this certificate.
*
* @return newly referenced public_key, NULL if none available
*/
public_key_t* (*get_public_key)(certificate_t *this);
/**
* Check the lifetime of the certificate.
*
* @param when check validity at a certain time (NULL for now)
* @param not_before receives certificates start of lifetime
* @param not_after receives certificates end of lifetime
* @return TRUE if when between not_after and not_before
*/
bool (*get_validity)(certificate_t *this, time_t *when,
time_t *not_before, time_t *not_after);
/**
* Get the certificate in an encoded form.
*
* @return allocated chunk of encoded cert
*/
chunk_t (*get_encoding)(certificate_t *this);
/**
* Check if two certificates are equal.
*
* @param other certificate to compair against this
* @return TRUE if certificates are equal
*/
bool (*equals)(certificate_t *this, certificate_t *other);
/**
* Get a new reference to the certificate.
*
* @return this, with an increased refcount
*/
certificate_t* (*get_ref)(certificate_t *this);
/**
* Destroy a certificate.
*/
void (*destroy)(certificate_t *this);
};
#endif /* CERTIFICATE_H_ @}*/
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2008 Martin Willi
* Copyright (C) 2006 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.
*
* $Id$
*/
#include "crl.h"
ENUM(crl_reason_names, CRL_UNSPECIFIED, CRL_REMOVE_FROM_CRL,
"unspecified",
"key compromise",
"ca compromise",
"affiliation changed",
"superseded",
"cessation of operation",
"certificate hold",
"reason #7",
"remove from crl",
);
@@ -0,0 +1,93 @@
/*
* Copyright (C) 2008 Martin Willi
* Copyright (C) 2006 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.
*/
/**
* @defgroup crl crl
* @{ @ingroup certificates
*/
#ifndef CRL_H_
#define CRL_H_
typedef struct crl_t crl_t;
typedef enum crl_reason_t crl_reason_t;
#include <library.h>
#include <utils/linked_list.h>
/**
* RFC 2459 CRL reason codes
*/
enum crl_reason_t {
CRL_UNSPECIFIED = 0,
CRL_KEY_COMPROMISE = 1,
CRL_CA_COMPROMISE = 2,
CRL_AFFILIATION_CHANGED = 3,
CRL_SUPERSEDED = 4,
CRL_CESSATION_OF_OPERATON = 5,
CRL_CERTIFICATE_HOLD = 6,
CRL_REMOVE_FROM_CRL = 8,
};
/**
* enum names for crl_reason_t
*/
extern enum_name_t *crl_reason_names;
/**
* X509 certificate revocation list (CRL) interface definition.
*/
struct crl_t {
/**
* Implements (parts of) the certificate_t interface
*/
certificate_t certificate;
/**
* Is that newer than this?
*
* @return TRUE if newer, FALSE otherwise
*/
bool (*is_newer)(crl_t *this, crl_t *that);
/**
* Get the CRL serial number.
*
* @return chunk pointing to internal crlNumber
*/
chunk_t (*get_serial)(crl_t *this);
/**
* Get the the authorityKeyIdentifier.
*
* @return authKeyIdentifier as identification_t*
*/
identification_t* (*get_authKeyIdentifier)(crl_t *this);
/**
* Create an enumerator over all revoked certificates.
*
* The enumerator takes 3 pointer arguments:
* chunk_t serial, time_t revocation_date, crl_reason_t reason
*
* @return enumerator over revoked certificates.
*/
enumerator_t* (*create_enumerator)(crl_t *this);
};
#endif /* CRL_H_ @}*/
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "ocsp_request.h"
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
/**
* @defgroup ocsp_request ocsp_request
* @{ @ingroup certificates
*/
#ifndef OCSP_REQUEST_H_
#define OCSP_REQUEST_H_
#include <credentials/certificates/certificate.h>
typedef struct ocsp_request_t ocsp_request_t;
/**
* OCSP request message.
*/
struct ocsp_request_t {
/**
* Implements certificiate_t interface
*/
certificate_t interface;
};
#endif /* OCSP_REQUEST_H_ @}*/
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "ocsp_response.h"
ENUM(ocsp_status_names, OCSP_SUCCESSFUL, OCSP_UNAUTHORIZED,
"successful",
"malformed request",
"internal error",
"try later",
"status #4",
"signature required",
"unauthorized"
);
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
/**
* @defgroup ocsp_response ocsp_response
* @{ @ingroup certificates
*/
#ifndef OCSP_RESPONSE_H_
#define OCSP_RESPONSE_H_
#include <credentials/certificates/x509.h>
#include <credentials/certificates/crl.h>
typedef struct ocsp_response_t ocsp_response_t;
typedef enum ocsp_status_t ocsp_status_t;
/**
* OCSP response status
*/
enum ocsp_status_t {
OCSP_SUCCESSFUL = 0,
OCSP_MALFORMEDREQUEST = 1,
OCSP_INTERNALERROR = 2,
OCSP_TRYLATER = 3,
OCSP_SIGREQUIRED = 5,
OCSP_UNAUTHORIZED = 6,
};
/**
* enum names for ocsp_status_t
*/
extern enum_name_t *ocsp_status_names;
/**
* OCSP response message.
*/
struct ocsp_response_t {
/**
* Implements certificiate_t interface
*/
certificate_t certificate;
/**
* Check the status of a certificate by this OCSP response.
*
* @param subject certificate to check status
* @param issuer issuer certificate of subject
* @param revocation_time receives time of revocation, if revoked
* @param revocation_reason receives reason of revocation, if revoked
* @param this_update creation time of revocation list
* @param next_update exptected time of next revocation list
* @return certificate revocation status
*/
cert_validation_t (*get_status)(ocsp_response_t *this,
x509_t *subject, x509_t *issuer,
time_t *revocation_time,
crl_reason_t *revocation_reason,
time_t *this_update, time_t *next_update);
/**
* Create an enumerator over the contained certificates.
*
* @return enumerator over certificate_t*
*/
enumerator_t* (*create_cert_enumerator)(ocsp_response_t *this);
};
#endif /* OCSP_RESPONSE_H_ @}*/
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "x509.h"
ENUM(x509_flag_names, X509_CA, X509_SELF_SIGNED,
"X509_CA",
"X509_AA",
"X509_OCSP_SIGNER",
"X509_SELF_SIGNED",
);
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2007-2008 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 x509 x509
* @{ @ingroup certificates
*/
#ifndef X509_H_
#define X509_H_
#include <utils/enumerator.h>
#include <credentials/certificates/certificate.h>
typedef struct x509_t x509_t;
typedef enum x509_flag_t x509_flag_t;
/**
* X.509 certificate flags.
*/
enum x509_flag_t {
/** cert has CA constraint */
X509_CA = (1<<0),
/** cert has AA constraint */
X509_AA = (1<<1),
/** cert has OCSP signer constraint */
X509_OCSP_SIGNER = (1<<2),
/** cert belongs to an end entity */
X509_PEER = (1<<3),
/** cert is self-signed */
X509_SELF_SIGNED = (1<<4),
};
/**
* enum names for x509 flags
*/
extern enum_name_t *x509_flag_names;
/**
* X.509 certificate interface.
*
* This interface adds additional methods to the certificate_t type to
* allow further operations on these certificates.
*/
struct x509_t {
/**
* Implements certificate_t.
*/
certificate_t interface;
/**
* Get the flags set for this certificate.
*
* @return set of flags
*/
x509_flag_t (*get_flags)(x509_t *this);
/**
* Set the flags for this certificate.
*
* @param flags set of flags
*/
void (*set_flags)(x509_t *this, x509_flag_t flags);
/**
* Get the certificate serial number.
*
* @return chunk pointing to internal serial number
*/
chunk_t (*get_serial)(x509_t *this);
/**
* Get the the authorityKeyIdentifier.
*
* @return authKeyIdentifier as identification_t*
*/
identification_t* (*get_authKeyIdentifier)(x509_t *this);
/**
* Create an enumerator over all subjectAltNames.
*
* @return enumerator over subjectAltNames as identification_t*
*/
enumerator_t* (*create_subjectAltName_enumerator)(x509_t *this);
/**
* Create an enumerator over all CRL URIs.
*
* @return enumerator over URIs as char*
*/
enumerator_t* (*create_crl_uri_enumerator)(x509_t *this);
/**
* Create an enumerator over all OCSP URIs.
*
* @return enumerator over URIs as char*
*/
enumerator_t* (*create_ocsp_uri_enumerator)(x509_t *this);
};
#endif /* X509_H_ @}*/
@@ -0,0 +1,263 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "credential_factory.h"
#include <debug.h>
#include <utils/linked_list.h>
#include <utils/mutex.h>
typedef struct private_credential_factory_t private_credential_factory_t;
/**
* private data of credential_factory
*/
struct private_credential_factory_t {
/**
* public functions
*/
credential_factory_t public;
/**
* list with entry_t
*/
linked_list_t *constructors;
/**
* mutex to lock access to modules
*/
mutex_t *mutex;
};
typedef struct entry_t entry_t;
struct entry_t {
/** kind of credential builder */
credential_type_t type;
/** subtype of credential, e.g. certificate_type_t */
int subtype;
/** builder construction function */
builder_constructor_t constructor;
};
/**
* Implementation of credential_factory_t.create_builder.
*/
static builder_t* create_builder(private_credential_factory_t *this,
credential_type_t type, int subtype)
{
enumerator_t *enumerator;
entry_t *entry;
builder_t *builder = NULL;
this->mutex->lock(this->mutex);
enumerator = this->constructors->create_enumerator(this->constructors);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->type == type && entry->subtype == subtype)
{
builder = entry->constructor(subtype);
if (builder)
{
break;
}
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return builder;
}
/**
* Implementation of credential_factory_t.add_builder_constructor.
*/
static void add_builder(private_credential_factory_t *this,
credential_type_t type, int subtype,
builder_constructor_t constructor)
{
entry_t *entry = malloc_thing(entry_t);
entry->type = type;
entry->subtype = subtype;
entry->constructor = constructor;
this->mutex->lock(this->mutex);
this->constructors->insert_last(this->constructors, entry);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of credential_factory_t.remove_builder.
*/
static void remove_builder(private_credential_factory_t *this,
builder_constructor_t constructor)
{
enumerator_t *enumerator;
entry_t *entry;
this->mutex->lock(this->mutex);
enumerator = this->constructors->create_enumerator(this->constructors);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->constructor == constructor)
{
this->constructors->remove_at(this->constructors, enumerator);
free(entry);
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of credential_factory_t.create.
*/
static void* create(private_credential_factory_t *this, credential_type_t type,
int subtype, ...)
{
builder_t *builder;
builder_part_t part;
va_list args;
builder = create_builder(this, type, subtype);
if (builder)
{
va_start(args, subtype);
while (TRUE)
{
part = va_arg(args, builder_part_t);
switch (part)
{
case BUILD_END:
break;
case BUILD_BLOB_ASN1_DER:
builder->add(builder, part, va_arg(args, chunk_t));
continue;
case BUILD_KEY_SIZE:
builder->add(builder, part, va_arg(args, u_int));
continue;
case BUILD_SIGNING_KEY:
case BUILD_PUBLIC_KEY:
case BUILD_SUBJECT:
case BUILD_SUBJECT_ALTNAME:
case BUILD_ISSUER:
case BUILD_ISSUER_ALTNAME:
case BUILD_SIGNING_CERT:
case BUILD_CA_CERT:
case BUILD_CERT:
builder->add(builder, part, va_arg(args, void*));
continue;
default:
DBG1("builder part %N not supported by factory",
builder_part_names, part);
continue;
}
break;
}
va_end(args);
return builder->build(builder);
}
/** shredder all data on failure */
va_start(args, subtype);
while (TRUE)
{
part = va_arg(args, builder_part_t);
switch (part)
{
case BUILD_END:
break;
case BUILD_BLOB_ASN1_DER:
{
chunk_t chunk = va_arg(args, chunk_t);
free(chunk.ptr);
continue;
}
case BUILD_SIGNING_KEY:
{
private_key_t *private = va_arg(args, private_key_t*);
private->destroy(private);
continue;
}
case BUILD_PUBLIC_KEY:
{
public_key_t *public = va_arg(args, public_key_t*);
public->destroy(public);
continue;
}
case BUILD_SUBJECT:
case BUILD_SUBJECT_ALTNAME:
case BUILD_ISSUER:
case BUILD_ISSUER_ALTNAME:
{
identification_t *id = va_arg(args, identification_t*);
id->destroy(id);
continue;
}
case BUILD_SIGNING_CERT:
case BUILD_CA_CERT:
case BUILD_CERT:
{
certificate_t *cert = va_arg(args, certificate_t*);
cert->destroy(cert);
continue;
}
case BUILD_KEY_SIZE:
continue;
default:
DBG1("builder part %N not supported by factory",
builder_part_names, part);
continue;
}
break;
}
va_end(args);
return NULL;
}
/**
* Implementation of credential_factory_t.destroy
*/
static void destroy(private_credential_factory_t *this)
{
this->constructors->destroy_function(this->constructors, free);
this->mutex->destroy(this->mutex);
free(this);
}
/*
* see header file
*/
credential_factory_t *credential_factory_create()
{
private_credential_factory_t *this = malloc_thing(private_credential_factory_t);
this->public.create = (void*(*)(credential_factory_t*, credential_type_t type, int subtype, ...))create;
this->public.create_builder = (builder_t*(*)(credential_factory_t*, credential_type_t type, int subtype))create_builder;
this->public.add_builder = (void(*)(credential_factory_t*,credential_type_t type, int subtype, builder_constructor_t constructor))add_builder;
this->public.remove_builder = (void(*)(credential_factory_t*,builder_constructor_t constructor))remove_builder;
this->public.destroy = (void(*)(credential_factory_t*))destroy;
this->constructors = linked_list_create();
this->mutex = mutex_create(MUTEX_RECURSIVE);
return &this->public;
}
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2008 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 credential_factory credential_factory
* @{ @ingroup credentials
*/
#ifndef CREDENTIAL_FACTORY_H_
#define CREDENTIAL_FACTORY_H_
typedef struct credential_factory_t credential_factory_t;
typedef enum credential_type_t credential_type_t;
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
#include <credentials/certificates/certificate.h>
#include <credentials/builder.h>
/**
* Kind of credential.
*/
enum credential_type_t {
/** private key, implemented in private_key_t */
CRED_PRIVATE_KEY,
/** public key, implemented in public_key_t */
CRED_PUBLIC_KEY,
/** certificates, implemented in certificate_t */
CRED_CERTIFICATE,
};
/**
* Manages credential construction functions and creates instances.
*/
struct credential_factory_t {
/**
* Create a credential using a list of builder_part_t's.
*
* The variable argument list takes builder_part_t types followed
* by the type specific value. The list must be terminated using BUILD_END.
*
* @param type credential type to build
* @param subtype subtype specific for type of the credential
* @param ... build_part_t arguments, BUILD_END terminated.
* @return type specific credential, NULL if failed
*/
void* (*create)(credential_factory_t *this, credential_type_t type,
int subtype, ...);
/**
* Create a builder instance to build credentials.
*
* @param type type of credentials the builder creates
* @param subtype type specific subtype, such as certificate_type_t
* @return builder instance
*/
builder_t* (*create_builder)(credential_factory_t *this,
credential_type_t type, int subtype);
/**
* Register a builder_t constructor function.
*
* @param type type of credential the builder creates
* @param constructor builder constructor function to register
*/
void (*add_builder)(credential_factory_t *this,
credential_type_t type, int subtype,
builder_constructor_t constructor);
/**
* Unregister a builder_t constructor function.
*
* @param constructor constructor function to unregister.
*/
void (*remove_builder)(credential_factory_t *this,
builder_constructor_t constructor);
/**
* Destroy a credential_factory instance.
*/
void (*destroy)(credential_factory_t *this);
};
/**
* Create a credential_factory instance.
*/
credential_factory_t *credential_factory_create();
#endif /* CREDENTIAL_FACTORY_H_ @}*/
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2007 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.
*
* $Id$
*/
#include "private_key.h"
@@ -0,0 +1,143 @@
/*
* Copyright (C) 2007 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.
*
* $Id$
*/
/**
* @defgroup private_key private_key
* @{ @ingroup keys
*/
#ifndef PRIVATE_KEY_H_
#define PRIVATE_KEY_H_
typedef struct private_key_t private_key_t;
#include <utils/identification.h>
#include <credentials/keys/public_key.h>
/**
* Abstract private key interface.
*/
struct private_key_t {
/**
* Get the key type.
*
* @return type of the key
*/
key_type_t (*get_type)(private_key_t *this);
/**
* Create a signature over a chunk of data.
*
* @param scheme signature scheme to use
* @param data chunk of data to sign
* @param signature where to allocate created signature
* @return TRUE if signature created
*/
bool (*sign)(private_key_t *this, signature_scheme_t scheme,
chunk_t data, chunk_t *signature);
/**
* Decrypt a chunk of data.
*
* @param crypto chunk containing encrypted data
* @param plain where to allocate decrypted data
* @return TRUE if data decrypted and plaintext allocated
*/
bool (*decrypt)(private_key_t *this, chunk_t crypto, chunk_t *plain);
/**
* Get the strength of the key in bytes.
*
* @return strength of the key in bytes
*/
size_t (*get_keysize) (private_key_t *this);
/**
* Get a unique key identifier, such as a hash over the public key.
*
* @param type type of the key ID to get
* @return unique ID of the key as identification_t, or NULL
*/
identification_t* (*get_id) (private_key_t *this, id_type_t type);
/**
* Get the public part from the private key.
*
* @return public key
*/
public_key_t* (*get_public_key)(private_key_t *this);
/**
* Check if a private key belongs to a public key.
*
* @param public public key
* @return TRUE, if keys belong together
*/
bool (*belongs_to) (private_key_t *this, public_key_t *public);
/**
* Get an encoded form of the private key.
*
* @todo Do we need a encoding type specification?
*
* @return allocated chunk containing encoded private key
*/
chunk_t (*get_encoding)(private_key_t *this);
/**
* Increase the refcount to this private key.
*
* @return this, with an increased refcount
*/
private_key_t* (*get_ref)(private_key_t *this);
/**
* Decrease refcount, destroy private_key if no more references.
*/
void (*destroy)(private_key_t *this);
};
/**
* Read a private key from a file.
*
* @param type type of the key
* @param filename filename to read key from
* @param passphrase passphrase to decrypt an encrypted key
* @return loaded private key, NULL if failed
*/
private_key_t *private_key_create_from_file(key_type_t type, char *filename,
chunk_t passphrase);
/**
* Create a private key from a chunk.
*
* @param type type of the key
* @param chunk chunk to create key from
* @return loaded private key, NULL if failed
*/
private_key_t *private_key_create_from_chunk(key_type_t type, chunk_t chunk);
/**
* Generate a new private key.
*
* @param type type of the key
* @param size key size in bytes
* @return generated private key, NULL if failed
*/
private_key_t *private_key_create_generated(key_type_t type, size_t size);
#endif /* PRIVATE_KEY_H_ @} */
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2007 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.
*
* $Id$
*/
#include "public_key.h"
ENUM(key_type_names, KEY_RSA, KEY_RSA,
"RSA"
);
ENUM(signature_scheme_names, SIGN_DEFAULT, SIGN_RSA_EMSA_PKCS1_SHA512,
"DEFAULT",
"RSA_EMSA_PKCS1_MD5",
"RSA_EMSA_PKCS1_SHA1",
"RSA_EMSA_PKCS1_SHA256",
"RSA_EMSA_PKCS1_SHA384",
"RSA_EMSA_PKCS1_SHA512",
);
@@ -0,0 +1,163 @@
/*
* Copyright (C) 2007 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.
*
* $Id$
*/
/**
* @defgroup public_key public_key
* @{ @ingroup keys
*/
#ifndef PUBLIC_KEY_H_
#define PUBLIC_KEY_H_
typedef struct public_key_t public_key_t;
typedef enum key_type_t key_type_t;
typedef enum key_id_type_t key_id_type_t;
typedef enum signature_scheme_t signature_scheme_t;
#include <library.h>
#include <utils/identification.h>
/**
* Type of a key pair, the used crypto system
*/
enum key_type_t {
/** key type wildcard */
KEY_ANY,
/** RSA crypto system as in PKCS#1 */
KEY_RSA,
/** DSS, ElGamal, ECDSA, ... */
};
/**
* Enum names for key_type_t
*/
extern enum_name_t *key_type_names;
/**
* Signature scheme for signature creation
*
* EMSA-PKCS1 signatures are from the PKCS#1 standard. They include
* the ASN1-OID of the used hash algorithm.
*/
enum signature_scheme_t {
/** default scheme of that underlying crypto system */
SIGN_DEFAULT,
/** EMSA-PKCS1 with MD5 */
SIGN_RSA_EMSA_PKCS1_MD5,
/** EMSA-PKCS1 signature as in PKCS#1 standard using SHA1 as hash. */
SIGN_RSA_EMSA_PKCS1_SHA1,
/** EMSA-PKCS1 signature as in PKCS#1 standard using SHA256 as hash. */
SIGN_RSA_EMSA_PKCS1_SHA256,
/** EMSA-PKCS1 signature as in PKCS#1 standard using SHA384 as hash. */
SIGN_RSA_EMSA_PKCS1_SHA384,
/** EMSA-PKCS1 signature as in PKCS#1 standard using SHA512 as hash. */
SIGN_RSA_EMSA_PKCS1_SHA512,
};
/**
* Enum names for signature_scheme_t
*/
extern enum_name_t *signature_scheme_names;
/**
* Abstract interface of a public key.
*/
struct public_key_t {
/**
* Get the key type.
*
* @return type of the key
*/
key_type_t (*get_type)(public_key_t *this);
/**
* Verifies a signature against a chunk of data.
*
* @param scheme signature scheme to use for verification, may be default
* @param data data to check signature against
* @param signature signature to check
* @return TRUE if signature matches
*/
bool (*verify)(public_key_t *this, signature_scheme_t scheme,
chunk_t data, chunk_t signature);
/**
* Encrypt a chunk of data.
*
* @param crypto chunk containing plaintext data
* @param plain where to allocate encrypted data
* @return TRUE if data successfully encrypted
*/
bool (*encrypt)(public_key_t *this, chunk_t crypto, chunk_t *plain);
/**
* Get the strength of the key in bytes.
*
* @return strength of the key in bytes
*/
size_t (*get_keysize) (public_key_t *this);
/**
* Get a unique key identifier, such as a hash over the key.
*
* @param type type of the key ID to get
* @return unique ID of the key as identification_t, or NULL
*/
identification_t* (*get_id) (public_key_t *this, id_type_t type);
/**
* Get an encoded form of the key.
*
* @todo Do we need a encoding type specification?
*
* @return allocated chunk containing encoded key
*/
chunk_t (*get_encoding)(public_key_t *this);
/**
* Increase the refcount of the key.
*
* @return this with an increased refcount
*/
public_key_t* (*get_ref)(public_key_t *this);
/**
* Destroy a public_key instance.
*/
void (*destroy)(public_key_t *this);
};
/**
* Read a public key from a file.
*
* @param type type of the key
* @param filename filename to read key from
* @return loaded public key, NULL if failed
*/
public_key_t *public_key_create_from_file(key_type_t type, char *filename);
/**
* Create a public key from a chunk.
*
* @param type type of the key
* @param chunk chunk to create key from
* @return loaded public key, NULL if failed
*/
public_key_t *public_key_create_from_chunk(key_type_t type, chunk_t chunk);
#endif /* PUBLIC_KEY_H_ @} */
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2007 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.
*
* $Id$
*/
#include "shared_key.h"
ENUM(shared_key_type_names, SHARED_ANY, SHARED_PIN,
"ANY",
"IKE",
"EAP",
"PRIVATE_KEY_PASS",
"PIN",
);
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2007 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 shared_key shared_key
* @{ @ingroup keys
*/
#ifndef SHARED_KEY_H_
#define SHARED_KEY_H_
#include <utils/enumerator.h>
#include <utils/identification.h>
typedef struct shared_key_t shared_key_t;
typedef enum shared_key_type_t shared_key_type_t;
/**
* Type of a shared key.
*/
enum shared_key_type_t {
/** wildcard for all keys */
SHARED_ANY,
/** PSK for IKE authentication */
SHARED_IKE,
/** key for a EAP authentication method */
SHARED_EAP,
/** key to decrypt encrypted private keys */
SHARED_PRIVATE_KEY_PASS,
/** PIN to unlock a smartcard */
SHARED_PIN,
};
/**
* enum names for shared_key_type_t
*/
extern enum_name_t *shared_key_type_names;
/**
* A symmetric key shared between multiple owners.
*
* This class is not thread save, do not add owners while others might be
* reading.
*/
struct shared_key_t {
/**
* Get the kind of this key.
*
* @return type of the key
*/
shared_key_type_t (*get_type)(shared_key_t *this);
/**
* Get the shared key data.
*
* @return chunk pointing to the internal key
*/
chunk_t (*get_key)(shared_key_t *this);
/**
* Increase refcount of the key.
*
* @return this with an increased refcount
*/
shared_key_t* (*get_ref)(shared_key_t *this);
/**
* Destroy a shared_key instance if all references are gone.
*/
void (*destroy)(shared_key_t *this);
};
#endif /** SHARED_KEY_H_ @} */
-636
View File
@@ -1,636 +0,0 @@
/**
* @file ac.c
*
* @brief Implementation of x509ac_t.
*
*/
/*
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
* Copyright (C) 2003 Martin Berner, Lukas Suter
* Copyright (C) 2007 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.
*
* RCSID $Id$
*/
#include <string.h>
#include <stdio.h>
#include <library.h>
#include <debug.h>
#include <asn1/asn1.h>
#include <asn1/pem.h>
#include <crypto/x509.h>
#include <crypto/ietf_attr_list.h>
#include <utils/identification.h>
#include <utils/linked_list.h>
#include <utils/lexparser.h>
#include "ac.h"
#define ACERT_WARNING_INTERVAL 1 /* day */
typedef struct private_x509ac_t private_x509ac_t;
/**
* Private data of a x509ac_t object.
*/
struct private_x509ac_t {
/**
* Public interface for this attribute certificate.
*/
x509ac_t public;
/**
* Time when attribute certificate was installed
*/
time_t installed;
/**
* X.509 attribute certificate in DER format
*/
chunk_t certificate;
/**
* X.509 attribute certificate body over which signature is computed
*/
chunk_t certificateInfo;
/**
* Version of the X.509 attribute certificate
*/
u_int version;
/**
* Serial number of the X.509 attribute certificate
*/
chunk_t serialNumber;
/**
* ID representing the issuer of the holder certificate
*/
identification_t *holderIssuer;
/**
* Serial number of the holder certificate
*/
chunk_t holderSerial;
/**
* ID representing the holder
*/
identification_t *entityName;
/**
* ID representing the attribute certificate issuer
*/
identification_t *issuerName;
/**
* Signature algorithm
*/
int sigAlg;
/**
* Start time of certificate validity
*/
time_t notBefore;
/**
* End time of certificate validity
*/
time_t notAfter;
/**
* List of charging attributes
*/
linked_list_t *charging;
/**
* List of groub attributes
*/
linked_list_t *groups;
/**
* Authority Key Identifier
*/
chunk_t authKeyID;
/**
* Authority Key Serial Number
*/
chunk_t authKeySerialNumber;
/**
* No revocation information available
*/
bool noRevAvail;
/**
* Signature algorithm (must be identical to sigAlg)
*/
int algorithm;
/**
* Signature
*/
chunk_t signature;
};
/**
* ASN.1 definition of roleSyntax
*/
static const asn1Object_t roleSyntaxObjects[] =
{
{ 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
{ 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
ASN1_OBJ }, /* 1 */
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
{ 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */
};
#define ROLE_ROOF 4
/**
* ASN.1 definition of an X509 attribute certificate
*/
static const asn1Object_t acObjects[] =
{
{ 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
{ 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
{ 2, "version", ASN1_INTEGER, ASN1_DEF |
ASN1_BODY }, /* 2 */
{ 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
{ 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
{ 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
{ 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
{ 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
ASN1_BODY }, /* 7 */
{ 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
{ 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
ASN1_OBJ }, /* 10 */
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
{ 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
{ 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/
{ 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
ASN1_BODY }, /* 14 */
{ 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/
{ 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
{ 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
{ 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
ASN1_OBJ }, /* 19 */
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
{ 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
{ 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
{ 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
{ 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
{ 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
ASN1_BODY }, /* 25 */
{ 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
{ 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
{ 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
{ 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
{ 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
ASN1_BODY }, /* 31 */
{ 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
{ 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
{ 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
{ 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
{ 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
{ 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
{ 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
{ 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
{ 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
{ 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
{ 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
{ 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
{ 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
{ 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
{ 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
{ 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
{ 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */
{ 4, "critical", ASN1_BOOLEAN, ASN1_DEF |
ASN1_BODY }, /* 50 */
{ 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */
{ 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */
{ 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */
{ 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */
};
#define AC_OBJ_CERTIFICATE 0
#define AC_OBJ_CERTIFICATE_INFO 1
#define AC_OBJ_VERSION 2
#define AC_OBJ_HOLDER_ISSUER 5
#define AC_OBJ_HOLDER_SERIAL 6
#define AC_OBJ_ENTITY_NAME 10
#define AC_OBJ_ISSUER_NAME 19
#define AC_OBJ_ISSUER 23
#define AC_OBJ_SIG_ALG 35
#define AC_OBJ_SERIAL_NUMBER 36
#define AC_OBJ_NOT_BEFORE 38
#define AC_OBJ_NOT_AFTER 39
#define AC_OBJ_ATTRIBUTE_TYPE 42
#define AC_OBJ_ATTRIBUTE_VALUE 44
#define AC_OBJ_EXTN_ID 49
#define AC_OBJ_CRITICAL 50
#define AC_OBJ_EXTN_VALUE 51
#define AC_OBJ_ALGORITHM 53
#define AC_OBJ_SIGNATURE 54
#define AC_OBJ_ROOF 55
/**
* Implements x509ac_t.is_valid
*/
static err_t is_valid(const private_x509ac_t *this, time_t *until)
{
time_t current_time = time(NULL);
DBG2(" not before : %T", &this->notBefore);
DBG2(" current time: %T", &current_time);
DBG2(" not after : %T", &this->notAfter);
if (until != NULL &&
(*until == UNDEFINED_TIME || this->notAfter < *until))
{
*until = this->notAfter;
}
if (current_time < this->notBefore)
{
return "is not valid yet";
}
if (current_time > this->notAfter)
{
return "has expired";
}
DBG2(" attribute certificate is valid");
return NULL;
}
/**
* Implements x509ac_t.is_newer
*/
static bool is_newer(const private_x509ac_t *this, const private_x509ac_t *other)
{
return this->notBefore > other->notBefore;
}
/**
* Implements x509ac_t.equals_holder.
*/
static bool equals_holder(const private_x509ac_t *this, const private_x509ac_t *other)
{
return this->holderIssuer->equals(this->holderIssuer, other->holderIssuer)
&& chunk_equals(this->holderSerial, other->holderSerial);
}
/**
* parses a directoryName
*/
static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name)
{
bool has_directoryName;
linked_list_t *list = linked_list_create();
x509_parse_generalNames(blob, level, implicit, list);
has_directoryName = list->get_count(list) > 0;
if (has_directoryName)
{
iterator_t *iterator = list->create_iterator(list, TRUE);
identification_t *directoryName;
bool first = TRUE;
while (iterator->iterate(iterator, (void**)&directoryName))
{
if (first)
{
*name = directoryName;
first = FALSE;
}
else
{
DBG1("more than one directory name - first selected");
directoryName->destroy(directoryName);
}
}
iterator->destroy(iterator);
}
else
{
DBG1("no directoryName found");
}
list->destroy(list);
return has_directoryName;
}
/**
* parses roleSyntax
*/
static void parse_roleSyntax(chunk_t blob, int level0)
{
asn1_ctx_t ctx;
chunk_t object;
u_int level;
int objectID = 0;
asn1_init(&ctx, blob, level0, FALSE, FALSE);
while (objectID < ROLE_ROOF)
{
if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx))
{
return;
}
switch (objectID)
{
default:
break;
}
objectID++;
}
}
/**
* Parses an X.509 attribute certificate
*/
static bool parse_certificate(chunk_t blob, private_x509ac_t *this)
{
asn1_ctx_t ctx;
bool critical;
chunk_t object;
u_int level;
int objectID = 0;
int type = OID_UNKNOWN;
int extn_oid = OID_UNKNOWN;
asn1_init(&ctx, blob, 0, FALSE, FALSE);
while (objectID < AC_OBJ_ROOF)
{
if (!extract_object(acObjects, &objectID, &object, &level, &ctx))
{
return FALSE;
}
/* those objects which will parsed further need the next higher level */
level++;
switch (objectID)
{
case AC_OBJ_CERTIFICATE:
this->certificate = object;
break;
case AC_OBJ_CERTIFICATE_INFO:
this->certificateInfo = object;
break;
case AC_OBJ_VERSION:
this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
DBG2(" v%d", this->version);
if (this->version != 2)
{
DBG1("v%d attribute certificates are not supported", this->version);
return FALSE;
}
break;
case AC_OBJ_HOLDER_ISSUER:
if (!parse_directoryName(object, level, FALSE, &this->holderIssuer))
{
return FALSE;
}
break;
case AC_OBJ_HOLDER_SERIAL:
this->holderSerial = object;
break;
case AC_OBJ_ENTITY_NAME:
if (!parse_directoryName(object, level, TRUE, &this->entityName))
{
return FALSE;
}
break;
case AC_OBJ_ISSUER_NAME:
if (!parse_directoryName(object, level, FALSE, &this->issuerName))
{
return FALSE;
}
break;
case AC_OBJ_SIG_ALG:
this->sigAlg = parse_algorithmIdentifier(object, level, NULL);
break;
case AC_OBJ_SERIAL_NUMBER:
this->serialNumber = object;
break;
case AC_OBJ_NOT_BEFORE:
this->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME);
break;
case AC_OBJ_NOT_AFTER:
this->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME);
break;
case AC_OBJ_ATTRIBUTE_TYPE:
type = known_oid(object);
break;
case AC_OBJ_ATTRIBUTE_VALUE:
{
switch (type)
{
case OID_AUTHENTICATION_INFO:
DBG2(" need to parse authenticationInfo");
break;
case OID_ACCESS_IDENTITY:
DBG2(" need to parse accessIdentity");
break;
case OID_CHARGING_IDENTITY:
ietfAttr_list_create_from_chunk(object, this->charging, level);
break;
case OID_GROUP:
ietfAttr_list_create_from_chunk(object, this->groups, level);
break;
case OID_ROLE:
parse_roleSyntax(object, level);
break;
default:
break;
}
}
break;
case AC_OBJ_EXTN_ID:
extn_oid = known_oid(object);
break;
case AC_OBJ_CRITICAL:
critical = object.len && *object.ptr;
DBG2(" %s",(critical)?"TRUE":"FALSE");
break;
case AC_OBJ_EXTN_VALUE:
{
switch (extn_oid)
{
case OID_CRL_DISTRIBUTION_POINTS:
DBG2(" need to parse crlDistributionPoints");
break;
case OID_AUTHORITY_KEY_ID:
x509_parse_authorityKeyIdentifier(object, level,
&this->authKeyID, &this->authKeySerialNumber);
break;
case OID_TARGET_INFORMATION:
DBG2(" need to parse targetInformation");
break;
case OID_NO_REV_AVAIL:
this->noRevAvail = TRUE;
break;
default:
break;
}
}
break;
case AC_OBJ_ALGORITHM:
this->algorithm = parse_algorithmIdentifier(object, level, NULL);
break;
case AC_OBJ_SIGNATURE:
this->signature = object;
break;
default:
break;
}
objectID++;
}
this->installed = time(NULL);
return TRUE;
}
/**
* Implementation of x509ac_t.list.
*/
static void list(const private_x509ac_t *this, FILE *out, bool utc)
{
time_t now = time(NULL);
fprintf(out, "%#T\n", &this->installed, utc);
if (this->entityName)
{
fprintf(out, " holder: '%D'\n", this->entityName);
}
if (this->holderIssuer)
{
fprintf(out, " hissuer: '%D'\n", this->holderIssuer);
}
if (this->holderSerial.ptr)
{
fprintf(out, " hserial: %#B\n", &this->holderSerial);
}
/* list all group attributes on a single line */
fprintf(out, " groups: ");
ietfAttr_list_list(this->groups, out);
fprintf(out, "\n");
fprintf(out, " issuer: '%D'\n", this->issuerName);
fprintf(out, " serial: %#B\n", &this->serialNumber);
fprintf(out, " validity: not before %#T, ", &this->notBefore, utc);
if (now < this->notBefore)
{
fprintf(out, "not valid yet (valid in %#V)\n", &now, &this->notBefore);
}
else
{
fprintf(out, "ok\n");
}
fprintf(out, " not after %#T, ", &this->notAfter, utc);
if (now > this->notAfter)
{
fprintf(out, "expired (%#V ago)\n", &now, &this->notAfter);
}
else
{
fprintf(out, "ok");
if (now > this->notAfter - ACERT_WARNING_INTERVAL * 60 * 60 * 24)
{
fprintf(out, " (expires in %#V)", &now, &this->notAfter);
}
fprintf(out, " \n");
}
if (this->authKeyID.ptr)
{
fprintf(out, " authkey: %#B\n", &this->authKeyID);
}
if (this->authKeySerialNumber.ptr)
{
fprintf(out, " aserial: %#B\n", &this->authKeySerialNumber);
}
}
/**
* Implements x509ac_t.destroy
*/
static void destroy(private_x509ac_t *this)
{
DESTROY_IF(this->holderIssuer);
DESTROY_IF(this->entityName);
DESTROY_IF(this->issuerName);
ietfAttr_list_destroy(this->charging);
ietfAttr_list_destroy(this->groups);
free(this->certificate.ptr);
free(this);
}
/**
* Described in header.
*/
x509ac_t *x509ac_create_from_chunk(chunk_t chunk)
{
private_x509ac_t *this = malloc_thing(private_x509ac_t);
/* initialize */
this->holderIssuer = NULL;
this->entityName = NULL;
this->issuerName = NULL;
this->charging = linked_list_create();
this->groups = linked_list_create();
/* public functions */
this->public.is_valid = (err_t (*) (const x509ac_t*,time_t*))is_valid;
this->public.is_newer = (bool (*) (const x509ac_t*,const x509ac_t*))is_newer;
this->public.equals_holder = (bool (*) (const x509ac_t*,const x509ac_t*))equals_holder;
this->public.list = (void (*) (const x509ac_t*,FILE*,bool))list;
this->public.destroy = (void (*) (x509ac_t*))destroy;
if (!parse_certificate(chunk, this))
{
destroy(this);
return NULL;
}
return &this->public;
}
/**
* Described in header.
*/
x509ac_t *x509ac_create_from_file(const char *filename)
{
bool pgp = FALSE;
chunk_t chunk = chunk_empty;
if (!pem_asn1_load_file(filename, NULL, "attribute certificate", &chunk, &pgp))
{
return NULL;
}
return x509ac_create_from_chunk(chunk);
}
-110
View File
@@ -1,110 +0,0 @@
/**
* @file ac.h
*
* @brief Interface of x509ac_t.
*
*/
/*
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
* Copyright (C) 2003 Martin Berner, Lukas Suter
* Copyright (C) 2007 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.
*
* RCSID $Id$
*/
#ifndef AC_H_
#define AC_H_
#include <library.h>
typedef struct x509ac_t x509ac_t;
/**
* @brief X.509 attribute certificate.
*
* @b Constructors:
* - x509ac_create_from_chunk()
* - x509ac_create_from_file()
*
* @ingroup crypto
*/
struct x509ac_t {
/**
* @brief Checks the validity interval of the attribute certificate
*
* @param this certificate being examined
* @param until until = min(until, notAfter)
* @return NULL if the certificate is valid
*/
err_t (*is_valid) (const x509ac_t *this, time_t *until);
/** @brief Checks if this attr cert is newer than the other attr cert
*
* @param this calling object
* @param other other attr cert object
* @return TRUE if this was issued more recently than other
*/
bool (*is_newer) (const x509ac_t *this, const x509ac_t *other);
/**
* @brief Checks if two attribute certificates belong to the same holder
*
* @param this calling attribute certificate
* @param that other attribute certificate
* @return TRUE if same holder
*/
bool (*equals_holder) (const x509ac_t *this, const x509ac_t *other);
/**
* @brief Log the attribute certificate info to out.
*
* @param this calling object
* @param out stream to write to
* @param utc TRUE for UTC times, FALSE for local time
*/
void (*list)(const x509ac_t *this, FILE *out, bool utc);
/**
* @brief Destroys the attribute certificate.
*
* @param this certificate to destroy
*/
void (*destroy) (x509ac_t *this);
};
/**
* @brief Read a x509 attribute certificate from a DER encoded blob.
*
* @param chunk chunk containing DER encoded data
* @return created x509ac_t certificate, or NULL if invalid.
*
* @ingroup crypto
*/
x509ac_t *x509ac_create_from_chunk(chunk_t chunk);
/**
* @brief Read a x509 attribute certificate from a DER encoded file.
*
* @param filename file containing DER encoded data
* @return created x509ac_t certificate, or NULL if invalid.
*
* @ingroup crypto
*/
x509ac_t *x509ac_create_from_file(const char *filename);
#endif /* AC_H_ */
-813
View File
@@ -1,813 +0,0 @@
/**
* @file ca.c
*
* @brief Implementation of ca_info_t.
*
*/
/*
* Copyright (C) 2007 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 <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include "x509.h"
#include "crl.h"
#include "ca.h"
#include "ac.h"
#include "certinfo.h"
#include "ocsp.h"
#include <library.h>
#include <debug.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <utils/fetcher.h>
typedef struct private_ca_info_t private_ca_info_t;
/**
* Private data of a ca_info_t object.
*/
struct private_ca_info_t {
/**
* Public interface for this ca info record
*/
ca_info_t public;
/**
* Name of the ca info record
*/
char *name;
/**
* Time when ca info record was installed
*/
time_t installed;
/**
* Distinguished Name of the CA
*/
x509_t *cacert;
/**
* List of attribute certificates
*/
linked_list_t *attrcerts;
/**
* List of crl URIs
*/
linked_list_t *crluris;
/**
* List of ocsp URIs
*/
linked_list_t *ocspuris;
/**
* CRL issued by this ca
*/
crl_t *crl;
/**
* List of certificate info records
*/
linked_list_t *certinfos;
/**
* mutex controls access to the elements:
* name, crluris, ocspuris, crl, and certinfos
*/
pthread_mutex_t mutex;
};
/**
* static options set by ca_info_set_options()
*/
static strict_t strict_crl_policy = STRICT_NO;
static bool cache_crls = FALSE;
static u_int crl_check_interval = 0;
/**
* Implements ca_info_t.equals
*/
static bool equals(const private_ca_info_t *this, const private_ca_info_t *that)
{
return chunk_equals(this->cacert->get_keyid(this->cacert),
that->cacert->get_keyid(that->cacert));
}
/**
* Implements ca_info_t.equals_name_release_info
*/
static bool equals_name_release_info(private_ca_info_t *this, const char *name)
{
bool found;
pthread_mutex_lock(&(this->mutex));
found = this->name != NULL && streq(this->name, name);
if (found)
{
this->crluris->destroy_offset(this->crluris,
offsetof(identification_t, destroy));
this->crluris = linked_list_create();
this->ocspuris->destroy_offset(this->ocspuris,
offsetof(identification_t, destroy));
this->ocspuris = linked_list_create();
free(this->name);
this->name = NULL;
}
pthread_mutex_unlock(&(this->mutex));
return found;
}
/**
* Implements ca_info_t.is_crl_issuer
*/
static bool is_cert_issuer(private_ca_info_t *this, const x509_t *cert)
{
return cert->is_issuer(cert, this->cacert);
}
/**
* Implements ca_info_t.is_crl_issuer
*/
static bool is_crl_issuer(private_ca_info_t *this, const crl_t *crl)
{
return crl->is_issuer(crl, this->cacert);
}
/**
* Implements ca_info_t.is_ca
*/
static bool is_ca(private_ca_info_t *this)
{
return this->cacert->is_ca(this->cacert);
}
/**
* Implements ca_info_t.is_strict
*/
static bool is_strict(private_ca_info_t *this)
{
bool strict = strict_crl_policy != STRICT_NO;
if (strict_crl_policy == STRICT_IFURI)
{
pthread_mutex_lock(&(this->mutex));
strict = this->crluris->get_count(this->crluris) > 0 ||
this->ocspuris->get_count(this->ocspuris) > 0;
pthread_mutex_unlock(&(this->mutex));
}
return strict;
}
/**
* Implements ca_info_t.has_crl
*/
static bool has_crl(private_ca_info_t *this)
{
bool found;
pthread_mutex_lock(&(this->mutex));
found = this->crl != NULL;
pthread_mutex_unlock(&(this->mutex));
return found;
}
/**
* Implements ca_info_t.has_certinfos
*/
static bool has_certinfos(private_ca_info_t *this)
{
bool found;
pthread_mutex_lock(&(this->mutex));
found = this->certinfos->get_count(this->certinfos) > 0;
pthread_mutex_unlock(&(this->mutex));
return found;
}
/**
* Implements ca_info_t.add_crl
*/
static void add_crl(private_ca_info_t *this, crl_t *crl)
{
pthread_mutex_lock(&(this->mutex));
if (this->crl)
{
if (crl->is_newer(crl, this->crl))
{
this->crl->destroy(this->crl);
this->crl = crl;
DBG1(" this crl is newer - existing crl replaced");
}
else
{
crl->destroy(crl);
DBG1(" this crl is not newer - existing crl retained");
}
}
else
{
this->crl = crl;
DBG2(" crl added");
}
pthread_mutex_unlock(&(this->mutex));
}
/**
* Implements ca_info_t.list_crl
*/
static void list_crl(private_ca_info_t *this, FILE *out, bool utc)
{
pthread_mutex_lock(&this->mutex);
this->crl->list(this->crl, out, utc);
pthread_mutex_unlock(&this->mutex);
}
/**
* Implements ca_info_t.list_certinfos
*/
static void list_certinfos(private_ca_info_t *this, FILE *out, bool utc)
{
iterator_t *iterator;
certinfo_t *certinfo;
chunk_t authkey;
pthread_mutex_lock(&this->mutex);
authkey = this->cacert->get_subjectKeyID(this->cacert);
fprintf(out," authname: '%D'\n", this->cacert->get_subject(this->cacert));
fprintf(out," authkey: %#B\n", &authkey);
iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
while (iterator->iterate(iterator, (void**)&certinfo))
{
time_t nextUpdate, thisUpdate, now;
chunk_t serial;
now = time(NULL);
nextUpdate = certinfo->get_nextUpdate(certinfo);
thisUpdate = certinfo->get_thisUpdate(certinfo);
serial = certinfo->get_serialNumber(certinfo);
fprintf(out, "%#T, until %#T, ", &thisUpdate, utc, &nextUpdate, utc);
if (now > nextUpdate)
{
fprintf(out, "expired (%#V ago)\n", &now, &nextUpdate);
}
else
{
fprintf(out, "ok (expires in %#V)\n", &now, &nextUpdate);
}
fprintf(out, " serial: %#B, %N\n", &serial,
cert_status_names, certinfo->get_status(certinfo));
}
iterator->destroy(iterator);
pthread_mutex_unlock(&this->mutex);
}
/**
* Find an exact copy of an identification in a linked list
*/
static identification_t* find_identification(linked_list_t *list, identification_t *id)
{
identification_t *found_id = NULL, *current_id;
iterator_t *iterator = list->create_iterator(list, TRUE);
while (iterator->iterate(iterator, (void**)&current_id))
{
if (id->equals(id, current_id))
{
found_id = current_id;
break;
}
}
iterator->destroy(iterator);
return found_id;
}
/**
* Add a unique identification to a linked list
*/
static identification_t *add_identification(linked_list_t *list, identification_t *id)
{
identification_t *found_id = find_identification(list, id);
if (found_id)
{
id->destroy(id);
return found_id;
}
else
{
list->insert_last(list, (void*)id);
return id;
}
}
/**
* Implements ca_info_t.add_crluri
*/
static void add_crluri(private_ca_info_t *this, chunk_t uri)
{
if (uri.len < 6 ||
(strncasecmp(uri.ptr, "http", 4) != 0 &&
strncasecmp(uri.ptr, "ldap", 4) != 0 &&
strncasecmp(uri.ptr, "file", 4) != 0 &&
strncasecmp(uri.ptr, "ftp", 3) != 0))
{
DBG1(" invalid crl uri '%.*s'", uri.len, uri.ptr);
return;
}
else
{
identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
pthread_mutex_lock(&(this->mutex));
add_identification(this->crluris, crluri);
pthread_mutex_unlock(&(this->mutex));
}
}
/**
* Implements ca_info_t.add_ocspuri
*/
static void add_ocspuri(private_ca_info_t *this, chunk_t uri)
{
if (uri.len < 7 || strncasecmp(uri.ptr, "http", 4) != 0)
{
DBG1(" invalid ocsp uri '%.*s'", uri.len, uri.ptr);
return;
}
else
{
identification_t *ocspuri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
pthread_mutex_lock(&(this->mutex));
add_identification(this->ocspuris, ocspuri);
pthread_mutex_unlock(&(this->mutex));
}
}
/**
* Implements ca_info_t.add_info.
*/
void add_info (private_ca_info_t *this, const private_ca_info_t *that)
{
pthread_mutex_lock(&(this->mutex));
if (this->name == NULL && that->name != NULL)
{
this->name = strdup(that->name);
}
pthread_mutex_unlock(&(this->mutex));
{
identification_t *uri;
iterator_t *iterator = that->crluris->create_iterator(that->crluris, TRUE);
while (iterator->iterate(iterator, (void**)&uri))
{
if (uri->get_type(uri) == ID_DER_ASN1_GN_URI)
{
add_crluri(this, uri->get_encoding(uri));
}
}
iterator->destroy(iterator);
}
{
identification_t *uri;
iterator_t *iterator = that->ocspuris->create_iterator(that->ocspuris, TRUE);
while (iterator->iterate(iterator, (void**)&uri))
{
if (uri->get_type(uri) == ID_DER_ASN1_GN_URI)
{
add_ocspuri(this, uri->get_encoding(uri));
}
}
iterator->destroy(iterator);
}
}
/**
* Implements ca_info_t.get_certificate.
*/
static x509_t* get_certificate(private_ca_info_t* this)
{
return this->cacert;
}
/**
* caches a crl by saving it to a given crl directory
*/
void cache_crl(private_ca_info_t* this, const char *crl_dir, crl_t *crl)
{
char buffer[BUF_LEN];
char *path;
char *pos = buffer;
int len = BUF_LEN;
int n;
chunk_t authKeyID = this->cacert->get_subjectKeyID(this->cacert);
chunk_t uri;
uri.ptr = buffer;
uri.len = 7 + strlen(crl_dir) + 1 + 2*authKeyID.len + 4;
if (uri.len >= BUF_LEN)
{
DBG1("file uri exceeds buffer length of %d bytes - crl not saved", BUF_LEN);
return;
}
/* print the file uri prefix */
n = snprintf(pos, len, "file://");
pos += n; len -= n;
/* remember the start of the path string */
path = pos;
/* print the default crl directory path */
n = snprintf(pos, len, "%s/", crl_dir);
pos += n; len -= n;
/* create and print a unique crl filename derived from the authKeyID */
while (authKeyID.len-- > 0)
{
n = snprintf(pos, len, "%02x", *authKeyID.ptr++);
pos += n; len -= n;
}
/* add the file suffix */
n = snprintf(pos, len, ".crl");
if (crl->write_to_file(crl, path, 0022, TRUE))
{
identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
add_identification(this->crluris, crluri);
}
}
/**
* Implements ca_info_t.verify_by_crl.
*/
static cert_status_t verify_by_crl(private_ca_info_t* this, certinfo_t *certinfo,
const char *crl_dir)
{
rsa_public_key_t *issuer_public_key = this->cacert->get_public_key(this->cacert);
bool stale;
pthread_mutex_lock(&(this->mutex));
if (this->crl == NULL)
{
stale = TRUE;
DBG1("no crl is locally available");
}
else
{
stale = !this->crl->is_valid(this->crl);
DBG1("crl is %s", stale? "stale":"valid");
}
if (stale && crl_check_interval > 0)
{
iterator_t *iterator = this->crluris->create_iterator(this->crluris, TRUE);
identification_t *uri;
while (iterator->iterate(iterator, (void**)&uri))
{
fetcher_t *fetcher;
char uri_string[BUF_LEN];
chunk_t uri_chunk = uri->get_encoding(uri);
chunk_t response_chunk;
snprintf(uri_string, BUF_LEN, "%.*s", uri_chunk.len, uri_chunk.ptr);
fetcher = fetcher_create(uri_string);
response_chunk = fetcher->get(fetcher);
fetcher->destroy(fetcher);
if (response_chunk.ptr != NULL)
{
crl_t *crl = crl_create_from_chunk(response_chunk);
if (crl == NULL)
{
free(response_chunk.ptr);
continue;
}
if (!is_crl_issuer(this, crl))
{
DBG1(" fetched crl has wrong issuer");
crl->destroy(crl);
continue;
}
if (!crl->verify(crl, issuer_public_key))
{
DBG1("fetched crl signature is invalid");
crl->destroy(crl);
continue;
}
DBG2("fetched crl signature is valid");
if (this->crl == NULL)
{
this->crl = crl;
}
else if (crl->is_newer(crl, this->crl))
{
this->crl->destroy(this->crl);
this->crl = crl;
DBG1("this crl is newer - existing crl replaced");
}
else
{
crl->destroy(crl);
DBG1("this crl is not newer - existing crl retained");
continue;
}
if (crl->is_valid(crl))
{
if (cache_crls && strncasecmp(uri_string, "file", 4) != 0)
{
cache_crl(this, crl_dir, crl);
}
/* we found a valid crl and therefore exit the fetch loop */
break;
}
else
{
DBG1("fetched crl is stale");
}
}
}
iterator->destroy(iterator);
}
if (this->crl)
{
if (!this->crl->verify(this->crl, issuer_public_key))
{
DBG1("crl signature is invalid");
goto ret;
}
DBG2("crl signature is valid");
this->crl->get_status(this->crl, certinfo);
}
ret:
pthread_mutex_unlock(&(this->mutex));
return certinfo->get_status(certinfo);
}
/**
* Implements ca_info_t.verify_by_ocsp.
*/
static cert_status_t verify_by_ocsp(private_ca_info_t* this,
certinfo_t *certinfo,
credential_store_t *credentials)
{
bool stale;
iterator_t *iterator;
certinfo_t *cached_certinfo = NULL;
int comparison = 1;
pthread_mutex_lock(&(this->mutex));
/* do we support OCSP at all? */
if (this->ocspuris->get_count(this->ocspuris) == 0)
{
goto ret;
}
iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
/* find the list insertion point in alphabetical order */
while(iterator->iterate(iterator, (void**)&cached_certinfo))
{
comparison = certinfo->compare_serialNumber(certinfo, cached_certinfo);
if (comparison <= 0)
{
break;
}
}
/* do we have a valid certinfo_t for this serial number in our cache? */
if (comparison == 0)
{
stale = cached_certinfo->get_nextUpdate(cached_certinfo) < time(NULL);
DBG1("ocsp status in cache is %s", stale ? "stale":"fresh");
}
else
{
stale = TRUE;
DBG1("ocsp status is not in cache");
}
if (stale)
{
ocsp_t *ocsp;
ocsp = ocsp_create(this->cacert, this->ocspuris);
ocsp->fetch(ocsp, certinfo, credentials);
if (certinfo->get_status(certinfo) != CERT_UNDEFINED)
{
if (comparison != 0)
{
cached_certinfo = certinfo_create(certinfo->get_serialNumber(certinfo));
if (comparison > 0)
{
this->certinfos->insert_last(this->certinfos, (void *)cached_certinfo);
}
else
{
iterator->insert_before(iterator, (void *)cached_certinfo);
}
}
cached_certinfo->update(cached_certinfo, certinfo);
}
ocsp->destroy(ocsp);
}
else
{
certinfo->update(certinfo, cached_certinfo);
}
iterator->destroy(iterator);
ret:
pthread_mutex_unlock(&(this->mutex));
return certinfo->get_status(certinfo);
}
/**
* Implements ca_info_t.purge_ocsp
*/
static void purge_ocsp(private_ca_info_t *this)
{
pthread_mutex_lock(&(this->mutex));
this->certinfos->destroy_offset(this->certinfos,
offsetof(certinfo_t, destroy));
this->certinfos = linked_list_create();
pthread_mutex_unlock(&(this->mutex));
}
/**
* Implements ca_info_t.destroy
*/
static void destroy(private_ca_info_t *this)
{
this->attrcerts->destroy_offset(this->attrcerts,
offsetof(x509ac_t, destroy));
this->crluris->destroy_offset(this->crluris,
offsetof(identification_t, destroy));
this->ocspuris->destroy_offset(this->ocspuris,
offsetof(identification_t, destroy));
this->certinfos->destroy_offset(this->certinfos,
offsetof(certinfo_t, destroy));
DESTROY_IF(this->crl);
free(this->name);
free(this);
}
/**
* list the info of this CA
*/
static void list(private_ca_info_t* this, FILE* out, bool utc)
{
chunk_t chunk;
identification_t *uri;
iterator_t *iterator;
bool first;
pthread_mutex_lock(&(this->mutex));
fprintf(out, "%#T", &this->installed, utc);
if (this->name)
{
fprintf(out, ", \"%s\"\n", this->name);
}
else
{
fprintf(out, "\n");
}
fprintf(out, " authname: '%D'\n", this->cacert->get_subject(this->cacert));
chunk = this->cacert->get_subjectKeyID(this->cacert);
fprintf(out, " authkey: %#B\n", &chunk);
chunk = this->cacert->get_keyid(this->cacert);
fprintf(out, " keyid: %#B\n", &chunk);
first = TRUE;
iterator = this->crluris->create_iterator(this->crluris, TRUE);
while (iterator->iterate(iterator, (void**)&uri))
{
fprintf(out, " %s '%D'\n", first ? "crluris:":" ", uri);
first = FALSE;
}
iterator->destroy(iterator);
first = TRUE;
iterator = this->ocspuris->create_iterator(this->ocspuris, TRUE);
while (iterator->iterate(iterator, (void**)&uri))
{
fprintf(out, " %s '%D'\n", first ? "ocspuris:":" ", uri);
first = FALSE;
}
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
}
/*
* Described in header.
*/
void ca_info_set_options(strict_t strict, bool cache, u_int interval)
{
strict_crl_policy = strict;
cache_crls = cache;
crl_check_interval = interval;
}
/*
* Described in header.
*/
ca_info_t *ca_info_create(const char *name, x509_t *cacert)
{
private_ca_info_t *this = malloc_thing(private_ca_info_t);
/* initialize */
this->installed = time(NULL);
this->name = (name == NULL)? NULL:strdup(name);
this->cacert = cacert;
this->attrcerts = linked_list_create();
this->crluris = linked_list_create();
this->ocspuris = linked_list_create();
this->certinfos = linked_list_create();
this->crl = NULL;
/* initialize the mutex */
pthread_mutex_init(&(this->mutex), NULL);
/* public functions */
this->public.equals = (bool (*) (const ca_info_t*,const ca_info_t*))equals;
this->public.equals_name_release_info = (bool (*) (ca_info_t*,const char*))equals_name_release_info;
this->public.is_cert_issuer = (bool (*) (ca_info_t*,const x509_t*))is_cert_issuer;
this->public.is_crl_issuer = (bool (*) (ca_info_t*,const crl_t*))is_crl_issuer;
this->public.is_ca = (bool (*) (ca_info_t*))is_ca;
this->public.is_strict = (bool (*) (ca_info_t*))is_strict;
this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info;
this->public.add_crl = (void (*) (ca_info_t*,crl_t*))add_crl;
this->public.has_crl = (bool (*) (ca_info_t*))has_crl;
this->public.has_certinfos = (bool (*) (ca_info_t*))has_certinfos;
this->public.list = (void (*) (ca_info_t*,FILE*,bool))list;
this->public.list_crl = (void (*) (ca_info_t*,FILE*,bool))list_crl;
this->public.list_certinfos = (void (*) (ca_info_t*,FILE*,bool))list_certinfos;
this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri;
this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri;
this->public.get_certificate = (x509_t* (*) (ca_info_t*))get_certificate;
this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,certinfo_t*, const char*))verify_by_crl;
this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,certinfo_t*,credential_store_t*))verify_by_ocsp;
this->public.purge_ocsp = (void (*) (ca_info_t*))purge_ocsp;
this->public.destroy = (void (*) (ca_info_t*))destroy;
return &this->public;
}
-243
View File
@@ -1,243 +0,0 @@
/**
* @file ca.h
*
* @brief Interface of ca_info_t.
*
*/
/*
* Copyright (C) 2007 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.
*/
#ifndef CA_H_
#define CA_H_
typedef struct ca_info_t ca_info_t;
#include <library.h>
#include "x509.h"
#include "crl.h"
#define MAX_CA_PATH_LEN 7
/*forward declaration */
struct credential_store_t;
/**
* @brief X.509 certification authority information record
*
* @b Constructors:
* - ca_info_create()
*
* @ingroup transforms
*/
struct ca_info_t {
/**
* @brief Compare two ca info records
*
* Comparison is done via the keyid of the ca certificate
*
* @param this first ca info object
* @param that second ca info objct
* @return TRUE if a match is found
*/
bool (*equals) (const ca_info_t *this, const ca_info_t* that);
/**
* @brief If the ca info record has the same name then release the name and URIs
*
* @param this ca info object
* @return TRUE if a match is found
*/
bool (*equals_name_release_info) (ca_info_t *this, const char *name);
/**
* @brief Checks if a certificate was issued by this ca
*
* @param this ca info object
* @param cert certificate to be checked
* @return TRUE if the issuing ca has been found
*/
bool (*is_cert_issuer) (ca_info_t *this, const x509_t *cert);
/**
* @brief Checks if a crl was issued by this ca
*
* @param this ca info object
* @param crl crl to be checked
* @return TRUE if the issuing ca has been found
*/
bool (*is_crl_issuer) (ca_info_t *this, const crl_t *crl);
/**
* @brief Checks if the ca certificate has the isCA flag set
*
* @param this ca info object
* @return TRUE if the isCA flag is set
*/
bool (*is_ca) (ca_info_t *this);
/**
* @brief Checks if the ca enforces a strict crl policy
*
* @param this ca info object
* @return TRUE if the crl policy is strict
*/
bool (*is_strict) (ca_info_t *this);
/**
* @brief Merges info from a secondary ca info object
*
* @param this primary ca info object
* @param that secondary ca info object
*/
void (*add_info) (ca_info_t *this, const ca_info_t *that);
/**
* @brief Adds a new or replaces an obsoleted CRL
*
* @param this ca info object
* @param crl crl to be added
*/
void (*add_crl) (ca_info_t *this, crl_t *crl);
/**
* @brief Does the CA have a CRL?
*
* @param this ca info object
* @return TRUE if crl is available
*/
bool (*has_crl) (ca_info_t *this);
/**
* @brief Does the CA have OCSP certinfos?
*
* @param this ca info object
* @return TRUE if there are any certinfos
*/
bool (*has_certinfos) (ca_info_t *this);
/**
* @brief Print the CA info onto the console
*
* @param this ca info object
* @param out output stream
* @param utc TRUE - utc
FALSE - local time
*/
void (*list) (ca_info_t *this, FILE *out, bool utc);
/**
* @brief List the CRL onto the console
*
* @param this ca info object
* @param out output stream
* @param utc TRUE - utc
FALSE - local time
*/
void (*list_crl) (ca_info_t *this, FILE *out, bool utc);
/**
* @brief List the OCSP certinfos onto the console
*
* @param this ca info object
* @param out output stream
* @param utc TRUE - utc
FALSE - local time
*/
void (*list_certinfos) (ca_info_t *this, FILE *out, bool utc);
/**
* @brief Adds a CRL URI to a list
*
* @param this ca info object
* @param uri crl uri to be added
*/
void (*add_crluri) (ca_info_t *this, chunk_t uri);
/**
* @brief Adds a OCSP URI to a list
*
* @param this ca info object
* @param uri ocsp uri to be added
*/
void (*add_ocspuri) (ca_info_t *this, chunk_t uri);
/**
* @brief Get the ca certificate
*
* @param this ca info object
* @return ca certificate
*/
x509_t* (*get_certificate) (ca_info_t *this);
/**
* @brief Verify the status of a certificate by CRL
*
* @param this ca info object
* @param certinfo detailed certificate status information
* @param crl_dir directory where fetched crls should be stored
* @return certificate status
*/
cert_status_t (*verify_by_crl) (ca_info_t *this, certinfo_t *certinfo, const char *crl_dir);
/**
* @brief Verify the status of a certificate by OCSP
*
* @param this ca info object
* @param certinfo detailed certificate status information
* @param credentials credential store needed for trust path verification
* @return certificate status
*/
cert_status_t (*verify_by_ocsp) (ca_info_t* this, certinfo_t* certinfo, struct credential_store_t* credentials);
/**
* @brief Purge the OCSP certinfos of a ca info record
*
* @param this ca info object
*/
void (*purge_ocsp) (ca_info_t *this);
/**
* @brief Destroys a ca info record
*
* @param this ca info to destroy
*/
void (*destroy) (ca_info_t *this);
};
/**
* @brief Set ca info options
*
* @param cache TRUE if crls shall be cached by storing them
* @param interval crl_check_interval to be set in seconds
*
* @ingroup crypto
*/
void ca_info_set_options(strict_t strict, bool cache, u_int interval);
/**
* @brief Create a ca info record
*
* @param name name of the ca info record
* @param cacert path to the ca certificate
* @return created ca_info_t, or NULL if invalid.
*
* @ingroup crypto
*/
ca_info_t *ca_info_create(const char *name, x509_t *cacert);
#endif /* CA_H_ */
-257
View File
@@ -1,257 +0,0 @@
/**
* @file certinfo.c
*
* @brief Implementation of certinfo_t.
*
*/
/*
* Copyright (C) 2006 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 <time.h>
#include <stdio.h>
#include <library.h>
#include "certinfo.h"
typedef struct private_certinfo_t private_certinfo_t;
/**
* Private data of a certinfo_t object.
*/
struct private_certinfo_t {
/**
* Public interface for this certificate status information object.
*/
certinfo_t public;
/**
* Serial number of the certificate
*/
chunk_t serialNumber;
/**
* Certificate status
*/
cert_status_t status;
/**
* Certificate status is for one-time use only
*/
bool once;
/**
* Time when the certificate status info was generated
*/
time_t thisUpdate;
/**
* Time when an updated certifcate status info will be available
*/
time_t nextUpdate;
/**
* Time of certificate revocation
*/
time_t revocationTime;
/**
* Reason of certificate revocation
*/
crl_reason_t revocationReason;
};
ENUM(cert_status_names, CERT_GOOD, CERT_UNTRUSTED,
"good",
"revoked",
"unknown",
"unknown",
"untrusted",
);
ENUM(crl_reason_names, REASON_UNSPECIFIED, REASON_REMOVE_FROM_CRL,
"unspecified",
"key compromise",
"ca compromise",
"affiliation changed",
"superseded",
"cessation of operation",
"certificate hold",
"reason #7",
"remove from crl",
);
/**
* Implements certinfo_t.compare_serialNumber
*/
static int compare_serialNumber(const private_certinfo_t *this, const private_certinfo_t *that)
{
return chunk_compare(this->serialNumber, that->serialNumber);
}
/**
* Implements certinfo_t.equals_serialNumber
*/
static bool equals_serialNumber(const private_certinfo_t *this, const private_certinfo_t *that)
{
return chunk_equals(this->serialNumber, that->serialNumber);
}
/**
* Implements certinfo_t.get_serialNumber
*/
static chunk_t get_serialNumber(const private_certinfo_t *this)
{
return this->serialNumber;
}
/**
* Implements certinfo_t.set_status
*/
static void set_status(private_certinfo_t *this, cert_status_t status)
{
this->status = status;
}
/**
* Implements certinfo_t.get_status
*/
static cert_status_t get_status(const private_certinfo_t *this)
{
return this->status;
}
/**
* Implements certinfo_t.set_thisUpdate
*/
static void set_thisUpdate(private_certinfo_t *this, time_t thisUpdate)
{
this->thisUpdate = thisUpdate;
}
/**
* Implements certinfo_t.get_thisUpdate
*/
static time_t get_thisUpdate(const private_certinfo_t *this)
{
return this->thisUpdate;
}
/**
* Implements certinfo_t.set_nextUpdate
*/
static void set_nextUpdate(private_certinfo_t *this, time_t nextUpdate)
{
this->nextUpdate = nextUpdate;
}
/**
* Implements certinfo_t.get_nextUpdate
*/
static time_t get_nextUpdate(const private_certinfo_t *this)
{
return this->nextUpdate;
}
/**
* Implements certinfo_t.set_revocationTime
*/
static void set_revocationTime(private_certinfo_t *this, time_t revocationTime)
{
this->revocationTime = revocationTime;
}
/**
* Implements certinfo_t.get_revocationTime
*/
static time_t get_revocationTime(const private_certinfo_t *this)
{
return this->revocationTime;
}
/**
* Implements certinfo_t.set_revocationReason
*/
static void set_revocationReason(private_certinfo_t *this, crl_reason_t reason)
{
this->revocationReason = reason;
}
/**
* Implements certinfo_t.get_revocationReason
*/
static crl_reason_t get_revocationReason(const private_certinfo_t *this)
{
return this->revocationReason;
}
/**
* Implements certinfo_t.update
*/
static void update(private_certinfo_t *this, const private_certinfo_t *that)
{
if (equals_serialNumber(this, that))
{
chunk_t this_serialNumber = this->serialNumber;
*this = *that;
this->serialNumber = this_serialNumber;
}
}
/**
* Implements certinfo_t.destroy
*/
static void destroy(private_certinfo_t *this)
{
free(this->serialNumber.ptr);
free(this);
}
/*
* Described in header.
*/
certinfo_t *certinfo_create(chunk_t serial)
{
private_certinfo_t *this = malloc_thing(private_certinfo_t);
/* initialize */
this->serialNumber = chunk_clone(serial);
this->status = CERT_UNDEFINED;
this->thisUpdate = UNDEFINED_TIME;
this->nextUpdate = UNDEFINED_TIME;
this->revocationTime = UNDEFINED_TIME;
this->revocationReason = REASON_UNSPECIFIED;
/* public functions */
this->public.compare_serialNumber = (int (*) (const certinfo_t*,const certinfo_t*))compare_serialNumber;
this->public.equals_serialNumber = (bool (*) (const certinfo_t*,const certinfo_t*))equals_serialNumber;
this->public.get_serialNumber = (chunk_t (*) (const certinfo_t*))get_serialNumber;
this->public.set_status = (void (*) (certinfo_t*,cert_status_t))set_status;
this->public.get_status = (cert_status_t (*) (const certinfo_t*))get_status;
this->public.set_thisUpdate = (void (*) (certinfo_t*,time_t))set_thisUpdate;
this->public.get_thisUpdate = (time_t (*) (const certinfo_t*))get_thisUpdate;
this->public.set_nextUpdate = (void (*) (certinfo_t*,time_t))set_nextUpdate;
this->public.get_nextUpdate = (time_t (*) (const certinfo_t*))get_nextUpdate;
this->public.set_revocationTime = (void (*) (certinfo_t*,time_t))set_revocationTime;
this->public.get_revocationTime = (time_t (*) (const certinfo_t*))get_revocationTime;
this->public.set_revocationReason = (void (*) (certinfo_t*, crl_reason_t))set_revocationReason;
this->public.get_revocationReason = (crl_reason_t(*) (const certinfo_t*))get_revocationReason;
this->public.update = (void (*) (certinfo_t*, const certinfo_t*))update;
this->public.destroy = (void (*) (certinfo_t*))destroy;
return &this->public;
}
-203
View File
@@ -1,203 +0,0 @@
/**
* @file certinfo.h
*
* @brief Interface of certinfo_t.
*
*/
/*
* Copyright (C) 2006 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.
*/
#ifndef CERTINFO_H_
#define CERTINFO_H_
typedef enum cert_status_t cert_status_t;
typedef enum crl_reason_t crl_reason_t;
typedef struct certinfo_t certinfo_t;
#include <library.h>
/**
* RFC 2560 OCSP - certificate status
*/
enum cert_status_t {
CERT_GOOD = 0,
CERT_REVOKED = 1,
CERT_UNKNOWN = 2,
CERT_UNDEFINED = 3,
CERT_UNTRUSTED = 4 /* private use */
};
extern enum_name_t *cert_status_names;
/**
* RFC 2459 CRL reason codes
*/
enum crl_reason_t {
REASON_UNSPECIFIED = 0,
REASON_KEY_COMPROMISE = 1,
REASON_CA_COMPROMISE = 2,
REASON_AFFILIATION_CHANGED = 3,
REASON_SUPERSEDED = 4,
REASON_CESSATION_OF_OPERATON = 5,
REASON_CERTIFICATE_HOLD = 6,
REASON_REMOVE_FROM_CRL = 8
};
extern enum_name_t *crl_reason_names;
/**
* @brief X.509 certificate status information
*
* @ingroup transforms
*/
struct certinfo_t {
/**
* @brief Check if both certinfo objects have the same serialNumber.
*
* @param this calling object
* @param that second certinfo_t object
* @return TRUE if the same serialNumber
*/
bool (*equals_serialNumber) (const certinfo_t *this, const certinfo_t *that);
/**
* @brief Compares two serial numbers.
*
* @param this calling object
* @param that second certinfo_t object
* @return negative if this is smaller than that
* zero if this equals that
* positive if this is greater than that
*/
int (*compare_serialNumber) (const certinfo_t *this, const certinfo_t *that);
/**
* @brief Get serial number.
*
* @param this calling object
* @return serialNumber
*/
chunk_t (*get_serialNumber) (const certinfo_t *this);
/**
* @brief Set certificate status.
*
* @param this calling object
* @param status status
*/
void (*set_status) (certinfo_t *this, cert_status_t status);
/**
* @brief Get certificate status.
*
* @param this calling object
* @return status
*/
cert_status_t (*get_status) (const certinfo_t *this);
/**
* @brief Set thisUpdate.
*
* @param this calling object
* @param thisUpdate thisUpdate
*/
void (*set_thisUpdate) (certinfo_t *this, time_t thisUpdate);
/**
* @brief Get thisUpdate.
*
* @param this calling object
* @return thisUpdate
*/
time_t (*get_thisUpdate) (const certinfo_t *this);
/**
* @brief Set nextUpdate.
*
* @param this calling object
* @param nextUpdate
*/
void (*set_nextUpdate) (certinfo_t *this, time_t nextUpdate);
/**
* @brief Get nextUpdate.
*
* @param this calling object
* @return nextUpdate
*/
time_t (*get_nextUpdate) (const certinfo_t *this);
/**
* @brief Set revocationTime.
*
* @param this calling object
* @param revocationTime revocationTime
*/
void (*set_revocationTime) (certinfo_t *this, time_t revocationTime);
/**
* @brief Get revocationTime.
*
* @param this calling object
* @return revocationTime
*/
time_t (*get_revocationTime) (const certinfo_t *this);
/**
* @brief Set revocationReason.
*
* @param this calling object
* @param reason revocationReason
*/
void (*set_revocationReason) (certinfo_t *this, crl_reason_t reason);
/**
* @brief Get revocationReason.
*
* @param this calling object
* @return revocationReason
*/
crl_reason_t (*get_revocationReason) (const certinfo_t *this);
/**
* @brief Set revocationReason.
*
* @param this calling object to be updated
* @param that object containing updated information
*/
void (*update) (certinfo_t *this, const certinfo_t *that);
/**
* @brief Destroys the certinfo_t object.
*
* @param this certinfo_t to destroy
*/
void (*destroy) (certinfo_t *this);
};
/**
* @brief Create a certinfo_t object.
*
* @param serial chunk serial number of the certificate
* @return created certinfo_t object
*
* @ingroup transforms
*/
certinfo_t *certinfo_create(chunk_t serial);
#endif /* CERTINFO_H_ */
-536
View File
@@ -1,536 +0,0 @@
/**
* @file crl.c
*
* @brief Implementation of crl_t.
*
*/
/*
* Copyright (C) 2006 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.
*
* RCSID $Id$
*/
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <library.h>
#include <debug.h>
#include <asn1/oid.h>
#include <asn1/asn1.h>
#include <asn1/pem.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
#include "certinfo.h"
#include "x509.h"
#include "crl.h"
#define CRL_WARNING_INTERVAL 7 /* days */
/* access structure for a revoked certificate */
typedef struct revokedCert_t revokedCert_t;
struct revokedCert_t {
chunk_t userCertificate;
time_t revocationDate;
crl_reason_t revocationReason;
};
typedef struct private_crl_t private_crl_t;
/**
* Private data of a crl_t object.
*/
struct private_crl_t {
/**
* Public interface for this crl.
*/
crl_t public;
/**
* Time when crl was installed
*/
time_t installed;
/**
* List of crlDistributionPoints
*/
linked_list_t *crlDistributionPoints;
/**
* X.509 crl in DER format
*/
chunk_t certificateList;
/**
* X.509 crl body over which signature is computed
*/
chunk_t tbsCertList;
/**
* Version of the X.509 crl
*/
u_int version;
/**
* Signature algorithm
*/
int sigAlg;
/**
* ID representing the crl issuer
*/
identification_t *issuer;
/**
* CRL number
*/
chunk_t crlNumber;
/**
* Time when the crl was generated
*/
time_t thisUpdate;
/**
* Time when an update crl will be available
*/
time_t nextUpdate;
/**
* List of identification_t's representing subjectAltNames
*/
linked_list_t *revokedCertificates;
/**
* Authority Key Identifier
*/
chunk_t authKeyID;
/**
* Authority Key Serial Number
*/
chunk_t authKeySerialNumber;
/**
* Signature algorithm (must be identical to sigAlg)
*/
int algorithm;
/**
* Signature
*/
chunk_t signature;
};
/**
* ASN.1 definition of an X.509 certificate revocation list
*/
static const asn1Object_t crlObjects[] = {
{ 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
{ 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
{ 2, "version", ASN1_INTEGER, ASN1_OPT |
ASN1_BODY }, /* 2 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
{ 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */
{ 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
{ 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */
{ 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */
{ 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT |
ASN1_LOOP }, /* 8 */
{ 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */
{ 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */
{ 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */
{ 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT |
ASN1_LOOP }, /* 12 */
{ 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
{ 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */
{ 6, "critical", ASN1_BOOLEAN, ASN1_DEF |
ASN1_BODY }, /* 15 */
{ 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */
{ 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */
{ 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */
{ 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */
{ 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */
{ 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */
{ 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */
{ 5, "critical", ASN1_BOOLEAN, ASN1_DEF |
ASN1_BODY }, /* 23 */
{ 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
{ 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
{ 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */
{ 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */
};
#define CRL_OBJ_CERTIFICATE_LIST 0
#define CRL_OBJ_TBS_CERT_LIST 1
#define CRL_OBJ_VERSION 2
#define CRL_OBJ_SIG_ALG 4
#define CRL_OBJ_ISSUER 5
#define CRL_OBJ_THIS_UPDATE 6
#define CRL_OBJ_NEXT_UPDATE 7
#define CRL_OBJ_USER_CERTIFICATE 10
#define CRL_OBJ_REVOCATION_DATE 11
#define CRL_OBJ_CRL_ENTRY_EXTN_ID 14
#define CRL_OBJ_CRL_ENTRY_CRITICAL 15
#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16
#define CRL_OBJ_EXTN_ID 22
#define CRL_OBJ_CRITICAL 23
#define CRL_OBJ_EXTN_VALUE 24
#define CRL_OBJ_ALGORITHM 27
#define CRL_OBJ_SIGNATURE 28
#define CRL_OBJ_ROOF 29
/**
* Parses a CRL revocation reason code
*/
static crl_reason_t parse_crl_reasonCode(chunk_t object)
{
crl_reason_t reason = REASON_UNSPECIFIED;
if (*object.ptr == ASN1_ENUMERATED && asn1_length(&object) == 1)
{
reason = *object.ptr;
}
DBG2(" '%N'", crl_reason_names, reason);
return reason;
}
/**
* Parses an X.509 Certificate Revocation List (CRL)
*/
bool parse_x509crl(chunk_t blob, u_int level0, private_crl_t *crl)
{
asn1_ctx_t ctx;
bool critical;
chunk_t extnID;
chunk_t userCertificate = chunk_empty;
revokedCert_t *revokedCert = NULL;
chunk_t object;
u_int level;
int objectID = 0;
asn1_init(&ctx, blob, level0, FALSE, FALSE);
while (objectID < CRL_OBJ_ROOF)
{
if (!extract_object(crlObjects, &objectID, &object, &level, &ctx))
return FALSE;
/* those objects which will parsed further need the next higher level */
level++;
switch (objectID)
{
case CRL_OBJ_CERTIFICATE_LIST:
crl->certificateList = object;
break;
case CRL_OBJ_TBS_CERT_LIST:
crl->tbsCertList = object;
break;
case CRL_OBJ_VERSION:
crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
DBG2(" v%d", crl->version);
break;
case CRL_OBJ_SIG_ALG:
crl->sigAlg = parse_algorithmIdentifier(object, level, NULL);
break;
case CRL_OBJ_ISSUER:
crl->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
DBG2(" '%D'", crl->issuer);
break;
case CRL_OBJ_THIS_UPDATE:
crl->thisUpdate = parse_time(object, level);
break;
case CRL_OBJ_NEXT_UPDATE:
crl->nextUpdate = parse_time(object, level);
break;
case CRL_OBJ_USER_CERTIFICATE:
userCertificate = object;
break;
case CRL_OBJ_REVOCATION_DATE:
revokedCert = malloc_thing(revokedCert_t);
revokedCert->userCertificate = userCertificate;
revokedCert->revocationDate = parse_time(object, level);
revokedCert->revocationReason = REASON_UNSPECIFIED;
crl->revokedCertificates->insert_last(crl->revokedCertificates, (void *)revokedCert);
break;
case CRL_OBJ_CRL_ENTRY_EXTN_ID:
case CRL_OBJ_EXTN_ID:
extnID = object;
break;
case CRL_OBJ_CRL_ENTRY_CRITICAL:
case CRL_OBJ_CRITICAL:
critical = object.len && *object.ptr;
DBG2(" %s",(critical)?"TRUE":"FALSE");
break;
case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
case CRL_OBJ_EXTN_VALUE:
{
int extn_oid = known_oid(extnID);
if (revokedCert && extn_oid == OID_CRL_REASON_CODE)
{
revokedCert->revocationReason = parse_crl_reasonCode(object);
}
else if (extn_oid == OID_AUTHORITY_KEY_ID)
{
x509_parse_authorityKeyIdentifier(object, level,
&crl->authKeyID, &crl->authKeySerialNumber);
}
else if (extn_oid == OID_CRL_NUMBER)
{
if (!parse_asn1_simple_object(&object, ASN1_INTEGER, level, "crlNumber"))
{
return FALSE;
}
crl->crlNumber = object;
}
}
break;
case CRL_OBJ_ALGORITHM:
crl->algorithm = parse_algorithmIdentifier(object, level, NULL);
if (crl->algorithm != crl->sigAlg)
{
DBG1(" signature algorithms do not agree");
return FALSE;
}
break;
case CRL_OBJ_SIGNATURE:
crl->signature = object;
break;
default:
break;
}
objectID++;
}
time(&crl->installed);
return TRUE;
}
/**
* Implements crl_t.is_valid
*/
static bool is_valid(const private_crl_t *this)
{
time_t current_time = time(NULL);
DBG2(" this update : %T", &this->thisUpdate);
DBG2(" current time: %T", &current_time);
DBG2(" next update: %T", &this->nextUpdate);
return current_time < this->nextUpdate;
}
/**
* Implements crl_t.get_issuer
*/
static identification_t *get_issuer(const private_crl_t *this)
{
return this->issuer;
}
/**
* Implements crl_t.equals_issuer
*/
static bool equals_issuer(const private_crl_t *this, const private_crl_t *other)
{
return (this->authKeyID.ptr)
? chunk_equals(this->authKeyID, other->authKeyID)
: (this->issuer->equals(this->issuer, other->issuer)
&& chunk_equals_or_null(this->authKeySerialNumber, other->authKeySerialNumber));
}
/**
* Implements crl_t.is_issuer
*/
static bool is_issuer(const private_crl_t *this, const x509_t *issuer)
{
return (this->authKeyID.ptr)
? chunk_equals(this->authKeyID, issuer->get_subjectKeyID(issuer))
: (this->issuer->equals(this->issuer, issuer->get_subject(issuer))
&& chunk_equals_or_null(this->authKeySerialNumber, issuer->get_serialNumber(issuer)));
}
/**
* Implements crl_t.is_newer
*/
static bool is_newer(const private_crl_t *this, const private_crl_t *other)
{
return (this->nextUpdate > other->nextUpdate);
}
/**
* Implements crl_t.verify
*/
static bool verify(const private_crl_t *this, const rsa_public_key_t *signer)
{
hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->algorithm);
if (algorithm == HASH_UNKNOWN)
{
DBG1(" unknown signature algorithm");
return FALSE;
}
return signer->verify_emsa_pkcs1_signature(signer, algorithm, this->tbsCertList, this->signature) == SUCCESS;
}
/**
* Implements crl_t.get_status
*/
static void get_status(const private_crl_t *this, certinfo_t *certinfo)
{
chunk_t serialNumber = certinfo->get_serialNumber(certinfo);
iterator_t *iterator;
revokedCert_t *revokedCert;
certinfo->set_nextUpdate(certinfo, this->nextUpdate);
certinfo->set_status(certinfo, CERT_GOOD);
iterator = this->revokedCertificates->create_iterator(this->revokedCertificates, TRUE);
while (iterator->iterate(iterator, (void**)&revokedCert))
{
if (chunk_equals(serialNumber, revokedCert->userCertificate))
{
certinfo->set_status(certinfo, CERT_REVOKED);
certinfo->set_revocationTime(certinfo, revokedCert->revocationDate);
certinfo->set_revocationReason(certinfo, revokedCert->revocationReason);
break;
}
}
iterator->destroy(iterator);
}
/**
* Implements crl_t.write_to_file.
*/
static bool write_to_file(private_crl_t *this, const char *path, mode_t mask, bool force)
{
return chunk_write(this->certificateList, path, "crl", mask, force);
}
/**
* Implements crl_t.destroy
*/
static void destroy(private_crl_t *this)
{
this->revokedCertificates->destroy_function(this->revokedCertificates, free);
this->crlDistributionPoints->destroy_offset(this->crlDistributionPoints,
offsetof(identification_t, destroy));
DESTROY_IF(this->issuer);
free(this->certificateList.ptr);
free(this);
}
/**
* Implementation of crl_t.list.
*/
static void list(private_crl_t *this, FILE* out, bool utc)
{
time_t now;
now = time(NULL);
fprintf(out, "%#T, revoked certs: %d\n", &this->installed, utc,
this->revokedCertificates->get_count(this->revokedCertificates));
fprintf(out, " issuer: '%D'\n", this->issuer);
if (this->crlNumber.ptr)
{
fprintf(out, " crlnumber: %#B\n", &this->crlNumber);
}
fprintf(out, " updates: this %#T\n", &this->thisUpdate, utc);
fprintf(out, " next %#T ", &this->nextUpdate, utc);
if (this->nextUpdate == UNDEFINED_TIME)
{
fprintf(out, "ok (expires never)\n");
}
else if (now > this->nextUpdate)
{
fprintf(out, "expired (%#V ago)\n", &now, &this->nextUpdate);
}
else if (now > this->nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24)
{
fprintf(out, "ok (expires in %#V)\n", &now, &this->nextUpdate);
}
else
{
fprintf(out, "ok\n");
}
if (this->authKeyID.ptr)
{
fprintf(out, " authkey: %#B\n", &this->authKeyID);
}
if (this->authKeySerialNumber.ptr)
{
fprintf(out, " aserial: %#B\n", &this->authKeySerialNumber);
}
}
/*
* Described in header.
*/
crl_t *crl_create_from_chunk(chunk_t chunk)
{
private_crl_t *this = malloc_thing(private_crl_t);
/* initialize */
this->crlDistributionPoints = linked_list_create();
this->tbsCertList = chunk_empty;
this->issuer = NULL;
this->crlNumber = chunk_empty;
this->revokedCertificates = linked_list_create();
this->authKeyID = chunk_empty;
this->authKeySerialNumber = chunk_empty;
/* public functions */
this->public.get_issuer = (identification_t* (*) (const crl_t*))get_issuer;
this->public.equals_issuer = (bool (*) (const crl_t*,const crl_t*))equals_issuer;
this->public.is_issuer = (bool (*) (const crl_t*,const x509_t*))is_issuer;
this->public.is_valid = (bool (*) (const crl_t*))is_valid;
this->public.is_newer = (bool (*) (const crl_t*,const crl_t*))is_newer;
this->public.verify = (bool (*) (const crl_t*,const rsa_public_key_t*))verify;
this->public.get_status = (void (*) (const crl_t*,certinfo_t*))get_status;
this->public.write_to_file = (bool (*) (const crl_t*,const char*,mode_t,bool))write_to_file;
this->public.list = (void(*)(crl_t*, FILE* out, bool utc))list;
this->public.destroy = (void (*) (crl_t*))destroy;
if (!parse_x509crl(chunk, 0, this))
{
destroy(this);
return NULL;
}
return &this->public;
}
/*
* Described in header.
*/
crl_t *crl_create_from_file(const char *filename)
{
bool pgp = FALSE;
chunk_t chunk = chunk_empty;
if (!pem_asn1_load_file(filename, NULL, "crl", &chunk, &pgp))
{
return NULL;
}
return crl_create_from_chunk(chunk);
}
-158
View File
@@ -1,158 +0,0 @@
/**
* @file crl.h
*
* @brief Interface of crl_t.
*
*/
/*
* Copyright (C) 2006 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.
*
* RCSID $Id$
*/
#ifndef CRL_H_
#define CRL_H_
typedef struct crl_t crl_t;
#include <library.h>
#include <crypto/rsa/rsa_public_key.h>
#include <crypto/certinfo.h>
#include <utils/identification.h>
#include <utils/iterator.h>
/**
* @brief X.509 certificate revocation list
*
* @b Constructors:
* - crl_create_from_chunk()
* - crl_create_from_file()
*
* @ingroup transforms
*/
struct crl_t {
/**
* @brief Get the crl's issuer ID.
*
* The resulting ID is always a identification_t
* of type ID_DER_ASN1_DN.
*
* @param this calling object
* @return issuers ID
*/
identification_t *(*get_issuer) (const crl_t *this);
/**
* @brief Check if both crls have the same issuer.
*
* @param this calling object
* @param other other crl
* @return TRUE if the same issuer
*/
bool (*equals_issuer) (const crl_t *this, const crl_t *other);
/**
* @brief Check if ia candidate cert is the issuer of the crl
*
* @param this calling object
* @param issuer candidate issuer of the crl
* @return TRUE if issuer
*/
bool (*is_issuer) (const crl_t *this, const x509_t *issuer);
/**
* @brief Checks the validity interval of the crl
*
* @param this calling object
* @return TRUE if the crl is valid
*/
bool (*is_valid) (const crl_t *this);
/**
* @brief Checks if this crl is newer (thisUpdate) than the other crl
*
* @param this calling object
* @param other other crl object
* @return TRUE if this was issued more recently than other
*/
bool (*is_newer) (const crl_t *this, const crl_t *other);
/**
* @brief Check if a crl is trustworthy.
*
* @param this calling object
* @param signer signer's RSA public key
* @return TRUE if crl is trustworthy
*/
bool (*verify) (const crl_t *this, const rsa_public_key_t *signer);
/**
* @brief Get the certificate status
*
* @param this calling object
* @param certinfo certinfo is updated
*/
void (*get_status) (const crl_t *this, certinfo_t *certinfo);
/**
* @brief Log the info of this CRL to out.
*
* @param this calling object
* @param out stream to write to
* @param utc TRUE for UTC, FALSE for local time
*/
void (*list)(crl_t *this, FILE* out, bool utc);
/**
* @brief Write a der-encoded crl to a file
*
* @param this calling object
* @param path path where the file is to be stored
* @param mask file access control rights
* @param force overwrite the file if it already exists
* @return TRUE if successfully written
*/
bool (*write_to_file) (const crl_t *this, const char *path, mode_t mask, bool force);
/**
* @brief Destroys the crl.
*
* @param this crl to destroy
*/
void (*destroy) (crl_t *this);
};
/**
* @brief Read a x509 crl from a DER encoded blob.
*
* @param chunk chunk containing DER encoded data
* @return created crl_t, or NULL if invalid.
*
* @ingroup transforms
*/
crl_t *crl_create_from_chunk(chunk_t chunk);
/**
* @brief Read a x509 crl from a DER encoded file.
*
* @param filename file containing DER encoded data
* @return created crl_t, or NULL if invalid.
*
* @ingroup transforms
*/
crl_t *crl_create_from_file(const char *filename);
#endif /* CRL_H_ */
+2 -32
View File
@@ -1,10 +1,3 @@
/**
* @file crypter.c
*
* @brief Generic constructor for crypter_t.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,15 +12,12 @@
* 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.
*
* $Id$
*/
#include "crypter.h"
#include <crypto/crypters/aes_cbc_crypter.h>
#include <crypto/crypters/des_crypter.h>
ENUM_BEGIN(encryption_algorithm_names, ENCR_UNDEFINED, ENCR_UNDEFINED,
"UNDEFINED");
ENUM_NEXT(encryption_algorithm_names, ENCR_DES_IV64, ENCR_DES_IV32, ENCR_UNDEFINED,
@@ -46,23 +36,3 @@ ENUM_NEXT(encryption_algorithm_names, ENCR_NULL, ENCR_AES_CTR, ENCR_DES_IV32,
"AES_CTR");
ENUM_END(encryption_algorithm_names, ENCR_AES_CTR);
/*
* Described in header.
*/
crypter_t *crypter_create(encryption_algorithm_t encryption_algorithm, size_t key_size)
{
switch (encryption_algorithm)
{
case ENCR_AES_CBC:
{
return (crypter_t*)aes_cbc_crypter_create(key_size);
}
case ENCR_DES:
case ENCR_3DES:
{
return (crypter_t*)des_crypter_create(encryption_algorithm);
}
default:
return NULL;
}
}
+29 -73
View File
@@ -1,10 +1,3 @@
/**
* @file crypter.h
*
* @brief Interface crypter_t
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,13 @@
* 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.
*
* $Id$
*/
/**
* @defgroup crypter crypter
* @{ @ingroup crypto
*/
#ifndef CRYPTER_H_
@@ -30,21 +30,12 @@ typedef struct crypter_t crypter_t;
#include <library.h>
/**
* @brief Encryption algorithm, as in IKEv2 RFC 3.3.2.
*
* Currently only the following algorithms are implemented:
* - ENCR_AES_CBC
* - ENCR_DES
* - ENCR_3DES
*
* @ingroup crypters
* Encryption algorithm, as in IKEv2 RFC 3.3.2.
*/
enum encryption_algorithm_t {
ENCR_UNDEFINED = 1024,
ENCR_DES_IV64 = 1,
/** Implemented in class des_crypter_t */
ENCR_DES = 2,
/** Implemented in class des_crypter_t */
ENCR_3DES = 3,
ENCR_RC5 = 4,
ENCR_IDEA = 5,
@@ -53,7 +44,6 @@ enum encryption_algorithm_t {
ENCR_3IDEA = 8,
ENCR_DES_IV32 = 9,
ENCR_NULL = 11,
/** Implemented in class aes_cbc_crypter_t */
ENCR_AES_CBC = 12,
ENCR_AES_CTR = 13
};
@@ -64,92 +54,58 @@ enum encryption_algorithm_t {
extern enum_name_t *encryption_algorithm_names;
/**
* @brief Generic interface for symmetric encryption algorithms.
*
* @b Constructors:
* - crypter_create()
*
* @ingroup crypters
* Generic interface for symmetric encryption algorithms.
*/
struct crypter_t {
/**
* @brief Encrypt a chunk of data and allocate space for the encrypted value.
* Encrypt a chunk of data and allocate space for the encrypted value.
*
* @param this calling object
* @param data data to encrypt
* @param iv initializing vector
* @param[out] encrypted pointer where the encrypted bytes will be written
* @return
* - SUCCESS
* - INVALID_ARG if data size not a multiple of block size
* @param data data to encrypt
* @param iv initializing vector
* @param encrypted pointer where the encrypted bytes will be written
* @return SUCCESS, or INVALID_ARG if size invalid
*/
status_t (*encrypt) (crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted);
status_t (*encrypt) (crypter_t *this, chunk_t data, chunk_t iv,
chunk_t *encrypted);
/**
* @brief Decrypt a chunk of data and allocate space for the decrypted value.
* Decrypt a chunk of data and allocate space for the decrypted value.
*
* @param this calling object
* @param data data to decrypt
* @param iv initializing vector
* @param[out] encrypted pointer where the decrypted bytes will be written
* @return
* - SUCCESS
* - INVALID_ARG if data size not a multiple of block size
* @param data data to decrypt
* @param iv initializing vector
* @param encrypted pointer where the decrypted bytes will be written
* @return SUCCESS, or INVALID_ARG if invalid
*/
status_t (*decrypt) (crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted);
status_t (*decrypt) (crypter_t *this, chunk_t data, chunk_t iv,
chunk_t *decrypted);
/**
* @brief Get the block size of this crypter_t object.
* Get the block size of the crypto algorithm.
*
* @param this calling object
* @return block size in bytes
*/
size_t (*get_block_size) (crypter_t *this);
/**
* @brief Get the key size of this crypter_t object.
* Get the key size of the crypto algorithm.
*
* @param this calling object
* @return key size in bytes
*/
size_t (*get_key_size) (crypter_t *this);
/**
* @brief Set the key for this crypter_t object.
* Set the key.
*
* @param this calling object
* @param key key to set
* @return
* - SUCCESS
* - INVALID_ARG if key length invalid
* @return SUCCESS, or INVALID_ARG if key length invalid
*/
status_t (*set_key) (crypter_t *this, chunk_t key);
/**
* @brief Destroys a crypter_t object.
*
* @param this calling object
* Destroys a crypter_t object.
*/
void (*destroy) (crypter_t *this);
};
/**
* @brief Generic constructor for crypter_t objects.
*
* Currently only the following algorithms are implemented:
* - ENCR_AES_CBC
* - ENCR_DES
* - ENCR_3DES
*
* The key_size is ignored for algorithms with fixed key size.
*
* @param encryption_algorithm Algorithm to use for crypter
* @param key_size size of the key in bytes
* @return
* - crypter_t object
* - NULL if encryption algorithm/key_size is not supported
*/
crypter_t *crypter_create(encryption_algorithm_t encryption_algorithm, size_t key_size);
#endif /*CRYPTER_H_*/
#endif /*CRYPTER_H_ @} */
+483
View File
@@ -0,0 +1,483 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "crypto_factory.h"
#include <utils/linked_list.h>
#include <utils/mutex.h>
typedef struct crypter_entry_t crypter_entry_t;
struct crypter_entry_t {
/** encryption algorithm */
encryption_algorithm_t algo;
/** associated constructor */
crypter_constructor_t create;
};
typedef struct signer_entry_t signer_entry_t;
struct signer_entry_t {
/** integrity algorithm */
integrity_algorithm_t algo;
/** associated constructor */
signer_constructor_t create;
};
typedef struct hasher_entry_t hasher_entry_t;
struct hasher_entry_t {
/** hash algorithm */
hash_algorithm_t algo;
/** associated constructor */
hasher_constructor_t create;
};
typedef struct prf_entry_t prf_entry_t;
struct prf_entry_t {
/** hash algorithm */
pseudo_random_function_t algo;
/** associated constructor */
prf_constructor_t create;
};
typedef struct dh_entry_t dh_entry_t;
struct dh_entry_t {
/** hash algorithm */
diffie_hellman_group_t group;
/** associated constructor */
dh_constructor_t create;
};
typedef struct private_crypto_factory_t private_crypto_factory_t;
/**
* private data of crypto_factory
*/
struct private_crypto_factory_t {
/**
* public functions
*/
crypto_factory_t public;
/**
* registered crypters, as crypter_entry_t
*/
linked_list_t *crypters;
/**
* registered signers, as signer_entry_t
*/
linked_list_t *signers;
/**
* registered hashers, as hasher_entry_t
*/
linked_list_t *hashers;
/**
* registered perfs, as prf_entry_t
*/
linked_list_t *prfs;
/**
* registered diffie hellman, as dh_entry_t
*/
linked_list_t *dhs;
/**
* mutex to lock access to modules
*/
mutex_t *mutex;
};
/**
* Implementation of crypto_factory_t.create_crypter.
*/
static crypter_t* create_crypter(private_crypto_factory_t *this,
encryption_algorithm_t algo, size_t key_size)
{
enumerator_t *enumerator;
crypter_entry_t *entry;
crypter_t *crypter = NULL;
this->mutex->lock(this->mutex);
enumerator = this->crypters->create_enumerator(this->crypters);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->algo == algo)
{
crypter = entry->create(algo, key_size);
if (crypter)
{
break;
}
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return crypter;
}
/**
* Implementation of crypto_factory_t.create_signer.
*/
static signer_t* create_signer(private_crypto_factory_t *this,
integrity_algorithm_t algo)
{
enumerator_t *enumerator;
signer_entry_t *entry;
signer_t *signer = NULL;
this->mutex->lock(this->mutex);
enumerator = this->signers->create_enumerator(this->signers);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->algo == algo)
{
signer = entry->create(algo);
if (signer)
{
break;
}
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return signer;
}
/**
* Implementation of crypto_factory_t.create_hasher.
*/
static hasher_t* create_hasher(private_crypto_factory_t *this,
hash_algorithm_t algo)
{
enumerator_t *enumerator;
hasher_entry_t *entry;
hasher_t *hasher = NULL;
this->mutex->lock(this->mutex);
enumerator = this->hashers->create_enumerator(this->hashers);
while (enumerator->enumerate(enumerator, &entry))
{
if (algo == HASH_PREFERRED || entry->algo == algo)
{
hasher = entry->create(entry->algo);
if (hasher)
{
break;
}
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return hasher;
}
/**
* Implementation of crypto_factory_t.create_prf.
*/
static prf_t* create_prf(private_crypto_factory_t *this,
pseudo_random_function_t algo)
{
enumerator_t *enumerator;
prf_entry_t *entry;
prf_t *prf = NULL;
this->mutex->lock(this->mutex);
enumerator = this->prfs->create_enumerator(this->prfs);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->algo == algo)
{
prf = entry->create(algo);
if (prf)
{
break;
}
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return prf;
}
/**
* Implementation of crypto_factory_t.create_dh.
*/
static diffie_hellman_t* create_dh(private_crypto_factory_t *this,
diffie_hellman_group_t group)
{
enumerator_t *enumerator;
dh_entry_t *entry;
diffie_hellman_t *diffie_hellman = NULL;
this->mutex->lock(this->mutex);
enumerator = this->dhs->create_enumerator(this->dhs);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->group == group)
{
diffie_hellman = entry->create(group);
if (diffie_hellman)
{
break;
}
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return diffie_hellman;
}
/**
* Implementation of crypto_factory_t.add_crypter.
*/
static void add_crypter(private_crypto_factory_t *this,
encryption_algorithm_t algo,
crypter_constructor_t create)
{
crypter_entry_t *entry = malloc_thing(crypter_entry_t);
entry->algo = algo;
entry->create = create;
this->mutex->lock(this->mutex);
this->crypters->insert_last(this->crypters, entry);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.remove_crypter.
*/
static void remove_crypter(private_crypto_factory_t *this,
crypter_constructor_t create)
{
crypter_entry_t *entry;
enumerator_t *enumerator;
this->mutex->lock(this->mutex);
enumerator = this->crypters->create_enumerator(this->crypters);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->create == create)
{
this->crypters->remove_at(this->crypters, enumerator);
free(entry);
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.add_signer.
*/
static void add_signer(private_crypto_factory_t *this,
integrity_algorithm_t algo, signer_constructor_t create)
{
signer_entry_t *entry = malloc_thing(signer_entry_t);
entry->algo = algo;
entry->create = create;
this->mutex->lock(this->mutex);
this->signers->insert_last(this->signers, entry);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.remove_signer.
*/
static void remove_signer(private_crypto_factory_t *this,
signer_constructor_t create)
{
signer_entry_t *entry;
enumerator_t *enumerator;
this->mutex->lock(this->mutex);
enumerator = this->signers->create_enumerator(this->signers);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->create == create)
{
this->signers->remove_at(this->signers, enumerator);
free(entry);
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.add_hasher.
*/
static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo,
hasher_constructor_t create)
{
hasher_entry_t *entry = malloc_thing(hasher_entry_t);
entry->algo = algo;
entry->create = create;
this->mutex->lock(this->mutex);
this->hashers->insert_last(this->hashers, entry);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.remove_hasher.
*/
static void remove_hasher(private_crypto_factory_t *this,
hasher_constructor_t create)
{
hasher_entry_t *entry;
enumerator_t *enumerator;
this->mutex->lock(this->mutex);
enumerator = this->hashers->create_enumerator(this->hashers);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->create == create)
{
this->hashers->remove_at(this->hashers, enumerator);
free(entry);
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.add_prf.
*/
static void add_prf(private_crypto_factory_t *this,
pseudo_random_function_t algo, prf_constructor_t create)
{
prf_entry_t *entry = malloc_thing(prf_entry_t);
entry->algo = algo;
entry->create = create;
this->mutex->lock(this->mutex);
this->prfs->insert_last(this->prfs, entry);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.remove_prf.
*/
static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create)
{
prf_entry_t *entry;
enumerator_t *enumerator;
this->mutex->lock(this->mutex);
enumerator = this->prfs->create_enumerator(this->prfs);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->create == create)
{
this->prfs->remove_at(this->prfs, enumerator);
free(entry);
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.add_dh.
*/
static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group,
dh_constructor_t create)
{
dh_entry_t *entry = malloc_thing(dh_entry_t);
entry->group = group;
entry->create = create;
this->mutex->lock(this->mutex);
this->dhs->insert_last(this->dhs, entry);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.remove_dh.
*/
static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create)
{
dh_entry_t *entry;
enumerator_t *enumerator;
this->mutex->lock(this->mutex);
enumerator = this->dhs->create_enumerator(this->dhs);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->create == create)
{
this->dhs->remove_at(this->dhs, enumerator);
free(entry);
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of crypto_factory_t.destroy
*/
static void destroy(private_crypto_factory_t *this)
{
this->crypters->destroy_function(this->crypters, free);
this->signers->destroy_function(this->signers, free);
this->hashers->destroy_function(this->hashers, free);
this->prfs->destroy_function(this->prfs, free);
this->dhs->destroy_function(this->dhs, free);
this->mutex->destroy(this->mutex);
free(this);
}
/*
* see header file
*/
crypto_factory_t *crypto_factory_create()
{
private_crypto_factory_t *this = malloc_thing(private_crypto_factory_t);
this->public.create_crypter = (crypter_t*(*)(crypto_factory_t*, encryption_algorithm_t, size_t))create_crypter;
this->public.create_signer = (signer_t*(*)(crypto_factory_t*, integrity_algorithm_t))create_signer;
this->public.create_hasher = (hasher_t*(*)(crypto_factory_t*, hash_algorithm_t))create_hasher;
this->public.create_prf = (prf_t*(*)(crypto_factory_t*, pseudo_random_function_t))create_prf;
this->public.create_dh = (diffie_hellman_t*(*)(crypto_factory_t*, diffie_hellman_group_t group))create_dh;
this->public.add_crypter = (void(*)(crypto_factory_t*, encryption_algorithm_t algo, crypter_constructor_t create))add_crypter;
this->public.remove_crypter = (void(*)(crypto_factory_t*, crypter_constructor_t create))remove_crypter;
this->public.add_signer = (void(*)(crypto_factory_t*, integrity_algorithm_t algo, signer_constructor_t create))add_signer;
this->public.remove_signer = (void(*)(crypto_factory_t*, signer_constructor_t create))remove_signer;
this->public.add_hasher = (void(*)(crypto_factory_t*, hash_algorithm_t algo, hasher_constructor_t create))add_hasher;
this->public.remove_hasher = (void(*)(crypto_factory_t*, hasher_constructor_t create))remove_hasher;
this->public.add_prf = (void(*)(crypto_factory_t*, pseudo_random_function_t algo, prf_constructor_t create))add_prf;
this->public.remove_prf = (void(*)(crypto_factory_t*, prf_constructor_t create))remove_prf;
this->public.add_dh = (void(*)(crypto_factory_t*, diffie_hellman_group_t algo, dh_constructor_t create))add_dh;
this->public.remove_dh = (void(*)(crypto_factory_t*, dh_constructor_t create))remove_dh;
this->public.destroy = (void(*)(crypto_factory_t*))destroy;
this->crypters = linked_list_create();
this->signers = linked_list_create();
this->hashers = linked_list_create();
this->prfs = linked_list_create();
this->dhs = linked_list_create();
this->mutex = mutex_create(MUTEX_RECURSIVE);
return &this->public;
}
+206
View File
@@ -0,0 +1,206 @@
/*
* Copyright (C) 2008 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 crypto_factory crypto_factory
* @{ @ingroup crypto
*/
#ifndef CRYPTO_FACTORY_H_
#define CRYPTO_FACTORY_H_
typedef struct crypto_factory_t crypto_factory_t;
#include <library.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/prf.h>
#include <crypto/diffie_hellman.h>
/**
* Constructor function for crypters
*/
typedef crypter_t* (*crypter_constructor_t)(encryption_algorithm_t algo,
size_t key_size);
/**
* Constructor function for signers
*/
typedef signer_t* (*signer_constructor_t)(integrity_algorithm_t algo);
/**
* Constructor function for hashers
*/
typedef hasher_t* (*hasher_constructor_t)(hash_algorithm_t algo);
/**
* Constructor function for pseudo random fucntions
*/
typedef prf_t* (*prf_constructor_t)(pseudo_random_function_t algo);
/**
* Constructor function for diffie hellman
*/
typedef diffie_hellman_t* (*dh_constructor_t)(diffie_hellman_group_t group);
/**
* Handles crypto modules and creates instances.
*/
struct crypto_factory_t {
/**
* Create a crypter instance.
*
* @param algo encryption algorithm
* @param key_size length of the key in bytes
* @return crypter_t instance, NULL if not supported
*/
crypter_t* (*create_crypter)(crypto_factory_t *this,
encryption_algorithm_t algo, size_t key_size);
/**
* Create a symmetric signer instance.
*
* @param algo MAC algorithm to use
* @return signer_t instance, NULL if not supported
*/
signer_t* (*create_signer)(crypto_factory_t *this,
integrity_algorithm_t algo);
/**
* Create a hasher instance.
*
* @param algo hash algorithm
* @return hasher_t instance, NULL if not supported
*/
hasher_t* (*create_hasher)(crypto_factory_t *this, hash_algorithm_t algo);
/**
* Create a pseudo random function instance.
*
* @param algo PRF algorithm to use
* @return prf_t instance, NULL if not supported
*/
prf_t* (*create_prf)(crypto_factory_t *this, pseudo_random_function_t algo);
/**
* Create a diffie hellman instance.
*
* @param group diffie hellman group
* @return diffie_hellman_t instance, NULL if not supported
*/
diffie_hellman_t* (*create_dh)(crypto_factory_t *this,
diffie_hellman_group_t group);
/**
* Register a crypter constructor.
*
* @param algo algorithm to constructor
* @param create constructor function for that algorithm
* @return
*/
void (*add_crypter)(crypto_factory_t *this, encryption_algorithm_t algo,
crypter_constructor_t create);
/**
* Unregister a crypter constructor.
*
* @param create constructor function to unregister
*/
void (*remove_crypter)(crypto_factory_t *this, crypter_constructor_t create);
/**
* Register a signer constructor.
*
* @param algo algorithm to constructor
* @param create constructor function for that algorithm
* @return
*/
void (*add_signer)(crypto_factory_t *this, integrity_algorithm_t algo,
signer_constructor_t create);
/**
* Unregister a signer constructor.
*
* @param create constructor function to unregister
*/
void (*remove_signer)(crypto_factory_t *this, signer_constructor_t create);
/**
* Register a hasher constructor.
*
* The first added hasher is the preferred hasher returned on
* create_hasher(HASH_PREFERRED).
*
* @param algo algorithm to constructor
* @param create constructor function for that algorithm
* @return
*/
void (*add_hasher)(crypto_factory_t *this, hash_algorithm_t algo,
hasher_constructor_t create);
/**
* Unregister a hasher constructor.
*
* @param create constructor function to unregister
*/
void (*remove_hasher)(crypto_factory_t *this, hasher_constructor_t create);
/**
* Register a prf constructor.
*
* @param algo algorithm to constructor
* @param create constructor function for that algorithm
* @return
*/
void (*add_prf)(crypto_factory_t *this, pseudo_random_function_t algo,
prf_constructor_t create);
/**
* Unregister a prf constructor.
*
* @param create constructor function to unregister
*/
void (*remove_prf)(crypto_factory_t *this, prf_constructor_t create);
/**
* Register a diffie hellman constructor.
*
* @param group dh group to constructor
* @param create constructor function for that algorithm
* @return
*/
void (*add_dh)(crypto_factory_t *this, diffie_hellman_group_t group,
dh_constructor_t create);
/**
* Unregister a diffie hellman constructor.
*
* @param create constructor function to unregister
*/
void (*remove_dh)(crypto_factory_t *this, dh_constructor_t create);
/**
* Destroy a crypto_factory instance.
*/
void (*destroy)(crypto_factory_t *this);
};
/**
* Create a crypto_factory instance.
*/
crypto_factory_t *crypto_factory_create();
#endif /* CRYPTO_FACTORY_H_ @}*/
+3 -558
View File
@@ -1,14 +1,5 @@
/**
* @file diffie_hellman.c
*
* @brief Implementation of diffie_hellman_t.
*
*/
/*
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
* Copyright (C) 1999, 2000, 2001 Henry Spencer.
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -21,15 +12,12 @@
* 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.
*
* $Id$
*/
#include <gmp.h>
#include "diffie_hellman.h"
#include <utils/randomizer.h>
#include <debug.h>
ENUM_BEGIN(diffie_hellman_group_names, MODP_NONE, MODP_1024_BIT,
"MODP_NONE",
"MODP_768_BIT",
@@ -44,546 +32,3 @@ ENUM_NEXT(diffie_hellman_group_names, MODP_2048_BIT, MODP_8192_BIT, MODP_1536_BI
"MODP_8192_BIT");
ENUM_END(diffie_hellman_group_names, MODP_8192_BIT);
/**
* Modulus of Group 1 (MODP_768_BIT).
*/
static u_int8_t group1_modulus[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80 ,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/**
* Modulus of Group 2 (MODP_1024_BIT).
*/
static u_int8_t group2_modulus[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51,0xEC,0xE6,0x53,0x81,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/**
* Modulus of Group 5 (MODP_1536_BIT).
*/
static u_int8_t group5_modulus[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
0xF1,0x74,0x6C,0x08,0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/**
* Modulus of Group 14 (MODP_2048_BIT).
*/
static u_int8_t group14_modulus[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
0x15,0x72,0x8E,0x5A,0x8A,0xAC,0xAA,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/**
* Modulus of Group 15 (MODP_3072_BIT).
*/
static u_int8_t group15_modulus[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
0x4B,0x82,0xD1,0x20,0xA9,0x3A,0xD2,0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/**
* Modulus of Group 16 (MODP_4096_BIT).
*/
static u_int8_t group16_modulus[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
0x4D,0xF4,0x35,0xC9,0x34,0x06,0x31,0x99,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/**
* Modulus of Group 17 (MODP_6144_BIT).
*/
static u_int8_t group17_modulus[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
0xE6,0x94,0xF9,0x1E,0x6D,0xCC,0x40,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
/**
* Modulus of Group 18 (MODP_8192_BIT).
*/
static u_int8_t group18_modulus[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
0xE6,0x94,0xF9,0x1E,0x6D,0xBE,0x11,0x59,0x74,0xA3,0x92,0x6F,0x12,0xFE,0xE5,0xE4,
0x38,0x77,0x7C,0xB6,0xA9,0x32,0xDF,0x8C,0xD8,0xBE,0xC4,0xD0,0x73,0xB9,0x31,0xBA,
0x3B,0xC8,0x32,0xB6,0x8D,0x9D,0xD3,0x00,0x74,0x1F,0xA7,0xBF,0x8A,0xFC,0x47,0xED,
0x25,0x76,0xF6,0x93,0x6B,0xA4,0x24,0x66,0x3A,0xAB,0x63,0x9C,0x5A,0xE4,0xF5,0x68,
0x34,0x23,0xB4,0x74,0x2B,0xF1,0xC9,0x78,0x23,0x8F,0x16,0xCB,0xE3,0x9D,0x65,0x2D,
0xE3,0xFD,0xB8,0xBE,0xFC,0x84,0x8A,0xD9,0x22,0x22,0x2E,0x04,0xA4,0x03,0x7C,0x07,
0x13,0xEB,0x57,0xA8,0x1A,0x23,0xF0,0xC7,0x34,0x73,0xFC,0x64,0x6C,0xEA,0x30,0x6B,
0x4B,0xCB,0xC8,0x86,0x2F,0x83,0x85,0xDD,0xFA,0x9D,0x4B,0x7F,0xA2,0xC0,0x87,0xE8,
0x79,0x68,0x33,0x03,0xED,0x5B,0xDD,0x3A,0x06,0x2B,0x3C,0xF5,0xB3,0xA2,0x78,0xA6,
0x6D,0x2A,0x13,0xF8,0x3F,0x44,0xF8,0x2D,0xDF,0x31,0x0E,0xE0,0x74,0xAB,0x6A,0x36,
0x45,0x97,0xE8,0x99,0xA0,0x25,0x5D,0xC1,0x64,0xF3,0x1C,0xC5,0x08,0x46,0x85,0x1D,
0xF9,0xAB,0x48,0x19,0x5D,0xED,0x7E,0xA1,0xB1,0xD5,0x10,0xBD,0x7E,0xE7,0x4D,0x73,
0xFA,0xF3,0x6B,0xC3,0x1E,0xCF,0xA2,0x68,0x35,0x90,0x46,0xF4,0xEB,0x87,0x9F,0x92,
0x40,0x09,0x43,0x8B,0x48,0x1C,0x6C,0xD7,0x88,0x9A,0x00,0x2E,0xD5,0xEE,0x38,0x2B,
0xC9,0x19,0x0D,0xA6,0xFC,0x02,0x6E,0x47,0x95,0x58,0xE4,0x47,0x56,0x77,0xE9,0xAA,
0x9E,0x30,0x50,0xE2,0x76,0x56,0x94,0xDF,0xC8,0x1F,0x56,0xE8,0x80,0xB9,0x6E,0x71,
0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
typedef struct modulus_entry_t modulus_entry_t;
/**
* Entry of the modulus list.
*/
struct modulus_entry_t {
/**
* Group number as it is defined in file transform_substructure.h.
*/
diffie_hellman_group_t group;
/**
* Pointer to first byte of modulus (network order).
*/
u_int8_t *modulus;
/*
* Length of modulus in bytes.
*/
size_t modulus_len;
/*
* Generator value.
*/
u_int16_t generator;
};
/**
* All supported modulus values.
*/
static modulus_entry_t modulus_entries[] = {
{MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 2},
{MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 2},
{MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 2},
{MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 2},
{MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 2},
{MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 2},
{MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 2},
{MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 2},
};
typedef struct private_diffie_hellman_t private_diffie_hellman_t;
/**
* Private data of an diffie_hellman_t object.
*
*/
struct private_diffie_hellman_t {
/**
* Public diffie_hellman_t interface.
*/
diffie_hellman_t public;
/**
* Diffie Hellman group number.
*/
u_int16_t group;
/*
* Generator value.
*/
mpz_t g;
/**
* My private value.
*/
mpz_t xa;
/**
* My public value.
*/
mpz_t ya;
/**
* Other public value.
*/
mpz_t yb;
/**
* Shared secret.
*/
mpz_t zz;
/**
* Modulus.
*/
mpz_t p;
/**
* Modulus length.
*/
size_t p_len;
/**
* True if shared secret is computed and stored in my_public_value.
*/
bool computed;
};
/**
* Implementation of diffie_hellman_t.set_other_public_value.
*/
static void set_other_public_value(private_diffie_hellman_t *this, chunk_t value)
{
mpz_t p_min_1;
mpz_init(p_min_1);
mpz_sub_ui(p_min_1, this->p, 1);
mpz_import(this->yb, value.len, 1, 1, 1, 0, value.ptr);
/* check public value:
* 1. 0 or 1 is invalid as 0^a = 0 and 1^a = 1
* 2. a public value larger or equal the modulus is invalid */
if (mpz_cmp_ui(this->yb, 1) > 0 ||
mpz_cmp(this->yb, p_min_1) < 0)
{
#ifdef EXTENDED_DH_TEST
/* 3. test if y ^ q mod p = 1, where q = (p - 1)/2. */
mpz_t q, one;
mpz_init(q);
mpz_init(one);
mpz_fdiv_q_2exp(q, p_min_1, 1);
mpz_powm(one, this->yb, q, this->p);
mpz_clear(q);
if (mpz_cmp_ui(one, 1) == 0)
{
mpz_powm(this->zz, this->yb, this->xa, this->p);
this->computed = TRUE;
}
else
{
DBG1("public DH value verification failed: y ^ q mod p != 1");
}
mpz_clear(one);
#else
mpz_powm(this->zz, this->yb, this->xa, this->p);
this->computed = TRUE;
#endif
}
else
{
DBG1("public DH value verification failed: y < 2 || y > p - 1 ");
}
mpz_clear(p_min_1);
}
/**
* Implementation of diffie_hellman_t.get_other_public_value.
*/
static status_t get_other_public_value(private_diffie_hellman_t *this,
chunk_t *value)
{
if (!this->computed)
{
return FAILED;
}
value->len = this->p_len;
value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->yb);
return SUCCESS;
}
/**
* Implementation of diffie_hellman_t.get_my_public_value.
*/
static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *value)
{
value->len = this->p_len;
value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->ya);
}
/**
* Implementation of diffie_hellman_t.get_shared_secret.
*/
static status_t get_shared_secret(private_diffie_hellman_t *this, chunk_t *secret)
{
if (!this->computed)
{
return FAILED;
}
secret->len = this->p_len;
secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->zz);
return SUCCESS;
}
/**
* Implementation of diffie_hellman_t.get_dh_group.
*/
static diffie_hellman_group_t get_dh_group(private_diffie_hellman_t *this)
{
return this->group;
}
/**
* Lookup the modulus in modulo table
*/
static status_t set_modulus(private_diffie_hellman_t *this)
{
int i;
status_t status = NOT_FOUND;
for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++)
{
if (modulus_entries[i].group == this->group)
{
chunk_t chunk;
chunk.ptr = modulus_entries[i].modulus;
chunk.len = modulus_entries[i].modulus_len;
mpz_import(this->p, chunk.len, 1, 1, 1, 0, chunk.ptr);
this->p_len = chunk.len;
mpz_set_ui(this->g, modulus_entries[i].generator);
status = SUCCESS;
break;
}
}
return status;
}
/**
* Implementation of diffie_hellman_t.destroy.
*/
static void destroy(private_diffie_hellman_t *this)
{
mpz_clear(this->p);
mpz_clear(this->xa);
mpz_clear(this->ya);
mpz_clear(this->yb);
mpz_clear(this->zz);
mpz_clear(this->g);
free(this);
}
/*
* Described in header.
*/
diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t group)
{
private_diffie_hellman_t *this = malloc_thing(private_diffie_hellman_t);
randomizer_t *randomizer;
chunk_t random;
status_t status;
/* public functions */
this->public.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret;
this->public.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value;
this->public.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value;
this->public.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value;
this->public.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group;
this->public.destroy = (void (*)(diffie_hellman_t *)) destroy;
/* private variables */
this->group = group;
mpz_init(this->p);
mpz_init(this->yb);
mpz_init(this->ya);
mpz_init(this->xa);
mpz_init(this->zz);
mpz_init(this->g);
this->computed = FALSE;
/* find a modulus according to group */
if (set_modulus(this) != SUCCESS)
{
destroy(this);
return NULL;
}
randomizer = randomizer_create();
status = randomizer->allocate_pseudo_random_bytes(
randomizer, this->p_len, &random);
randomizer->destroy(randomizer);
if (status != SUCCESS)
{
destroy(this);
return NULL;
}
mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr);
chunk_free(&random);
mpz_powm(this->ya, this->g, this->xa, this->p);
return &this->public;
}
+18 -50
View File
@@ -1,10 +1,3 @@
/**
* @file diffie_hellman.h
*
* @brief Interface of diffie_hellman_t.
*
*/
/*
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,13 @@
* 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.
*
* $Id$
*/
/**
* @defgroup diffie_hellman diffie_hellman
* @{ @ingroup crypto
*/
#ifndef DIFFIE_HELLMAN_H_
@@ -30,13 +30,10 @@ typedef struct diffie_hellman_t diffie_hellman_t;
#include <library.h>
/**
* @brief Diffie-Hellman group.
* Diffie-Hellman group.
*
* The modulus (or group) to use for a Diffie-Hellman calculation.
*
* See IKEv2 RFC 3.3.2 and RFC 3526.
*
* @ingroup crypto
*/
enum diffie_hellman_group_t {
MODP_NONE = 0,
@@ -56,89 +53,60 @@ enum diffie_hellman_group_t {
extern enum_name_t *diffie_hellman_group_names;
/**
* @brief Implementation of the Diffie-Hellman algorithm, as in RFC2631.
*
* @b Constructors:
* - diffie_hellman_create()
*
* @ingroup crypto
* Implementation of the Diffie-Hellman algorithm, as in RFC2631.
*/
struct diffie_hellman_t {
/**
* @brief Returns the shared secret of this diffie hellman exchange.
* Returns the shared secret of this diffie hellman exchange.
*
* Space for returned secret is allocated and must be
* freed by the caller.
*
* @param this calling object
* @param secret shared secret will be written into this chunk
* @return
* - SUCCESS
* - FAILED if not both DH values are set
* @return SUCCESS, FAILED if not both DH values are set
*/
status_t (*get_shared_secret) (diffie_hellman_t *this, chunk_t *secret);
/**
* @brief Sets the public value of partner.
* Sets the public value of partner.
*
* Chunk gets cloned and can be destroyed afterwards.
*
* @param this calling object
* @param value public value of partner
*/
void (*set_other_public_value) (diffie_hellman_t *this, chunk_t value);
/**
* @brief Gets the public value of partner.
* Gets the public value of partner.
*
* Space for returned chunk is allocated and must be freed by the caller.
*
* @param this calling object
* @param value public value of partner is stored at this location
* @return
* - SUCCESS
* - FAILED if other public value not set
* @return SUCCESS, FAILED if other public value not set
*/
status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *value);
/**
* @brief Gets the own public value to transmit.
* Gets the own public value to transmit.
*
* Space for returned chunk is allocated and must be freed by the caller.
*
* @param this calling object
* @param value public value of caller is stored at this location
*/
void (*get_my_public_value) (diffie_hellman_t *this, chunk_t *value);
/**
* @brief Get the DH group used.
* Get the DH group used.
*
* @param this calling object
* @return DH group set in construction
*/
diffie_hellman_group_t (*get_dh_group) (diffie_hellman_t *this);
/**
* @brief Destroys an diffie_hellman_t object.
*
* @param this diffie_hellman_t object to destroy
* Destroys an diffie_hellman_t object.
*/
void (*destroy) (diffie_hellman_t *this);
};
/**
* @brief Creates a new diffie_hellman_t object.
*
* @param group Diffie Hellman group number to use
* @return
* - diffie_hellman_t object
* - NULL if dh group not supported
*
* @ingroup crypto
*/
diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t group);
#endif /*DIFFIE_HELLMAN_H_*/
#endif /*DIFFIE_HELLMAN_H_ @} */
+10 -55
View File
@@ -1,10 +1,3 @@
/**
* @file hasher.c
*
* @brief Generic constructor for hasher_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter
* Copyright (C) 2005-2006 Martin Willi
@@ -21,91 +14,53 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
#include "hasher.h"
#include <asn1/oid.h>
#include <crypto/hashers/sha1_hasher.h>
#include <crypto/hashers/sha2_hasher.h>
#include <crypto/hashers/md5_hasher.h>
ENUM(hash_algorithm_names, HASH_UNKNOWN, HASH_SHA512,
"HASH_UNKNOWN",
"HASH_PREFERRED",
"HASH_MD2",
"HASH_MD5",
"HASH_SHA1",
"HASH_SHA1_NOFINAL",
"HASH_SHA256",
"HASH_SHA384",
"HASH_SHA512"
);
/*
* Described in header.
*/
hasher_t *hasher_create(hash_algorithm_t hash_algorithm)
{
switch (hash_algorithm)
{
case HASH_SHA1:
{
return (hasher_t*)sha1_hasher_create();
}
case HASH_SHA256:
case HASH_SHA384:
case HASH_SHA512:
{
return (hasher_t*)sha2_hasher_create(hash_algorithm);
}
case HASH_MD5:
{
return (hasher_t*)md5_hasher_create();
}
default:
return NULL;
}
}
/*
* Described in header.
*/
hash_algorithm_t hasher_algorithm_from_oid(int oid)
{
hash_algorithm_t algorithm;
switch (oid)
{
case OID_MD2:
case OID_MD2_WITH_RSA:
algorithm = HASH_MD2;
break;
return HASH_MD2;
case OID_MD5:
case OID_MD5_WITH_RSA:
algorithm = HASH_MD5;
break;
return HASH_MD5;
case OID_SHA1:
case OID_SHA1_WITH_RSA:
algorithm = HASH_SHA1;
break;
return HASH_SHA1;
case OID_SHA256:
case OID_SHA256_WITH_RSA:
algorithm = HASH_SHA256;
break;
return HASH_SHA256;
case OID_SHA384:
case OID_SHA384_WITH_RSA:
algorithm = HASH_SHA384;
break;
return HASH_SHA384;
case OID_SHA512:
case OID_SHA512_WITH_RSA:
algorithm = HASH_SHA512;
break;
return HASH_SHA512;
default:
algorithm = HASH_UNKNOWN;
return HASH_UNKNOWN;
}
return algorithm;
}
/*
+40 -102
View File
@@ -1,10 +1,3 @@
/**
* @file hasher.h
*
* @brief Interface hasher_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter
* Copyright (C) 2005-2006 Martin Willi
@@ -21,7 +14,12 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
/**
* @defgroup traffic_selector traffic_selector
* @{ @ingroup config
*/
#ifndef HASHER_H_
@@ -33,30 +31,21 @@ typedef struct hasher_t hasher_t;
#include <library.h>
/**
* @brief Algorithms to use for hashing.
*
* Currently only the following algorithms are implemented:
* - HASH_MD5
* - HASH_SHA1
* - HASH_SHA256
* - HASH_SHA384
* - HASH_SHA512
*
* @ingroup hashers
* Algorithms to use for hashing.
*/
enum hash_algorithm_t {
HASH_UNKNOWN = 0,
HASH_MD2 = 1,
/** Implemented in class md5_hasher_t */
HASH_MD5 = 2,
/** Implemented in class sha1_hasher_t */
HASH_SHA1 = 3,
/** Implemented in class sha2_hasher_t */
HASH_SHA256 = 4,
/** Implemented in class sha2_hasher_t */
HASH_SHA384 = 5,
/** Implemented in class sha2_hasher_t */
HASH_SHA512 = 6,
/** not specified hash function */
HASH_UNKNOWN = 0,
/** preferred hash function, general purpose */
HASH_PREFERRED = 1,
HASH_MD2 = 2,
HASH_MD5 = 3,
HASH_SHA1 = 4,
/** special SHA1 which does not run SHA1Final, but copies the state */
HASH_SHA1_NOFINAL = 5,
HASH_SHA256 = 6,
HASH_SHA384 = 7,
HASH_SHA512 = 8,
};
#define HASH_SIZE_MD2 16
@@ -65,7 +54,6 @@ enum hash_algorithm_t {
#define HASH_SIZE_SHA256 32
#define HASH_SIZE_SHA384 48
#define HASH_SIZE_SHA512 64
#define HASH_SIZE_MAX 64
/**
* enum names for hash_algorithm_t.
@@ -73,16 +61,11 @@ enum hash_algorithm_t {
extern enum_name_t *hash_algorithm_names;
/**
* @brief Generic interface for all hash functions.
*
* @b Constructors:
* - hasher_create()
*
* @ingroup hashers
* Generic interface for all hash functions.
*/
struct hasher_t {
/**
* @brief Hash data and write it in the buffer.
* Hash data and write it in the buffer.
*
* If the parameter hash is NULL, no result is written back
* and more data can be appended to already hashed data.
@@ -91,108 +74,63 @@ struct hasher_t {
* The hash output parameter must hold at least
* hash_t.get_block_size() bytes.
*
* @param this calling object
* @param data data to hash
* @param[out] hash pointer where the hash will be written
* @param data data to hash
* @param hash pointer where the hash will be written
*/
void (*get_hash) (hasher_t *this, chunk_t data, u_int8_t *hash);
/**
* @brief Hash data and allocate space for the hash.
* Hash data and allocate space for the hash.
*
* If the parameter hash is NULL, no result is written back
* and more data can be appended to already hashed data.
* If not, the result is written back and the hasher is reset.
*
* @param this calling object
* @param data chunk with data to hash
* @param[out] hash chunk which will hold allocated hash
* @param data chunk with data to hash
* @param hash chunk which will hold allocated hash
*/
void (*allocate_hash) (hasher_t *this, chunk_t data, chunk_t *hash);
/**
* @brief Get the size of the resulting hash.
* Get the size of the resulting hash.
*
* @param this calling object
* @return hash size in bytes
* @return hash size in bytes
*/
size_t (*get_hash_size) (hasher_t *this);
/**
* @brief Resets the hashers state.
*
* @param this calling object
* Resets the hashers state.
*/
void (*reset) (hasher_t *this);
/**
* @brief Get the state of the hasher.
*
* A hasher stores internal state information. This state may be
* manipulated to include a "seed" into the hashing operation. It used by
* some exotic protocols (such as AKA).
* The data pointed by chunk may be manipulated, but not replaced nor freed.
* This is more a hack than a feature. The hasher's state may be byte
* order dependant; use with care.
*
* @param this calling object
*/
chunk_t (*get_state) (hasher_t *this);
/**
* @brief Destroys a hasher object.
*
* @param this calling object
* Destroys a hasher object.
*/
void (*destroy) (hasher_t *this);
};
/**
* @brief Generic interface to create a hasher_t.
* Conversion of ASN.1 OID to hash algorithm.
*
* @param hash_algorithm Algorithm to use for hashing
* @return
* - hasher_t object
* - NULL if algorithm not supported
*
* @ingroup hashers
*/
hasher_t *hasher_create(hash_algorithm_t hash_algorithm);
/**
* @brief Conversion of ASN.1 OID to hash algorithm.
*
* @param oid ASN.1 OID
* @return
* - hash algorithm
* - HASH_UNKNOWN if OID unsuported
*
* @ingroup hashers
* @param oid ASN.1 OID
* @return hash algorithm, HASH_UNKNOWN if OID unsuported
*/
hash_algorithm_t hasher_algorithm_from_oid(int oid);
/**
* @brief Conversion of hash algorithm into ASN.1 OID.
* Conversion of hash algorithm into ASN.1 OID.
*
* @param alg hash algorithm
* @return
* - ASN.1 hash OID if known hash algorithm
* - OID_UNKNOW
*
* @ingroup hashers
* @param alg hash algorithm
* @return ASN.1 OID, or OID_UNKNOW
*/
int hasher_algorithm_to_oid(hash_algorithm_t alg);
/**
* @brief Conversion of hash signature algorithm into ASN.1 OID.
* Conversion of hash signature algorithm into ASN.1 OID.
*
* @param alg hash algorithm
* @return
* - ASN.1 signature OID if known hash algorithm
* - OID_UNKNOW
*
* @ingroup hashers
* @param alg hash algorithm
* @return ASN.1 OID if, or OID_UNKNOW
*/
int hasher_signature_algorithm_to_oid(hash_algorithm_t alg);
#endif /* HASHER_H_ */
#endif /* HASHER_H_ @} */
-405
View File
@@ -1,405 +0,0 @@
/**
* @file ietf_attr.c
*
* @brief Implementation of ietfAttr_t.
*
*/
/*
* Copyright (C) 2007 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 <string.h>
#include <stdio.h>
#include <debug.h>
#include <asn1/asn1.h>
#include <utils/lexparser.h>
#include "ietf_attr_list.h"
/**
* Private definition of ietfAttribute kinds
*/
typedef enum {
IETF_ATTRIBUTE_OCTETS = 0,
IETF_ATTRIBUTE_OID = 1,
IETF_ATTRIBUTE_STRING = 2
} ietfAttribute_t;
typedef struct ietfAttr_t ietfAttr_t;
/**
* Private definition of an ietfAttribute
*/
struct ietfAttr_t {
/**
* IETF attribute kind
*/
ietfAttribute_t kind;
/**
* IETF attribute valuse
*/
chunk_t value;
/**
* Compares two ietfAttributes
*
* return -1 if this is earlier in the alphabet than other
* return 0 if this equals other
* return +1 if this is later in the alphabet than other
*
* @param this calling object
* @param other other object
*/
int (*compare) (const ietfAttr_t *this ,const ietfAttr_t *other);
/**
* Destroys the ietfAttr_t object.
*
* @param this ietfAttr_t to destroy
*/
void (*destroy) (ietfAttr_t *this);
};
/**
* Implements ietfAttr_t.compare.
*/
static int ietfAttr_compare(const ietfAttr_t *this ,const ietfAttr_t *other)
{
int cmp_len, len, cmp_value;
/* OID attributes are appended after STRING and OCTETS attributes */
if (this->kind != IETF_ATTRIBUTE_OID && other->kind == IETF_ATTRIBUTE_OID)
{
return -1;
}
if (this->kind == IETF_ATTRIBUTE_OID && other->kind != IETF_ATTRIBUTE_OID)
{
return 1;
}
cmp_len = this->value.len - other->value.len;
len = (cmp_len < 0)? this->value.len : other->value.len;
cmp_value = memcmp(this->value.ptr, other->value.ptr, len);
return (cmp_value == 0)? cmp_len : cmp_value;
}
/**
* Implements ietfAttr_t.destroy.
*/
static void ietfAttr_destroy(ietfAttr_t *this)
{
free(this->value.ptr);
free(this);
}
/**
* Creates an ietfAttr_t object.
*/
static ietfAttr_t *ietfAttr_create(ietfAttribute_t kind, chunk_t value)
{
ietfAttr_t *this = malloc_thing(ietfAttr_t);
/* initialize */
this->kind = kind;
this->value = chunk_clone(value);
/* function */
this->compare = ietfAttr_compare;
this->destroy = ietfAttr_destroy;
return this;
}
/**
* Adds an ietfAttr_t object to a sorted linked list
*/
static void ietfAttr_add(linked_list_t *list, ietfAttr_t *attr)
{
iterator_t *iterator = list->create_iterator(list, TRUE);
ietfAttr_t *current_attr;
bool found = FALSE;
while (iterator->iterate(iterator, (void **)&current_attr))
{
int cmp = attr->compare(attr, current_attr);
if (cmp > 0)
{
continue;
}
if (cmp == 0)
{
attr->destroy(attr);
}
else
{
iterator->insert_before(iterator, attr);
}
found = TRUE;
break;
}
iterator->destroy(iterator);
if (!found)
{
list->insert_last(list, attr);
}
}
/*
* Described in header.
*/
bool ietfAttr_list_equals(linked_list_t *list_a, linked_list_t *list_b)
{
bool result = TRUE;
/* lists must have the same number of attributes */
if (list_a->get_count(list_a) != list_b->get_count(list_b))
{
return FALSE;
}
/* empty lists - no attributes */
if (list_a->get_count(list_a) == 0)
{
return TRUE;
}
/* compare two alphabetically-sorted lists */
{
iterator_t *iterator_a = list_a->create_iterator(list_a, TRUE);
iterator_t *iterator_b = list_b->create_iterator(list_b, TRUE);
ietfAttr_t *attr_a, *attr_b;
while (iterator_a->iterate(iterator_a, (void **)&attr_a) &&
iterator_b->iterate(iterator_b, (void **)&attr_b))
{
if (attr_a->compare(attr_a, attr_b) != 0)
{
/* we have a mismatch */
result = FALSE;
break;
}
}
iterator_a->destroy(iterator_a);
iterator_b->destroy(iterator_b);
}
return result;
}
/*
* Described in header.
*/
void ietfAttr_list_list(linked_list_t *list, FILE *out)
{
iterator_t *iterator = list->create_iterator(list, TRUE);
ietfAttr_t *attr;
bool first = TRUE;
while (iterator->iterate(iterator, (void **)&attr))
{
if (first)
{
first = FALSE;
}
else
{
fprintf(out, ", ");
}
switch (attr->kind)
{
case IETF_ATTRIBUTE_OCTETS:
case IETF_ATTRIBUTE_STRING:
fprintf(out, "%.*s", (int)attr->value.len, attr->value.ptr);
break;
case IETF_ATTRIBUTE_OID:
{
int oid = known_oid(attr->value);
if (oid == OID_UNKNOWN)
{
fprintf(out, "0x#B", &attr->value);
}
else
{
fprintf(out, "%s", oid_names[oid]);
}
}
break;
default:
break;
}
}
iterator->destroy(iterator);
}
/*
* Described in header.
*/
void ietfAttr_list_create_from_string(char *msg, linked_list_t *list)
{
chunk_t line = { msg, strlen(msg) };
while (eat_whitespace(&line))
{
chunk_t group;
/* extract the next comma-separated group attribute */
if (!extract_token(&group, ',', &line))
{
group = line;
line.len = 0;
}
/* remove any trailing spaces */
while (group.len > 0 && *(group.ptr + group.len - 1) == ' ')
{
group.len--;
}
/* add the group attribute to the list */
if (group.len > 0)
{
ietfAttr_t *attr = ietfAttr_create(IETF_ATTRIBUTE_STRING, group);
ietfAttr_add(list, attr);
}
}
}
/**
* ASN.1 definition of ietfAttrSyntax
*/
static const asn1Object_t ietfAttrSyntaxObjects[] =
{
{ 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
{ 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
ASN1_BODY }, /* 1 */
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
{ 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */
{ 2, "octets", ASN1_OCTET_STRING, ASN1_OPT |
ASN1_BODY }, /* 4 */
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
{ 2, "oid", ASN1_OID, ASN1_OPT |
ASN1_BODY }, /* 6 */
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
{ 2, "string", ASN1_UTF8STRING, ASN1_OPT |
ASN1_BODY }, /* 8 */
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
{ 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */
};
#define IETF_ATTR_OCTETS 4
#define IETF_ATTR_OID 6
#define IETF_ATTR_STRING 8
#define IETF_ATTR_ROOF 11
/*
* Described in header.
*/
void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0)
{
asn1_ctx_t ctx;
chunk_t object;
u_int level;
int objectID = 0;
asn1_init(&ctx, chunk, level0, FALSE, FALSE);
while (objectID < IETF_ATTR_ROOF)
{
if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx))
{
return;
}
switch (objectID)
{
case IETF_ATTR_OCTETS:
case IETF_ATTR_OID:
case IETF_ATTR_STRING:
{
ietfAttribute_t kind = (objectID - IETF_ATTR_OCTETS) / 2;
ietfAttr_t *attr = ietfAttr_create(kind, object);
ietfAttr_add(list, attr);
}
break;
default:
break;
}
objectID++;
}
}
/*
* Described in header.
*/
chunk_t ietfAttr_list_encode(linked_list_t *list)
{
chunk_t ietfAttributes;
size_t size = 0;
u_char *pos;
iterator_t *iterator = list->create_iterator(list, TRUE);
ietfAttr_t *attr;
/* precalculate the total size of all values */
while (iterator->iterate(iterator, (void **)&attr))
{
size_t len = attr->value.len;
size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len;
}
iterator->destroy(iterator);
pos = build_asn1_object(&ietfAttributes, ASN1_SEQUENCE, size);
iterator = list->create_iterator(list, TRUE);
while (iterator->iterate(iterator, (void **)&attr))
{
chunk_t ietfAttribute;
asn1_t type = ASN1_NULL;
switch (attr->kind)
{
case IETF_ATTRIBUTE_OCTETS:
type = ASN1_OCTET_STRING;
break;
case IETF_ATTRIBUTE_STRING:
type = ASN1_UTF8STRING;
break;
case IETF_ATTRIBUTE_OID:
type = ASN1_OID;
break;
}
ietfAttribute = asn1_simple_object(type, attr->value);
/* copy ietfAttribute into ietfAttributes chunk */
memcpy(pos, ietfAttribute.ptr, ietfAttribute.len);
pos += ietfAttribute.len;
free(ietfAttribute.ptr);
}
iterator->destroy(iterator);
return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes);
}
/*
* Described in header.
*/
void ietfAttr_list_destroy(linked_list_t *list)
{
list->destroy_offset(list, offsetof(ietfAttr_t, destroy));
}
-89
View File
@@ -1,89 +0,0 @@
/**
* @file ietf_attr_list.h
*
* @brief Handling of ietfAttr_t linked lists
*
*/
/*
* Copyright (C) 2007 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.
*/
#ifndef IETF_ATTR_LIST_H_
#define IETF_ATTR_LIST_H_
#include <library.h>
#include <utils/linked_list.h>
/**
* @brief Compare two linked lists of ietfAttr_t objects for equality
*
* @param list_a first alphabetically-sorted list
* @param list_b second alphabetically-sorted list
* @return TRUE if equal
*
* @ingroup crypto
*/
bool ietfAttr_list_equals(linked_list_t *list_a, linked_list_t *list_b);
/**
* @brief Lists a linked list of ietfAttr_t objects
*
* @param list alphabetically-sorted linked list of attributes
@param out output file
*
* @ingroup crypto
*/
void ietfAttr_list_list(linked_list_t *list, FILE *out);
/**
* @brief Create a linked list of ietfAttr_t objects from a string
*
* @param msg string with comma-separated group names
* @param list alphabetically-sorted linked list of attributes
*
* @ingroup crypto
*/
void ietfAttr_list_create_from_string(char *msg, linked_list_t *list);
/**
* @brief Create a linked list of ietfAttr_t objects from an ASN.1-coded chunk
*
* @param chunk chunk containing ASN.1-coded attributes
* @param list alphabetically-sorted linked list of attributes
* @param level0 parsing level
*/
void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0);
/**
* @brief Encode a linked list of ietfAttr_t objects into an ASN.1-coded chunk
*
* @param list alphabetically-sorted linked list of attributes
* @return chunk containing ASN.1-coded attributes
*/
chunk_t ietfAttr_list_encode(linked_list_t *list);
/**
* @brief Destroys a linked list of ietfAttr_t objects
*
* @param list list to be destroyed
*
* @ingroup crypto
*/
void ietfAttr_list_destroy(linked_list_t *list);
#endif /* IETF_ATTR_LIST_H_ */
-934
View File
@@ -1,934 +0,0 @@
/**
* @file ocsp.c
*
* @brief Implementation of ocsp_t.
*
*/
/* Support of the Online Certificate Status Protocol (OCSP)
*
* Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
* Copyright (C) 2007 Andreas Steffen
*
* Hochschule für 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.
*
* RCSID $Id$
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <asn1/oid.h>
#include <asn1/asn1.h>
#include <utils/identification.h>
#include <utils/randomizer.h>
#include <utils/fetcher.h>
#include <debug.h>
#include "hashers/hasher.h"
#include "rsa/rsa_public_key.h"
#include "certinfo.h"
#include "x509.h"
#include "ocsp.h"
#define NONCE_LENGTH 16
typedef struct private_ocsp_t private_ocsp_t;
/**
* Private data of a ocsp_t object.
*/
struct private_ocsp_t {
/**
* Public interface for this ocsp object.
*/
ocsp_t public;
/**
* CA certificate.
*/
x509_t *cacert;
/**
* Requestor certificate
*/
x509_t *requestor_cert;
/**
* Linked list of ocsp uris
*/
linked_list_t *uris;
/**
* Linked list of certinfos to be requested
*/
linked_list_t *certinfos;
/**
* Nonce required for ocsp request and response
*/
chunk_t nonce;
/**
* SHA-1 hash over issuer distinguished name
*/
chunk_t authNameID;
/**
* SHA-1 hash over issuer public key
*/
chunk_t authKeyID;
};
ENUM(response_status_names, STATUS_SUCCESSFUL, STATUS_UNAUTHORIZED,
"successful",
"malformed request",
"internal error",
"try later",
"signature required",
"unauthorized"
);
/* response container */
typedef struct response_t response_t;
struct response_t {
chunk_t chunk;
chunk_t tbs;
identification_t *responder_id_name;
chunk_t responder_id_key;
time_t produced_at;
chunk_t responses;
chunk_t nonce;
int algorithm;
chunk_t signature;
x509_t *responder_cert;
/**
* @brief Destroys the response_t object
*
* @param this response_t to destroy
*/
void (*destroy) (response_t *this);
};
/**
* Implements response_t.destroy.
*/
static void response_destroy(response_t *this)
{
DESTROY_IF(this->responder_id_name);
DESTROY_IF(this->responder_cert);
free(this->chunk.ptr);
free(this);
}
/**
* Creates a response_t object
*/
static response_t* response_create_from_chunk(chunk_t chunk)
{
response_t *this = malloc_thing(response_t);
this->chunk = chunk;
this->tbs = chunk_empty;
this->responder_id_name = NULL;
this->responder_id_key = chunk_empty;
this->produced_at = UNDEFINED_TIME;
this->responses = chunk_empty;
this->nonce = chunk_empty;
this->algorithm = OID_UNKNOWN;
this->signature = chunk_empty;
this->responder_cert = NULL;
this->destroy = (void (*) (response_t*))response_destroy;
return this;
}
/* some OCSP specific prefabricated ASN.1 constants */
static u_char ASN1_nonce_oid_str[] = {
0x06, 0x09,
0x2B, 0x06,
0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
};
static u_char ASN1_response_oid_str[] = {
0x06, 0x09,
0x2B, 0x06,
0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
};
static u_char ASN1_response_content_str[] = {
0x04, 0x0D,
0x30, 0x0B,
0x06, 0x09,
0x2B, 0x06,
0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
};
static const chunk_t ASN1_nonce_oid = chunk_from_buf(ASN1_nonce_oid_str);
static const chunk_t ASN1_response_oid = chunk_from_buf(ASN1_response_oid_str);
static const chunk_t ASN1_response_content = chunk_from_buf(ASN1_response_content_str);
/* asn.1 definitions for parsing */
static const asn1Object_t ocspResponseObjects[] = {
{ 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
{ 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */
{ 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */
{ 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
{ 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */
{ 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */
{ 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */
};
#define OCSP_RESPONSE_STATUS 1
#define OCSP_RESPONSE_TYPE 4
#define OCSP_RESPONSE 5
#define OCSP_RESPONSE_ROOF 7
static const asn1Object_t basicResponseObjects[] = {
{ 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
{ 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
{ 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE |
ASN1_DEF }, /* 2 */
{ 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
{ 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */
{ 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
{ 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */
{ 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
{ 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */
{ 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
{ 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
{ 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */
{ 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */
{ 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */
{ 5, "critical", ASN1_BOOLEAN, ASN1_BODY |
ASN1_DEF }, /* 16 */
{ 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */
{ 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
{ 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */
{ 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */
{ 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */
{ 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */
{ 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */
{ 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
{ 1, "end opt", ASN1_EOC, ASN1_END } /* 26 */
};
#define BASIC_RESPONSE_TBS_DATA 1
#define BASIC_RESPONSE_VERSION 3
#define BASIC_RESPONSE_ID_BY_NAME 5
#define BASIC_RESPONSE_ID_BY_KEY 8
#define BASIC_RESPONSE_PRODUCED_AT 10
#define BASIC_RESPONSE_RESPONSES 11
#define BASIC_RESPONSE_EXT_ID 15
#define BASIC_RESPONSE_CRITICAL 16
#define BASIC_RESPONSE_EXT_VALUE 17
#define BASIC_RESPONSE_ALGORITHM 20
#define BASIC_RESPONSE_SIGNATURE 21
#define BASIC_RESPONSE_CERTIFICATE 24
#define BASIC_RESPONSE_ROOF 27
static const asn1Object_t responsesObjects[] = {
{ 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
{ 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */
{ 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */
};
#define RESPONSES_SINGLE_RESPONSE 1
#define RESPONSES_ROOF 3
static const asn1Object_t singleResponseObjects[] = {
{ 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */
{ 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
{ 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */
{ 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */
{ 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */
{ 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */
{ 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
{ 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */
{ 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */
{ 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */
{ 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
{ 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
{ 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */
{ 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */
{ 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
{ 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */
{ 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */
{ 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
{ 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */
{ 4, "critical", ASN1_BOOLEAN, ASN1_BODY |
ASN1_DEF }, /* 24 */
{ 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */
{ 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */
{ 1, "end opt", ASN1_EOC, ASN1_END } /* 27 */
};
#define SINGLE_RESPONSE_ALGORITHM 2
#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
#define SINGLE_RESPONSE_SERIAL_NUMBER 5
#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
#define SINGLE_RESPONSE_THIS_UPDATE 16
#define SINGLE_RESPONSE_NEXT_UPDATE 18
#define SINGLE_RESPONSE_EXT_ID 23
#define SINGLE_RESPONSE_CRITICAL 24
#define SINGLE_RESPONSE_EXT_VALUE 25
#define SINGLE_RESPONSE_ROOF 28
/**
* build requestorName (into TBSRequest)
*/
static chunk_t build_requestor_name(private_ocsp_t *this)
{
identification_t *requestor_name = this->requestor_cert->get_subject(this->requestor_cert);
return asn1_wrap(ASN1_CONTEXT_C_1, "m",
asn1_simple_object(ASN1_CONTEXT_C_4,
requestor_name->get_encoding(requestor_name)));
}
/**
* build request (into requestList)
* no singleRequestExtensions used
*/
static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo)
{
chunk_t serialNumber = certinfo->get_serialNumber(certinfo);
chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm",
asn1_algorithmIdentifier(OID_SHA1),
asn1_simple_object(ASN1_OCTET_STRING, this->authNameID),
asn1_simple_object(ASN1_OCTET_STRING, this->authKeyID),
asn1_simple_object(ASN1_INTEGER, serialNumber));
return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
}
/**
* build requestList (into TBSRequest)
*/
static chunk_t build_request_list(private_ocsp_t *this)
{
chunk_t requestList;
size_t datalen = 0;
linked_list_t *request_list = linked_list_create();
{
iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
certinfo_t *certinfo;
while (iterator->iterate(iterator, (void**)&certinfo))
{
chunk_t *request = malloc_thing(chunk_t);
*request = build_request(this, certinfo);
request_list->insert_last(request_list, (void*)request);
datalen += request->len;
}
iterator->destroy(iterator);
}
{
iterator_t *iterator = request_list->create_iterator(request_list, TRUE);
chunk_t *request;
u_char *pos = build_asn1_object(&requestList, ASN1_SEQUENCE, datalen);
while (iterator->iterate(iterator, (void**)&request))
{
memcpy(pos, request->ptr, request->len);
pos += request->len;
free(request->ptr);
free(request);
}
iterator->destroy(iterator);
request_list->destroy(request_list);
}
return requestList;
}
/**
* build nonce extension (into requestExtensions)
*/
static chunk_t build_nonce_extension(private_ocsp_t *this)
{
randomizer_t *randomizer = randomizer_create();
/* generate a random nonce */
randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LENGTH, &this->nonce);
randomizer->destroy(randomizer);
return asn1_wrap(ASN1_SEQUENCE, "cm",
ASN1_nonce_oid,
asn1_simple_object(ASN1_OCTET_STRING, this->nonce));
}
/**
* build requestExtensions (into TBSRequest)
*/
static chunk_t build_request_ext(private_ocsp_t *this)
{
return asn1_wrap(ASN1_CONTEXT_C_2, "m",
asn1_wrap(ASN1_SEQUENCE, "mm",
build_nonce_extension(this),
asn1_wrap(ASN1_SEQUENCE, "cc",
ASN1_response_oid,
ASN1_response_content
)
)
);
}
/**
* build TBSRequest (into OCSPRequest)
*/
static chunk_t build_tbs_request(private_ocsp_t *this, bool has_requestor_cert)
{
/* version is skipped since the default is ok */
return asn1_wrap(ASN1_SEQUENCE, "mmm",
(has_requestor_cert)? build_requestor_name(this): chunk_empty,
build_request_list(this),
build_request_ext(this));
}
/**
* build signature into ocsp request
* gets built only if a request cert with a corresponding private key is found
*/
static chunk_t build_signature(private_ocsp_t *this, chunk_t tbsRequest)
{
/* TODO */
return chunk_empty;
}
/**
* assembles an ocsp request and sets the nonce field in private_ocsp_t to the sent nonce
*/
static chunk_t ocsp_build_request(private_ocsp_t *this)
{
bool has_requestor_cert;
chunk_t keyid = this->cacert->get_keyid(this->cacert);
chunk_t tbsRequest, signature;
DBG2("assembling ocsp request");
DBG2("issuer: '%D'", this->cacert->get_subject(this->cacert));
DBG2("keyid: %#B", &keyid);
/* looks for requestor cert and matching private key */
has_requestor_cert = FALSE;
/* TODO has_requestor_cert = get_ocsp_requestor_cert(location); */
/* build content */
tbsRequest = build_tbs_request(this, has_requestor_cert);
/* sign tbsReuqest */
signature = (has_requestor_cert)? build_signature(this, tbsRequest): chunk_empty;
return asn1_wrap(ASN1_SEQUENCE, "mm",
tbsRequest,
signature);
return signature;
}
/**
* parse a basic OCSP response
*/
static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res)
{
u_int level, version;
asn1_ctx_t ctx;
bool critical;
chunk_t object;
int objectID = 0;
int extn_oid = OID_UNKNOWN;
asn1_init(&ctx, blob, level0, FALSE, FALSE);
while (objectID < BASIC_RESPONSE_ROOF)
{
if (!extract_object(basicResponseObjects, &objectID, &object, &level, &ctx))
{
return FALSE;
}
switch (objectID)
{
case BASIC_RESPONSE_TBS_DATA:
res->tbs = object;
break;
case BASIC_RESPONSE_VERSION:
version = (object.len)? (1 + (u_int)*object.ptr) : 1;
if (version != OCSP_BASIC_RESPONSE_VERSION)
{
DBG1("wrong ocsp basic response version (version= %i)", version);
return FALSE;
}
break;
case BASIC_RESPONSE_ID_BY_NAME:
res->responder_id_name = identification_create_from_encoding(ID_DER_ASN1_DN, object);
DBG2(" '%D'", res->responder_id_name);
break;
case BASIC_RESPONSE_ID_BY_KEY:
res->responder_id_key = object;
break;
case BASIC_RESPONSE_PRODUCED_AT:
res->produced_at = asn1totime(&object, ASN1_GENERALIZEDTIME);
break;
case BASIC_RESPONSE_RESPONSES:
res->responses = object;
break;
case BASIC_RESPONSE_EXT_ID:
extn_oid = known_oid(object);
break;
case BASIC_RESPONSE_CRITICAL:
critical = object.len && *object.ptr;
DBG2(" %s", critical? "TRUE" : "FALSE");
break;
case BASIC_RESPONSE_EXT_VALUE:
if (extn_oid == OID_NONCE)
res->nonce = object;
break;
case BASIC_RESPONSE_ALGORITHM:
res->algorithm = parse_algorithmIdentifier(object, level+1, NULL);
break;
case BASIC_RESPONSE_SIGNATURE:
res->signature = object;
break;
case BASIC_RESPONSE_CERTIFICATE:
{
chunk_t blob = chunk_clone(object);
res->responder_cert = x509_create_from_chunk(blob, level+1);
}
break;
}
objectID++;
}
return TRUE;
}
/**
* parse an ocsp response and return the result as a response_t struct
*/
static response_status ocsp_parse_response(response_t *res)
{
asn1_ctx_t ctx;
chunk_t object;
u_int level;
int objectID = 0;
int ocspResponseType = OID_UNKNOWN;
response_status rStatus = STATUS_INTERNALERROR;
asn1_init(&ctx, res->chunk, 0, FALSE, FALSE);
while (objectID < OCSP_RESPONSE_ROOF)
{
if (!extract_object(ocspResponseObjects, &objectID, &object, &level, &ctx))
{
return STATUS_INTERNALERROR;
}
switch (objectID)
{
case OCSP_RESPONSE_STATUS:
rStatus = (response_status) *object.ptr;
DBG2(" '%N'", response_status_names, rStatus);
switch (rStatus)
{
case STATUS_SUCCESSFUL:
break;
case STATUS_MALFORMEDREQUEST:
case STATUS_INTERNALERROR:
case STATUS_TRYLATER:
case STATUS_SIGREQUIRED:
case STATUS_UNAUTHORIZED:
DBG1("unsuccessful ocsp response: server said '%N'",
response_status_names, rStatus);
return rStatus;
default:
return STATUS_INTERNALERROR;
}
break;
case OCSP_RESPONSE_TYPE:
ocspResponseType = known_oid(object);
break;
case OCSP_RESPONSE:
{
switch (ocspResponseType)
{
case OID_BASIC:
if (!ocsp_parse_basic_response(object, level+1, res))
{
return STATUS_INTERNALERROR;
}
break;
default:
DBG1("ocsp response is not of type BASIC");
DBG1("ocsp response OID: %#B", &object);
return STATUS_INTERNALERROR;
}
}
break;
}
objectID++;
}
return rStatus;
}
/**
* Check if the OCSP response has a valid signature
*/
static bool ocsp_valid_response(response_t *res, x509_t *ocsp_cert)
{
rsa_public_key_t *public_key;
time_t until = UNDEFINED_TIME;
err_t ugh;
hash_algorithm_t algorithm = hasher_algorithm_from_oid(res->algorithm);
if (algorithm == HASH_UNKNOWN)
{
DBG1("unknown signature algorithm");
return FALSE;
}
DBG2("verifying ocsp response signature:");
DBG2("signer: '%D'", ocsp_cert->get_subject(ocsp_cert));
DBG2("issuer: '%D'", ocsp_cert->get_issuer(ocsp_cert));
ugh = ocsp_cert->is_valid(ocsp_cert, &until);
if (ugh != NULL)
{
DBG1("ocsp signer certificate %s", ugh);
return FALSE;
}
public_key = ocsp_cert->get_public_key(ocsp_cert);
return public_key->verify_emsa_pkcs1_signature(public_key, algorithm, res->tbs, res->signature) == SUCCESS;
}
/**
* parse a single OCSP response
*/
static bool ocsp_parse_single_response(private_ocsp_t *this, chunk_t blob, int level0)
{
u_int level, extn_oid;
asn1_ctx_t ctx;
bool critical;
chunk_t object;
int objectID = 0;
certinfo_t *certinfo = NULL;
asn1_init(&ctx, blob, level0, FALSE, FALSE);
while (objectID < SINGLE_RESPONSE_ROOF)
{
if (!extract_object(singleResponseObjects, &objectID, &object, &level, &ctx))
{
return FALSE;
}
switch (objectID)
{
case SINGLE_RESPONSE_ALGORITHM:
if (parse_algorithmIdentifier(object, level+1, NULL) != OID_SHA1)
{
DBG1("only sha-1 hash supported in ocsp single response");
return FALSE;
}
break;
case SINGLE_RESPONSE_ISSUER_NAME_HASH:
if (!chunk_equals(object, this->authNameID))
{
DBG1("ocsp single response has wrong issuer name hash");
return FALSE;
}
break;
case SINGLE_RESPONSE_ISSUER_KEY_HASH:
if (!chunk_equals(object, this->authKeyID))
{
DBG1("ocsp single response has wrong issuer key hash");
return FALSE;
}
break;
case SINGLE_RESPONSE_SERIAL_NUMBER:
{
iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
certinfo_t *current_certinfo;
while (iterator->iterate(iterator, (void**)&current_certinfo))
{
if (chunk_equals(object, current_certinfo->get_serialNumber(current_certinfo)))
{
certinfo = current_certinfo;
}
}
iterator->destroy(iterator);
if (certinfo == NULL)
{
DBG1("unrequested serial number in ocsp single response");
return FALSE;
}
}
break;
case SINGLE_RESPONSE_CERT_STATUS_GOOD:
certinfo->set_status(certinfo, CERT_GOOD);
break;
case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
certinfo->set_status(certinfo, CERT_REVOKED);
break;
case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
certinfo->set_revocationTime(certinfo,
asn1totime(&object, ASN1_GENERALIZEDTIME));
break;
case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
certinfo->set_revocationReason(certinfo,
(object.len == 1) ? *object.ptr : REASON_UNSPECIFIED);
break;
case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
certinfo->set_status(certinfo, CERT_UNKNOWN);
break;
case SINGLE_RESPONSE_THIS_UPDATE:
certinfo->set_thisUpdate(certinfo,
asn1totime(&object, ASN1_GENERALIZEDTIME));
break;
case SINGLE_RESPONSE_NEXT_UPDATE:
certinfo->set_nextUpdate(certinfo,
asn1totime(&object, ASN1_GENERALIZEDTIME));
break;
case SINGLE_RESPONSE_EXT_ID:
extn_oid = known_oid(object);
break;
case SINGLE_RESPONSE_CRITICAL:
critical = object.len && *object.ptr;
DBG2(" %s", critical ? "TRUE" : "FALSE");
case SINGLE_RESPONSE_EXT_VALUE:
break;
}
objectID++;
}
return TRUE;
}
/**
* verify and process ocsp response and update the ocsp cache
*/
static void ocsp_process_response(private_ocsp_t *this, response_t *res, credential_store_t *credentials)
{
x509_t *ocsp_cert = NULL;
/* parse the ocsp response without looking at the single responses yet */
response_status status = ocsp_parse_response(res);
if (status != STATUS_SUCCESSFUL)
{
DBG1("error in ocsp response");
return;
}
/* check if there was a nonce in the request */
if (this->nonce.ptr != NULL && res->nonce.ptr == NULL)
{
DBG1("ocsp response contains no nonce, replay attack possible");
}
/* check if the nonces are identical */
if (res->nonce.ptr != NULL && !chunk_equals(res->nonce, this->nonce))
{
DBG1("invalid nonce in ocsp response");
return;
}
/* check if we received a trusted responder certificate */
if (res->responder_cert)
{
if (res->responder_cert->is_ocsp_signer(res->responder_cert))
{
DBG2("received certificate is ocsp signer");
if (credentials->is_trusted(credentials, "OCSP signing", res->responder_cert))
{
DBG1("received ocsp signer certificate is trusted");
ocsp_cert = credentials->add_auth_certificate(credentials,
res->responder_cert, AUTH_OCSP);
res->responder_cert = NULL;
}
else
{
DBG1("received ocsp signer certificate is not trusted - rejected");
}
}
else
{
DBG1("received certificate is no ocsp signer - rejected");
}
}
/* if we didn't receive a trusted responder cert, search the credential store */
if (ocsp_cert == NULL)
{
ocsp_cert = credentials->get_auth_certificate(credentials,
AUTH_OCSP|AUTH_CA, res->responder_id_name);
if (ocsp_cert == NULL)
{
DBG1("no ocsp signer certificate found");
return;
}
}
/* check the response signature */
if (!ocsp_valid_response(res, ocsp_cert))
{
DBG1("ocsp response signature is invalid");
return;
}
DBG2("ocsp response signature is valid");
/* now parse the single responses one at a time */
{
u_int level;
asn1_ctx_t ctx;
chunk_t object;
int objectID = 0;
asn1_init(&ctx, res->responses, 0, FALSE, FALSE);
while (objectID < RESPONSES_ROOF)
{
if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx))
{
return;
}
if (objectID == RESPONSES_SINGLE_RESPONSE)
{
ocsp_parse_single_response(this, object, level+1);
}
objectID++;
}
}
}
/**
* Implements ocsp_t.fetch.
*/
static void fetch(private_ocsp_t *this, certinfo_t *certinfo, credential_store_t *credentials)
{
chunk_t request;
response_t *response = NULL;
if (this->uris->get_count(this->uris) == 0)
{
return;
}
this->certinfos->insert_last(this->certinfos, (void*)certinfo);
request = ocsp_build_request(this);
DBG3("ocsp request: %B", &request);
{
iterator_t *iterator = this->uris->create_iterator(this->uris, TRUE);
identification_t *uri;
while (iterator->iterate(iterator, (void**)&uri))
{
fetcher_t *fetcher;
char uri_string[BUF_LEN];
chunk_t uri_chunk = uri->get_encoding(uri);
chunk_t response_chunk;
snprintf(uri_string, BUF_LEN, "%.*s", uri_chunk.len, uri_chunk.ptr);
fetcher = fetcher_create(uri_string);
response_chunk = fetcher->post(fetcher, "application/ocsp-request", request);
fetcher->destroy(fetcher);
if (response_chunk.ptr != NULL)
{
response = response_create_from_chunk(response_chunk);
break;
}
}
iterator->destroy(iterator);
}
free(request.ptr);
if (response == NULL)
{
return;
}
DBG3("ocsp response: %B", &response->chunk);
ocsp_process_response(this, response, credentials);
response->destroy(response);
}
/**
* Implements ocsp_t.destroy.
*/
static void destroy(private_ocsp_t *this)
{
this->certinfos->destroy(this->certinfos);
free(this->authNameID.ptr);
free(this->nonce.ptr);
free(this);
}
/*
* Described in header.
*/
ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris)
{
private_ocsp_t *this = malloc_thing(private_ocsp_t);
/* initialize */
this->cacert = cacert;
this->uris = uris;
this->certinfos = linked_list_create();
this->nonce = chunk_empty;
this->authKeyID = cacert->get_subjectKeyID(cacert);
{
hasher_t *hasher = hasher_create(HASH_SHA1);
identification_t *issuer = cacert->get_subject(cacert);
hasher->allocate_hash(hasher, issuer->get_encoding(issuer),
&this->authNameID);
hasher->destroy(hasher);
}
/* public functions */
this->public.fetch = (void (*) (ocsp_t*,certinfo_t*,credential_store_t*))fetch;
this->public.destroy = (void (*) (ocsp_t*))destroy;
return &this->public;
}
+12 -22
View File
@@ -1,12 +1,4 @@
/**
* @file ocsp.h
*
* @brief Interface of ocsp_t
*
*/
/* Support of the Online Certificate Status Protocol (OCSP) Support
*
/*
* Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
* Copyright (C) 2007 Andreas Steffen
*
@@ -22,7 +14,12 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
/**
* @defgroup ocsp ocsp
* @{ @ingroup crypto
*/
#ifndef OCSP_H_
@@ -51,39 +48,32 @@ typedef enum {
} response_status;
/**
* @brief Online Certficate Status Protocol (OCSP)
*
* @ingroup transforms
* Online Certficate Status Protocol (OCSP)
*/
struct ocsp_t {
/**
* @brief Fetches the actual certificate status via OCSP
* Fetches the actual certificate status via OCSP
*
* @param uris linked list of ocsp uris
* @param certinfo certificate status info to be updated
* @param credentials credential store needed for trust path verification
*/
void (*fetch) (ocsp_t *this, certinfo_t *certinfo, credential_store_t *credentials);
/**
* @brief Destroys the ocsp_t object.
*
* @param this ocsp object to destroy
* Destroys the ocsp_t object.
*/
void (*destroy) (ocsp_t *this);
};
/**
* @brief Create an ocsp_t object.
* Create an ocsp_t object.
*
* @param cacert ca certificate
* @param uris linked list of ocsp uris
* @return created ocsp_t object
*
* @ingroup transforms
*/
ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris);
#endif /* OCSP_H_ */
#endif /* OCSP_H_ @} */
+22 -12
View File
@@ -1,10 +1,3 @@
/**
* @file pkcs7.c
*
* @brief Implementation of pkcs7_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Copyright (C) 2002-2008 Andreas Steffen
@@ -21,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
#include <stdlib.h>
@@ -459,10 +452,18 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
}
else
{
hasher_t *hasher = hasher_create(algorithm);
hasher_t *hasher;
chunk_t hash;
bool valid;
hasher = lib->crypto->create_hasher(lib->crypto, algorithm)
if (hasher == NULL)
{
DBG1("hash algorithm %N not supported",
hash_algorithm_names, algorithm);
free(messageDigest.ptr);
return FALSE;
}
hasher->allocate_hash(hasher, this->data, &hash);
hasher->destroy(hasher);
DBG3("hash: %B", &hash);
@@ -873,15 +874,24 @@ bool build_signedData(private_pkcs7_t *this, rsa_private_key_t *private_key,
if (this->attributes != NULL)
{
if (this->data.ptr != NULL)
if(this->data.ptr != NULL)
{
hasher_t *hasher;
hasher = lib->crypto->create_hasher(lib->crypto, alg);
if (hasher == NULL)
{
DBG1(" hash algorithm %N not support",
hash_algorithm_names, alg);
return FALSE;
}
/* take the current time as signingTime */
time_t now = time(NULL);
chunk_t signingTime = timetoasn1(&now, ASN1_UTCTIME);
chunk_t messageDigest, attributes;
hasher_t *hasher = hasher_create(alg);
hasher->allocate_hash(hasher, this->data, &messageDigest);
hasher->destroy(hasher);
this->attributes->set_attribute(this->attributes,
+32 -61
View File
@@ -1,10 +1,3 @@
/**
* @file pkcs7.h
*
* @brief Interface of pkcs7_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Copyright (C) 2002-2008 Andreas Steffen
@@ -21,11 +14,16 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
/**
* @defgroup pkcs7 pkcs7
* @{ @ingroup crypto
*/
#ifndef _PKCS7_H
#define _PKCS7_H
#ifndef _PKCS7_H_
#define _PKCS7_H_
typedef struct pkcs7_t pkcs7_t;
@@ -37,60 +35,48 @@ typedef struct pkcs7_t pkcs7_t;
#include <utils/iterator.h>
/**
* @brief PKCS#7 contentInfo object.
*
* @b Constructors:
* -pkcs7_create_from_chunk()
* -pkcs7_create_from_data()
*
* @ingroup crypto
* PKCS#7 contentInfo object.
*/
struct pkcs7_t {
/**
* @brief Check if the PKCS#7 contentType is data
* Check if the PKCS#7 contentType is data
*
* @param this calling object
* @return TRUE if the contentType is data
*/
bool (*is_data) (pkcs7_t *this);
/**
* @brief Check if the PKCS#7 contentType is signedData
* Check if the PKCS#7 contentType is signedData
*
* @param this calling object
* @return TRUE if the contentType is signedData
*/
bool (*is_signedData) (pkcs7_t *this);
/**
* @brief Check if the PKCS#7 contentType is envelopedData
* Check if the PKCS#7 contentType is envelopedData
*
* @param this calling object
* @return TRUE if the contentType is envelopedData
*/
bool (*is_envelopedData) (pkcs7_t *this);
/**
* @brief Parse a PKCS#7 data content.
* Parse a PKCS#7 data content.
*
* @param this calling object
* @return TRUE if parsing was successful
*/
bool (*parse_data) (pkcs7_t *this);
/**
* @brief Parse a PKCS#7 signedData content.
* Parse a PKCS#7 signedData content.
*
* @param this calling object
* @param cacert cacert used to verify the signature
* @return TRUE if parsing was successful
*/
bool (*parse_signedData) (pkcs7_t *this, x509_t *cacert);
/**
* @brief Parse a PKCS#7 envelopedData content.
* Parse a PKCS#7 envelopedData content.
*
* @param this calling object
* @param serialNumber serialNumber of the request
* @param key RSA private key used to decrypt the symmetric key
* @return TRUE if parsing was successful
@@ -98,112 +84,97 @@ struct pkcs7_t {
bool (*parse_envelopedData) (pkcs7_t *this, chunk_t serialNumber, rsa_private_key_t *key);
/**
* @brief Returns the parsed data object
* Returns the parsed data object
*
* @param this calling object
* @return chunk containing the data object
*/
chunk_t (*get_data) (pkcs7_t *this);
/**
* @brief Returns the a DER-encoded contentInfo object
* Returns the a DER-encoded contentInfo object
*
* @param this calling object
* @return chunk containing the contentInfo object
*/
chunk_t (*get_contentInfo) (pkcs7_t *this);
/**
* @brief Create an iterator for the certificates.
* Create an iterator for the certificates.
*
* @param this calling object
* @return iterator for the certificates
*/
iterator_t *(*create_certificate_iterator) (pkcs7_t *this);
/**
* @brief Add a certificate.
* Add a certificate.
*
* @param this calling object
* @param cert certificate to be included
*/
void (*set_certificate) (pkcs7_t *this, x509_t *cert);
/**
* @brief Add authenticated attributes.
* Add authenticated attributes.
*
* @param this calling object
* @param attributes attributes to be included
*/
void (*set_attributes) (pkcs7_t *this, pkcs9_t *attributes);
/**
* @brief Build a data object
* Build a data object
*
* @param this PKCS#7 data to be built
* @return TRUE if build was successful
*/
bool (*build_data) (pkcs7_t *this);
/**
* @brief Build an envelopedData object
* Build an envelopedData object
*
* @param this PKCS#7 data object to envelop
* @param cert receivers's certificate
* @param alg encryption algorithm
* @return TRUE if build was successful
*/
bool (*build_envelopedData) (pkcs7_t *this, x509_t *cert, encryption_algorithm_t alg);
bool (*build_envelopedData) (pkcs7_t *this, x509_t *cert,
encryption_algorithm_t alg);
/**
* @brief Build an signedData object
* Build an signedData object
*
* @param this PKCS#7 data object to sign
* @param key signer's RSA private key
* @param alg digest algorithm used for signature
* @return TRUE if build was successful
*/
bool (*build_signedData) (pkcs7_t *this, rsa_private_key_t *key, hash_algorithm_t alg);
bool (*build_signedData) (pkcs7_t *this, rsa_private_key_t *key,
hash_algorithm_t alg);
/**
* @brief Destroys the contentInfo object.
*
* @param this PKCS#7 contentInfo object to destroy
* Destroys the contentInfo object.
*/
void (*destroy) (pkcs7_t *this);
};
/**
* @brief Read a PKCS#7 contentInfo object from a DER encoded chunk.
* Read a PKCS#7 contentInfo object from a DER encoded chunk.
*
* @param chunk chunk containing DER encoded data
* @param level ASN.1 parsing start level
* @return created pkcs7_contentInfo object, or NULL if invalid.
*
* @ingroup crypto
*/
pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level);
/**
* @brief Create a PKCS#7 contentInfo object
* Create a PKCS#7 contentInfo object
*
* @param chunk chunk containing data
* @return created pkcs7_contentInfo object.
*
* @ingroup crypto
*/
pkcs7_t *pkcs7_create_from_data(chunk_t data);
/**
* @brief Read a X.509 certificate from a DER encoded file.
* Read a X.509 certificate from a DER encoded file.
*
* @param filename file containing DER encoded data
* @param label label describing kind of PKCS#7 file
* @return created pkcs7_t object, or NULL if invalid.
*
* @ingroup crypto
*/
pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label);
#endif /* _PKCS7_H */
#endif /* _PKCS7_H_ @} */
+1 -9
View File
@@ -1,13 +1,5 @@
/**
* @file pkcs9.c
*
* @brief Implementation of pkcs9_t.
*
*/
/*
* Copyright (C)2008 Andreas Steffen
*
* Hochschule fuer Technik Rapperswil, Switzerland
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id: pkcs7.c 3423 2008-01-22 10:32:37Z andreas $
* $Id$
*/
#include <library.h>
+21 -42
View File
@@ -1,13 +1,5 @@
/**
* @file pkcs7.h
*
* @brief Interface of pkcs9_t.
*
*/
/*
* Copyright (C) 2008 Andreas Steffen
*
* Copyright (C) 2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,102 +12,89 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id: pkcs7.h 3423 2008-01-22 10:32:37Z andreas $
* $Id$
*/
/**
* @defgroup pkcs9 pkcs9
* @{ @ingroup crypto
*/
#ifndef _PKCS9_H
#define _PKCS9_H
#ifndef PKCS9_H_
#define PKCS9_H_
typedef struct pkcs9_t pkcs9_t;
#include <library.h>
/**
* @brief PKCS#9 .
*
* @b Constructors:
* -pkcs9_create_from_chunk()
* -pkcs9_create()
*
* @ingroup crypto
* PKCS#9 attributes.
*/
struct pkcs9_t {
/**
* @brief generate ASN.1 encoding of attribute list
*
* @param this PKCS#9 attribute list to be encoded
* Generate ASN.1 encoding of attribute list
*/
void (*build_encoding) (pkcs9_t *this);
/**
* @brief gets ASN.1 encoding of PKCS#9 attribute list
* Gets ASN.1 encoding of PKCS#9 attribute list
*
* @param this calling object
* @return ASN.1 encoded PKCSI#9 list
*/
chunk_t (*get_encoding) (pkcs9_t *this);
/**
* @brief gets a PKCS#9 attribute
* Gets a PKCS#9 attribute
*
* @param this calling object
* @param oid OID of the attribute
* @return ASN.1 encoded value of the attribute
*/
chunk_t (*get_attribute) (pkcs9_t *this, int oid);
/**
* @brief adds a PKCS#9 attribute
* Adds a PKCS#9 attribute
*
* @param this calling object
* @param oid OID of the attribute
* @param value ASN.1 encoded value of the attribute
*/
void (*set_attribute) (pkcs9_t *this, int oid, chunk_t value);
/**
* @brief gets a PKCS#9 messageDigest attribute
* Gets a PKCS#9 messageDigest attribute
*
* @param this calling object
* @return messageDigest
*/
chunk_t (*get_messageDigest) (pkcs9_t *this);
/**
* @brief add a PKCS#9 messageDigest attribute
* Add a PKCS#9 messageDigest attribute
*
* @param this calling object
* @param value messageDigest
*/
void (*set_messageDigest) (pkcs9_t *this, chunk_t value);
/**
* @brief Destroys the PKCS#9 attribute list.
*
* @param this PKCS#9 attribute list to destroy
* Destroys the PKCS#9 attribute list.
*/
void (*destroy) (pkcs9_t *this);
};
/**
* @brief Read a PKCS#9 attribute list from a DER encoded chunk.
* Read a PKCS#9 attribute list from a DER encoded chunk.
*
* @param chunk chunk containing DER encoded data
* @param level ASN.1 parsing start level
* @return created pkcs9 attribute list, or NULL if invalid.
*
* @ingroup crypto
*/
pkcs9_t *pkcs9_create_from_chunk(chunk_t chunk, u_int level);
/**
* @brief Create an empty PKCS#9 attribute list
* Create an empty PKCS#9 attribute list
*
* @param chunk chunk containing data
* @return created pkcs9 attribute list.
*
* @ingroup crypto
*/
pkcs9_t *pkcs9_create(void);
#endif /* _PKCS9_H */
#endif /* PKCS9_H_ @} */
+2 -7
View File
@@ -1,10 +1,3 @@
/**
* @file prf_plus.c
*
* @brief Implementation of prf_plus_t.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,8 @@
* 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.
*
* $Id$
*/
#include <string.h>
+17 -29
View File
@@ -1,10 +1,3 @@
/**
* @file prf_plus.h
*
* @brief Interface for prf_plus.h.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,13 @@
* 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.
*
* $Id$
*/
/**
* @defgroup prf_plus prf_plus
* @{ @ingroup crypto
*/
#ifndef PRF_PLUS_H_
@@ -29,53 +29,43 @@ typedef struct prf_plus_t prf_plus_t;
#include <crypto/prfs/prf.h>
/**
* @brief Implementation of the prf+ function described in IKEv2 RFC.
* Implementation of the prf+ function described in IKEv2 RFC.
*
* This class implements the prf+ algorithm. Internally it uses a pseudo random
* function, which implements the prf_t interface.
*
* See IKEv2 RFC 2.13.
*
* @b Constructors:
* - prf_plus_create()
*
* @ingroup transforms
*/
struct prf_plus_t {
/**
* @brief Get pseudo random bytes.
* Get pseudo random bytes.
*
* Get the next few bytes of the prf+ output. Space
* must be allocated by the caller.
*
* @param this calling object
* @param length number of bytes to get
* @param[out] buffer pointer where the generated bytes will be written
* @param length number of bytes to get
* @param buffer pointer where the generated bytes will be written
*/
void (*get_bytes) (prf_plus_t *this, size_t length, u_int8_t *buffer);
/**
* @brief Allocate pseudo random bytes.
* Allocate pseudo random bytes.
*
* Get the next few bytes of the prf+ output. This function
* will allocate the required space.
*
* @param this calling object
* @param length number of bytes to get
* @param[out] chunk chunk which will hold generated bytes
* @param length number of bytes to get
* @param chunk chunk which will hold generated bytes
*/
void (*allocate_bytes) (prf_plus_t *this, size_t length, chunk_t *chunk);
/**
* @brief Destroys a prf_plus_t object.
*
* @param this calling object
* Destroys a prf_plus_t object.
*/
void (*destroy) (prf_plus_t *this);
};
/**
* @brief Creates a new prf_plus_t object.
* Creates a new prf_plus_t object.
*
* Seed will be cloned. prf will
* not be cloned, must be destroyed outside after
@@ -84,9 +74,7 @@ struct prf_plus_t {
* @param prf prf object to use
* @param seed input seed for prf
* @return prf_plus_t object
*
* @ingroup transforms
*/
prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed);
#endif /*PRF_PLUS_H_*/
#endif /*PRF_PLUS_H_ @} */
+2 -38
View File
@@ -1,10 +1,3 @@
/**
* @file prf.c
*
* @brief Generic constructor for all prf_t
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,15 +12,12 @@
* 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.
*
* $Id$
*/
#include "prf.h"
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/hmac_prf.h>
#include <crypto/prfs/fips_prf.h>
ENUM_BEGIN(pseudo_random_function_names, PRF_UNDEFINED, PRF_FIPS_DES,
"PRF_UNDEFINED",
"PRF_FIPS_SHA1_160",
@@ -42,29 +32,3 @@ ENUM_NEXT(pseudo_random_function_names, PRF_HMAC_MD5, PRF_HMAC_SHA2_512, PRF_FIP
"PRF_HMAC_SHA2_512");
ENUM_END(pseudo_random_function_names, PRF_HMAC_SHA2_512);
/*
* Described in header.
*/
prf_t *prf_create(pseudo_random_function_t pseudo_random_function)
{
switch (pseudo_random_function)
{
case PRF_HMAC_SHA1:
return (prf_t*)hmac_prf_create(HASH_SHA1);
case PRF_HMAC_MD5:
return (prf_t*)hmac_prf_create(HASH_MD5);
case PRF_HMAC_SHA2_256:
return (prf_t*)hmac_prf_create(HASH_SHA256);
case PRF_HMAC_SHA2_384:
return (prf_t*)hmac_prf_create(HASH_SHA384);
case PRF_HMAC_SHA2_512:
return (prf_t*)hmac_prf_create(HASH_SHA512);
case PRF_FIPS_SHA1_160:
return (prf_t*)fips_prf_create(20, g_sha1);
case PRF_FIPS_DES:
case PRF_HMAC_TIGER:
case PRF_AES128_CBC:
default:
return NULL;
}
}
+23 -52
View File
@@ -1,10 +1,3 @@
/**
* @file prf.h
*
* @brief Interface prf_t.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,13 @@
* 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.
*
* $Id$
*/
/**
* @defgroup prf prf
* @{ @ingroup crypto
*/
#ifndef PRF_H_
@@ -30,12 +30,10 @@ typedef struct prf_t prf_t;
#include <library.h>
/**
* @brief Pseudo random function, as in IKEv2 RFC 3.3.2.
* Pseudo random function, as in IKEv2 RFC 3.3.2.
*
* PRF algorithms not defined in IKEv2 are allocated in "private use"
* space.
*
* @ingroup prfs
*/
enum pseudo_random_function_t {
PRF_UNDEFINED = 1024,
@@ -63,80 +61,53 @@ enum pseudo_random_function_t {
extern enum_name_t *pseudo_random_function_names;
/**
* @brief Generic interface for pseudo-random-functions.
*
* @b Constructors:
* - prf_create()
* - hmac_prf_create()
*
* @todo Implement more prf algorithms
*
* @ingroup prfs
* Generic interface for pseudo-random-functions.
*/
struct prf_t {
/**
* @brief Generates pseudo random bytes and writes them in the buffer.
* Generates pseudo random bytes and writes them in the buffer.
*
* @param this calling object
* @param seed a chunk containing the seed for the next bytes
* @param[out] buffer pointer where the generated bytes will be written
* @param seed a chunk containing the seed for the next bytes
* @param buffer pointer where the generated bytes will be written
*/
void (*get_bytes) (prf_t *this, chunk_t seed, u_int8_t *buffer);
/**
* @brief Generates pseudo random bytes and allocate space for them.
* Generates pseudo random bytes and allocate space for them.
*
* @param this calling object
* @param seed a chunk containing the seed for the next bytes
* @param[out] chunk chunk which will hold generated bytes
* @param seed a chunk containing the seed for the next bytes
* @param chunk chunk which will hold generated bytes
*/
void (*allocate_bytes) (prf_t *this, chunk_t seed, chunk_t *chunk);
/**
* @brief Get the block size of this prf_t object.
* Get the block size of this prf_t object.
*
* @param this calling object
* @return block size in bytes
* @return block size in bytes
*/
size_t (*get_block_size) (prf_t *this);
/**
* @brief Get the key size of this prf_t object.
* Get the key size of this prf_t object.
*
* This is a suggestion only, all implemented PRFs accept variable key
* length.
*
* @param this calling object
* @return key size in bytes
* @return key size in bytes
*/
size_t (*get_key_size) (prf_t *this);
/**
* @brief Set the key for this prf_t object.
* Set the key for this prf_t object.
*
* @param this calling object
* @param key key to set
* @param key key to set
*/
void (*set_key) (prf_t *this, chunk_t key);
/**
* @brief Destroys a prf object.
*
* @param this calling object
* Destroys a prf object.
*/
void (*destroy) (prf_t *this);
};
/**
* @brief Generic constructor for a prf_t oject.
*
* @param pseudo_random_function Algorithm to use
* @return
* - prf_t object
* - NULL if prf algorithm not supported
*
* @ingroup prfs
*/
prf_t *prf_create(pseudo_random_function_t pseudo_random_function);
#endif /*PRF_H_*/
#endif /*PRF_H_ @} */
@@ -1,722 +0,0 @@
/**
* @file rsa_private_key.c
*
* @brief Implementation of rsa_private_key_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2007-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.
*
* RCSID $Id$
*/
#include <gmp.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "rsa_public_key.h"
#include "rsa_private_key.h"
#include <debug.h>
#include <asn1/asn1.h>
#include <asn1/pem.h>
#include <utils/randomizer.h>
/**
* defined in rsa_public_key.c
*/
extern chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e);
extern chunk_t rsa_public_key_id_create(const mpz_t n, const mpz_t e);
/**
* Public exponent to use for key generation.
*/
#define PUBLIC_EXPONENT 0x10001
typedef struct private_rsa_private_key_t private_rsa_private_key_t;
/**
* Private data of a rsa_private_key_t object.
*/
struct private_rsa_private_key_t {
/**
* Public interface for this signer.
*/
rsa_private_key_t public;
/**
* Version of key, as encoded in PKCS#1
*/
u_int version;
/**
* Public modulus.
*/
mpz_t n;
/**
* Public exponent.
*/
mpz_t e;
/**
* Private prime 1.
*/
mpz_t p;
/**
* Private Prime 2.
*/
mpz_t q;
/**
* Private exponent.
*/
mpz_t d;
/**
* Private exponent 1.
*/
mpz_t exp1;
/**
* Private exponent 2.
*/
mpz_t exp2;
/**
* Private coefficient.
*/
mpz_t coeff;
/**
* Keysize in bytes.
*/
size_t k;
/**
* Keyid formed as a SHA-1 hash of a publicKeyInfo object
*/
chunk_t keyid;
/**
* @brief Implements the RSADP algorithm specified in PKCS#1.
*
* @param this calling object
* @param data data to process
* @return processed data
*/
chunk_t (*rsadp) (private_rsa_private_key_t *this, chunk_t data);
/**
* @brief Implements the RSASP1 algorithm specified in PKCS#1.
* @param this calling object
* @param data data to process
* @return processed data
*/
chunk_t (*rsasp1) (private_rsa_private_key_t *this, chunk_t data);
};
/* ASN.1 definition of a PKCS#1 RSA private key */
static const asn1Object_t privkey_objects[] = {
{ 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
{ 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
{ 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
{ 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
{ 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
{ 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
{ 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
{ 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
{ 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
{ 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
ASN1_LOOP }, /* 10 */
{ 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
{ 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
{ 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
{ 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
{ 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */
};
#define PRIV_KEY_VERSION 1
#define PRIV_KEY_MODULUS 2
#define PRIV_KEY_PUB_EXP 3
#define PRIV_KEY_PRIV_EXP 4
#define PRIV_KEY_PRIME1 5
#define PRIV_KEY_PRIME2 6
#define PRIV_KEY_EXP1 7
#define PRIV_KEY_EXP2 8
#define PRIV_KEY_COEFF 9
#define PRIV_KEY_ROOF 16
/**
* Auxiliary function overwriting private key material with
* pseudo-random bytes before releasing it
*/
static void mpz_clear_randomized(mpz_t z)
{
size_t len = mpz_size(z) * GMP_LIMB_BITS / BITS_PER_BYTE;
u_int8_t *random_bytes = alloca(len);
randomizer_t *randomizer = randomizer_create();
randomizer->get_pseudo_random_bytes(randomizer, len, random_bytes);
/* overwrite mpz_t with pseudo-random bytes before clearing it */
mpz_import(z, len, 1, 1, 1, 0, random_bytes);
mpz_clear(z);
randomizer->destroy(randomizer);
}
/**
* Generate a random prime number with prime_len bytes
*/
static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_len, mpz_t *prime)
{
randomizer_t *randomizer;
chunk_t random_bytes;
status_t status;
randomizer = randomizer_create();
mpz_init(*prime);
do
{
DBG1(" generating %d bit prime from %s ...", BITS_PER_BYTE * prime_len, DEV_RANDOM);
status = randomizer->allocate_random_bytes(randomizer, prime_len, &random_bytes);
if (status != SUCCESS)
{
randomizer->destroy(randomizer);
mpz_clear(*prime);
return FAILED;
}
/* make sure most significant bit is set */
random_bytes.ptr[0] = random_bytes.ptr[0] | 0x80;
/* convert chunk to mpz value */
mpz_import(*prime, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
/* get next prime */
mpz_nextprime (*prime, *prime);
/* free the random_bytes after overwriting them with a pseudo-random sequence */
chunk_free_randomized(&random_bytes);
}
/* check if it isnt too large */
while (((mpz_sizeinbase(*prime, 2) + 7) / BITS_PER_BYTE) > prime_len);
randomizer->destroy(randomizer);
return SUCCESS;
}
/**
* Implementation of private_rsa_private_key_t.rsadp and private_rsa_private_key_t.rsasp1.
*/
static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data)
{
mpz_t t1, t2;
chunk_t decrypted;
mpz_init(t1);
mpz_init(t2);
mpz_import(t1, data.len, 1, 1, 1, 0, data.ptr);
mpz_powm(t2, t1, this->exp1, this->p); /* m1 = c^dP mod p */
mpz_powm(t1, t1, this->exp2, this->q); /* m2 = c^dQ mod Q */
mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
mpz_mod(t2, t2, this->p);
mpz_mul(t2, t2, this->coeff);
mpz_mod(t2, t2, this->p);
mpz_mul(t2, t2, this->q); /* m = m2 + h q */
mpz_add(t1, t1, t2);
decrypted.len = this->k;
decrypted.ptr = mpz_export(NULL, NULL, 1, decrypted.len, 1, 0, t1);
mpz_clear_randomized(t1);
mpz_clear_randomized(t2);
return decrypted;
}
/**
* Implementation of rsa_private_key_t.pkcs1_decrypt.
*/
static status_t pkcs1_decrypt(private_rsa_private_key_t *this,
chunk_t in, chunk_t *out)
{
status_t status = FAILED;
chunk_t em, em_ori;
/* decrypt the input data */
em = em_ori = this->rsadp(this, in);
/* PKCS#1 v1.5 EME encryption formatting
* EM = 00 || 02 || PS || 00 || M
* PS = pseudo-random nonzero octets
*/
/* check for magic bytes */
if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x02)
{
DBG1("incorrect padding - probably wrong RSA key");
goto end;
}
em.ptr += 2;
em.len -= 2;
/* the plaintext data starts after first 0x00 byte */
while (em.len-- > 0 && *em.ptr++ != 0x00);
if (em.len == 0)
{
DBG1("no plaintext data found");
goto end;
}
*out = chunk_clone(em);
status = SUCCESS;
end:
free(em_ori.ptr);
return status;
}
/**
* Implementation of rsa_private_key_t.build_emsa_pkcs1_signature.
*/
static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this,
hash_algorithm_t hash_algorithm,
chunk_t data, chunk_t *signature)
{
hasher_t *hasher;
chunk_t em, digestInfo, hash;
int hash_oid = hasher_algorithm_to_oid(hash_algorithm);
if (hash_oid == OID_UNKNOWN)
{
return NOT_SUPPORTED;
}
/* get hasher */
hasher = hasher_create(hash_algorithm);
if (hasher == NULL)
{
return NOT_SUPPORTED;
}
/* build hash */
hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
/* build DER-encoded digestInfo */
digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
asn1_algorithmIdentifier(hash_oid),
asn1_simple_object(ASN1_OCTET_STRING, hash)
);
chunk_free(&hash);
/* build chunk to rsa-decrypt:
* EM = 0x00 || 0x01 || PS || 0x00 || T.
* PS = 0xFF padding, with length to fill em
* T = encoded_hash
*/
em.len = this->k;
em.ptr = malloc(em.len);
/* fill em with padding */
memset(em.ptr, 0xFF, em.len);
/* set magic bytes */
*(em.ptr) = 0x00;
*(em.ptr+1) = 0x01;
*(em.ptr + em.len - digestInfo.len - 1) = 0x00;
/* set DER-encoded hash */
memcpy(em.ptr + em.len - digestInfo.len, digestInfo.ptr, digestInfo.len);
/* build signature */
*signature = this->rsasp1(this, em);
free(digestInfo.ptr);
free(em.ptr);
return SUCCESS;
}
/**
* Implementation of rsa_private_key_t.pkcs1_write.
*/
static bool pkcs1_write(private_rsa_private_key_t *this, const char *filename, bool force)
{
bool status;
chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm",
ASN1_INTEGER_0,
asn1_integer_from_mpz(this->n),
asn1_integer_from_mpz(this->e),
asn1_integer_from_mpz(this->d),
asn1_integer_from_mpz(this->p),
asn1_integer_from_mpz(this->q),
asn1_integer_from_mpz(this->exp1),
asn1_integer_from_mpz(this->exp2),
asn1_integer_from_mpz(this->coeff));
status = chunk_write(pkcs1, filename, "pkcs1", 0066, force);
chunk_free_randomized(&pkcs1);
return status;
}
/**
* Implementation of rsa_private_key_t.get_public_key.
*/
rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
{
return rsa_public_key_create(this->n, this->e);
}
/**
* Implementation of rsa_private_key.belongs_to.
*/
static bool belongs_to(private_rsa_private_key_t *this, rsa_public_key_t *public)
{
return chunk_equals(this->keyid, public->get_keyid(public));
}
/**
* Check the loaded key if it is valid and usable
* TODO: Log errors
*/
static status_t check(private_rsa_private_key_t *this)
{
mpz_t t, u, q1;
status_t status = SUCCESS;
/* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.
* We actually require more (for security).
*/
if (this->k < 512 / BITS_PER_BYTE)
{
return FAILED;
}
/* we picked a max modulus size to simplify buffer allocation */
if (this->k > 8192 / BITS_PER_BYTE)
{
return FAILED;
}
mpz_init(t);
mpz_init(u);
mpz_init(q1);
/* check that n == p * q */
mpz_mul(u, this->p, this->q);
if (mpz_cmp(u, this->n) != 0)
{
status = FAILED;
}
/* check that e divides neither p-1 nor q-1 */
mpz_sub_ui(t, this->p, 1);
mpz_mod(t, t, this->e);
if (mpz_cmp_ui(t, 0) == 0)
{
status = FAILED;
}
mpz_sub_ui(t, this->q, 1);
mpz_mod(t, t, this->e);
if (mpz_cmp_ui(t, 0) == 0)
{
status = FAILED;
}
/* check that d is e^-1 (mod lcm(p-1, q-1)) */
/* see PKCS#1v2, aka RFC 2437, for the "lcm" */
mpz_sub_ui(q1, this->q, 1);
mpz_sub_ui(u, this->p, 1);
mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */
mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */
mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */
mpz_mul(t, this->d, this->e);
mpz_mod(t, t, u);
if (mpz_cmp_ui(t, 1) != 0)
{
status = FAILED;
}
/* check that exp1 is d mod (p-1) */
mpz_sub_ui(u, this->p, 1);
mpz_mod(t, this->d, u);
if (mpz_cmp(t, this->exp1) != 0)
{
status = FAILED;
}
/* check that exp2 is d mod (q-1) */
mpz_sub_ui(u, this->q, 1);
mpz_mod(t, this->d, u);
if (mpz_cmp(t, this->exp2) != 0)
{
status = FAILED;
}
/* check that coeff is (q^-1) mod p */
mpz_mul(t, this->coeff, this->q);
mpz_mod(t, t, this->p);
if (mpz_cmp_ui(t, 1) != 0)
{
status = FAILED;
}
mpz_clear_randomized(t);
mpz_clear_randomized(u);
mpz_clear_randomized(q1);
return status;
}
/**
* Implementation of rsa_private_key.destroy.
*/
static void destroy(private_rsa_private_key_t *this)
{
mpz_clear_randomized(this->n);
mpz_clear_randomized(this->e);
mpz_clear_randomized(this->p);
mpz_clear_randomized(this->q);
mpz_clear_randomized(this->d);
mpz_clear_randomized(this->exp1);
mpz_clear_randomized(this->exp2);
mpz_clear_randomized(this->coeff);
chunk_free_randomized(&this->keyid);
free(this);
}
/**
* Internal generic constructor
*/
static private_rsa_private_key_t *rsa_private_key_create_empty(void)
{
private_rsa_private_key_t *this = malloc_thing(private_rsa_private_key_t);
/* public functions */
this->public.pkcs1_decrypt = (status_t (*) (rsa_private_key_t*,chunk_t,chunk_t*))pkcs1_decrypt;
this->public.build_emsa_pkcs1_signature = (status_t (*) (rsa_private_key_t*,hash_algorithm_t,chunk_t,chunk_t*))build_emsa_pkcs1_signature;
this->public.pkcs1_write = (bool (*) (rsa_private_key_t*,const char*,bool))pkcs1_write;
this->public.get_public_key = (rsa_public_key_t* (*) (rsa_private_key_t*))get_public_key;
this->public.belongs_to = (bool (*) (rsa_private_key_t*,rsa_public_key_t*))belongs_to;
this->public.destroy = (void (*) (rsa_private_key_t*))destroy;
/* private functions */
this->rsadp = rsadp;
this->rsasp1 = rsadp; /* same algorithm */
this->keyid = chunk_empty;
return this;
}
/*
* See header
*/
rsa_private_key_t *rsa_private_key_create(size_t key_size)
{
mpz_t p, q, n, e, d, exp1, exp2, coeff;
mpz_t m, q1, t;
private_rsa_private_key_t *this;
size_t key_len = key_size / BITS_PER_BYTE;
size_t prime_len = key_len / 2;
/* Get values of primes p and q */
if (compute_prime(this, prime_len, &p) != SUCCESS)
{
return NULL;
}
if (compute_prime(this, prime_len, &q) != SUCCESS)
{
mpz_clear(p);
return NULL;
}
mpz_init(t);
mpz_init(n);
mpz_init(d);
mpz_init(exp1);
mpz_init(exp2);
mpz_init(coeff);
/* Swapping Primes so p is larger then q */
if (mpz_cmp(p, q) < 0)
{
mpz_swap(p, q);
}
mpz_mul(n, p, q); /* n = p*q */
mpz_init_set_ui(e, PUBLIC_EXPONENT); /* assign public exponent */
mpz_init_set(m, p); /* m = p */
mpz_sub_ui(m, m, 1); /* m = m -1 */
mpz_init_set(q1, q); /* q1 = q */
mpz_sub_ui(q1, q1, 1); /* q1 = q1 -1 */
mpz_gcd(t, m, q1); /* t = gcd(p-1, q-1) */
mpz_mul(m, m, q1); /* m = (p-1)*(q-1) */
mpz_divexact(m, m, t); /* m = m / t */
mpz_gcd(t, m, e); /* t = gcd(m, e) (greatest common divisor) */
mpz_invert(d, e, m); /* e has an inverse mod m */
if (mpz_cmp_ui(d, 0) < 0) /* make sure d is positive */
{
mpz_add(d, d, m);
}
mpz_sub_ui(t, p, 1); /* t = p-1 */
mpz_mod(exp1, d, t); /* exp1 = d mod p-1 */
mpz_sub_ui(t, q, 1); /* t = q-1 */
mpz_mod(exp2, d, t); /* exp2 = d mod q-1 */
mpz_invert(coeff, q, p); /* coeff = q^-1 mod p */
if (mpz_cmp_ui(coeff, 0) < 0) /* make coeff d is positive */
{
mpz_add(coeff, coeff, p);
}
mpz_clear_randomized(q1);
mpz_clear_randomized(m);
mpz_clear_randomized(t);
/* determine exact the modulus size in bits */
key_size = mpz_sizeinbase(n, 2);
/* create and fill in rsa_private_key_t object */
this = rsa_private_key_create_empty();
this->k = (key_size + 7) / BITS_PER_BYTE;
this->keyid = rsa_public_key_id_create(n, e);
*(this->p) = *p;
*(this->q) = *q;
*(this->n) = *n;
*(this->e) = *e;
*(this->d) = *d;
*(this->exp1) = *exp1;
*(this->exp2) = *exp2;
*(this->coeff) = *coeff;
DBG1("generated %d bit RSA key with keyid: %#B", key_size, &this->keyid);
return &this->public;
}
/*
* see header
*/
rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob)
{
asn1_ctx_t ctx;
chunk_t object;
u_int level;
int objectID = 0;
private_rsa_private_key_t *this;
this = rsa_private_key_create_empty();
mpz_init(this->n);
mpz_init(this->e);
mpz_init(this->p);
mpz_init(this->q);
mpz_init(this->d);
mpz_init(this->exp1);
mpz_init(this->exp2);
mpz_init(this->coeff);
asn1_init(&ctx, blob, 0, FALSE, TRUE);
while (objectID < PRIV_KEY_ROOF)
{
if (!extract_object(privkey_objects, &objectID, &object, &level, &ctx))
{
destroy(this);
return FALSE;
}
switch (objectID)
{
case PRIV_KEY_VERSION:
if (object.len > 0 && *object.ptr != 0)
{
destroy(this);
return NULL;
}
break;
case PRIV_KEY_MODULUS:
mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
break;
case PRIV_KEY_PUB_EXP:
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
break;
case PRIV_KEY_PRIV_EXP:
mpz_import(this->d, object.len, 1, 1, 1, 0, object.ptr);
break;
case PRIV_KEY_PRIME1:
mpz_import(this->p, object.len, 1, 1, 1, 0, object.ptr);
break;
case PRIV_KEY_PRIME2:
mpz_import(this->q, object.len, 1, 1, 1, 0, object.ptr);
break;
case PRIV_KEY_EXP1:
mpz_import(this->exp1, object.len, 1, 1, 1, 0, object.ptr);
break;
case PRIV_KEY_EXP2:
mpz_import(this->exp2, object.len, 1, 1, 1, 0, object.ptr);
break;
case PRIV_KEY_COEFF:
mpz_import(this->coeff, object.len, 1, 1, 1, 0, object.ptr);
break;
}
objectID++;
}
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
this->keyid = rsa_public_key_id_create(this->n, this->e);
if (check(this) != SUCCESS)
{
destroy(this);
return NULL;
}
else
{
return &this->public;
}
}
/*
* see header
*/
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, chunk_t *passphrase)
{
bool pgp = FALSE;
chunk_t chunk = chunk_empty;
rsa_private_key_t *key = NULL;
if (!pem_asn1_load_file(filename, passphrase, "private key", &chunk, &pgp))
return NULL;
key = rsa_private_key_create_from_chunk(chunk);
chunk_free_randomized(&chunk);
return key;
}
@@ -1,163 +0,0 @@
/**
* @file rsa_private_key.h
*
* @brief Interface of rsa_private_key_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2007-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.
*
* RCSID $Id$
*/
#ifndef RSA_PRIVATE_KEY_H_
#define RSA_PRIVATE_KEY_H_
typedef struct rsa_private_key_t rsa_private_key_t;
#include <library.h>
#include <crypto/rsa/rsa_public_key.h>
#include <crypto/hashers/hasher.h>
/**
* @brief RSA private key with associated functions.
*
* Currently only supports signing using EMSA encoding.
*
* @b Constructors:
* - rsa_private_key_create()
* - rsa_private_key_create_from_chunk()
* - rsa_private_key_create_from_file()
*
* @see rsa_public_key_t
*
* @ingroup rsa
*/
struct rsa_private_key_t {
/**
* @brief Decrypt a data block based on EME-PKCS1 encoding.
*
*
* @param this calling object
* @param data encrypted input data
* @param out decrypted output data
* @return
* - SUCCESS
* - FAILED if padding is not correct
*/
status_t (*pkcs1_decrypt) (rsa_private_key_t *this, chunk_t in, chunk_t *out);
/**
* @brief Build a signature over a chunk using EMSA-PKCS1 encoding.
*
* This signature creates a hash using the specified hash algorithm, concatenates
* it with an ASN1-OID of the hash algorithm and runs the RSASP1 function
* on it.
*
* @param this calling object
* @param hash_algorithm hash algorithm to use for hashing
* @param data data to sign
* @param[out] signature allocated signature
* @return
* - SUCCESS
* - INVALID_STATE, if key not set
* - NOT_SUPPORTED, if hash algorithm not supported
*/
status_t (*build_emsa_pkcs1_signature) (rsa_private_key_t *this, hash_algorithm_t hash_algorithm, chunk_t data, chunk_t *signature);
/**
* @brief Writes an RSA private key to a file in PKCS#1 format.
*
* @param this calling object
* @param filename file to which the key should be written.
* @param force if TRUE overwrite existing file
* @return TRUE if successful - FALSE otherwise
*/
bool (*pkcs1_write) (rsa_private_key_t *this, const char *filename, bool force);
/**
* @brief Create a rsa_public_key_t with the public part of the key.
*
* @param this calling object
* @return public_key
*/
rsa_public_key_t *(*get_public_key) (rsa_private_key_t *this);
/**
* @brief Check if a private key belongs to a public key.
*
* Compares the public part of the private key with the
* public key, return TRUE if it equals.
*
* @param this private key
* @param public public key
* @return TRUE, if keys belong together
*/
bool (*belongs_to) (rsa_private_key_t *this, rsa_public_key_t *public);
/**
* @brief Destroys the private key.
*
* @param this private key to destroy
*/
void (*destroy) (rsa_private_key_t *this);
};
/**
* @brief Generate a new RSA key with specified key length.
*
* @param key_size size of the key in bits
* @return generated rsa_private_key_t.
*
* @ingroup rsa
*/
rsa_private_key_t *rsa_private_key_create(size_t key_size);
/**
* @brief Load an RSA private key from a chunk.
*
* Load a key from a chunk, encoded as described in PKCS#1
* (ASN1 DER encoded).
*
* @param chunk chunk containing the DER encoded key
* @return loaded rsa_private_key_t, or NULL
*
* @ingroup rsa
*/
rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk);
/**
* @brief Load an RSA private key from a file.
*
* Load a key from a file, which is either in a unencrypted binary
* format (DER), or in a (encrypted) PEM format. The supplied
* passphrase is used to decrypt an ecrypted key.
*
* @param filename filename which holds the key
* @param passphrase optional passphase for decryption, can be NULL
* @return loaded rsa_private_key_t, or NULL
*
* @todo Implement PEM file loading
* @todo Implement key decryption
*
* @ingroup rsa
*/
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, chunk_t *passphrase);
#endif /*RSA_PRIVATE_KEY_H_*/
@@ -1,516 +0,0 @@
/**
* @file rsa_public_key.c
*
* @brief Implementation of rsa_public_key_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2007-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.
*
* RCSID $Id$
*/
#include <gmp.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "rsa_public_key.h"
#include <debug.h>
#include <utils/randomizer.h>
#include <crypto/hashers/hasher.h>
#include <asn1/asn1.h>
#include <asn1/pem.h>
/* ASN.1 definition of RSApublicKey */
static const asn1Object_t pubkeyObjects[] = {
{ 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
{ 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
};
#define PUB_KEY_RSA_PUBLIC_KEY 0
#define PUB_KEY_MODULUS 1
#define PUB_KEY_EXPONENT 2
#define PUB_KEY_ROOF 3
/* ASN.1 definition of digestInfo */
static const asn1Object_t digestInfoObjects[] = {
{ 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
{ 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
{ 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
};
#define DIGEST_INFO 0
#define DIGEST_INFO_ALGORITHM 1
#define DIGEST_INFO_DIGEST 2
#define DIGEST_INFO_ROOF 3
typedef struct private_rsa_public_key_t private_rsa_public_key_t;
/**
* Private data structure with signing context.
*/
struct private_rsa_public_key_t {
/**
* Public interface for this signer.
*/
rsa_public_key_t public;
/**
* Public modulus.
*/
mpz_t n;
/**
* Public exponent.
*/
mpz_t e;
/**
* Keysize in bytes.
*/
size_t k;
/**
* Keyid formed as a SHA-1 hash of a publicKeyInfo object
*/
chunk_t keyid;
/**
* @brief Implements the RSAEP algorithm specified in PKCS#1.
*
* @param this calling object
* @param data data to process
* @return processed data
*/
chunk_t (*rsaep) (const private_rsa_public_key_t *this, chunk_t data);
/**
* @brief Implements the RSASVP1 algorithm specified in PKCS#1.
*
* @param this calling object
* @param data data to process
* @return processed data
*/
chunk_t (*rsavp1) (const private_rsa_public_key_t *this, chunk_t data);
};
/**
* Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1
*/
static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data)
{
mpz_t m, c;
chunk_t encrypted;
mpz_init(c);
mpz_init(m);
mpz_import(m, data.len, 1, 1, 1, 0, data.ptr);
mpz_powm(c, m, this->e, this->n);
encrypted.len = this->k;
encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c);
mpz_clear(c);
mpz_clear(m);
return encrypted;
}
/**
* Implementation of rsa_public_key_t.eme_pkcs1_encrypt.
*/
static status_t pkcs1_encrypt(private_rsa_public_key_t *this,
chunk_t in, chunk_t *out)
{
chunk_t em;
u_char *pos;
int padding = this->k - in.len - 3;
if (padding < 8)
{
DBG1("rsa padding of %d bytes is too small", padding);
return FAILED;
}
em.len = this->k;
em.ptr = pos = malloc(em.len);
/* add padding according to PKCS#1 7.2.1 1.+2. */
*pos++ = 0x00;
*pos++ = 0x02;
/* pad with pseudo random bytes unequal to zero */
{
randomizer_t *randomizer = randomizer_create();
/* pad with pseudo random bytes unequal to zero */
while (padding--)
{
randomizer->get_pseudo_random_bytes(randomizer, 1, pos);
while (!*pos)
{
randomizer->get_pseudo_random_bytes(randomizer, 1, pos);
}
pos++;
}
randomizer->destroy(randomizer);
}
/* append the padding terminator */
*pos++ = 0x00;
/* now add the data */
memcpy(pos, in.ptr, in.len);
*out = this->rsaep(this, em);
free(em.ptr);
return SUCCESS;
}
/**
* Implementation of rsa_public_key.verify_emsa_pkcs1_signature.
*/
static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this,
hash_algorithm_t algorithm,
chunk_t data, chunk_t signature)
{
chunk_t em_ori, em;
status_t res = FAILED;
/* remove any preceding 0-bytes from signature */
while (signature.len && *(signature.ptr) == 0x00)
{
signature.len -= 1;
signature.ptr++;
}
if (signature.len > this->k)
{
return INVALID_ARG;
}
/* unpack signature */
em_ori = em = this->rsavp1(this, signature);
/* result should look like this:
* EM = 0x00 || 0x01 || PS || 0x00 || T.
* PS = 0xFF padding, with length to fill em
* T = oid || hash
*/
/* check magic bytes */
if (*(em.ptr) != 0x00 || *(em.ptr+1) != 0x01)
{
DBG2("incorrect padding - probably wrong RSA key");
goto end;
}
em.ptr += 2;
em.len -= 2;
/* find magic 0x00 */
while (em.len > 0)
{
if (*em.ptr == 0x00)
{
/* found magic byte, stop */
em.ptr++;
em.len--;
break;
}
else if (*em.ptr != 0xFF)
{
/* bad padding, decryption failed ?!*/
goto end;
}
em.ptr++;
em.len--;
}
if (em.len == 0)
{
/* no digestInfo found */
goto end;
}
/* parse ASN.1-based digestInfo */
{
asn1_ctx_t ctx;
chunk_t object;
u_int level;
int objectID = 0;
hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
asn1_init(&ctx, em, 0, FALSE, FALSE);
while (objectID < DIGEST_INFO_ROOF)
{
if (!extract_object(digestInfoObjects, &objectID, &object, &level, &ctx))
{
goto end;
}
switch (objectID)
{
case DIGEST_INFO:
if (em.len > object.len)
{
DBG1("digestInfo field in signature is followed by %u surplus bytes",
em.len - object.len);
goto end;
}
break;
case DIGEST_INFO_ALGORITHM:
{
int hash_oid = parse_algorithmIdentifier(object, level+1, NULL);
hash_algorithm = hasher_algorithm_from_oid(hash_oid);
if (hash_algorithm == HASH_UNKNOWN
|| (algorithm != HASH_UNKNOWN && hash_algorithm != algorithm))
{
DBG1("wrong hash algorithm used in signature");
goto end;
}
}
break;
case DIGEST_INFO_DIGEST:
{
chunk_t hash;
hasher_t *hasher = hasher_create(hash_algorithm);
if (object.len != hasher->get_hash_size(hasher))
{
DBG1("hash size in signature is %u bytes instead of %u bytes",
object.len, hasher->get_hash_size(hasher));
hasher->destroy(hasher);
goto end;
}
/* build our own hash */
hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
/* compare the hashes */
res = memeq(object.ptr, hash.ptr, hash.len) ? SUCCESS : FAILED;
free(hash.ptr);
}
break;
default:
break;
}
objectID++;
}
}
end:
free(em_ori.ptr);
return res;
}
/**
* Implementation of rsa_public_key_t.get_modulus.
*/
static mpz_t *get_modulus(const private_rsa_public_key_t *this)
{
return (mpz_t*)&this->n;
}
/**
* Implementation of rsa_public_key_t.get_keysize.
*/
static size_t get_keysize(const private_rsa_public_key_t *this)
{
return this->k;
}
/**
* Build a DER-encoded publicKeyInfo object from an RSA public key.
* Also used in rsa_private_key.c.
*/
chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e)
{
chunk_t publicKey = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_integer_from_mpz(n),
asn1_integer_from_mpz(e));
return asn1_wrap(ASN1_SEQUENCE, "cm",
asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
asn1_bitstring("m", publicKey));
}
/**
* Form the RSA keyid as a SHA-1 hash of a publicKeyInfo object
* Also used in rsa_private_key.c.
*/
chunk_t rsa_public_key_id_create(mpz_t n, mpz_t e)
{
chunk_t keyid;
chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(n, e);
hasher_t *hasher = hasher_create(HASH_SHA1);
hasher->allocate_hash(hasher, publicKeyInfo, &keyid);
hasher->destroy(hasher);
free(publicKeyInfo.ptr);
return keyid;
}
/**
* Implementation of rsa_public_key_t.get_publicKeyInfo.
*/
static chunk_t get_publicKeyInfo(const private_rsa_public_key_t *this)
{
return rsa_public_key_info_to_asn1(this->n, this->e);
}
/**
* Implementation of rsa_public_key_t.get_keyid.
*/
static chunk_t get_keyid(const private_rsa_public_key_t *this)
{
return this->keyid;
}
/* forward declaration used by rsa_public_key_t.clone */
private_rsa_public_key_t *rsa_public_key_create_empty(void);
/**
* Implementation of rsa_public_key_t.clone.
*/
static rsa_public_key_t* _clone(const private_rsa_public_key_t *this)
{
private_rsa_public_key_t *clone = rsa_public_key_create_empty();
mpz_init_set(clone->n, this->n);
mpz_init_set(clone->e, this->e);
clone->keyid = chunk_clone(this->keyid);
clone->k = this->k;
return &clone->public;
}
/**
* Implementation of rsa_public_key_t.destroy.
*/
static void destroy(private_rsa_public_key_t *this)
{
mpz_clear(this->n);
mpz_clear(this->e);
free(this->keyid.ptr);
free(this);
}
/**
* Generic private constructor
*/
private_rsa_public_key_t *rsa_public_key_create_empty(void)
{
private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t);
/* public functions */
this->public.pkcs1_encrypt = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t*))pkcs1_encrypt;
this->public.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
this->public.get_modulus = (mpz_t *(*) (const rsa_public_key_t*))get_modulus;
this->public.get_keysize = (size_t (*) (const rsa_public_key_t*))get_keysize;
this->public.get_publicKeyInfo = (chunk_t (*) (const rsa_public_key_t*))get_publicKeyInfo;
this->public.get_keyid = (chunk_t (*) (const rsa_public_key_t*))get_keyid;
this->public.clone = (rsa_public_key_t* (*) (const rsa_public_key_t*))_clone;
this->public.destroy = (void (*) (rsa_public_key_t*))destroy;
/* private functions */
this->rsaep = rsaep;
this->rsavp1 = rsaep; /* same algorithm */
return this;
}
/*
* See header
*/
rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e)
{
private_rsa_public_key_t *this = rsa_public_key_create_empty();
mpz_init_set(this->n, n);
mpz_init_set(this->e, e);
this->k = (mpz_sizeinbase(n, 2) + 7) / BITS_PER_BYTE;
this->keyid = rsa_public_key_id_create(n, e);
return &this->public;
}
/*
* See header
*/
rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob)
{
asn1_ctx_t ctx;
chunk_t object;
u_int level;
int objectID = 0;
private_rsa_public_key_t *this = rsa_public_key_create_empty();
mpz_init(this->n);
mpz_init(this->e);
asn1_init(&ctx, blob, 0, FALSE, FALSE);
while (objectID < PUB_KEY_ROOF)
{
if (!extract_object(pubkeyObjects, &objectID, &object, &level, &ctx))
{
destroy(this);
return FALSE;
}
switch (objectID)
{
case PUB_KEY_MODULUS:
mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
break;
case PUB_KEY_EXPONENT:
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
break;
}
objectID++;
}
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
this->keyid = rsa_public_key_id_create(this->n, this->e);
return &this->public;
}
/*
* See header
*/
rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
{
bool pgp = FALSE;
chunk_t chunk = chunk_empty;
rsa_public_key_t *pubkey = NULL;
if (!pem_asn1_load_file(filename, NULL, "public key", &chunk, &pgp))
{
return NULL;
}
pubkey = rsa_public_key_create_from_chunk(chunk);
free(chunk.ptr);
return pubkey;
}
@@ -1,173 +0,0 @@
/**
* @file rsa_public_key.h
*
* @brief Interface of rsa_public_key_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2007-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.
*
* RCSID $Id$
*/
#ifndef RSA_PUBLIC_KEY_H_
#define RSA_PUBLIC_KEY_H_
typedef struct rsa_public_key_t rsa_public_key_t;
#include <gmp.h>
#include <library.h>
#include <crypto/hashers/hasher.h>
/**
* @brief RSA public key with associated functions.
*
* Currently only supports signature verification using
* the EMSA encoding (see PKCS1)
*
* @b Constructors:
* - rsa_public_key_create()
* - rsa_public_key_create_from_chunk()
* - rsa_public_key_create_from_file()
*
* @ingroup rsa
*/
struct rsa_public_key_t {
/**
* @brief Encrypt a data block using EME-PKCS1 encoding.
*
*
* @param this calling object
* @param data plaintext input data
* @param out encrypted output data
* @return
* - SUCCESS
* - FAILED if data block is too large
*/
status_t (*pkcs1_encrypt) (rsa_public_key_t *this, chunk_t in, chunk_t *out);
/**
* @brief Verify an EMSA-PKCS1 encoded signature.
*
* Processes the supplied signature with the RSAVP1 function,
* selects the hash algorithm form the resultign ASN1-OID and
* verifies the hash against the supplied data.
*
* @param this rsa_public_key to use
* @param data data to sign
# @param algorithm hash algorithm the signature is based on
* @param signature signature to verify
* @return
* - SUCCESS, if signature ok
* - INVALID_STATE, if key not set
* - NOT_SUPPORTED, if hash algorithm not supported
* - INVALID_ARG, if signature is not a signature
* - FAILED if signature invalid or unable to verify
*/
status_t (*verify_emsa_pkcs1_signature) (const rsa_public_key_t *this,
hash_algorithm_t algorithm,
chunk_t data, chunk_t signature);
/**
* @brief Get the modulus of the key.
*
* @param this calling object
* @return modulus (n) of the key
*/
mpz_t *(*get_modulus) (const rsa_public_key_t *this);
/**
* @brief Get the size of the modulus in bytes.
*
* @param this calling object
* @return size of the modulus (n) in bytes
*/
size_t (*get_keysize) (const rsa_public_key_t *this);
/**
* @brief Get the DER encoded publicKeyInfo object.
*
* @param this calling object
* @return DER encoded publicKeyInfo object
*/
chunk_t (*get_publicKeyInfo) (const rsa_public_key_t *this);
/**
* @brief Get the keyid formed as the SHA-1 hash of a publicKeyInfo object.
*
* @param this calling object
* @return keyid in the form of a SHA-1 hash
*/
chunk_t (*get_keyid) (const rsa_public_key_t *this);
/**
* @brief Clone the public key.
*
* @param this public key to clone
* @return clone of this
*/
rsa_public_key_t *(*clone) (const rsa_public_key_t *this);
/**
* @brief Destroys the public key.
*
* @param this public key to destroy
*/
void (*destroy) (rsa_public_key_t *this);
};
/**
* @brief Create a RSA public key from modulus and public exponent.
*
* @param n modulus
* @param e public exponent
* @return created rsa_public_key_t
*
* @ingroup rsa
*/
rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e);
/**
* @brief Load an RSA public key from a chunk.
*
* Load a key from a chunk, encoded in the more frequently
* used publicKeyInfo object (ASN1 DER encoded).
*
* @param chunk chunk containing the DER encoded key
* @return loaded rsa_public_key_t, or NULL
*
* @ingroup rsa
*/
rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t chunk);
/**
* @brief Load an RSA public key from a file.
*
* Load a key from a file, which is either in binary
* format (DER), or in PEM format.
*
* @param filename filename which holds the key
* @return loaded rsa_public_key_t, or NULL
*
* @ingroup rsa
*/
rsa_public_key_t *rsa_public_key_create_from_file(char *filename);
#endif /*RSA_PUBLIC_KEY_H_*/
+2 -32
View File
@@ -1,10 +1,3 @@
/**
* @file signer.c
*
* @brief Implementation of generic signer_t constructor.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,12 +12,12 @@
* 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.
*
* $Id$
*/
#include "signer.h"
#include <crypto/signers/hmac_signer.h>
ENUM_BEGIN(integrity_algorithm_names, AUTH_UNDEFINED, AUTH_HMAC_SHA1_128,
"UNDEFINED",
"AUTH_HMAC_SHA1_128");
@@ -40,26 +33,3 @@ ENUM_NEXT(integrity_algorithm_names, AUTH_HMAC_SHA2_256_128, AUTH_HMAC_SHA2_512_
"AUTH_HMAC_SHA2_512_256");
ENUM_END(integrity_algorithm_names, AUTH_HMAC_SHA2_512_256);
/*
* Described in header.
*/
signer_t *signer_create(integrity_algorithm_t integrity_algorithm)
{
switch(integrity_algorithm)
{
case AUTH_HMAC_SHA1_96:
return (signer_t *)hmac_signer_create(HASH_SHA1, 12);
case AUTH_HMAC_SHA1_128:
return (signer_t *)hmac_signer_create(HASH_SHA1, 16);
case AUTH_HMAC_MD5_96:
return (signer_t *)hmac_signer_create(HASH_MD5, 12);
case AUTH_HMAC_SHA2_256_128:
return (signer_t *)hmac_signer_create(HASH_SHA256, 16);
case AUTH_HMAC_SHA2_384_192:
return (signer_t *)hmac_signer_create(HASH_SHA384, 24);
case AUTH_HMAC_SHA2_512_256:
return (signer_t *)hmac_signer_create(HASH_SHA512, 32);
default:
return NULL;
}
}
+27 -57
View File
@@ -1,10 +1,3 @@
/**
* @file signer.h
*
* @brief Interface for signer_t.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -19,6 +12,13 @@
* 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.
*
* $Id$
*/
/**
* @defgroup signer signer
* @{ @ingroup crypto
*/
#ifndef SIGNER_H_
@@ -30,11 +30,9 @@ typedef struct signer_t signer_t;
#include <library.h>
/**
* @brief Integrity algorithm, as in IKEv2 RFC 3.3.2.
* Integrity algorithm, as in IKEv2 RFC 3.3.2.
*
* Algorithms not specified in IKEv2 are allocated in private use space.
*
* @ingroup signers
*/
enum integrity_algorithm_t {
AUTH_UNDEFINED = 1024,
@@ -61,93 +59,65 @@ enum integrity_algorithm_t {
extern enum_name_t *integrity_algorithm_names;
/**
* @brief Generig interface for a symmetric signature algorithm.
*
* @b Constructors:
* - signer_create()
* - hmac_signer_create()
*
* @todo Implement more integrity algorithms
*
* @ingroup signers
* Generig interface for a symmetric signature algorithm.
*/
struct signer_t {
/**
* @brief Generate a signature.
* Generate a signature.
*
* If buffer is NULL, data is processed and prepended to a next call until
* buffer is a valid pointer.
*
* @param this calling object
* @param data a chunk containing the data to sign
* @param[out] buffer pointer where the signature will be written
* @param data a chunk containing the data to sign
* @param buffer pointer where the signature will be written
*/
void (*get_signature) (signer_t *this, chunk_t data, u_int8_t *buffer);
/**
* @brief Generate a signature and allocate space for it.
* Generate a signature and allocate space for it.
*
* If chunk is NULL, data is processed and prepended to a next call until
* chunk is a valid chunk pointer.
*
* @param this calling object
* @param data a chunk containing the data to sign
* @param[out] chunk chunk which will hold the allocated signature
* @param data a chunk containing the data to sign
* @param chunk chunk which will hold the allocated signature
*/
void (*allocate_signature) (signer_t *this, chunk_t data, chunk_t *chunk);
/**
* @brief Verify a signature.
* Verify a signature.
*
* @param this calling object
* @param data a chunk containing the data to verify
* @param signature a chunk containing the signature
* @return TRUE, if signature is valid, FALSE otherwise
* @param data a chunk containing the data to verify
* @param signature a chunk containing the signature
* @return TRUE, if signature is valid, FALSE otherwise
*/
bool (*verify_signature) (signer_t *this, chunk_t data, chunk_t signature);
/**
* @brief Get the block size of this signature algorithm.
* Get the block size of this signature algorithm.
*
* @param this calling object
* @return block size in bytes
* @return block size in bytes
*/
size_t (*get_block_size) (signer_t *this);
/**
* @brief Get the key size of the signature algorithm.
* Get the key size of the signature algorithm.
*
* @param this calling object
* @return key size in bytes
* @return key size in bytes
*/
size_t (*get_key_size) (signer_t *this);
/**
* @brief Set the key for this object.
* Set the key for this object.
*
* @param this calling object
* @param key key to set
* @param key key to set
*/
void (*set_key) (signer_t *this, chunk_t key);
/**
* @brief Destroys a signer_t object.
*
* @param this calling object
* Destroys a signer_t object.
*/
void (*destroy) (signer_t *this);
};
/**
* @brief Creates a new signer_t object.
*
* @param integrity_algorithm Algorithm to use for signing and verifying.
* @return
* - signer_t object
* - NULL if signer not supported
*
* @ingroup signers
*/
signer_t *signer_create(integrity_algorithm_t integrity_algorithm);
#endif /*SIGNER_H_*/
#endif /*SIGNER_H_ @} */
File diff suppressed because it is too large Load Diff
-406
View File
@@ -1,406 +0,0 @@
/**
* @file x509.h
*
* @brief Interface of x509_t.
*
*/
/*
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
* Copyright (C) 2002 Mario Strasser
* Copyright (C) 2006 Martin Willi
* Copyright (C) 2000-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.
*
* RCSID $Id$
*/
#ifndef X509_H_
#define X509_H_
typedef struct x509_t x509_t;
#include <library.h>
#include <crypto/rsa/rsa_private_key.h>
#include <crypto/hashers/hasher.h>
#include <crypto/certinfo.h>
#include <crypto/ca.h>
#include <utils/identification.h>
#include <utils/iterator.h>
#include <utils/linked_list.h>
/* authority flags */
#define AUTH_NONE 0x00 /* no authorities */
#define AUTH_CA 0x01 /* certification authority */
#define AUTH_AA 0x02 /* authorization authority */
#define AUTH_OCSP 0x04 /* ocsp signing authority */
/**
* @brief X.509 certificate.
*
* @b Constructors:
* - x509_create()
* - x509_create_from_chunk()
* - x509_create_from_file()
*
* @ingroup crypto
*/
struct x509_t {
/**
* @brief Set trusted public key life.
*
* @param this calling object
* @param until time until public key is trusted
*/
void (*set_until) (x509_t *this, time_t until);
/**
* @brief Get trusted public key life.
*
* @param this calling object
* @return time until public key is trusted
*/
time_t (*get_until) (const x509_t *this);
/**
* @brief Set the certificate status
*
* @param this calling object
* @param status certificate status
*/
void (*set_status) (x509_t *this, cert_status_t status);
/**
* @brief Get the certificate status
*
* @param this calling object
* @return certificate status
*/
cert_status_t (*get_status) (const x509_t *this);
/**
* @brief Add authority flags
*
* @param this calling object
* @param flag flags to be added
*/
void (*add_authority_flags) (x509_t *this, u_int flags);
/**
* @brief Get authority flags
*
* @param this calling object
* @return authority flags
*/
u_int (*get_authority_flags) (x509_t *this);
/**
* @brief Check a specific authority flag
*
* @param this calling object
* @param flag flag to be checked
* @return TRUE if flag is present
*/
bool (*has_authority_flag) (x509_t *this, u_int flag);
/**
* @brief Get the DER-encoded X.509 certificate body
*
* @param this calling object
* @return DER-encoded X.509 certificate
*/
chunk_t (*get_certificate) (const x509_t *this);
/**
* @brief Get the RSA public key from the certificate.
*
* @param this calling object
* @return public_key
*/
rsa_public_key_t *(*get_public_key) (const x509_t *this);
/**
* @brief Get serial number from the certificate.
*
* @param this calling object
* @return serialNumber
*/
chunk_t (*get_serialNumber) (const x509_t *this);
/**
* @brief Get subjectKeyID from the certificate.
*
* @param this calling object
* @return subjectKeyID
*/
chunk_t (*get_subjectKeyID) (const x509_t *this);
/**
* @brief Get keyid from the certificate's public key.
*
* @param this calling object
* @return keyid
*/
chunk_t (*get_keyid) (const x509_t *this);
/**
* @brief Get the issuerDistinguishedName
*
* The resulting ID is always a identification_t
* of type ID_DER_ASN1_DN.
*
* @param this calling object
* @return issuers ID
*/
identification_t *(*get_issuer) (const x509_t *this);
/**
* @brief Get the subjectDistinguishedName.
*
* The resulting ID is always a identification_t
* of type ID_DER_ASN1_DN.
*
* @param this calling object
* @return subjects ID
*/
identification_t *(*get_subject) (const x509_t *this);
/**
* @brief Set a link ca info
*
* @param this calling object
* @param ca_info link to the info record of the issuing ca
*/
void (*set_ca_info) (x509_t *this, ca_info_t *ca_info);
/**
* @brief Get the .
*
* The resulting ID is always a identification_t
* of type ID_DER_ASN1_DN.
*
* @param this calling object
* @return link to the info record of the issuing ca
* or NULL if it does not [yet] exist
*/
ca_info_t *(*get_ca_info) (const x509_t *this);
/**
* @brief Create an iterator for the crlDistributionPoints.
*
* @param this calling object
* @return iterator for crlDistributionPoints
*/
iterator_t *(*create_crluri_iterator) (const x509_t *this);
/**
* @brief Create an iterator for the ocspAccessLocations.
*
* @param this calling object
* @return iterator for ocspAccessLocations
*/
iterator_t *(*create_ocspuri_iterator) (const x509_t *this);
/**
* @brief Check if a certificate is trustworthy
*
* @param this calling object
* @param signer signer's RSA public key
*/
bool (*verify) (const x509_t *this, const rsa_public_key_t *signer);
/**
* @brief Compare two certificates.
*
* Comparison is done via the certificates signature.
*
* @param this first cert for compare
* @param other second cert for compare
* @return TRUE if signature is equal
*/
bool (*equals) (const x509_t *this, const x509_t *that);
/**
* @brief Checks if the certificate contains a subjectAltName equal to id.
*
* @param this certificate being examined
* @param id id which is being compared to the subjectAltNames
* @return TRUE if a match is found
*/
bool (*equals_subjectAltName) (const x509_t *this, identification_t *id);
/**
* @brief Checks if the subject of the other cert is the issuer of this cert.
*
* @param this certificate
* @param issuer potential issuer certificate
* @return TRUE if issuer is found
*/
bool (*is_issuer) (const x509_t *this, const x509_t *issuer);
/**
* @brief Checks the validity interval of the certificate
*
* @param this certificate being examined
* @param until until = min(until, notAfter)
* @return NULL if the certificate is valid
*/
err_t (*is_valid) (const x509_t *this, time_t *until);
/**
* @brief Returns the CA basic constraints flag
*
* @param this certificate being examined
* @return TRUE if the CA flag is set
*/
bool (*is_ca) (const x509_t *this);
/**
* @brief Returns the OCSPSigner extended key usage flag
*
* @param this certificate being examined
* @return TRUE if the OCSPSigner flag is set
*/
bool (*is_ocsp_signer) (const x509_t *this);
/**
* @brief Checks if the certificate is self-signed (subject equals issuer)
*
* @param this certificate being examined
* @return TRUE if self-signed
*/
bool (*is_self_signed) (const x509_t *this);
/**
* @brief Log the certificate info to out.
*
* @param this calling object
* @param out stream to write to
* @param utc TRUE for UTC times, FALSE for local time
*/
void (*list) (x509_t *this, FILE *out, bool utc);
/**
* @brief Adds a list of subjectAltNames
*
* @param this calling object
* @param subjectAltNames list of subjectAltNames to be added
*/
void (*add_subjectAltNames) (x509_t *this, linked_list_t *subjectAltNames);
/**
* @brief Builds a DER-encoded signed X.509 certificate
*
* @param this calling object
* @param alg hash algorithm used to compute the certificate digest
* @param private_key RSA private key used to sign the certificate digest
*/
void (*build_encoding) (x509_t *this, hash_algorithm_t alg, rsa_private_key_t *private_key);
/**
* @brief Destroys the certificate.
*
* @param this certificate to destroy
*/
void (*destroy) (x509_t *this);
};
/**
* @brief Create a X.509 certificate from its components
*
* @param serialNumber chunk containing the serialNumber
* @param issuer issuer distinguished name
* @param notBefore start date of validity
* @param notAfter end date of validity
* @param subject subject distinguished name
* @param public_key public key
*
* @return created x509_t certificate, or NULL if invalid.
*
* @ingroup crypto
*/
x509_t *x509_create(chunk_t serialNumber, identification_t *issuer,
time_t notBefore, time_t notAfter,
identification_t *subject,
rsa_public_key_t *public_key);
/**
* @brief Read a X.509 certificate from a DER encoded blob.
*
* @param chunk chunk containing DER encoded data
* @return created x509_t certificate, or NULL if invalid.
*
* @ingroup crypto
*/
x509_t *x509_create_from_chunk(chunk_t chunk, u_int level);
/**
* @brief Read a X.509 certificate from a DER encoded file.
*
* @param filename file containing DER encoded data
* @param label label describing kind of certificate
* @return created x509_t certificate, or NULL if invalid.
*
* @ingroup crypto
*/
x509_t *x509_create_from_file(const char *filename, const char *label);
/**
* @brief Parses a DER encoded authorityKeyIdentifier
*
* @param blob blob containing DER encoded data
* @param level0 indicates the current parsing level
* @param authKeyID assigns the authorityKeyIdentifier
* @param authKeySerialNumber assigns the authKeySerialNumber
*
* @ingroup crypto
*/
void x509_parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID, chunk_t *authKeySerialNumber);
/**
* @brief Parses DER encoded generalNames
*
* @param blob blob containing DER encoded data
* @param level0 indicates the current parsing level
* @param implicit implicit coding is used
* @param list list of decoded generalNames
*
* @ingroup crypto
*/
void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list);
/**
* @brief Builds a DER encoded list of generalNames
*
* @param list list of generalNames to be encoded
* @return DER encoded list of generalNames
*
* @ingroup crypto
*/
chunk_t x509_build_generalNames(linked_list_t *list);
/**
* @brief Builds a DER encoded list of subjectAltNames
*
* @param list list of subjectAltNames to be encoded
* @return DER encoded list of subjectAltNames
*
* @ingroup crypto
*/
chunk_t x509_build_subjectAltNames(linked_list_t *list);
#endif /* X509_H_ */
+103
View File
@@ -0,0 +1,103 @@
/*
* Copyright (C) 2008 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 database database
* @{ @ingroup database
*/
#ifndef DATABASE_H_
#define DATABASE_H_
typedef enum db_type_t db_type_t;
typedef struct database_t database_t;
#include <utils/enumerator.h>
/**
* Database column types
*/
enum db_type_t {
/** integer type, argument is an "int" */
DB_INT,
/** unsigned integer, argument is an "u_int" */
DB_UINT,
/** string type, argument is a "char*" */
DB_TEXT,
/** binary large object type, argument is a "chunk_t" */
DB_BLOB,
/** floating point, argument is a "double" */
DB_DOUBLE,
/** NULL, takes no argument */
DB_NULL,
};
/**
* Interface for a database implementation.
*
* @code
int affected, rowid, aint;
char *atext;
database_t *db;
enumerator_t *enumerator;
db = lib->database->create("mysql://user:pass@host/database");
affected = db->execute(db, &rowid, "INSERT INTO table VALUES (?, ?)",
DB_INT, 77, DB_TEXT, "a text");
printf("inserted %d row, new row ID: %d\n", affected, rowid);
enumerator = db->query(db, "SELECT aint, atext FROM table WHERE aint > ?",
DB_INT, 10, // 1 argument to SQL string
DB_INT, DB_TEXT); // 2 enumerated types in query
if (enumerator)
{
while (enumerator->enumerate(enumerator, &aint, &atext))
{
printf("%d: %s\n", aint, atext);
}
enumerator->destroy(enumerator);
}
@endcode
*/
struct database_t {
/**
* Run a query which returns rows, such as a SELECT.
*
* @param sql sql query string, containing '?' placeholders
* @param ... list of sql placeholder db_type_t followed by its value,
* followed by enumerators arguments as db_type_t's
* @return enumerator as defined with arguments, NULL on failure
*/
enumerator_t* (*query)(database_t *this, char *sql, ...);
/**
* Execute a query which dows not return rows, such as INSERT.
*
* @param rowid pointer to write inserted AUTO_INCREMENT row ID, or NULL
* @param sql sql string, containing '?' placeholders
* @param ... list of sql placeholder db_type_t followed by its value
* @return number of affected rows, < 0 on failure
*/
int (*execute)(database_t *this, int *rowid, char *sql, ...);
/**
* Destroy a database connection.
*/
void (*destroy)(database_t *this);
};
#endif /* DATABASE_H_ @}*/
@@ -0,0 +1,119 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "database_factory.h"
#include <utils/linked_list.h>
#include <utils/mutex.h>
typedef struct private_database_factory_t private_database_factory_t;
/**
* private data of database_factory
*/
struct private_database_factory_t {
/**
* public functions
*/
database_factory_t public;
/**
* list of registered database_t implementations
*/
linked_list_t *databases;
/**
* mutex to lock access to databases
*/
mutex_t *mutex;
};
/**
* Implementation of database_factory_t.create.
*/
static database_t* create(private_database_factory_t *this, char *uri)
{
enumerator_t *enumerator;
database_t *database = NULL;
database_constructor_t create;
this->mutex->lock(this->mutex);
enumerator = this->databases->create_enumerator(this->databases);
while (enumerator->enumerate(enumerator, &create))
{
database = create(uri);
if (database)
{
break;
}
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return database;
}
/**
* Implementation of database_factory_t.add_database.
*/
static void add_database(private_database_factory_t *this,
database_constructor_t create)
{
this->mutex->lock(this->mutex);
this->databases->insert_last(this->databases, create);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of database_factory_t.remove_database.
*/
static void remove_database(private_database_factory_t *this,
database_constructor_t create)
{
this->mutex->lock(this->mutex);
this->databases->remove(this->databases, create, NULL);
this->mutex->unlock(this->mutex);
}
/**
* Implementation of database_factory_t.destroy
*/
static void destroy(private_database_factory_t *this)
{
this->databases->destroy(this->databases);
this->mutex->destroy(this->mutex);
free(this);
}
/*
* see header file
*/
database_factory_t *database_factory_create()
{
private_database_factory_t *this = malloc_thing(private_database_factory_t);
this->public.create = (database_t*(*)(database_factory_t*, char *url))create;
this->public.add_database = (void(*)(database_factory_t*, database_constructor_t))add_database;
this->public.remove_database = (void(*)(database_factory_t*, database_constructor_t))remove_database;
this->public.destroy = (void(*)(database_factory_t*))destroy;
this->databases = linked_list_create();
this->mutex = mutex_create(MUTEX_DEFAULT);
return &this->public;
}
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2008 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 database_factory database_factory
* @{ @ingroup database
*/
#ifndef DATABASE_FACTORY_H_
#define DATABASE_FACTORY_H_
typedef struct database_factory_t database_factory_t;
#include <database/database.h>
/**
* Generic database construction function.
*
* @param uri implementation specific connection URI
*/
typedef database_t*(*database_constructor_t)(char *uri);
/**
* Create instances of database connections using registered constructors.
*/
struct database_factory_t {
/**
* Create a database connection instance.
*
* @param uri implementation specific connection URI
* @return database_t instance, NULL if not supported/failed
*/
database_t* (*create)(database_factory_t *this, char *uri);
/**
* Register a database constructor.
*
* @param create database constructor to register
*/
void (*add_database)(database_factory_t *this, database_constructor_t create);
/**
* Unregister a previously registered database constructor.
*
* @param create database constructor to unregister
*/
void (*remove_database)(database_factory_t *this, database_constructor_t create);
/**
* Destroy a database_factory instance.
*/
void (*destroy)(database_factory_t *this);
};
/**
* Create a database_factory instance.
*/
database_factory_t *database_factory_create();
#endif /* DATABASE_FACTORY_H_ @}*/
+2 -7
View File
@@ -1,10 +1,3 @@
/**
* @file library.c
*
* @brief Logging functions for the library.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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.
*
* $Id$
*/
#include <stdarg.h>
+8 -8
View File
@@ -1,10 +1,3 @@
/**
* @file log.h
*
* @brief Logging functions for the library.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,13 @@
* 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.
*
* $Id$
*/
/**
* @defgroup debug debug
* @{ @ingroup libstrongswan
*/
#ifndef DEBUG_H_
@@ -60,4 +60,4 @@ extern void (*dbg) (int level, char *fmt, ...);
/** default logging function, prints to stderr */
void dbg_default(int level, char *fmt, ...);
#endif /* DEBUG_H_ */
#endif /* DEBUG_H_ @} */
+22 -11
View File
@@ -1,10 +1,3 @@
/**
* @file library.c
*
* @brief enum value to string conversion functions.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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.
*
* $Id$
*/
#include <stddef.h>
@@ -46,7 +41,7 @@ static char *enum_name(enum_name_t *e, int val)
/**
* output handler in printf() for enum names
*/
static int print_enum(FILE *stream, const struct printf_info *info,
static int print(FILE *stream, const struct printf_info *info,
const void *const *args)
{
enum_name_t *ed = *((enum_name_t**)(args[0]));
@@ -65,9 +60,25 @@ static int print_enum(FILE *stream, const struct printf_info *info,
}
/**
* register printf() handlers
* arginfo handler for printf() hook
*/
static void __attribute__ ((constructor))print_register()
static int arginfo(const struct printf_info *info, size_t n, int *argtypes)
{
register_printf_function(PRINTF_ENUM, print_enum, arginfo_ptr_int);
if (n > 1)
{
argtypes[0] = PA_POINTER;
argtypes[1] = PA_INT;
}
return 2;
}
/**
* return printf hook functions
*/
printf_hook_functions_t enum_get_printf_hooks()
{
printf_hook_functions_t hooks = {print, arginfo};
return hooks;
}
+34 -21
View File
@@ -1,12 +1,5 @@
/**
* @file enum.h
*
* @brief enum value to string conversion functions.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,15 +11,24 @@
* 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.
*
* $Id$
*/
/**
* @defgroup enum enum
* @{ @ingroup libstrongswan
*/
#ifndef ENUM_H_
#define ENUM_H_
#include <printf_hook.h>
typedef struct enum_name_t enum_name_t;
/**
* @brief Struct to store names for enums.
* Struct to store names for enums.
*
* To print the string representation of enumeration values, the strings
* are stored in these structures. Every enum_name contains a range
@@ -34,14 +36,16 @@ typedef struct enum_name_t enum_name_t;
* Use the convenience macros to define these linked ranges.
*
* For a single range, use:
* ENUM(name, first, last, string1, string2, ...)
*
* @code
ENUM(name, first, last, string1, string2, ...)
@endcode
* For multiple linked ranges, use:
* ENUM_BEGIN(name, first, last, string1, string2, ...)
* ENUM_NEXT(name, first, last, last_from_previous, string3, ...)
* ENUM_NEXT(name, first, last, last_from_previous, string4, ...)
* ENUM_END(name, last_from_previous)
*
* @code
ENUM_BEGIN(name, first, last, string1, string2, ...)
ENUM_NEXT(name, first, last, last_from_previous, string3, ...)
ENUM_NEXT(name, first, last, last_from_previous, string4, ...)
ENUM_END(name, last_from_previous)
@endcode
* The ENUM and the ENUM_END define a enum_name_t pointer with the name supplied
* in "name".
*
@@ -62,7 +66,7 @@ struct enum_name_t {
};
/**
* @brief Begin a new enum_name list.
* Begin a new enum_name list.
*
* @param name name of the enum_name list
* @param first enum value of the first enum string
@@ -72,7 +76,7 @@ struct enum_name_t {
#define ENUM_BEGIN(name, first, last, ...) static enum_name_t name##last = {first, last, NULL, { __VA_ARGS__ }}
/**
* @brief Continue a enum name list startetd with ENUM_BEGIN.
* Continue a enum name list startetd with ENUM_BEGIN.
*
* @param name name of the enum_name list
* @param first enum value of the first enum string
@@ -83,7 +87,7 @@ struct enum_name_t {
#define ENUM_NEXT(name, first, last, prev, ...) static enum_name_t name##last = {first, last, &name##prev, { __VA_ARGS__ }}
/**
* @brief Complete enum name list started with ENUM_BEGIN.
* Complete enum name list started with ENUM_BEGIN.
*
* @param name name of the enum_name list
* @param prev enum value of the "last" defined in ENUM_BEGIN/previous ENUM_NEXT
@@ -91,7 +95,7 @@ struct enum_name_t {
#define ENUM_END(name, prev) enum_name_t *name = &name##prev;
/**
* @brief Define a enum name with only one range.
* Define a enum name with only one range.
*
* This is a convenience macro to use when a enum_name list contains only
* one range, and is equal as defining ENUM_BEGIN followed by ENUM_END.
@@ -103,4 +107,13 @@ struct enum_name_t {
*/
#define ENUM(name, first, last, ...) ENUM_BEGIN(name, first, last, __VA_ARGS__); ENUM_END(name, last)
#endif /* ENUM_H_ */
/**
* Get printf hook functions for enum_names_t.
*
* The handler takes the arguments: enum_names_t *names, int value
*
* @return printf hook functions
*/
printf_hook_functions_t enum_get_printf_hooks();
#endif /* ENUM_H_ @}*/
+105
View File
@@ -0,0 +1,105 @@
/*
* Copyright (C) 2008 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 fetcher fetcher
* @{ @ingroup fetcher
*/
#ifndef FETCHER_H_
#define FETCHER_H_
typedef struct fetcher_t fetcher_t;
typedef enum fetcher_option_t fetcher_option_t;
#include <stdarg.h>
#include <library.h>
/**
* Fetching options to use for fetcher_t.fetch() call.
*/
enum fetcher_option_t {
/**
* Data to include in fetch request, e.g. on a HTTP post.
* Additional argument is a chunk_t
*/
FETCH_REQUEST_DATA,
/**
* Mime-Type of data included in FETCH_REQUEST_DATA.
* Additional argument is a char*.
*/
FETCH_REQUEST_TYPE,
/**
* Timeout to use for fetch, in seconds.
* Additional argument is u_int
*/
FETCH_TIMEOUT,
/**
* end of fetching options
*/
FETCH_END,
};
/**
* Constructor function which creates fetcher instances.
*
* @return fetcher instance
*/
typedef fetcher_t* (*fetcher_constructor_t)();
/**
* Fetcher interface, an implementation fetches data from an URL.
*/
struct fetcher_t {
/**
* Fetch data from URI into chunk.
*
* The fetcher returns NOT_SUPPORTED to indicate that it is uncappable
* to handle such URLs. Other return values indicate a failure, and
* fetching of that URL gets cancelled.
*
* @param uri URI to fetch from
* @param result chunk which receives allocated data
* @return
* - SUCCESS if fetch was successful
* - NOT_SUPPORTED if fetcher does not support such URLs
* - FAILED, NOT_FOUND, PARSE_ERROR on failure
*/
status_t (*fetch)(fetcher_t *this, char *uri, chunk_t *result);
/**
* Set a fetcher option, as defined in fetcher_option_t.
*
* Arguments passed to options must stay in memory until fetch() returns.
*
* @param option option to set
* @param ... variable argument(s) to option
* @return TRUE if option supported, FALSE otherwise
*/
bool (*set_option)(fetcher_t *this, fetcher_option_t option, ...);
/**
* Destroy the fetcher instance.
*/
void (*destroy)(fetcher_t *this);
};
#endif /* FETCHER_H_ @}*/
+206
View File
@@ -0,0 +1,206 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "fetcher_manager.h"
#include <debug.h>
#include <utils/linked_list.h>
#include <utils/mutex.h>
typedef struct private_fetcher_manager_t private_fetcher_manager_t;
/**
* private data of fetcher_manager
*/
struct private_fetcher_manager_t {
/**
* public functions
*/
fetcher_manager_t public;
/**
* list of registered fetchers, as entry_t
*/
linked_list_t *fetchers;
/**
* read write lock to list
*/
pthread_rwlock_t lock;
};
typedef struct {
/** assocaited fetcher construction function */
fetcher_constructor_t create;
/** URL this fetcher support */
char *url;
} entry_t;
/**
* destroy an entry_t
*/
static void entry_destroy(entry_t *entry)
{
free(entry->url);
free(entry);
}
/**
* Implementation of fetcher_manager_t.fetch.
*/
static status_t fetch(private_fetcher_manager_t *this,
char *url, chunk_t *response, ...)
{
enumerator_t *enumerator;
status_t status = NOT_SUPPORTED;
entry_t *entry;
bool capable = FALSE;
pthread_rwlock_rdlock(&this->lock);
enumerator = this->fetchers->create_enumerator(this->fetchers);
while (enumerator->enumerate(enumerator, &entry))
{
fetcher_option_t opt;
fetcher_t *fetcher;
bool good = TRUE;
va_list args;
/* check URL support of fetcher */
if (strncasecmp(entry->url, url, strlen(entry->url)))
{
continue;
}
/* create fetcher instance and set options */
fetcher = entry->create();
if (!fetcher)
{
continue;
}
va_start(args, response);
while (good)
{
opt = va_arg(args, fetcher_option_t);
switch (opt)
{
case FETCH_REQUEST_DATA:
good = fetcher->set_option(fetcher, opt, va_arg(args, chunk_t));
continue;
case FETCH_REQUEST_TYPE:
good = fetcher->set_option(fetcher, opt, va_arg(args, char*));
continue;
case FETCH_TIMEOUT:
good = fetcher->set_option(fetcher, opt, va_arg(args, u_int));
continue;
case FETCH_END:
break;;
}
break;
}
va_end(args);
if (!good)
{ /* fetcher does not support supplied options, try another */
fetcher->destroy(fetcher);
continue;
}
status = fetcher->fetch(fetcher, url, response);
fetcher->destroy(fetcher);
/* try another fetcher only if this one does not support that URL */
if (status == NOT_SUPPORTED)
{
continue;
}
capable = TRUE;
break;
}
enumerator->destroy(enumerator);
pthread_rwlock_unlock(&this->lock);
if (!capable)
{
DBG1("unable to fetch from %s, no capable fetcher found", url);
}
return status;
}
/**
* Implementation of fetcher_manager_t.add_fetcher.
*/
static void add_fetcher(private_fetcher_manager_t *this,
fetcher_constructor_t create, char *url)
{
entry_t *entry = malloc_thing(entry_t);
entry->url = strdup(url);
entry->create = create;
pthread_rwlock_wrlock(&this->lock);
this->fetchers->insert_last(this->fetchers, entry);
pthread_rwlock_unlock(&this->lock);
}
/**
* Implementation of fetcher_manager_t.remove_fetcher.
*/
static void remove_fetcher(private_fetcher_manager_t *this,
fetcher_constructor_t create)
{
enumerator_t *enumerator;
entry_t *entry;
pthread_rwlock_wrlock(&this->lock);
enumerator = this->fetchers->create_enumerator(this->fetchers);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->create == create)
{
this->fetchers->remove_at(this->fetchers, enumerator);
entry_destroy(entry);
}
}
enumerator->destroy(enumerator);
pthread_rwlock_unlock(&this->lock);
}
/**
* Implementation of fetcher_manager_t.destroy
*/
static void destroy(private_fetcher_manager_t *this)
{
this->fetchers->destroy_function(this->fetchers, (void*)entry_destroy);
pthread_rwlock_destroy(&this->lock);
free(this);
}
/*
* see header file
*/
fetcher_manager_t *fetcher_manager_create()
{
private_fetcher_manager_t *this = malloc_thing(private_fetcher_manager_t);
this->public.fetch = (status_t(*)(fetcher_manager_t*, char *url, chunk_t *response, ...))fetch;
this->public.add_fetcher = (void(*)(fetcher_manager_t*, fetcher_constructor_t,char*))add_fetcher;
this->public.remove_fetcher = (void(*)(fetcher_manager_t*, fetcher_constructor_t))remove_fetcher;
this->public.destroy = (void(*)(fetcher_manager_t*))destroy;
this->fetchers = linked_list_create();
pthread_rwlock_init(&this->lock, NULL);
return &this->public;
}
@@ -0,0 +1,74 @@
/*
* Copyright (C) 2008 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 fetcher_manager fetcher_manager
* @{ @ingroup fetcher
*/
#ifndef FETCHER_MANAGER_H_
#define FETCHER_MANAGER_H_
typedef struct fetcher_manager_t fetcher_manager_t;
#include <fetcher/fetcher.h>
/**
* Fetches from URIs using registerd fetcher_t instances.
*/
struct fetcher_manager_t {
/**
* Fetch data from URI into chunk.
*
* The variable argument list contains fetcher_option_t's, followed
* by a option specific data argument.
*
* @param uri URI to fetch from
* @param result chunk which receives allocated data
* @param options FETCH_END terminated fetcher_option_t arguments
* @return status indicating result of fetch
*/
status_t (*fetch)(fetcher_manager_t *this, char *url, chunk_t *response, ...);
/**
* Register a fetcher implementation.
*
* @param constructor fetcher constructor function
* @param url URL type this fetcher fetches, e.g. "http://"
*/
void (*add_fetcher)(fetcher_manager_t *this,
fetcher_constructor_t constructor, char *url);
/**
* Unregister a previously registered fetcher implementation.
*
* @param constructor fetcher constructor function to unregister
*/
void (*remove_fetcher)(fetcher_manager_t *this,
fetcher_constructor_t constructor);
/**
* Destroy a fetcher_manager instance.
*/
void (*destroy)(fetcher_manager_t *this);
};
/**
* Create a fetcher_manager instance.
*/
fetcher_manager_t *fetcher_manager_create();
#endif /* FETCHER_MANAGER_H_ @}*/
+2 -7
View File
@@ -1,10 +1,3 @@
/**
* @file fips.c
*
* @brief Implementation of the libstrongswan integrity test.
*
*/
/*
* Copyright (C) 2007 Bruno Krieg, Daniel Wydler
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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.
*
* $Id$
*/
#include <stdio.h>
+16 -17
View File
@@ -1,11 +1,3 @@
/**
* @file fips.h
*
* @brief Interface of the libstrongswan integrity test
*
* @ingroup fips
*/
/*
* Copyright (C) 2007 Bruno Krieg, Daniel Wydler
* Hochschule fuer Technik Rapperswil
@@ -19,6 +11,13 @@
* 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.
*
* $Id$
*/
/**
* @defgroup fips fips
* @{ @ingroup fips
*/
#ifndef FIPS_H_
@@ -27,21 +26,21 @@
#include <library.h>
/**
* @brief compute HMAC signature over RODATA and TEXT sections of libstrongswan
* compute HMAC signature over RODATA and TEXT sections of libstrongswan
*
* @param key key used for HMAC signature in ASCII string format
* @param signature HMAC signature in HEX string format
* @return TRUE if HMAC signature computation was successful
* @param key key used for HMAC signature in ASCII string format
* @param signature HMAC signature in HEX string format
* @return TRUE if HMAC signature computation was successful
*/
bool fips_compute_hmac_signature(const char *key, char *signature);
/**
* @brief verify HMAC signature over RODATA and TEXT sections of libstrongswan
* verify HMAC signature over RODATA and TEXT sections of libstrongswan
*
* @param key key used for HMAC signature in ASCII string format
* @param signature signature value from fips_signature.h in HEX string format
* @return TRUE if signatures agree
* @param key key used for HMAC signature in ASCII string format
* @param signature signature value from fips_signature.h in HEX string format
* @return TRUE if signatures agree
*/
bool fips_verify_hmac_signature(const char *key, const char *signature);
#endif /*FIPS_H_*/
#endif /*FIPS_H_ @} */
+2 -7
View File
@@ -1,14 +1,9 @@
/**
* @file fips_canister_end.c
*
* @brief Marks the end of TEXT and RODATA.
*
*/
/* ====================================================================
* Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
* and usage in source and binary forms are granted according to the
* OpenSSL license.
*
* $Id$
*/
#include <stdio.h>
+2 -7
View File
@@ -1,14 +1,9 @@
/**
* @file fips_canister_start.c
*
* @brief Marks the start of TEXT and RODATA.
*
*/
/* ====================================================================
* Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
* and usage in source and binary forms are granted according to the
* OpenSSL license.
*
* $Id$
*/
#include <stdio.h>
+3 -8
View File
@@ -1,10 +1,3 @@
/**
* @file fips_signer.c
*
* @brief Computes a HMAC signature and stores it in fips_signature.h.
*
*/
/*
* Copyright (C) 2007 Bruno Krieg, Daniel Wydler
* Hochschule fuer Technik Rapperswil, Switzerland
@@ -18,6 +11,8 @@
* 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.
*
* $Id$
*/
#include <stdio.h>
@@ -57,7 +52,7 @@ int main(int argc, char* argv[])
fprintf(f, "const char *hmac_key = \"%s\";\n", hmac_key);
fprintf(f, "const char *hmac_signature = \"%s\";\n", hmac_signature);
fprintf(f, "\n");
fprintf(f, "#endif /* FIPS_SIGNATURE_H_ */\n");
fprintf(f, "#endif /* FIPS_SIGNATURE_H_ @} */\n");
fclose(f);
exit(0);
}
+81 -165
View File
@@ -1,13 +1,5 @@
/**
* @file library.c
*
* @brief Helper functions and definitions.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -19,175 +11,99 @@
* 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.
*
* $Id$
*/
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <pthread.h>
#include "library.h"
#include <printf_hook.h>
#include <stdlib.h>
ENUM(status_names, SUCCESS, DESTROY_ME,
"SUCCESS",
"FAILED",
"OUT_OF_RES",
"ALREADY_DONE",
"NOT_SUPPORTED",
"INVALID_ARG",
"NOT_FOUND",
"PARSE_ERROR",
"VERIFY_ERROR",
"INVALID_STATE",
"DESTROY_ME",
"NEED_MORE",
);
#include <utils.h>
#include <chunk.h>
#include <utils/identification.h>
#include <utils/host.h>
#include <utils/leak_detective.h>
typedef struct private_library_t private_library_t;
/**
* Described in header.
* private data of library
*/
void *clalloc(void * pointer, size_t size)
struct private_library_t {
/**
* public functions
*/
library_t public;
#ifdef LEAK_DETECTIVE
/**
* Memory leak detective, if enabled
*/
leak_detective_t *detective;
#endif /* LEAK_DETECTIVE */
};
/**
* library instance
*/
library_t *lib;
/**
* Implementation of library_t.destroy
*/
void library_deinit()
{
void *data;
data = malloc(size);
private_library_t *this = (private_library_t*)lib;
this->public.plugins->destroy(this->public.plugins);
this->public.settings->destroy(this->public.settings);
this->public.creds->destroy(this->public.creds);
this->public.crypto->destroy(this->public.crypto);
this->public.fetcher->destroy(this->public.fetcher);
this->public.db->destroy(this->public.db);
this->public.printf_hook->destroy(this->public.printf_hook);
memcpy(data, pointer,size);
#ifdef LEAK_DETECTIVE
if (this->detective)
{
this->detective->destroy(this->detective);
}
#endif /* LEAK_DETECTIVE */
free(this);
lib = NULL;
}
/*
* see header file
*/
void library_init(char *settings)
{
printf_hook_t *pfh;
private_library_t *this = malloc_thing(private_library_t);
lib = &this->public;
return (data);
}
#ifdef LEAK_DETECTIVE
this->detective = leak_detective_create();
#endif /* LEAK_DETECTIVE */
/**
* Described in header.
*/
void memxor(u_int8_t dest[], u_int8_t src[], size_t n)
{
size_t i;
for (i = 0; i < n; i++)
{
dest[i] ^= src[i];
}
}
/**
* We use a single mutex for all refcount variables. This
* is not optimal for performance, but the critical section
* is not that long...
* TODO: Consider to include a mutex in each refcount_t variable.
*/
static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Described in header.
*
* TODO: May be implemented with atomic CPU instructions
* instead of a mutex.
*/
void ref_get(refcount_t *ref)
{
pthread_mutex_lock(&ref_mutex);
(*ref)++;
pthread_mutex_unlock(&ref_mutex);
}
/**
* Described in header.
*
* TODO: May be implemented with atomic CPU instructions
* instead of a mutex.
*/
bool ref_put(refcount_t *ref)
{
bool more_refs;
pfh = printf_hook_create();
this->public.printf_hook = pfh;
pthread_mutex_lock(&ref_mutex);
more_refs = --(*ref);
pthread_mutex_unlock(&ref_mutex);
return !more_refs;
}
/**
* output handler in printf() for time_t
*/
static int print_time(FILE *stream, const struct printf_info *info,
const void *const *args)
{
static const char* months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
time_t *time = *((time_t**)(args[0]));
bool utc = TRUE;
struct tm t;
pfh->add_handler(pfh, 'b', mem_get_printf_hooks());
pfh->add_handler(pfh, 'B', chunk_get_printf_hooks());
pfh->add_handler(pfh, 'D', identification_get_printf_hooks());
pfh->add_handler(pfh, 'H', host_get_printf_hooks());
pfh->add_handler(pfh, 'N', enum_get_printf_hooks());
pfh->add_handler(pfh, 'T', time_get_printf_hooks());
pfh->add_handler(pfh, 'V', time_delta_get_printf_hooks());
if (info->alt)
{
utc = *((bool*)(args[1]));
}
if (time == UNDEFINED_TIME)
{
return fprintf(stream, "--- -- --:--:--%s----",
info->alt ? " UTC " : " ");
}
if (utc)
{
gmtime_r(time, &t);
}
else
{
localtime_r(time, &t);
}
return fprintf(stream, "%s %02d %02d:%02d:%02d%s%04d",
months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
this->public.crypto = crypto_factory_create();
this->public.creds = credential_factory_create();
this->public.fetcher = fetcher_manager_create();
this->public.db = database_factory_create();
this->public.settings = settings_create(settings);
this->public.plugins = plugin_loader_create();
}
/**
* output handler in printf() for time deltas
*/
static int print_time_delta(FILE *stream, const struct printf_info *info,
const void *const *args)
{
char* unit = "second";
time_t *arg1, *arg2;
time_t delta;
arg1 = *((time_t**)(args[0]));
if (info->alt)
{
arg2 = *((time_t**)(args[1]));
delta = abs(*arg1 - *arg2);
}
else
{
delta = *arg1;
}
if (delta > 2 * 60 * 60 * 24)
{
delta /= 60 * 60 * 24;
unit = "day";
}
else if (delta > 2 * 60 * 60)
{
delta /= 60 * 60;
unit = "hour";
}
else if (delta > 2 * 60)
{
delta /= 60;
unit = "minute";
}
return fprintf(stream, "%d %s%s", delta, unit, (delta == 1)? "":"s");
}
/**
* register printf() handlers for time_t
*/
static void __attribute__ ((constructor))print_register()
{
register_printf_function(PRINTF_TIME, print_time, arginfo_ptr_alt_ptr_int);
register_printf_function(PRINTF_TIME_DELTA, print_time_delta, arginfo_ptr_alt_ptr_ptr);
}
+78 -284
View File
@@ -1,12 +1,5 @@
/**
* @file library.h
*
* @brief Helper functions and definitions.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -19,318 +12,119 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
* $Id$
*/
/**
* @defgroup libstrongswan libstrongswan
*
* @defgroup asn1 asn1
* @ingroup libstrongswan
*
* @defgroup credentials credentials
* @ingroup libstrongswan
*
* @defgroup keys keys
* @ingroup credentials
*
* @defgroup certificates certificates
* @ingroup credentials
*
* @defgroup crypto crypto
* @ingroup libstrongswan
* @defgroup database database
* @ingroup libstrongswan
* @defgroup fetcher fetcher
* @ingroup libstrongswan
* @defgroup fips fips
* @ingroup libstrongswan
* @defgroup plugins plugins
* @ingroup libstrongswan
* @defgroup utils utils
* @ingroup libstrongswan
*/
/**
* @defgroup library library
* @{ @ingroup libstrongswan
*/
#ifndef LIBRARY_H_
#define LIBRARY_H_
/**
* @defgroup libstrongswan libstrongswan
*
* libstrongswan: library with various cryptographic, X.509 trust chain and
* identity management functions.
*/
#include <utils.h>
#include <chunk.h>
#include <settings.h>
#include <printf_hook.h>
#include <plugins/plugin_loader.h>
#include <crypto/crypto_factory.h>
#include <credentials/credential_factory.h>
#include <fetcher/fetcher_manager.h>
#include <database/database_factory.h>
typedef struct library_t library_t;
/**
* @defgroup asn1 asn1
*
* ASN.1 definitions, parser and generator functions.
*
* @ingroup libstrongswan
* Libstrongswan library context, contains library relevant globals.
*/
struct library_t {
/**
* @defgroup crypto crypto
*
* Various cryptographic algorithms.
*
* @ingroup libstrongswan
*/
/**
* @defgroup crypters crypters
*
* Symmetric encryption algorithms, used for
* encryption and decryption.
*
* @ingroup crypto
*/
/**
* @defgroup hashers hashers
*
* Hashing algorithms, such as MD5 or SHA1
*
* @ingroup crypto
*/
/**
* @defgroup prfs prfs
*
* Pseudo random functions, used to generate
* pseude random byte sequences.
*
* @ingroup crypto
*/
/**
* @defgroup rsa rsa
*
* RSA private/public key algorithm.
*
* @ingroup crypto
*/
/**
* @defgroup signers signers
*
* Symmetric signing algorithms,
* used to ensure message integrity.
*
* @ingroup crypto
*/
/**
* @defgroup fips fips
*
* Code integrity check of libstrongswan
*
* @ingroup libstrongswan
*/
/**
* @defgroup utils utils
*
* Generic helper classes.
*
* @ingroup libstrongswan
*/
#include <gmp.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stddef.h>
#include <printf.h>
#include <enum.h>
/**
* Number of bits in a byte
*/
#define BITS_PER_BYTE 8
/**
* Default length for various auxiliary text buffers
*/
#define BUF_LEN 512
/**
* Macro compares two strings for equality
*/
#define streq(x,y) (strcmp(x, y) == 0)
/**
* Macro compares two strings for equality
*/
#define strneq(x,y,len) (strncmp(x, y, len) == 0)
/**
* Macro compares two binary blobs for equality
*/
#define memeq(x,y,len) (memcmp(x, y, len) == 0)
/**
* Macro gives back larger of two values.
*/
#define max(x,y) ((x) > (y) ? (x):(y))
/**
* Macro gives back smaller of two values.
*/
#define min(x,y) ((x) < (y) ? (x):(y))
/**
* Call destructor of an object, if object != NULL
*/
#define DESTROY_IF(obj) if (obj) obj->destroy(obj)
/**
* Call offset destructor of an object, if object != NULL
*/
#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
/**
* Call function destructor of an object, if object != NULL
*/
#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
/**
* Debug macro to follow control flow
*/
#define POS printf("%s, line %d\n", __FILE__, __LINE__)
/**
* Macro to allocate a sized type.
*/
#define malloc_thing(thing) ((thing*)malloc(sizeof(thing)))
/**
* Assign a function as a class method
*/
#define ASSIGN(method, function) (method = (typeof(method))function)
/**
* time_t not defined
*/
#define UNDEFINED_TIME 0
/**
* General purpose boolean type.
*/
typedef int bool;
#define FALSE 0
#define TRUE 1
typedef enum status_t status_t;
/**
* Return values of function calls.
*/
enum status_t {
/**
* Call succeeded.
* Printf hook registering facility
*/
SUCCESS,
printf_hook_t *printf_hook;
/**
* Call failed.
* crypto algorithm registry and factory
*/
FAILED,
crypto_factory_t *crypto;
/**
* Out of resources.
* credential constructor registry and factory
*/
OUT_OF_RES,
credential_factory_t *creds;
/**
* The suggested operation is already done
* URL fetching facility
*/
ALREADY_DONE,
fetcher_manager_t *fetcher;
/**
* Not supported.
* database construction factory
*/
NOT_SUPPORTED,
database_factory_t *db;
/**
* One of the arguments is invalid.
* plugin loading facility
*/
INVALID_ARG,
plugin_loader_t *plugins;
/**
* Something could not be found.
* various settings loaded from settings file
*/
NOT_FOUND,
/**
* Error while parsing.
*/
PARSE_ERROR,
/**
* Error while verifying.
*/
VERIFY_ERROR,
/**
* Object in invalid state.
*/
INVALID_STATE,
/**
* Destroy object which called method belongs to.
*/
DESTROY_ME,
/**
* Another call to the method is required.
*/
NEED_MORE,
settings_t *settings;
};
/**
* used by strict_crl_policy
*/
typedef enum {
STRICT_NO,
STRICT_YES,
STRICT_IFURI
} strict_t;
/**
* enum_names for type status_t.
*/
extern enum_name_t *status_names;
/**
* deprecated pluto style return value:
* error message, NULL for success
*/
typedef const char *err_t;
/**
* Handle struct timeval like an own type.
*/
typedef struct timeval timeval_t;
/**
* Handle struct timespec like an own type.
*/
typedef struct timespec timespec_t;
/**
* Handle struct chunk_t like an own type.
*/
typedef struct sockaddr sockaddr_t;
/**
* Clone a data to a newly allocated buffer
*/
void *clalloc(void *pointer, size_t size);
/**
* Same as memcpy, but XORs src into dst instead of copy
*/
void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
/**
* Special type to count references
*/
typedef volatile u_int refcount_t;
/**
* @brief Get a new reference.
* Initialize library, creates "lib" instance.
*
* Increments the reference counter atomic.
*
* @param ref pointer to ref counter
* @param settings file to read settings from, may be NULL for none
*/
void ref_get(refcount_t *ref);
void library_init(char *settings);
/**
* @brief Put back a unused reference.
*
* Decrements the reference counter atomic and
* says if more references available.
*
* @param ref pointer to ref counter
* @return TRUE if no more references counted
* Deinitialize library, destroys "lib" instance.
*/
bool ref_put(refcount_t *ref);
void library_deinit();
/**
* Library instance, set after between library_init() and library_deinit() calls.
*/
extern library_t *lib;
#include <chunk.h>
#include <printf_hook.h>
#endif /* LIBRARY_H_ */
#endif /* LIBRARY_H_ @}*/
+10
View File
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libstrongswan-aes.la
libstrongswan_aes_la_SOURCES = aes_plugin.h aes_plugin.c aes_crypter.c aes_crypter.h
libstrongswan_aes_la_LDFLAGS = -module
@@ -1,11 +1,4 @@
/**
* @file aes_cbc_crypter.c
*
* @brief Implementation of aes_cbc_crypter_t
*
*/
/*
/*
* Copyright (C) 2001 Dr B. R. Gladman <brg@gladman.uk.net>
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -20,11 +13,11 @@
* 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.
*
* $Id$
*/
#include "aes_cbc_crypter.h"
#include "aes_crypter.h"
/*
* The number of key schedule words for different block and key lengths
@@ -43,19 +36,19 @@
#define AES_BLOCK_SIZE 16
typedef struct private_aes_cbc_crypter_t private_aes_cbc_crypter_t;
typedef struct private_aes_crypter_t private_aes_crypter_t;
/**
* @brief Class implementing the AES symmetric encryption algorithm.
* Class implementing the AES symmetric encryption algorithm.
*
* @ingroup crypters
*/
struct private_aes_cbc_crypter_t {
struct private_aes_crypter_t {
/**
* Public part of this class.
*/
aes_cbc_crypter_t public;
aes_crypter_t public;
/**
* Number of words in the key input block.
@@ -91,7 +84,7 @@ struct private_aes_cbc_crypter_t {
* @param[in] in_blk block to decrypt
* @param[out] out_blk decrypted data are written to this location
*/
void (*decrypt_block) (const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]);
void (*decrypt_block) (const private_aes_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]);
/**
* Encrypts a block.
@@ -102,7 +95,7 @@ struct private_aes_cbc_crypter_t {
* @param[in] in_blk block to encrypt
* @param[out] out_blk encrypted data are written to this location
*/
void (*encrypt_block) (const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]);
void (*encrypt_block) (const private_aes_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[]);
};
@@ -1243,9 +1236,9 @@ switch(nc) \
#endif
/**
* Implementation of private_aes_cbc_crypter_t.encrypt_block.
* Implementation of private_aes_crypter_t.encrypt_block.
*/
static void encrypt_block(const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[])
static void encrypt_block(const private_aes_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[])
{ u_int32_t locals(b0, b1);
const u_int32_t *kp = this->aes_e_key;
@@ -1304,9 +1297,9 @@ static void encrypt_block(const private_aes_cbc_crypter_t *this, const unsigned
}
/**
* Implementation of private_aes_cbc_crypter_t.decrypt_block.
* Implementation of private_aes_crypter_t.decrypt_block.
*/
static void decrypt_block(const private_aes_cbc_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[])
static void decrypt_block(const private_aes_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[])
{ u_int32_t locals(b0, b1);
const u_int32_t *kp = this->aes_d_key;
@@ -1367,7 +1360,7 @@ static void decrypt_block(const private_aes_cbc_crypter_t *this, const unsigned
/**
* Implementation of crypter_t.decrypt.
*/
static status_t decrypt (private_aes_cbc_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted)
static status_t decrypt (private_aes_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted)
{
int ret, pos;
const u_int32_t *iv_i;
@@ -1415,7 +1408,7 @@ static status_t decrypt (private_aes_cbc_crypter_t *this, chunk_t data, chunk_t
/**
* Implementation of crypter_t.decrypt.
*/
static status_t encrypt (private_aes_cbc_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted)
static status_t encrypt (private_aes_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted)
{
int ret, pos;
const u_int32_t *iv_i;
@@ -1460,7 +1453,7 @@ static status_t encrypt (private_aes_cbc_crypter_t *this, chunk_t data, chunk_t
/**
* Implementation of crypter_t.get_block_size.
*/
static size_t get_block_size (private_aes_cbc_crypter_t *this)
static size_t get_block_size (private_aes_crypter_t *this)
{
return AES_BLOCK_SIZE;
}
@@ -1468,7 +1461,7 @@ static size_t get_block_size (private_aes_cbc_crypter_t *this)
/**
* Implementation of crypter_t.get_key_size.
*/
static size_t get_key_size (private_aes_cbc_crypter_t *this)
static size_t get_key_size (private_aes_crypter_t *this)
{
return this->key_size;
}
@@ -1476,7 +1469,7 @@ static size_t get_key_size (private_aes_cbc_crypter_t *this)
/**
* Implementation of crypter_t.set_key.
*/
static status_t set_key (private_aes_cbc_crypter_t *this, chunk_t key)
static status_t set_key (private_aes_crypter_t *this, chunk_t key)
{
u_int32_t *kf, *kt, rci, f = 0;
u_int8_t *in_key = key.ptr;
@@ -1570,9 +1563,9 @@ static status_t set_key (private_aes_cbc_crypter_t *this, chunk_t key)
}
/**
* Implementation of crypter_t.destroy and aes_cbc_crypter_t.destroy.
* Implementation of crypter_t.destroy and aes_crypter_t.destroy.
*/
static void destroy (private_aes_cbc_crypter_t *this)
static void destroy (private_aes_crypter_t *this)
{
free(this);
}
@@ -1580,16 +1573,24 @@ static void destroy (private_aes_cbc_crypter_t *this)
/*
* Described in header
*/
aes_cbc_crypter_t *aes_cbc_crypter_create(size_t key_size)
aes_crypter_t *aes_crypter_create(encryption_algorithm_t algo, size_t key_size)
{
private_aes_cbc_crypter_t *this = malloc_thing(private_aes_cbc_crypter_t);
private_aes_crypter_t *this;
if (algo != ENCR_AES_CBC)
{
return NULL;
}
this = malloc_thing(private_aes_crypter_t);
#if !defined(FIXED_TABLES)
if(!tab_gen) { gen_tabs(); tab_gen = 1; }
#endif
this->key_size = key_size;
switch(key_size) {
switch(key_size)
{
case 32: /* bytes */
this->aes_Nkey = 8;
break;
@@ -1,13 +1,5 @@
/**
* @file aes_cbc_crypter.h
*
* @brief Interface of aes_cbc_crypter_t
*
*/
/*
* Copyright (C) 2001 Dr B. R. Gladman <brg@gladman.uk.net>
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -22,22 +14,22 @@
* for more details.
*/
#ifndef AES_CBC_CRYPTER_H_
#define AES_CBC_CRYPTER_H_
/**
* @defgroup aes_crypter aes_crypter
* @{ @ingroup aes_p
*/
typedef struct aes_cbc_crypter_t aes_cbc_crypter_t;
#ifndef AES_CRYPTER_H_
#define AES_CRYPTER_H_
typedef struct aes_crypter_t aes_crypter_t;
#include <crypto/crypters/crypter.h>
/**
* @brief Class implementing the AES symmetric encryption algorithm.
*
* @b Constructors:
* - aes_cbc_crypter_create()
*
* @ingroup crypters
* Class implementing the AES encryption algorithm.
*/
struct aes_cbc_crypter_t {
struct aes_crypter_t {
/**
* The crypter_t interface.
@@ -46,16 +38,13 @@ struct aes_cbc_crypter_t {
};
/**
* @brief Constructor to create aes_cbc_crypter_t objects.
*
* Supported key sizes are: 16, 24 or 32.
* Constructor to create aes_crypter_t objects.
*
* @param key_size key size in bytes
* @return
* - aes_cbc_crypter_t object
* - NULL if key size not supported
* @param algo algorithm to implement
* @return aes_crypter_t object, NULL if not supported
*/
aes_cbc_crypter_t *aes_cbc_crypter_create(size_t key_size);
aes_crypter_t *aes_crypter_create(encryption_algorithm_t algo,
size_t key_size);
#endif /* AES_CBC_CRYPTER_H_ */
#endif /* AES_CRYPTER_H_ @}*/
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "aes_plugin.h"
#include <library.h>
#include "aes_crypter.h"
typedef struct private_aes_plugin_t private_aes_plugin_t;
/**
* private data of aes_plugin
*/
struct private_aes_plugin_t {
/**
* public functions
*/
aes_plugin_t public;
};
/**
* Implementation of aes_plugin_t.destroy
*/
static void destroy(private_aes_plugin_t *this)
{
lib->crypto->remove_crypter(lib->crypto,
(crypter_constructor_t)aes_crypter_create);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
private_aes_plugin_t *this = malloc_thing(private_aes_plugin_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC,
(crypter_constructor_t)aes_crypter_create);
return &this->public.plugin;
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2008 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 aes_p aes
* @ingroup plugins
*
* @defgroup aes_plugin aes_plugin
* @{ @ingroup aes_p
*/
#ifndef AES_PLUGIN_H_
#define AES_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct aes_plugin_t aes_plugin_t;
/**
* Plugin implementing AES based algorithms in software.
*/
struct aes_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a aes_plugin instance.
*/
plugin_t *plugin_create();
#endif /* AES_PLUGIN_H_ @}*/
@@ -0,0 +1,11 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libstrongswan-curl.la
libstrongswan_curl_la_SOURCES = curl_plugin.h curl_plugin.c curl_fetcher.c curl_fetcher.h
libstrongswan_curl_la_LDFLAGS = -module
libstrongswan_curl_la_LIBADD = -lcurl
@@ -0,0 +1,176 @@
/*
* Copyright (C) 2008 Martin Willi
* Copyright (C) 2007 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.
*
* $Id$
*/
#include <curl/curl.h>
#include <library.h>
#include <debug.h>
#include "curl_fetcher.h"
#define DEFAULT_TIMEOUT 10
typedef struct private_curl_fetcher_t private_curl_fetcher_t;
/**
* private data of a curl_fetcher_t object.
*/
struct private_curl_fetcher_t {
/**
* Public data
*/
curl_fetcher_t public;
/**
* CURL handle
*/
CURL* curl;
/**
* request type, as set with FETCH_REQUEST_TYPE
*/
char *request_type;
};
/**
* writes data into a dynamically resizeable chunk_t
*/
static size_t append(void *ptr, size_t size, size_t nmemb, chunk_t *data)
{
size_t realsize = size * nmemb;
data->ptr = (u_char*)realloc(data->ptr, data->len + realsize);
if (data->ptr)
{
memcpy(&data->ptr[data->len], ptr, realsize);
data->len += realsize;
}
return realsize;
}
/**
* Implements fetcher_t.fetch.
*/
static status_t fetch(private_curl_fetcher_t *this, char *uri, chunk_t *result)
{
struct curl_slist *headers = NULL;
char error[CURL_ERROR_SIZE];
char buf[256];;
status_t status;
*result = chunk_empty;
if (curl_easy_setopt(this->curl, CURLOPT_URL, uri) != CURLE_OK)
{ /* URL type not supported by curl */
return NOT_SUPPORTED;
}
curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, error);
curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE);
curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT);
curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)append);
curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void*)result);
if (this->request_type)
{
snprintf(buf, sizeof(buf), "Content-Type: %s", this->request_type);
headers = curl_slist_append(headers, buf);
curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, headers);
}
DBG2("sending http request to '%s'...", uri);
switch (curl_easy_perform(this->curl))
{
case CURLE_UNSUPPORTED_PROTOCOL:
status = NOT_SUPPORTED;
break;
case CURLE_OK:
status = SUCCESS;
break;
default:
DBG1("libcurl http request failed: %s", error);
status = FAILED;
break;
}
curl_slist_free_all(headers);
return status;
}
/**
* Implementation of fetcher_t.set_option.
*/
static bool set_option(private_curl_fetcher_t *this, fetcher_option_t option, ...)
{
va_list args;
va_start(args, option);
switch (option)
{
case FETCH_REQUEST_DATA:
{
chunk_t data = va_arg(args, chunk_t);
curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, data.ptr);
curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, data.len);
return TRUE;
}
case FETCH_REQUEST_TYPE:
{
this->request_type = va_arg(args, char*);
return TRUE;
}
case FETCH_TIMEOUT:
{
curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT,
va_arg(args, u_int));
return TRUE;
}
default:
return FALSE;
}
}
/**
* Implements fetcher_t.destroy
*/
static void destroy(private_curl_fetcher_t *this)
{
curl_easy_cleanup(this->curl);
free(this);
}
/*
* Described in header.
*/
curl_fetcher_t *curl_fetcher_create()
{
private_curl_fetcher_t *this = malloc_thing(private_curl_fetcher_t);
this->curl = curl_easy_init();
if (this->curl == NULL)
{
free(this);
return NULL;
}
this->request_type = NULL;
this->public.interface.fetch = (status_t(*)(fetcher_t*,char*,chunk_t*))fetch;
this->public.interface.set_option = (bool(*)(fetcher_t*, fetcher_option_t option, ...))set_option;
this->public.interface.destroy = (void (*)(fetcher_t*))destroy;
return &this->public;
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2008 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 curl_fetcher curl_fetcher
* @{ @ingroup curl_p
*/
#ifndef CURL_FETCHER_H_
#define CURL_FETCHER_H_
typedef struct curl_fetcher_t curl_fetcher_t;
/**
* Fetcher implementation using libcurl
*/
struct curl_fetcher_t {
/**
* Implements fetcher interface
*/
fetcher_t interface;
/**
* Destroy a curl_fetcher instance.
*/
void (*destroy)(curl_fetcher_t *this);
};
/**
* Create a curl_fetcher instance.
*/
curl_fetcher_t *curl_fetcher_create();
#endif /* CURL_FETCHER_H_ @}*/
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "curl_plugin.h"
#include <library.h>
#include <debug.h>
#include "curl_fetcher.h"
#include <curl/curl.h>
typedef struct private_curl_plugin_t private_curl_plugin_t;
/**
* private data of curl_plugin
*/
struct private_curl_plugin_t {
/**
* public functions
*/
curl_plugin_t public;
};
/**
* Implementation of curl_plugin_t.curltroy
*/
static void destroy(private_curl_plugin_t *this)
{
lib->fetcher->remove_fetcher(lib->fetcher,
(fetcher_constructor_t)curl_fetcher_create);
curl_global_cleanup();
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
CURLcode res;
private_curl_plugin_t *this = malloc_thing(private_curl_plugin_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
res = curl_global_init(CURL_GLOBAL_NOTHING);
if (res == CURLE_OK)
{
lib->fetcher->add_fetcher(lib->fetcher,
(fetcher_constructor_t)curl_fetcher_create, "file://");
lib->fetcher->add_fetcher(lib->fetcher,
(fetcher_constructor_t)curl_fetcher_create, "http://");
lib->fetcher->add_fetcher(lib->fetcher,
(fetcher_constructor_t)curl_fetcher_create, "https://");
lib->fetcher->add_fetcher(lib->fetcher,
(fetcher_constructor_t)curl_fetcher_create, "ftp://");
}
else
{
DBG1("global libcurl initializing failed: %s, curl disabled",
curl_easy_strerror(res));
}
return &this->public.plugin;
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2008 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 curl_p curl
* @ingroup plugins
*
* @defgroup curl_plugin curl_plugin
* @{ @ingroup curl_p
*/
#ifndef CURL_PLUGIN_H_
#define CURL_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct curl_plugin_t curl_plugin_t;
/**
* Plugin implementing fetcher interface using libcurl http library.
*/
struct curl_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a curl_plugin instance.
*/
plugin_t *plugin_create();
#endif /* CURL_PLUGIN_H_ @}*/
+10
View File
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libstrongswan-des.la
libstrongswan_des_la_SOURCES = des_plugin.h des_plugin.c des_crypter.c des_crypter.h
libstrongswan_des_la_LDFLAGS = -module
@@ -1,10 +1,3 @@
/**
* @file des_crypter.c
*
* @brief Implementation of des_crypter_t
*
*/
/* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -61,6 +54,8 @@
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*
* $Id$
*/
#include "des_crypter.h"
@@ -1,12 +1,5 @@
/**
* @file des_crypter.h
*
* @brief Interface of des_crypter_t
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,6 +13,11 @@
* for more details.
*/
/**
* @defgroup des_crypter des_crypter
* @{ @ingroup des_p
*/
#ifndef DES_CRYPTER_H_
#define DES_CRYPTER_H_
@@ -29,12 +27,7 @@ typedef struct des_crypter_t des_crypter_t;
/**
* @brief Class implementing the DES and 3DES encryption algorithms.
*
* @b Constructors:
* - des_crypter_create()
*
* @ingroup crypters
* Class implementing the DES and 3DES encryption algorithms.
*/
struct des_crypter_t {
@@ -45,14 +38,12 @@ struct des_crypter_t {
};
/**
* @brief Constructor to create des_crypter_t objects.
* Constructor to create des_crypter_t objects.
*
* @param algo ENCR_DES for single DES, ENCR_3DES for triple DES
* @return
* - des_crypter_t object
* - NULL if algo not supported
* @return des_crypter_t object, NULL if algo not supported
*/
des_crypter_t *des_crypter_create(encryption_algorithm_t algo);
#endif /* DES_CRYPTER_H_ */
#endif /* DES_CRYPTER_H_ @}*/
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2008 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.
*
* $Id$
*/
#include "des_plugin.h"
#include <library.h>
#include "des_crypter.h"
typedef struct private_des_plugin_t private_des_plugin_t;
/**
* private data of des_plugin
*/
struct private_des_plugin_t {
/**
* public functions
*/
des_plugin_t public;
};
/**
* Implementation of des_plugin_t.destroy
*/
static void destroy(private_des_plugin_t *this)
{
lib->crypto->remove_crypter(lib->crypto,
(crypter_constructor_t)des_crypter_create);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
private_des_plugin_t *this = malloc_thing(private_des_plugin_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
lib->crypto->add_crypter(lib->crypto, ENCR_DES,
(crypter_constructor_t)des_crypter_create);
lib->crypto->add_crypter(lib->crypto, ENCR_3DES,
(crypter_constructor_t)des_crypter_create);
return &this->public.plugin;
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2008 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 des_p des
* @ingroup plugins
*
* @defgroup des_plugin des_plugin
* @{ @ingroup des_p
*/
#ifndef DES_PLUGIN_H_
#define DES_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct des_plugin_t des_plugin_t;
/**
* Plugin implementing DES based algorithms in software.
*/
struct des_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a des_plugin instance.
*/
plugin_t *plugin_create();
#endif /* DES_PLUGIN_H_ @}*/
@@ -0,0 +1,10 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libstrongswan-fips-prf.la
libstrongswan_fips_prf_la_SOURCES = fips_prf_plugin.h fips_prf_plugin.c fips_prf.c fips_prf.h
libstrongswan_fips_prf_la_LDFLAGS = -module
@@ -1,10 +1,3 @@
/**
* @file fips_prf.c
*
* @brief Implementation for fips_prf_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
* 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.
*
* $Id$
*/
#include "fips_prf.h"
@@ -47,10 +42,15 @@ struct private_fips_prf_t {
*/
size_t b;
/**
* associated hasher when using SHA1 mode
*/
hasher_t *hasher;
/**
* G function, either SHA1 or DES
*/
void (*g)(u_int8_t t[], chunk_t c, u_int8_t res[]);
void (*g)(private_fips_prf_t *this, u_int8_t t[], chunk_t c, u_int8_t res[]);
};
/**
@@ -61,6 +61,7 @@ static u_int8_t t[] = {
0xDC,0xFE,0x10,0x32,0x54,0x76,0xC3,0xD2,0xE1,0xF0,
};
/**
* sum = (a + b) mod 2 ^ (length * 8)
*/
@@ -139,7 +140,7 @@ static void get_bytes(private_fips_prf_t *this, chunk_t seed, u_int8_t w[])
add_mod(this->b, xkey, xseed, xval);
DBG3("XVAL %b", xval, this->b);
/* b. wi = G(t, XVAL ) */
this->g(t, xval_chunk, &w[i * this->b]);
this->g(this, t, xval_chunk, &w[i * this->b]);
DBG3("w[%d] %b", i, &w[i * this->b], this->b);
/* c. XKEY = (1 + XKEY + wi) mod 2b */
add_mod(this->b, xkey, &w[i * this->b], sum);
@@ -186,12 +187,9 @@ static void set_key(private_fips_prf_t *this, chunk_t key)
/**
* Implementation of the G() function based on SHA1
*/
void g_sha1(u_int8_t t[], chunk_t c, u_int8_t res[])
void g_sha1(private_fips_prf_t *this, u_int8_t t[], chunk_t c, u_int8_t res[])
{
hasher_t *hasher;
u_int8_t buf[64];
chunk_t state_chunk;
u_int32_t *state, *iv, *hash;
if (c.len < sizeof(buf))
{
@@ -207,24 +205,8 @@ void g_sha1(u_int8_t t[], chunk_t c, u_int8_t res[])
c.len = sizeof(buf);
}
/* our SHA1 hasher's state is 32-Bit integers in host order. We must
* convert them */
hasher = hasher_create(HASH_SHA1);
state_chunk = hasher->get_state(hasher);
state = (u_int32_t*)state_chunk.ptr;
iv = (u_int32_t*)t;
hash = (u_int32_t*)res;
state[0] = htonl(iv[0]);
state[1] = htonl(iv[1]);
state[2] = htonl(iv[2]);
state[3] = htonl(iv[3]);
hasher->get_hash(hasher, c, NULL);
hash[0] = htonl(state[0]);
hash[1] = htonl(state[1]);
hash[2] = htonl(state[2]);
hash[3] = htonl(state[3]);
hash[4] = htonl(state[4]);
hasher->destroy(hasher);
/* calculate the special (HASH_SHA1_STATE) hash*/
this->hasher->get_hash(this->hasher, c, res);
}
/**
@@ -232,6 +214,7 @@ void g_sha1(u_int8_t t[], chunk_t c, u_int8_t res[])
*/
static void destroy(private_fips_prf_t *this)
{
this->hasher->destroy(this->hasher);
free(this->key);
free(this);
}
@@ -239,7 +222,7 @@ static void destroy(private_fips_prf_t *this)
/*
* Described in header.
*/
fips_prf_t *fips_prf_create(size_t b, void(*g)(u_int8_t[],chunk_t,u_int8_t[]))
fips_prf_t *fips_prf_create(pseudo_random_function_t algo)
{
private_fips_prf_t *this = malloc_thing(private_fips_prf_t);
@@ -250,9 +233,29 @@ fips_prf_t *fips_prf_create(size_t b, void(*g)(u_int8_t[],chunk_t,u_int8_t[]))
this->public.prf_interface.set_key = (void (*) (prf_t *,chunk_t))set_key;
this->public.prf_interface.destroy = (void (*) (prf_t *))destroy;
this->g = g;
this->b = b;
this->key = malloc(b);
switch (algo)
{
case PRF_FIPS_SHA1_160:
{
this->g = g_sha1;
this->b = 20;
this->hasher = lib->crypto->create_hasher(lib->crypto,
HASH_SHA1_NOFINAL);
if (this->hasher == NULL)
{
free(this);
return NULL;
}
break;
}
case PRF_FIPS_DES:
/* not implemented yet */
default:
free(this);
return NULL;
}
this->key = malloc(this->b);
return &(this->public);
return &this->public;
}

Some files were not shown because too many files have changed in this diff Show More