../svn-commit.tmp

This commit is contained in:
Martin Willi
2006-04-05 12:10:50 +00:00
parent 3dbbbf3e16
commit 6862128151
171 changed files with 674 additions and 1355 deletions
+37
View File
@@ -0,0 +1,37 @@
# Copyright (C) 2005 Jan Hutter, 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.
#
CRYPTO_DIR= $(LIB_DIR)crypto/
include $(CRYPTO_DIR)crypters/Makefile.crypters
include $(CRYPTO_DIR)hashers/Makefile.hashers
include $(CRYPTO_DIR)prfs/Makefile.prfs
include $(CRYPTO_DIR)signers/Makefile.signers
include $(CRYPTO_DIR)rsa/Makefile.rsa
LIB_OBJS+= $(BUILD_DIR)diffie_hellman.o
$(BUILD_DIR)diffie_hellman.o : $(CRYPTO_DIR)diffie_hellman.c $(CRYPTO_DIR)diffie_hellman.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)hmac.o
$(BUILD_DIR)hmac.o : $(CRYPTO_DIR)hmac.c $(CRYPTO_DIR)hmac.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)prf_plus.o
$(BUILD_DIR)prf_plus.o : $(CRYPTO_DIR)prf_plus.c $(CRYPTO_DIR)prf_plus.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)certificate.o
$(BUILD_DIR)certificate.o : $(CRYPTO_DIR)certificate.c $(CRYPTO_DIR)certificate.h
$(CC) $(CFLAGS) -c -o $@ $<
+230
View File
@@ -0,0 +1,230 @@
/**
* @file certificate.c
*
* @brief Implementation of certificate_t.
*
*/
/*
* Copyright (C) 2006 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 <gmp.h>
#include <sys/stat.h>
#include <unistd.h>
#include "certificate.h"
#include <daemon.h>
#include <utils/allocator.h>
#include <asn1/der_decoder.h>
typedef struct private_certificate_t private_certificate_t;
/**
* Private data of a certificate_t object.
*/
struct private_certificate_t {
/**
* Public interface for this signer.
*/
certificate_t public;
u_int version;
u_int serial;
chunk_t sign_alg;
time_t not_before;
time_t not_after;
chunk_t pubkey;
chunk_t pubkey_alg;
bool has_issuer_uid;
chunk_t issuer_uid;
bool has_subject_uid;
chunk_t subject_uid;
chunk_t tbs_cert;
chunk_t signature;
rsa_public_key_t *public_key;
};
#define OSET(x) offsetof(private_certificate_t, x)
/**
* Rules for de-/encoding of a certificate from/in ASN1
*/
static asn1_rule_t certificate_rules[] = {
{ASN1_SEQUENCE, 0, 0, 0 }, /* certificate */
{ ASN1_SEQUENCE, ASN1_RAW, OSET(tbs_cert), 0 }, /* tbsCertificate */
{ ASN1_TAG_E_0, ASN1_DEFAULT, OSET(version), 0 }, /* EXPLICIT */
{ ASN1_INTEGER, ASN1_DEFAULT, OSET(version), 0 }, /* version DEFAULT v1(0) */
{ ASN1_INTEGER, 0, OSET(serial), 0 }, /* serialNumber */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* signature */
{ ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
{ ASN1_END, 0, 0, 0 }, /* signature */
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* issuer */
// { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
// { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
// { ASN1_OID, 0, 0, 0 }, /* AttributeType */
// { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
// { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
// { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
{ ASN1_END, 0, 0, 0 }, /* issuer */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* validity */
{ ASN1_CHOICE, 0, 0, 0 }, /* notBefore */
{ ASN1_UTCTIME, 0, OSET(not_before), 0 }, /* utcTime */
{ ASN1_GENERALIZEDTIME, 0, OSET(not_before), 0 }, /* generalTime */
{ ASN1_END, 0, 0, 0 }, /* notBefore */
{ ASN1_CHOICE, 0, 0, 0 }, /* notAfter */
{ ASN1_UTCTIME, 0, OSET(not_after), 0 }, /* utcTime */
{ ASN1_GENERALIZEDTIME, 0, OSET(not_after), 0 }, /* generalTime */
{ ASN1_END, 0, 0, 0 }, /* notAfter */
{ ASN1_END, 0, 0, 0 }, /* validity */
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* subject */
// { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
// { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
// { ASN1_OID, 0, 0, 0 }, /* AttributeType */
// { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
// { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
// { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
{ ASN1_END, 0, 0, 0 }, /* subject */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* subjectPublicKeyInfo */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* algorithm */
{ ASN1_OID, 0, OSET(pubkey_alg), 0 }, /* algorithm-oid */
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
{ ASN1_END, 0, 0, 0 }, /* algorithm */
{ ASN1_BITSTRING, 0, OSET(pubkey), 0 }, /* subjectPublicKey */
{ ASN1_END, 0, 0, 0 }, /* subjectPublicKeyInfo */
{ ASN1_TAG_I_1, ASN1_OPTIONAL, 0, OSET(has_issuer_uid)}, /* IMPLICIT */
{ ASN1_BITSTRING, ASN1_OPTIONAL, OSET(issuer_uid), 0 }, /* issuerUniqueID OPTIONAL */
{ ASN1_TAG_I_2, ASN1_OPTIONAL, 0, OSET(has_subject_uid)},/* IMPLICIT */
{ ASN1_BITSTRING, ASN1_OPTIONAL, OSET(subject_uid), 0 }, /* subjectUniqueID OPTIONAL */
{ ASN1_TAG_E_3, ASN1_OPTIONAL, 0, 0 }, /* EXPLICIT */
{ ASN1_SEQUENCE, ASN1_OF|ASN1_OPTIONAL, 0, 0 }, /* extensions OPTIONAL */
// { ASN1_SEQUENCE, 0, 0, 0, }, /* extension */
// { ASN1_OID, 0, 0, 0 }, /* extnID */
// { ASN1_BOOLEAN, ASN1_DEFAULT, 0, FALSE }, /* critical */
// { ASN1_OCTETSTRING, 0, 0, 0, }, /* extnValue */
// { ASN1_END, 0, 0, 0, }, /* extension */
{ ASN1_END, 0, 0, 0, }, /* extensions */
{ ASN1_END, 0, 0, 0 }, /* tbsCertificate */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* signatureAlgorithm */
{ ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
{ ASN1_END, 0, 0, 0 }, /* signatureAlgorithm */
{ ASN1_BITSTRING, 0, OSET(signature), 0 }, /* signatureValue */
{ASN1_END, 0, 0, 0 }, /* certificate */
};
/**
* Implementation of certificate.get_public_key.
*/
static rsa_public_key_t *get_public_key(private_certificate_t *this)
{
return this->public_key->clone(this->public_key);
}
/**
* Implementation of certificate.destroy.
*/
static void destroy(private_certificate_t *this)
{
this->public_key->destroy(this->public_key);
allocator_free(this->pubkey.ptr);
allocator_free(this->signature.ptr);
allocator_free(this->tbs_cert.ptr);
allocator_free(this);
}
/*
* Described in header.
*/
certificate_t *certificate_create_from_chunk(chunk_t chunk)
{
private_certificate_t *this = allocator_alloc_thing(private_certificate_t);
der_decoder_t *dd;
/* public functions */
this->public.get_public_key = (rsa_public_key_t *(*) (certificate_t*))get_public_key;
this->public.destroy = (void (*) (certificate_t*))destroy;
/* initialize */
this->pubkey = CHUNK_INITIALIZER;
this->signature = CHUNK_INITIALIZER;
this->tbs_cert = CHUNK_INITIALIZER;
dd = der_decoder_create(certificate_rules);
if (dd->decode(dd, chunk, this) != SUCCESS)
{
allocator_free(this);
dd->destroy(dd);
return NULL;
}
dd->destroy(dd);
this->public_key = rsa_public_key_create_from_chunk(this->pubkey);
if (this->public_key == NULL)
{
allocator_free(this->pubkey.ptr);
allocator_free(this);
return NULL;
}
return &this->public;
}
/*
* Described in header.
*/
certificate_t *certificate_create_from_file(char *filename)
{
struct stat stb;
FILE *file;
char *buffer;
chunk_t chunk;
if (stat(filename, &stb) == -1)
{
return NULL;
}
buffer = alloca(stb.st_size);
file = fopen(filename, "r");
if (file == NULL)
{
return NULL;
}
if (fread(buffer, stb.st_size, 1, file) == -1)
{
return NULL;
}
chunk.ptr = buffer;
chunk.len = stb.st_size;
return certificate_create_from_chunk(chunk);
}
+70
View File
@@ -0,0 +1,70 @@
/**
* @file certificate.h
*
* @brief Interface of certificate_t.
*
*/
/*
* Copyright (C) 2006 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.
*/
#ifndef CERTIFICATE_H_
#define CERTIFICATE_H_
#include <types.h>
#include <definitions.h>
#include <crypto/rsa/rsa_public_key.h>
typedef struct certificate_t certificate_t;
/**
* @brief X509 certificate.
*
* @b Constructors:
* - certificate_create_from_chunk()
*
* @ingroup transforms
*/
struct certificate_t {
/**
* @brief Get the RSA public key from the certificate.
*
* @param this calling object
* @return public_key
*/
rsa_public_key_t *(*get_public_key) (certificate_t *this);
/**
* @brief Destroys the private key.
*
* @param this private key to destroy
*/
void (*destroy) (certificate_t *this);
};
/**
* @brief Read a certificate from a blob.
*
* @return created certificate_t.
*
* @ingroup transforms
*/
certificate_t *certificate_create_from_chunk(chunk_t chunk);
certificate_t *certificate_create_from_file(char *filename);
#endif /* CERTIFICATE_H_ */
@@ -0,0 +1,23 @@
# Copyright (C) 2005 Jan Hutter, 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.
#
CRYPTERS_DIR= $(CRYPTO_DIR)crypters/
LIB_OBJS+= $(BUILD_DIR)crypter.o
$(BUILD_DIR)crypter.o : $(CRYPTERS_DIR)crypter.c $(CRYPTERS_DIR)crypter.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)aes_cbc_crypter.o
$(BUILD_DIR)aes_cbc_crypter.o : $(CRYPTERS_DIR)aes_cbc_crypter.c $(CRYPTERS_DIR)aes_cbc_crypter.h
$(CC) $(CFLAGS) -c -o $@ $<
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,61 @@
/**
* @file aes_cbc_crypter.h
*
* @brief Interface of aes_cbc_crypter_t
*
*/
/*
* Copyright (C) 2001 Dr B. R. Gladman <[email protected]>
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef AES_CBC_CRYPTER_H_
#define AES_CBC_CRYPTER_H_
#include <crypto/crypters/crypter.h>
typedef struct aes_cbc_crypter_t aes_cbc_crypter_t;
/**
* @brief Class implementing the AES symmetric encryption algorithm.
*
* @b Constructors:
* - aes_cbc_crypter_create()
*
* @ingroup crypters
*/
struct aes_cbc_crypter_t {
/**
* The crypter_t interface.
*/
crypter_t crypter_interface;
};
/**
* @brief Constructor to create aes_cbc_crypter_t objects.
*
* Supported key sizes are: 16, 24 or 32.
*
* @param key_size key size in bytes
* @return
* - aes_cbc_crypter_t object
* - NULL if key size not supported
*/
aes_cbc_crypter_t *aes_cbc_crypter_create(size_t key_size);
#endif /* AES_CBC_CRYPTER_H_ */
+63
View File
@@ -0,0 +1,63 @@
/**
* @file crypter.c
*
* @brief Generic constructor for crypter_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 "crypter.h"
#include <crypto/crypters/aes_cbc_crypter.h>
/**
* String mappings for encryption_algorithm_t.
*/
mapping_t encryption_algorithm_m[] = {
{ENCR_UNDEFINED, "ENCR_UNDEFINED"},
{ENCR_DES_IV64, "ENCR_DES_IV64"},
{ENCR_DES, "ENCR_DES"},
{ENCR_3DES, "ENCR_3DES"},
{ENCR_RC5, "ENCR_RC5"},
{ENCR_IDEA, "ENCR_IDEA"},
{ENCR_CAST, "ENCR_CAST"},
{ENCR_BLOWFISH, "ENCR_BLOWFISH"},
{ENCR_3IDEA, "ENCR_3IDEA"},
{ENCR_DES_IV32, "ENCR_DES_IV32"},
{ENCR_NULL, "ENCR_NULL"},
{ENCR_AES_CBC, "ENCR_AES_CBC"},
{ENCR_AES_CTR, "ENCR_AES_CTR"},
{MAPPING_END, NULL}
};
/*
* 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);
}
default:
return NULL;
}
}
+153
View File
@@ -0,0 +1,153 @@
/**
* @file crypter.h
*
* @brief Interface crypter_t
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef CRYPTER_H_
#define CRYPTER_H_
#include <types.h>
typedef enum encryption_algorithm_t encryption_algorithm_t;
/**
* @brief Encryption algorithm, as in IKEv2 RFC 3.3.2.
*
* Currently only the following algorithms are implemented and therefore supported:
* - ENCR_AES_CBC
*
* @todo Implement more enryption algorithms, such as 3DES
*
* @ingroup crypters
*/
enum encryption_algorithm_t {
ENCR_UNDEFINED = 1024,
ENCR_DES_IV64 = 1,
ENCR_DES = 2,
ENCR_3DES = 3,
ENCR_RC5 = 4,
ENCR_IDEA = 5,
ENCR_CAST = 6,
ENCR_BLOWFISH = 7,
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
};
/**
* String mappings for encryption_algorithm_t.
*/
extern mapping_t encryption_algorithm_m[];
typedef struct crypter_t crypter_t;
/**
* @brief Generic interface for symmetric encryption algorithms.
*
* @b Constructors:
* - crypter_create()
*
* @ingroup crypters
*/
struct crypter_t {
/**
* @brief 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
*/
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.
*
* @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
*/
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.
*
* @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.
*
* @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.
*
* @param this calling object
* @param key key to set
* @return
* - SUCCESS
* - 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
*/
void (*destroy) (crypter_t *this);
};
/**
* @brief Generic constructor for crypter_t objects.
*
* Currently only the following algorithms are implemented and therefore supported:
* - ENCR_AES_CBC
*
* 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_*/
+616
View File
@@ -0,0 +1,616 @@
/**
* @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 Jan Hutter, 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 <gmp.h>
#include <stdio.h>
#include "diffie_hellman.h"
#include <daemon.h>
#include <utils/allocator.h>
#include <utils/randomizer.h>
/**
* String mappings for diffie_hellman_group_t.
*/
mapping_t diffie_hellman_group_m[] = {
{MODP_UNDEFINED, "MODP_UNDEFINED"},
{MODP_768_BIT, "MODP_768_BIT"},
{MODP_1024_BIT, "MODP_1024_BIT"},
{MODP_1536_BIT, "MODP_1536_BIT"},
{MODP_2048_BIT, "MODP_2048_BIT"},
{MODP_3072_BIT, "MODP_3072_BIT"},
{MODP_4096_BIT, "MODP_4096_BIT"},
{MODP_6144_BIT, "MODP_6144_BIT"},
{MODP_8192_BIT, "MODP_8192_BIT"},
{MAPPING_END, NULL}
};
/**
* 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_info_entry_t modulus_info_entry_t;
/**
* Entry of the modulus list.
*/
struct modulus_info_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_length;
/*
* Generator value.
*/
u_int16_t generator;
};
/**
* All supported modulus values.
*/
static modulus_info_entry_t modulus_info_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 dh_group_number;
/**
* Modulus.
*/
mpz_t modulus;
/**
* Modulus length.
*/
size_t modulus_length;
/*
* Generator value.
*/
u_int16_t generator;
/**
* My private value .
*/
mpz_t my_private_value;
/**
* My public value.
*/
mpz_t my_public_value;
/**
* Other public value.
*/
mpz_t other_public_value;
/**
* Shared secret.
*/
mpz_t shared_secret;
/**
* True if shared secret is computed and stored in my_public_value.
*/
bool shared_secret_is_computed;
/**
* Sets the modulus for a specific diffie hellman group.
*
* @param this calling object
* @return
* SUCCESS if modulus could be found
* NOT_FOUND if modulus not supported
*/
status_t (*set_modulus) (private_diffie_hellman_t *this);
/**
* Makes sure my public value is computed.
*
* @param this calling object
*/
void (*compute_public_value) (private_diffie_hellman_t *this);
/**
* Computes shared secret (other public value must be available).
*
* @param this calling object
*/
void (*compute_shared_secret) (private_diffie_hellman_t *this);
};
/**
* Implementation of private_diffie_hellman_t.set_modulus.
*/
static status_t set_modulus(private_diffie_hellman_t *this)
{
int i;
status_t status = NOT_FOUND;
for (i = 0; i < (sizeof(modulus_info_entries) / sizeof(modulus_info_entry_t)); i++)
{
if (modulus_info_entries[i].group == this->dh_group_number)
{
chunk_t modulus_chunk;
modulus_chunk.ptr = modulus_info_entries[i].modulus;
modulus_chunk.len = modulus_info_entries[i].modulus_length;
mpz_import(this->modulus, modulus_chunk.len, 1, 1, 1, 0, modulus_chunk.ptr);
this->modulus_length = modulus_chunk.len;
this->generator = modulus_info_entries[i].generator;
status = SUCCESS;
break;
}
}
return status;
}
/**
* Implementation of diffie_hellman_t.set_other_public_value.
*/
static void set_other_public_value(private_diffie_hellman_t *this,chunk_t public_value)
{
mpz_import(this->other_public_value, public_value.len, 1, 1, 1, 0, public_value.ptr);
this->compute_shared_secret(this);
}
/**
* Implementation of diffie_hellman_t.get_other_public_value.
*/
static status_t get_other_public_value(private_diffie_hellman_t *this,chunk_t *public_value)
{
if (!this->shared_secret_is_computed)
{
return FAILED;
}
public_value->len = this->modulus_length;
public_value->ptr = mpz_export(NULL, NULL, 1, public_value->len, 1, 0, this->other_public_value);
return SUCCESS;
}
/**
* Implementation of private_diffie_hellman_t.compute_shared_secret.
*/
static void compute_shared_secret (private_diffie_hellman_t *this)
{
/* initialize my public value */
mpz_init(this->shared_secret);
/* calculate my public value */
mpz_powm(this->shared_secret,this->other_public_value,this->my_private_value,this->modulus);
this->shared_secret_is_computed = TRUE;
}
/**
* Implementation of private_diffie_hellman_t.compute_public_value.
*/
static void compute_public_value (private_diffie_hellman_t *this)
{
mpz_t generator;
/* initialize generator and set it*/
mpz_init_set_ui (generator,this->generator);
/* initialize my public value */
mpz_init(this->my_public_value);
/* calculate my public value */
mpz_powm(this->my_public_value,generator,this->my_private_value,this->modulus);
/* generator not used anymore */
mpz_clear(generator);
}
/**
* Implementation of diffie_hellman_t.get_my_public_value.
*/
static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *public_value)
{
public_value->len = this->modulus_length;
public_value->ptr = mpz_export(NULL, NULL, 1, public_value->len, 1, 0, this->my_public_value);
}
/**
* Implementation of diffie_hellman_t.get_shared_secret.
*/
static status_t get_shared_secret(private_diffie_hellman_t *this,chunk_t *secret)
{
if (!this->shared_secret_is_computed)
{
return FAILED;
}
secret->len = this->modulus_length;
secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->shared_secret);
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->dh_group_number;
}
/**
* Implementation of diffie_hellman_t.destroy.
*/
static void destroy(private_diffie_hellman_t *this)
{
mpz_clear(this->modulus);
mpz_clear(this->my_private_value);
mpz_clear(this->my_public_value);
mpz_clear(this->other_public_value);
if (this->shared_secret_is_computed)
{
/* other public value gets initialized together with shared secret */
mpz_clear(this->shared_secret);
}
allocator_free(this);
}
/*
* Described in header.
*/
diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number)
{
private_diffie_hellman_t *this = allocator_alloc_thing(private_diffie_hellman_t);
randomizer_t *randomizer;
chunk_t random_bytes;
/* 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 functions */
this->set_modulus = set_modulus;
this->compute_public_value = compute_public_value;
this->compute_shared_secret = compute_shared_secret;
/* private variables */
this->dh_group_number = dh_group_number;
mpz_init(this->modulus);
mpz_init(this->other_public_value);
mpz_init(this->my_private_value);
/* set this->modulus */
if (this->set_modulus(this) != SUCCESS)
{
allocator_free(this);
return NULL;
}
randomizer = randomizer_create();
if (randomizer == NULL)
{
allocator_free(this);
return NULL;
}
if (randomizer->allocate_pseudo_random_bytes(randomizer, this->modulus_length, &random_bytes) != SUCCESS)
{
randomizer->destroy(randomizer);
allocator_free(this);
return NULL;
}
mpz_import(this->my_private_value, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
allocator_free_chunk(&random_bytes);
randomizer->destroy(randomizer);
this->compute_public_value(this);
this->shared_secret_is_computed = FALSE;
return &(this->public);
}
+149
View File
@@ -0,0 +1,149 @@
/**
* @file diffie_hellman.h
*
* @brief Interface of diffie_hellman_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef DIFFIE_HELLMAN_H_
#define DIFFIE_HELLMAN_H_
#include <types.h>
typedef enum diffie_hellman_group_t diffie_hellman_group_t;
/**
* @brief Diffie-Hellman group.
*
* The modulus (or group) to use for a Diffie-Hellman calculation.
*
* See IKEv2 RFC 3.3.2 and RFC 3526.
*
* @ingroup transforms
*/
enum diffie_hellman_group_t {
MODP_UNDEFINED = 1024,
MODP_768_BIT = 1,
MODP_1024_BIT = 2,
MODP_1536_BIT = 5,
MODP_2048_BIT = 14,
MODP_3072_BIT = 15,
MODP_4096_BIT = 16,
MODP_6144_BIT = 17,
MODP_8192_BIT = 18
};
/**
* String mappings for diffie_hellman_group_t.
*/
extern mapping_t diffie_hellman_group_m[];
typedef struct diffie_hellman_t diffie_hellman_t;
/**
* @brief Implementation of the widely used Diffie-Hellman algorithm.
*
* @b Constructors:
* - diffie_hellman_create()
*
* @ingroup transforms
*/
struct diffie_hellman_t {
/**
* @brief Returns the shared secret of this diffie hellman exchange.
*
* @warning Space for returned secret is allocated and must be
* freed by the caller.
*
* @param this calling diffie_hellman_t object
* @param[out] secret shared secret will be written into this chunk
* @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.
*
* chunk gets cloned and can be destroyed afterwards.
*
* @param this calling diffie_hellman_t object
* @param public_value public value of partner
*/
void (*set_other_public_value) (diffie_hellman_t *this, chunk_t public_value);
/**
* @brief Gets the public value of partner.
*
* @warning Space for returned chunk is allocated and must be
* freed by the caller.
*
* @param this calling diffie_hellman_t object
* @param[out] public_value public value of partner is stored at this location
* @return
* - SUCCESS
* - FAILED if other public value not set
*/
status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *public_value);
/**
* @brief Gets the public value of caller
*
* @warning Space for returned chunk is allocated and must be
* freed by the caller.
*
* @param this calling diffie_hellman_t object
* @param[out] public_value public value of caller is stored at this location
*/
void (*get_my_public_value) (diffie_hellman_t *this, chunk_t *public_value);
/**
* @brief Get the DH group used.
*
* @param this calling diffie_hellman_t 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
*/
void (*destroy) (diffie_hellman_t *this);
};
/**
* @brief Creates a new diffie_hellman_t object.
*
* The first diffie hellman public value gets automatically created.
*
* @param dh_group_number Diffie Hellman group number to use
* @return
* - diffie_hellman_t object
* - NULL if dh group not supported
*
* @ingroup transforms
*/
diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number);
#endif /*DIFFIE_HELLMAN_H_*/
@@ -0,0 +1,27 @@
# Copyright (C) 2005 Jan Hutter, 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.
#
HASHERS_DIR= $(CRYPTO_DIR)hashers/
LIB_OBJS+= $(BUILD_DIR)hasher.o
$(BUILD_DIR)hasher.o : $(HASHERS_DIR)hasher.c $(HASHERS_DIR)hasher.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)sha1_hasher.o
$(BUILD_DIR)sha1_hasher.o : $(HASHERS_DIR)sha1_hasher.c $(HASHERS_DIR)sha1_hasher.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)md5_hasher.o
$(BUILD_DIR)md5_hasher.o : $(HASHERS_DIR)md5_hasher.c $(HASHERS_DIR)md5_hasher.h
$(CC) $(CFLAGS) -c -o $@ $<
+60
View File
@@ -0,0 +1,60 @@
/**
* @file hasher.c
*
* @brief Generic constructor for hasher_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 "hasher.h"
#include <crypto/hashers/sha1_hasher.h>
#include <crypto/hashers/md5_hasher.h>
/**
* String mappings for hash_algorithm_t.
*/
mapping_t hash_algorithm_m[] = {
{HASH_MD2,"HASH_MD2"},
{HASH_MD5,"HASH_MD5"},
{HASH_SHA1,"HASH_SHA1"},
{HASH_SHA256,"HASH_SHA256"},
{HASH_SHA384,"HASH_SHA384"},
{HASH_SHA512,"HASH_SHA512"},
{MAPPING_END, NULL}
};
/*
* 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_MD5:
{
return (hasher_t*)md5_hasher_create();
}
default:
return NULL;
}
}
+147
View File
@@ -0,0 +1,147 @@
/**
* @file hasher.h
*
* @brief Interface hasher_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef HASHER_H_
#define HASHER_H_
#include <types.h>
typedef enum hash_algorithm_t hash_algorithm_t;
/**
* @brief Algorithms to use for hashing.
*
* Currently only the following algorithms are implemented and therefore supported:
* - HASH_MD5
* - HASH_SHA1
*
* @ingroup hashers
*
*/
enum hash_algorithm_t {
HASH_MD2,
/**
* Implemented in class md5_hasher_t.
*/
HASH_MD5,
/**
* Implemented in class sha1_hasher_t.
*/
HASH_SHA1,
HASH_SHA256,
HASH_SHA384,
HASH_SHA512,
};
/**
* String mappings for hash_algorithm_t.
*/
extern mapping_t hash_algorithm_m[];
typedef struct hasher_t hasher_t;
/**
* @brief Generic interface for all hash functions.
*
* @b Constructors:
* - hasher_create()
* - md5_hasher_create()
* - sha1_hasher_create()
*
* @see
* - md5_hasher_t
* - sha1_hasher_t
*
* @todo Implement more hash algorithms
*
* @ingroup hashers
*/
struct hasher_t {
/**
* @brief Hash data and write it in the buffer.
*
* If the parameter hash is NULL, no result is written back
* an more data can be appended to already hashed data.
* If not, the result is written back and the hasher is reseted.
*
* @warning: 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
*/
void (*get_hash) (hasher_t *this, chunk_t data, u_int8_t *hash);
/**
* @brief Hash data and allocate space for the hash.
*
* If the parameter hash is NULL, no result is written back
* an more data can be appended to already hashed data.
* If not, the result is written back and the hasher is reseted.
*
* @param this calling object
* @param data chunk with data to hash
* @param[out] hash chunk which will hold allocated hash
*/
void (*allocate_hash) (hasher_t *this, chunk_t data, chunk_t *hash);
/**
* @brief Get the block size of this hashing function.
*
* @param this calling object
* @return block size in bytes
*/
size_t (*get_block_size) (hasher_t *this);
/**
* @brief Resets the hashers state, which allows
* computation of a completely new hash.
*
* @param this calling object
*/
void (*reset) (hasher_t *this);
/**
* @brief Destroys a hasher object.
*
* @param this calling object
*/
void (*destroy) (hasher_t *this);
};
/**
* @brief Generic interface to create a hasher_t.
*
* @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);
#endif /*HASHER_H_*/
+393
View File
@@ -0,0 +1,393 @@
/**
* @file md5_hasher.c
*
* @brief Implementation of md5_hasher_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
* Copyright (C) 1991-1992, RSA Data Security, Inc. Created 1991.
* All rights reserved.
*
* Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
* Ported to fulfill hasher_t interface.
*
* 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 "md5_hasher.h"
#include <definitions.h>
#include <utils/allocator.h>
#define BLOCK_SIZE_MD5 16
/* Constants for MD5Transform routine. */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static u_int8_t PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* ugly macro stuff
*/
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
typedef struct private_md5_hasher_t private_md5_hasher_t;
/**
* Private data structure with hasing context.
*/
struct private_md5_hasher_t {
/**
* Public interface for this hasher.
*/
md5_hasher_t public;
/*
* State of the hasher.
*/
u_int32_t state[5];
u_int32_t count[2];
u_int8_t buffer[64];
};
#if BYTE_ORDER != LITTLE_ENDIAN
/* Encodes input (u_int32_t) into output (u_int8_t). Assumes len is
* a multiple of 4.
*/
static void Encode (u_int8_t *output, u_int32_t *input, size_t *len)
{
size_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (u_int8_t)(input[i] & 0xff);
output[j+1] = (u_int8_t)((input[i] >> 8) & 0xff);
output[j+2] = (u_int8_t)((input[i] >> 16) & 0xff);
output[j+3] = (u_int8_t)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (u_int8_t) into output (u_int32_t). Assumes len is
* a multiple of 4.
*/
static void Decode(u_int32_t *output, u_int8_t *input, size_t len)
{
size_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[i] = ((u_int32_t)input[j]) | (((u_int32_t)input[j+1]) << 8) |
(((u_int32_t)input[j+2]) << 16) | (((u_int32_t)input[j+3]) << 24);
}
}
#elif BYTE_ORDER == LITTLE_ENDIAN
#define Encode memcpy
#define Decode memcpy
#endif
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform(u_int32_t state[4], u_int8_t block[64])
{
u_int32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode(x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
/* MD5 block update operation. Continues an MD5 message-digest
* operation, processing another message block, and updating the
* context.
*/
static void MD5Update(private_md5_hasher_t *this, u_int8_t *input, size_t inputLen)
{
u_int32_t i;
size_t index, partLen;
/* Compute number of bytes mod 64 */
index = (u_int8_t)((this->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((this->count[0] += (inputLen << 3)) < (inputLen << 3))
{
this->count[1]++;
}
this->count[1] += (inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen)
{
memcpy(&this->buffer[index], input, partLen);
MD5Transform (this->state, this->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
{
MD5Transform (this->state, &input[i]);
}
index = 0;
}
else
{
i = 0;
}
/* Buffer remaining input */
memcpy(&this->buffer[index], &input[i], inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
* the message digest and zeroizing the context.
*/
static void MD5Final (private_md5_hasher_t *this, u_int8_t digest[16])
{
u_int8_t bits[8];
size_t index, padLen;
/* Save number of bits */
Encode (bits, this->count, 8);
/* Pad out to 56 mod 64. */
index = (size_t)((this->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (this, PADDING, padLen);
/* Append length (before padding) */
MD5Update (this, bits, 8);
if (digest != NULL) /* Bill Simpson's padding */
{
/* store state in digest */
Encode (digest, this->state, 16);
}
}
/**
* Implementation of hasher_t.get_hash.
*/
static void get_hash(private_md5_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
MD5Update(this, chunk.ptr, chunk.len);
if (buffer != NULL)
{
MD5Final(this, buffer);
this->public.hasher_interface.reset(&(this->public.hasher_interface));
}
}
/**
* Implementation of hasher_t.allocate_hash.
*/
static void allocate_hash(private_md5_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
chunk_t allocated_hash;
MD5Update(this, chunk.ptr, chunk.len);
if (hash != NULL)
{
allocated_hash.ptr = allocator_alloc(BLOCK_SIZE_MD5);
allocated_hash.len = BLOCK_SIZE_MD5;
MD5Final(this, allocated_hash.ptr);
this->public.hasher_interface.reset(&(this->public.hasher_interface));
*hash = allocated_hash;
}
}
/**
* Implementation of hasher_t.get_block_size.
*/
static size_t get_block_size(private_md5_hasher_t *this)
{
return BLOCK_SIZE_MD5;
}
/**
* Implementation of hasher_t.reset.
*/
static void reset(private_md5_hasher_t *this)
{
this->state[0] = 0x67452301;
this->state[1] = 0xefcdab89;
this->state[2] = 0x98badcfe;
this->state[3] = 0x10325476;
this->count[0] = 0;
this->count[1] = 0;
}
/**
* Implementation of hasher_t.destroy.
*/
static void destroy(private_md5_hasher_t *this)
{
allocator_free(this);
}
/*
* Described in header.
*/
md5_hasher_t *md5_hasher_create()
{
private_md5_hasher_t *this = allocator_alloc_thing(private_md5_hasher_t);
this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash;
this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash;
this->public.hasher_interface.get_block_size = (size_t (*) (hasher_t*))get_block_size;
this->public.hasher_interface.reset = (void (*) (hasher_t*))reset;
this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy;
/* initialize */
this->public.hasher_interface.reset(&(this->public.hasher_interface));
return &(this->public);
}
+60
View File
@@ -0,0 +1,60 @@
/**
* @file md5_hasher.h
*
* @brief Interface for md5_hasher_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef MD5_HASHER_H_
#define MD5_HASHER_H_
#include <crypto/hashers/hasher.h>
typedef struct md5_hasher_t md5_hasher_t;
/**
* @brief Implementation of hasher_t interface using the
* MD5 algorithm.
*
* @b Constructors:
* - hasher_create() using HASH_MD5 as algorithm
* - md5_hasher_create()
*
* @see hasher_t
*
* @ingroup hashers
*/
struct md5_hasher_t {
/**
* Generic hasher_t interface for this hasher.
*/
hasher_t hasher_interface;
};
/**
* @brief Creates a new md5_hasher_t.
*
* @return md5_hasher_t object
*
* @ingroup hashers
*/
md5_hasher_t *md5_hasher_create();
#endif /*MD5_HASHER_H_*/
+268
View File
@@ -0,0 +1,268 @@
/**
* @file sha1_hasher.c
*
* @brief Implementation of hasher_sha_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* Ported from Steve Reid's <[email protected]> implementation
* "SHA1 in C" found in strongSwan.
*
* 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 "sha1_hasher.h"
#include <definitions.h>
#include <utils/allocator.h>
#define BLOCK_SIZE_SHA1 20
/*
* ugly macro stuff
*/
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
#if BYTE_ORDER == LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) |(rol(block->l[i],8)&0x00FF00FF))
#elif BYTE_ORDER == BIG_ENDIAN
#define blk0(i) block->l[i]
#else
#error "Endianness not defined!"
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
typedef struct private_sha1_hasher_t private_sha1_hasher_t;
/**
* Private data structure with hasing context.
*/
struct private_sha1_hasher_t {
/**
* Public interface for this hasher.
*/
sha1_hasher_t public;
/*
* State of the hasher.
*/
u_int32_t state[5];
u_int32_t count[2];
u_int8_t buffer[64];
};
/*
* Hash a single 512-bit block. This is the core of the algorithm. *
*/
static void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64])
{
u_int32_t a, b, c, d, e;
typedef union {
u_int8_t c[64];
u_int32_t l[16];
} CHAR64LONG16;
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
memcpy(block, buffer, 64);
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
memset(block, '\0', sizeof(block));
}
/*
* Run your data through this.
*/
static void SHA1Update(private_sha1_hasher_t* this, u_int8_t *data, u_int32_t len)
{
u_int32_t i;
u_int32_t j;
j = this->count[0];
if ((this->count[0] += len << 3) < j)
{
this->count[1]++;
}
this->count[1] += (len>>29);
j = (j >> 3) & 63;
if ((j + len) > 63)
{
memcpy(&this->buffer[j], data, (i = 64-j));
SHA1Transform(this->state, this->buffer);
for ( ; i + 63 < len; i += 64)
{
SHA1Transform(this->state, &data[i]);
}
j = 0;
}
else
{
i = 0;
}
memcpy(&this->buffer[j], &data[i], len - i);
}
/*
* Add padding and return the message digest.
*/
static void SHA1Final(private_sha1_hasher_t *this, u_int8_t *digest)
{
u_int32_t i;
u_int8_t finalcount[8];
u_int8_t c;
for (i = 0; i < 8; i++)
{
finalcount[i] = (u_int8_t)((this->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
c = 0200;
SHA1Update(this, &c, 1);
while ((this->count[0] & 504) != 448)
{
c = 0000;
SHA1Update(this, &c, 1);
}
SHA1Update(this, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++)
{
digest[i] = (u_int8_t)((this->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
}
/**
* Implementation of hasher_t.get_hash.
*/
static void get_hash(private_sha1_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
{
SHA1Update(this, chunk.ptr, chunk.len);
if (buffer != NULL)
{
SHA1Final(this, buffer);
this->public.hasher_interface.reset(&(this->public.hasher_interface));
}
}
/**
* Implementation of hasher_t.allocate_hash.
*/
static void allocate_hash(private_sha1_hasher_t *this, chunk_t chunk, chunk_t *hash)
{
chunk_t allocated_hash;
SHA1Update(this, chunk.ptr, chunk.len);
if (hash != NULL)
{
allocated_hash.ptr = allocator_alloc(BLOCK_SIZE_SHA1);
allocated_hash.len = BLOCK_SIZE_SHA1;
SHA1Final(this, allocated_hash.ptr);
this->public.hasher_interface.reset(&(this->public.hasher_interface));
*hash = allocated_hash;
}
}
/**
* Implementation of hasher_t.get_block_size.
*/
static size_t get_block_size(private_sha1_hasher_t *this)
{
return BLOCK_SIZE_SHA1;
}
/**
* Implementation of hasher_t.reset.
*/
static void reset(private_sha1_hasher_t *this)
{
this->state[0] = 0x67452301;
this->state[1] = 0xEFCDAB89;
this->state[2] = 0x98BADCFE;
this->state[3] = 0x10325476;
this->state[4] = 0xC3D2E1F0;
this->count[0] = 0;
this->count[1] = 0;
}
/**
* Implementation of hasher_t.destroy.
*/
static void destroy(private_sha1_hasher_t *this)
{
allocator_free(this);
}
/*
* Described in header.
*/
sha1_hasher_t *sha1_hasher_create()
{
private_sha1_hasher_t *this = allocator_alloc_thing(private_sha1_hasher_t);
this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash;
this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash;
this->public.hasher_interface.get_block_size = (size_t (*) (hasher_t*))get_block_size;
this->public.hasher_interface.reset = (void (*) (hasher_t*))reset;
this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy;
/* initialize */
this->public.hasher_interface.reset(&(this->public.hasher_interface));
return &(this->public);
}
+60
View File
@@ -0,0 +1,60 @@
/**
* @file sha1_hasher.h
*
* @brief Interface of sha1_hasher_t
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef SHA1_HASHER_H_
#define SHA1_HASHER_H_
#include <crypto/hashers/hasher.h>
typedef struct sha1_hasher_t sha1_hasher_t;
/**
* @brief Implementation of hasher_t interface using the
* SHA1 algorithm.
*
* @b Constructors:
* - hasher_create() using HASH_SHA1 as algorithm
* - sha1_hasher_create()
*
* @see hasher_t
*
* @ingroup hashers
*/
struct sha1_hasher_t {
/**
* Generic hasher_t interface for this hasher.
*/
hasher_t hasher_interface;
};
/**
* @brief Creates a new sha1_hasher_t.
*
* @return sha1_hasher_t object
*
* @ingroup hashers
*/
sha1_hasher_t *sha1_hasher_create();
#endif /*SHA1_HASHER_H_*/
+210
View File
@@ -0,0 +1,210 @@
/**
* @file hmac.c
*
* @brief Implementation of hmac_t.
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 hmac 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 hmac License
* for more details.
*/
#include "hmac.h"
#include <utils/allocator.h>
typedef struct private_hmac_t private_hmac_t;
/**
* Private data of a hmac_t object.
*
* The variable names are the same as in the RFC.
*/
struct private_hmac_t {
/**
* Public hmac_t interface.
*/
hmac_t hmac;
/**
* Block size, as in RFC.
*/
u_int8_t b;
/**
* Hash function.
*/
hasher_t *h;
/**
* Previously xor'ed key using opad.
*/
chunk_t opaded_key;
/**
* Previously xor'ed key using ipad.
*/
chunk_t ipaded_key;
};
/**
* Implementation of hmac_t.get_mac.
*/
static void get_mac(private_hmac_t *this, chunk_t data, u_int8_t *out)
{
/* H(K XOR opad, H(K XOR ipad, text))
*
* if out is NULL, we append text to the inner hash.
* else, we complete the inner and do the outer.
*
*/
u_int8_t buffer[this->h->get_block_size(this->h)];
chunk_t inner;
if (out == NULL)
{
/* append data to inner */
this->h->get_hash(this->h, data, NULL);
}
else
{
/* append and do outer hash */
inner.ptr = buffer;
inner.len = this->h->get_block_size(this->h);
/* complete inner */
this->h->get_hash(this->h, data, buffer);
/* do outer */
this->h->get_hash(this->h, this->opaded_key, NULL);
this->h->get_hash(this->h, inner, out);
/* reinit for next call */
this->h->get_hash(this->h, this->ipaded_key, NULL);
}
}
/**
* Implementation of hmac_t.allocate_mac.
*/
static void allocate_mac(private_hmac_t *this, chunk_t data, chunk_t *out)
{
/* allocate space and use get_mac */
if (out == NULL)
{
/* append mode */
this->hmac.get_mac(&(this->hmac), data, NULL);
}
else
{
out->len = this->h->get_block_size(this->h);
out->ptr = allocator_alloc(out->len);
this->hmac.get_mac(&(this->hmac), data, out->ptr);
}
}
/**
* Implementation of hmac_t.get_block_size.
*/
static size_t get_block_size(private_hmac_t *this)
{
return this->h->get_block_size(this->h);
}
/**
* Implementation of hmac_t.set_key.
*/
static void set_key(private_hmac_t *this, chunk_t key)
{
int i;
u_int8_t buffer[this->b];
memset(buffer, 0, this->b);
if (key.len > this->b)
{
/* if key is too long, it will be hashed */
this->h->get_hash(this->h, key, buffer);
}
else
{
/* if not, just copy it in our pre-padded k */
memcpy(buffer, key.ptr, key.len);
}
/* apply ipad and opad to key */
for (i = 0; i < this->b; i++)
{
this->ipaded_key.ptr[i] = buffer[i] ^ 0x36;
this->opaded_key.ptr[i] = buffer[i] ^ 0x5C;
}
/* begin hashing of inner pad */
this->h->reset(this->h);
this->h->get_hash(this->h, this->ipaded_key, NULL);
}
/**
* Implementation of hmac_t.destroy.
*/
static void destroy(private_hmac_t *this)
{
this->h->destroy(this->h);
allocator_free(this->opaded_key.ptr);
allocator_free(this->ipaded_key.ptr);
allocator_free(this);
}
/*
* Described in header
*/
hmac_t *hmac_create(hash_algorithm_t hash_algorithm)
{
private_hmac_t *this;
this = allocator_alloc_thing(private_hmac_t);
/* set hmac_t methods */
this->hmac.get_mac = (void (*)(hmac_t *,chunk_t,u_int8_t*))get_mac;
this->hmac.allocate_mac = (void (*)(hmac_t *,chunk_t,chunk_t*))allocate_mac;
this->hmac.get_block_size = (size_t (*)(hmac_t *))get_block_size;
this->hmac.set_key = (void (*)(hmac_t *,chunk_t))set_key;
this->hmac.destroy = (void (*)(hmac_t *))destroy;
/* set b, according to hasher */
switch (hash_algorithm)
{
case HASH_SHA1:
case HASH_MD5:
this->b = 64;
break;
default:
allocator_free(this);
return NULL;
}
/* build the hasher */
this->h = hasher_create(hash_algorithm);
/* build ipad and opad */
this->opaded_key.ptr = allocator_alloc(this->b);
this->opaded_key.len = this->b;
this->ipaded_key.ptr = allocator_alloc(this->b);
this->ipaded_key.len = this->b;
return &(this->hmac);
}
+118
View File
@@ -0,0 +1,118 @@
/**
* @file hmac.h
*
* @brief Interface of hmac_t.
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef HMAC_H_
#define HMAC_H_
#include <crypto/hashers/hasher.h>
#include <definitions.h>
typedef struct hmac_t hmac_t;
/**
* @brief Message authentication using hash functions.
*
* This class implements the message authenticaion algorithm
* described in RFC2104. It uses a hash function, wich must
* be implemented as a hasher_t class.
*
* See http://www.faqs.org/rfcs/rfc2104.html for RFC.
* @see
* - hasher_t
* - prf_hmac_t
*
* @b Constructors:
* - hmac_create()
*
* @ingroup transforms
*/
struct hmac_t {
/**
* @brief Generate message authentication code.
*
* If buffer is NULL, no result is given back. A next call will
* append the data to already supplied data. If buffer is not NULL,
* the mac of all apended data is calculated, returned and the
* state of the hmac_t is reseted.
*
* @param this calling object
* @param data chunk of data to authenticate
* @param[out] buffer pointer where the generated bytes will be written
*/
void (*get_mac) (hmac_t *this, chunk_t data, u_int8_t *buffer);
/**
* @brief Generates message authentication code and
* allocate space for them.
*
* If chunk is NULL, no result is given back. A next call will
* append the data to already supplied. If chunk is not NULL,
* the mac of all apended data is calculated, returned and the
* state of the hmac_t reset;
*
* @param this calling object
* @param data chunk of data to authenticate
* @param[out] chunk chunk which will hold generated bytes
*/
void (*allocate_mac) (hmac_t *this, chunk_t data, chunk_t *chunk);
/**
* @brief Get the block size of this hmac_t object.
*
* @param this calling object
* @return block size in bytes
*/
size_t (*get_block_size) (hmac_t *this);
/**
* @brief Set the key for this hmac_t object.
*
* Any key length is accepted.
*
* @param this calling object
* @param key key to set
*/
void (*set_key) (hmac_t *this, chunk_t key);
/**
* @brief Destroys a hmac_t object.
*
* @param this calling object
*/
void (*destroy) (hmac_t *this);
};
/**
* @brief Creates a new hmac_t object.
*
* Creates a hasher_t object internally.
*
* @param hash_algorithm hash algorithm to use
* @return
* - hmac_t object
* - NULL if hash algorithm is not supported
*
* @ingroup transforms
*/
hmac_t *hmac_create(hash_algorithm_t hash_algorithm);
#endif /*HMAC_H_*/
+157
View File
@@ -0,0 +1,157 @@
/**
* @file prf_plus.c
*
* @brief Implementation of prf_plus_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 "prf_plus.h"
#include <utils/allocator.h>
#include <definitions.h>
typedef struct private_prf_plus_t private_prf_plus_t;
/**
* Private data of an prf_plus_t object.
*
*/
struct private_prf_plus_t {
/**
* Public interface of prf_plus_t.
*/
prf_plus_t public;
/**
* PRF to use.
*/
prf_t *prf;
/**
* Initial seed.
*/
chunk_t seed;
/**
* Buffer to store current PRF result.
*/
chunk_t buffer;
/**
* Already given out bytes in current buffer.
*/
size_t given_out;
/**
* Octet which will be appended to the seed.
*/
u_int8_t appending_octet;
};
/**
* Implementation of prf_plus_t.get_bytes.
*/
static void get_bytes(private_prf_plus_t *this, size_t length, u_int8_t *buffer)
{
chunk_t appending_chunk;
size_t bytes_in_round;
size_t total_bytes_written = 0;
appending_chunk.ptr = &(this->appending_octet);
appending_chunk.len = 1;
while (length > 0)
{ /* still more to do... */
if (this->buffer.len == this->given_out)
{ /* no bytes left in buffer, get next*/
this->prf->get_bytes(this->prf, this->buffer, NULL);
this->prf->get_bytes(this->prf, this->seed, NULL);
this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr);
this->given_out = 0;
this->appending_octet++;
}
/* how many bytes can we write in this round ? */
bytes_in_round = min(length, this->buffer.len - this->given_out);
/* copy bytes from buffer with offset */
memcpy(buffer + total_bytes_written, this->buffer.ptr + this->given_out, bytes_in_round);
length -= bytes_in_round;
this->given_out += bytes_in_round;
total_bytes_written += bytes_in_round;
}
}
/**
* Implementation of prf_plus_t.allocate_bytes.
*/
static void allocate_bytes(private_prf_plus_t *this, size_t length, chunk_t *chunk)
{
chunk->ptr = allocator_alloc(length);
chunk->len = length;
this->public.get_bytes(&(this->public), length, chunk->ptr);
}
/**
* Implementation of prf_plus_t.destroy.
*/
static void destroy(private_prf_plus_t *this)
{
allocator_free(this->buffer.ptr);
allocator_free(this->seed.ptr);
allocator_free(this);
}
/*
* Description in header.
*/
prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed)
{
private_prf_plus_t *this;
chunk_t appending_chunk;
this = allocator_alloc_thing(private_prf_plus_t);
/* set public methods */
this->public.get_bytes = (void (*)(prf_plus_t *,size_t,u_int8_t*))get_bytes;
this->public.allocate_bytes = (void (*)(prf_plus_t *,size_t,chunk_t*))allocate_bytes;
this->public.destroy = (void (*)(prf_plus_t *))destroy;
/* take over prf */
this->prf = prf;
/* allocate buffer for prf output */
this->buffer.len = prf->get_block_size(prf);
this->buffer.ptr = allocator_alloc(this->buffer.len);
this->appending_octet = 0x01;
/* clone seed */
this->seed.ptr = allocator_clone_bytes(seed.ptr, seed.len);
this->seed.len = seed.len;
/* do the first run */
appending_chunk.ptr = &(this->appending_octet);
appending_chunk.len = 1;
this->prf->get_bytes(this->prf, this->seed, NULL);
this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr);
this->given_out = 0;
this->appending_octet++;
return &(this->public);
}
+93
View File
@@ -0,0 +1,93 @@
/**
* @file prf_plus.h
*
* @brief Interface for prf_plus.h.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef PRF_PLUS_H_
#define PRF_PLUS_H_
#include <crypto/prfs/prf.h>
typedef struct prf_plus_t prf_plus_t;
/**
* @brief 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 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
*/
void (*get_bytes) (prf_plus_t *this, size_t length, u_int8_t *buffer);
/**
* @brief 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
*/
void (*allocate_bytes) (prf_plus_t *this, size_t length, chunk_t *chunk);
/**
* @brief Destroys a prf_plus_t object.
*
* @param this calling object
*/
void (*destroy) (prf_plus_t *this);
};
/**
* @brief Creates a new prf_plus_t object.
*
* Seed will be cloned. prf will
* not be cloned, must be destroyed outside after
* prf_plus_t usage.
*
* @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_*/
+23
View File
@@ -0,0 +1,23 @@
# Copyright (C) 2005 Jan Hutter, 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.
#
PRFS_DIR= $(CRYPTO_DIR)prfs/
LIB_OBJS+= $(BUILD_DIR)prf.o
$(BUILD_DIR)prf.o : $(PRFS_DIR)prf.c $(PRFS_DIR)prf.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)hmac_prf.o
$(BUILD_DIR)hmac_prf.o : $(PRFS_DIR)hmac_prf.c $(PRFS_DIR)hmac_prf.h
$(CC) $(CFLAGS) -c -o $@ $<
+118
View File
@@ -0,0 +1,118 @@
/**
* @file hmac_prf.c
*
* @brief Implementation for hmac_prf_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 "hmac_prf.h"
#include <utils/allocator.h>
#include <crypto/hmac.h>
typedef struct private_hmac_prf_t private_hmac_prf_t;
/**
* Private data of a hma_prf_t object.
*/
struct private_hmac_prf_t {
/**
* Public hmac_prf_t interface.
*/
hmac_prf_t public;
/**
* Hmac to use for generation.
*/
hmac_t *hmac;
};
/**
* Implementation of prf_t.get_bytes.
*/
static void get_bytes(private_hmac_prf_t *this, chunk_t seed, u_int8_t *buffer)
{
this->hmac->get_mac(this->hmac, seed, buffer);
}
/**
* Implementation of prf_t.allocate_bytes.
*/
static void allocate_bytes(private_hmac_prf_t *this, chunk_t seed, chunk_t *chunk)
{
this->hmac->allocate_mac(this->hmac, seed, chunk);
}
/**
* Implementation of prf_t.get_block_size.
*/
static size_t get_block_size(private_hmac_prf_t *this)
{
return this->hmac->get_block_size(this->hmac);
}
/**
* Implementation of prf_t.get_block_size.
*/
static size_t get_key_size(private_hmac_prf_t *this)
{
/* for HMAC prfs, IKEv2 uses block size as key size */
return this->hmac->get_block_size(this->hmac);
}
/**
* Implementation of prf_t.set_key.
*/
static void set_key(private_hmac_prf_t *this, chunk_t key)
{
this->hmac->set_key(this->hmac, key);
}
/**
* Implementation of prf_t.destroy.
*/
static void destroy(private_hmac_prf_t *this)
{
allocator_free(this);
this->hmac->destroy(this->hmac);
}
/*
* Described in header.
*/
hmac_prf_t *hmac_prf_create(hash_algorithm_t hash_algorithm)
{
private_hmac_prf_t *this = allocator_alloc_thing(private_hmac_prf_t);
this->public.prf_interface.get_bytes = (void (*) (prf_t *,chunk_t,u_int8_t*))get_bytes;
this->public.prf_interface.allocate_bytes = (void (*) (prf_t*,chunk_t,chunk_t*))allocate_bytes;
this->public.prf_interface.get_block_size = (size_t (*) (prf_t*))get_block_size;
this->public.prf_interface.get_key_size = (size_t (*) (prf_t*))get_key_size;
this->public.prf_interface.set_key = (void (*) (prf_t *,chunk_t))set_key;
this->public.prf_interface.destroy = (void (*) (prf_t *))destroy;
this->hmac = hmac_create(hash_algorithm);
if (this->hmac == NULL)
{
allocator_free(this);
return NULL;
}
return &(this->public);
}
+64
View File
@@ -0,0 +1,64 @@
/**
* @file hmac_prf.h
*
* @brief Interface of hmac_prf_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef PRF_HMAC_H_
#define PRF_HMAC_H_
#include <types.h>
#include <crypto/prfs/prf.h>
#include <crypto/hashers/hasher.h>
typedef struct hmac_prf_t hmac_prf_t;
/**
* @brief Implementation of prf_t interface using the
* HMAC algorithm.
*
* This simply wraps a hmac_t in a prf_t. More a question of
* interface matching.
*
* @b Constructors:
* - hmac_prf_create()
*
* @ingroup prfs
*/
struct hmac_prf_t {
/**
* Generic prf_t interface for this hmac_prf_t class.
*/
prf_t prf_interface;
};
/**
* @brief Creates a new hmac_prf_t object.
*
* @param hash_algorithm hmac's hash algorithm
* @return
* - hmac_prf_t object
* - NULL if hash not supported
*
* @ingroup prfs
*/
hmac_prf_t *hmac_prf_create(hash_algorithm_t hash_algorithm);
#endif /*PRF_HMAC_SHA1_H_*/
+67
View File
@@ -0,0 +1,67 @@
/**
* @file prf.c
*
* @brief Generic constructor for all prf_t
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 "prf.h"
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/hmac_prf.h>
/**
* String mappings for encryption_algorithm_t.
*/
mapping_t pseudo_random_function_m[] = {
{PRF_UNDEFINED, "PRF_UNDEFINED"},
{PRF_HMAC_MD5, "PRF_HMAC_MD5"},
{PRF_HMAC_SHA1, "PRF_HMAC_SHA1"},
{PRF_HMAC_TIGER, "PRF_HMAC_TIGER"},
{PRF_AES128_CBC, "PRF_AES128_CBC"},
{MAPPING_END, NULL}
};
/*
* 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_TIGER:
case PRF_AES128_CBC:
default:
return NULL;
}
}
+136
View File
@@ -0,0 +1,136 @@
/**
* @file prf.h
*
* @brief Interface prf_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef PRF_H_
#define PRF_H_
#include <types.h>
typedef enum pseudo_random_function_t pseudo_random_function_t;
/**
* @brief Pseudo random function, as in IKEv2 RFC 3.3.2.
*
* Currently only the following algorithms are implemented and therefore supported:
* - PRF_HMAC_MD5
* - PRF_HMAC_SHA1
*
* @ingroup prfs
*/
enum pseudo_random_function_t {
PRF_UNDEFINED = 1024,
/**
* Implemented in class hmac_prf_t.
*/
PRF_HMAC_MD5 = 1,
/**
* Implemented in class hmac_prf_t.
*/
PRF_HMAC_SHA1 = 2,
PRF_HMAC_TIGER = 3,
PRF_AES128_CBC = 4
};
/**
* String mappings for encryption_algorithm_t.
*/
extern mapping_t pseudo_random_function_m[];
typedef struct prf_t prf_t;
/**
* @brief Generic interface for pseudo-random-functions.
*
* @b Constructors:
* - prf_create()
* - hmac_prf_create()
*
* @todo Implement more prf algorithms
*
* @ingroup prfs
*/
struct prf_t {
/**
* @brief 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
*/
void (*get_bytes) (prf_t *this, chunk_t seed, u_int8_t *buffer);
/**
* @brief 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
*/
void (*allocate_bytes) (prf_t *this, chunk_t seed, chunk_t *chunk);
/**
* @brief Get the block size of this prf_t object.
*
* @param this calling object
* @return block size in bytes
*/
size_t (*get_block_size) (prf_t *this);
/**
* @brief Get the key size of this prf_t object.
*
* @param this calling object
* @return key size in bytes
*/
size_t (*get_key_size) (prf_t *this);
/**
* @brief Set the key for this prf_t object.
*
* @param this calling object
* @param key key to set
*/
void (*set_key) (prf_t *this, chunk_t key);
/**
* @brief Destroys a prf object.
*
* @param this calling 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_*/
+23
View File
@@ -0,0 +1,23 @@
# Copyright (C) 2005 Jan Hutter, 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.
#
RSA_DIR= $(CRYPTO_DIR)rsa/
LIB_OBJS+= $(BUILD_DIR)rsa_private_key.o
$(BUILD_DIR)rsa_private_key.o : $(RSA_DIR)rsa_private_key.c $(RSA_DIR)rsa_private_key.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)rsa_public_key.o
$(BUILD_DIR)rsa_public_key.o : $(RSA_DIR)rsa_public_key.c $(RSA_DIR)rsa_public_key.h
$(CC) $(CFLAGS) -c -o $@ $<
+615
View File
@@ -0,0 +1,615 @@
/**
* @file rsa_private_key.c
*
* @brief Implementation of rsa_private_key_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 <gmp.h>
#include <sys/stat.h>
#include <unistd.h>
#include "rsa_private_key.h"
#include <daemon.h>
#include <utils/allocator.h>
#include <asn1/der_decoder.h>
/*
* Oids for hash algorithms are defined in
* rsa_public_key.c.
*/
extern u_int8_t md2_oid[18];
extern u_int8_t md5_oid[18];
extern u_int8_t sha1_oid[15];
extern u_int8_t sha256_oid[19];
extern u_int8_t sha384_oid[19];
extern u_int8_t sha512_oid[19];
/**
* 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;
/**
* @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);
/**
* @brief Generate a prime value.
*
* @param this calling object
* @param prime_size size of the prime, in bytes
* @param[out] prime uninitialized mpz
*/
status_t (*compute_prime) (private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime);
};
/**
* Rules for de-/encoding of a private key from/in ASN1
*/
static asn1_rule_t rsa_private_key_rules[] = {
{ASN1_SEQUENCE, 0, 0, 0},
{ ASN1_INTEGER, 0, offsetof(private_rsa_private_key_t, version), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, n), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, e), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, d), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, p), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, q), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, exp1), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, exp2), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, coeff), 0},
{ASN1_END, 0, 0, 0},
};
static private_rsa_private_key_t *rsa_private_key_create_empty();
/**
* Implementation of private_rsa_private_key_t.compute_prime.
*/
static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime)
{
randomizer_t *randomizer;
chunk_t random_bytes;
status_t status;
randomizer = randomizer_create();
mpz_init(*prime);
do
{
status = randomizer->allocate_random_bytes(randomizer, prime_size, &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);
allocator_free(random_bytes.ptr);
}
/* check if it isnt too large */
while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_size);
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(t1);
mpz_clear(t2);
return decrypted;
}
/**
* Implementation of rsa_private_key.build_emsa_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 hash;
chunk_t oid;
chunk_t em;
/* get oid string prepended to hash */
switch (hash_algorithm)
{
case HASH_MD2:
{
oid.ptr = md2_oid;
oid.len = sizeof(md2_oid);
break;
}
case HASH_MD5:
{
oid.ptr = md5_oid;
oid.len = sizeof(md5_oid);
break;
}
case HASH_SHA1:
{
oid.ptr = sha1_oid;
oid.len = sizeof(sha1_oid);
break;
}
case HASH_SHA256:
{
oid.ptr = sha256_oid;
oid.len = sizeof(sha256_oid);
break;
}
case HASH_SHA384:
{
oid.ptr = sha384_oid;
oid.len = sizeof(sha384_oid);
break;
}
case HASH_SHA512:
{
oid.ptr = sha512_oid;
oid.len = sizeof(sha512_oid);
break;
}
default:
{
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 chunk to rsa-decrypt:
* EM = 0x00 || 0x01 || PS || 0x00 || T.
* PS = 0xFF padding, with length to fill em
* T = oid || hash
*/
em.len = this->k;
em.ptr = allocator_alloc(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 - hash.len - oid.len - 1) = 0x00;
/* set hash */
memcpy(em.ptr + em.len - hash.len, hash.ptr, hash.len);
/* set oid */
memcpy(em.ptr + em.len - hash.len - oid.len, oid.ptr, oid.len);
/* build signature */
*signature = this->rsasp1(this, em);
allocator_free(hash.ptr);
allocator_free(em.ptr);
return SUCCESS;
}
/**
* Implementation of rsa_private_key.get_key.
*/
static status_t get_key(private_rsa_private_key_t *this, chunk_t *key)
{
chunk_t n, e, p, q, d, exp1, exp2, coeff;
n.len = this->k;
n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, this->n);
e.len = this->k;
e.ptr = mpz_export(NULL, NULL, 1, e.len, 1, 0, this->e);
p.len = this->k;
p.ptr = mpz_export(NULL, NULL, 1, p.len, 1, 0, this->p);
q.len = this->k;
q.ptr = mpz_export(NULL, NULL, 1, q.len, 1, 0, this->q);
d.len = this->k;
d.ptr = mpz_export(NULL, NULL, 1, d.len, 1, 0, this->d);
exp1.len = this->k;
exp1.ptr = mpz_export(NULL, NULL, 1, exp1.len, 1, 0, this->exp1);
exp2.len = this->k;
exp2.ptr = mpz_export(NULL, NULL, 1, exp2.len, 1, 0, this->exp2);
coeff.len = this->k;
coeff.ptr = mpz_export(NULL, NULL, 1, coeff.len, 1, 0, this->coeff);
key->len = this->k * 8;
key->ptr = allocator_alloc(key->len);
memcpy(key->ptr + this->k * 0, n.ptr , n.len);
memcpy(key->ptr + this->k * 1, e.ptr, e.len);
memcpy(key->ptr + this->k * 2, p.ptr, p.len);
memcpy(key->ptr + this->k * 3, q.ptr, q.len);
memcpy(key->ptr + this->k * 4, d.ptr, d.len);
memcpy(key->ptr + this->k * 5, exp1.ptr, exp1.len);
memcpy(key->ptr + this->k * 6, exp2.ptr, exp2.len);
memcpy(key->ptr + this->k * 7, coeff.ptr, coeff.len);
allocator_free(n.ptr);
allocator_free(e.ptr);
allocator_free(p.ptr);
allocator_free(q.ptr);
allocator_free(d.ptr);
allocator_free(exp1.ptr);
allocator_free(exp2.ptr);
allocator_free(coeff.ptr);
return SUCCESS;
}
/**
* Implementation of rsa_private_key.save_key.
*/
static status_t save_key(private_rsa_private_key_t *this, char *file)
{
return NOT_SUPPORTED;
}
/**
* Implementation of rsa_private_key.get_public_key.
*/
rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
{
return NULL;
}
/**
* Implementation of rsa_private_key.belongs_to.
*/
static bool belongs_to(private_rsa_private_key_t *this, rsa_public_key_t *public)
{
if (mpz_cmp(this->n, *public->get_modulus(public)) == 0)
{
return TRUE;
}
return FALSE;
}
/**
* Implementation of rsa_private_key.clone.
*/
static rsa_private_key_t* _clone(private_rsa_private_key_t *this)
{
private_rsa_private_key_t *clone = rsa_private_key_create_empty();
mpz_init_set(clone->n, this->n);
mpz_init_set(clone->e, this->e);
mpz_init_set(clone->p, this->p);
mpz_init_set(clone->q, this->q);
mpz_init_set(clone->d, this->d);
mpz_init_set(clone->exp1, this->exp1);
mpz_init_set(clone->exp2, this->exp2);
mpz_init_set(clone->coeff, this->coeff);
clone->k = this->k;
return &clone->public;
}
/**
* Implementation of rsa_private_key.destroy.
*/
static void destroy(private_rsa_private_key_t *this)
{
mpz_clear(this->n);
mpz_clear(this->e);
mpz_clear(this->p);
mpz_clear(this->q);
mpz_clear(this->d);
mpz_clear(this->exp1);
mpz_clear(this->exp2);
mpz_clear(this->coeff);
allocator_free(this);
}
/**
* Internal generic constructor
*/
static private_rsa_private_key_t *rsa_private_key_create_empty()
{
private_rsa_private_key_t *this = allocator_alloc_thing(private_rsa_private_key_t);
/* public functions */
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.get_key = (status_t (*) (rsa_private_key_t*,chunk_t*))get_key;
this->public.save_key = (status_t (*) (rsa_private_key_t*,char*))save_key;
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.clone = (rsa_private_key_t*(*)(rsa_private_key_t*))_clone;
this->public.destroy = (void (*) (rsa_private_key_t*))destroy;
/* private functions */
this->rsadp = rsadp;
this->rsasp1 = rsadp; /* same algorithm */
this->compute_prime = compute_prime;
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;
this = rsa_private_key_create_empty();
key_size = key_size / 8;
/* Get values of primes p and q */
if (this->compute_prime(this, key_size/2, &p) != SUCCESS)
{
allocator_free(this);
return NULL;
}
if (this->compute_prime(this, key_size/2, &q) != SUCCESS)
{
mpz_clear(p);
allocator_free(this);
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_set(t, p);
mpz_set(p, q);
mpz_set(q, t);
}
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(q1);
mpz_clear(m);
mpz_clear(t);
/* apply values */
*(this->p) = *p;
*(this->q) = *q;
*(this->n) = *n;
*(this->e) = *e;
*(this->d) = *d;
*(this->exp1) = *exp1;
*(this->exp2) = *exp2;
*(this->coeff) = *coeff;
/* set key size in bytes */
this->k = key_size;
return &this->public;
}
/*
* see header
*/
rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk)
{
private_rsa_private_key_t *this;
der_decoder_t *dd;
status_t status;
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);
dd = der_decoder_create(rsa_private_key_rules);
status = dd->decode(dd, chunk, this);
dd->destroy(dd);
if (status != SUCCESS)
{
destroy(this);
return NULL;
}
this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
return &this->public;
}
/*
* see header
*/
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, char *passphrase)
{
chunk_t chunk;
struct stat stb;
FILE *file;
char *buffer;
if (stat(filename, &stb) == -1)
{
return NULL;
}
buffer = alloca(stb.st_size);
file = fopen(filename, "r");
if (file == NULL)
{
return NULL;
}
if (fread(buffer, stb.st_size, 1, file) != 1)
{
return NULL;
}
chunk.ptr = buffer;
chunk.len = stb.st_size;
return rsa_private_key_create_from_chunk(chunk);
}
+185
View File
@@ -0,0 +1,185 @@
/**
* @file rsa_private_key.h
*
* @brief Interface of rsa_private_key_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef RSA_PRIVATE_KEY_H_
#define RSA_PRIVATE_KEY_H_
#include <types.h>
#include <definitions.h>
#include <crypto/rsa/rsa_public_key.h>
#include <crypto/hashers/hasher.h>
typedef struct rsa_private_key_t rsa_private_key_t;
/**
* @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
*
* @todo Implement get_key(), save_key(), get_public_key()
*
* @ingroup rsa
*/
struct rsa_private_key_t {
/**
* @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 Gets the key.
*
* UNIMPLEMENTED!
*
* @param this calling object
* @param key key (in a propriarity format)
* @return
* - SUCCESS
* - INVALID_STATE, if key not set
*/
status_t (*get_key) (rsa_private_key_t *this, chunk_t *key);
/**
* @brief Saves a key to a file.
*
* Not implemented!
*
* @param this calling object
* @param file file to which the key should be written.
* @return NOT_SUPPORTED
*/
status_t (*save_key) (rsa_private_key_t *this, char *file);
/**
* @brief Generate a new key.
*
* Generates a new private_key with specified key size
*
* @param this calling object
* @param key_size size of the key in bits
* @return
* - SUCCESS
* - INVALID_ARG if key_size invalid
*/
status_t (*generate_key) (rsa_private_key_t *this, size_t key_size);
/**
* @brief Create a rsa_public_key_t with the public
* parts 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 Clone the private key.
*
* @param this private key to clone
* @return clone of this
*/
rsa_private_key_t *(*clone) (rsa_private_key_t *this);
/**
* @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 lenght.
*
* @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
* @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, char *passphrase);
#endif /*RSA_PRIVATE_KEY_H_*/
+468
View File
@@ -0,0 +1,468 @@
/**
* @file rsa_public_key.c
*
* @brief Implementation of rsa_public_key_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 <gmp.h>
#include <sys/stat.h>
#include <unistd.h>
#include "rsa_public_key.h"
#include <daemon.h>
#include <utils/allocator.h>
#include <crypto/hashers/hasher.h>
#include <asn1/der_decoder.h>
/*
* For simplicity,
* we use these predefined values for
* hash algorithm OIDs. These also contain
* the length of the following hash.
* These values are also used in rsa_private_key.c.
*/
u_int8_t md2_oid[] = {
0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,
0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,
0x04,0x10
};
u_int8_t md5_oid[] = {
0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,
0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,
0x04,0x10
};
u_int8_t sha1_oid[] = {
0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,
0x03,0x02,0x1a,0x05,0x00,0x04,0x14
};
u_int8_t sha256_oid[] = {
0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,
0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
0x00,0x04,0x20
};
u_int8_t sha384_oid[] = {
0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,
0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,
0x00,0x04,0x30
};
u_int8_t sha512_oid[] = {
0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,
0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,
0x00,0x04,0x40
};
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;
/**
* @brief Implements the RSAEP algorithm specified in PKCS#1.
*
* @param this calling object
* @param data data to process
* @return processed data
*/
chunk_t (*rsaep) (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) (private_rsa_public_key_t *this, chunk_t data);
};
typedef struct rsa_public_key_info_t rsa_public_key_info_t;
/**
* KeyInfo, as it appears in a public key file
*/
struct rsa_public_key_info_t {
/**
* Algorithm for this key
*/
chunk_t algorithm_oid;
/**
* Public key, parseable with rsa_public_key_rules
*/
chunk_t public_key;
};
/**
* Rules for de-/encoding of a public key from/in ASN1
*/
static asn1_rule_t rsa_public_key_rules[] = {
{ASN1_SEQUENCE, 0, 0, 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_public_key_t, n), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_public_key_t, e), 0},
{ASN1_END, 0, 0, 0},
};
/**
* Rules for de-/encoding of a PublicKeyInfo from/in ASN1
*/
static asn1_rule_t rsa_public_key_info_rules[] = {
{ASN1_SEQUENCE, 0, 0, 0},
{ ASN1_SEQUENCE, 0, 0, 0},
{ ASN1_OID, 0, offsetof(rsa_public_key_info_t, algorithm_oid), 0},
{ ASN1_NULL, 0, 0, 0},
{ ASN1_END, 0, 0, 0},
{ ASN1_BITSTRING, 0, offsetof(rsa_public_key_info_t, public_key), 0},
{ASN1_END, 0, 0, 0},
};
private_rsa_public_key_t *rsa_public_key_create_empty();
/**
* Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1
*/
static chunk_t rsaep(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.verify_emsa_pkcs1_signature.
*/
static status_t verify_emsa_pkcs1_signature(private_rsa_public_key_t *this, chunk_t data, chunk_t signature)
{
hasher_t *hasher = NULL;
chunk_t hash;
chunk_t em;
u_int8_t *pos;
if (signature.len > this->k)
{
return INVALID_ARG;
}
/* unpack signature */
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))
{
allocator_free(em.ptr);
return FAILED;
}
/* find magic 0x00 */
pos = em.ptr + 2;
while (pos <= em.ptr + em.len)
{
if (*pos == 0x00)
{
/* found magic byte, stop */
pos++;
break;
}
else if (*pos != 0xFF)
{
/* bad padding, decryption failed ?!*/
allocator_free(em.ptr);
return FAILED;
}
pos++;
}
if (pos + 20 > em.ptr + em.len)
{
/* not enought room for oid compare */
allocator_free(em.ptr);
return FAILED;
}
if (memcmp(md2_oid, pos, sizeof(md2_oid)) == 0)
{
hasher = hasher_create(HASH_MD2);
pos += sizeof(md2_oid);
}
else if (memcmp(md5_oid, pos, sizeof(md5_oid)) == 0)
{
hasher = hasher_create(HASH_MD5);
pos += sizeof(md5_oid);
}
else if (memcmp(sha1_oid, pos, sizeof(sha1_oid)) == 0)
{
hasher = hasher_create(HASH_SHA1);
pos += sizeof(sha1_oid);
}
else if (memcmp(sha256_oid, pos, sizeof(sha256_oid)) == 0)
{
hasher = hasher_create(HASH_SHA256);
pos += sizeof(sha256_oid);
}
else if (memcmp(sha384_oid, pos, sizeof(sha384_oid)) == 0)
{
hasher = hasher_create(HASH_SHA384);
pos += sizeof(sha384_oid);
}
else if (memcmp(sha512_oid, pos, sizeof(sha512_oid)) == 0)
{
hasher = hasher_create(HASH_SHA512);
pos += sizeof(sha512_oid);
}
if (hasher == NULL)
{
/* not supported hash algorithm */
allocator_free(em.ptr);
return NOT_SUPPORTED;
}
if (pos + hasher->get_block_size(hasher) != em.ptr + em.len)
{
/* bad length */
allocator_free(em.ptr);
hasher->destroy(hasher);
return FAILED;
}
/* build own hash for a compare */
hasher->allocate_hash(hasher, data, &hash);
hasher->destroy(hasher);
if (memcmp(hash.ptr, pos, hash.len) != 0)
{
/* hash does not equal */
allocator_free(hash.ptr);
allocator_free(em.ptr);
return FAILED;
}
/* seems good */
allocator_free(hash.ptr);
allocator_free(em.ptr);
return SUCCESS;
}
/**
* Implementation of rsa_public_key.get_key.
*/
static status_t get_key(private_rsa_public_key_t *this, chunk_t *key)
{
chunk_t n, e;
n.len = this->k;
n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, this->n);
e.len = this->k;
e.ptr = mpz_export(NULL, NULL, 1, e.len, 1, 0, this->e);
key->len = this->k * 2;
key->ptr = allocator_alloc(key->len);
memcpy(key->ptr, n.ptr, n.len);
memcpy(key->ptr + n.len, e.ptr, e.len);
allocator_free(n.ptr);
allocator_free(e.ptr);
return SUCCESS;
}
/**
* Implementation of rsa_public_key.save_key.
*/
static status_t save_key(private_rsa_public_key_t *this, char *file)
{
return NOT_SUPPORTED;
}
/**
* Implementation of rsa_public_key.get_modulus.
*/
static mpz_t *get_modulus(private_rsa_public_key_t *this)
{
return &this->n;
}
/**
* Implementation of rsa_public_key.clone.
*/
static rsa_public_key_t* _clone(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->k = this->k;
return &clone->public;
}
/**
* Implementation of rsa_public_key.destroy.
*/
static void destroy(private_rsa_public_key_t *this)
{
mpz_clear(this->n);
mpz_clear(this->e);
allocator_free(this);
}
/**
* Generic private constructor
*/
private_rsa_public_key_t *rsa_public_key_create_empty()
{
private_rsa_public_key_t *this = allocator_alloc_thing(private_rsa_public_key_t);
/* public functions */
this->public.verify_emsa_pkcs1_signature = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
this->public.get_key = (status_t (*) (rsa_public_key_t*,chunk_t*))get_key;
this->public.save_key = (status_t (*) (rsa_public_key_t*,char*))save_key;
this->public.get_modulus = (mpz_t *(*) (rsa_public_key_t*))get_modulus;
this->public.clone = (rsa_public_key_t* (*) (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_from_chunk(chunk_t chunk)
{
der_decoder_t *dd;
status_t status;
private_rsa_public_key_t *this;
this = rsa_public_key_create_empty();
mpz_init(this->n);
mpz_init(this->e);
dd = der_decoder_create(rsa_public_key_rules);
status = dd->decode(dd, chunk, this);
dd->destroy(dd);
if (status != SUCCESS)
{
destroy(this);
return NULL;
}
this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
return &this->public;
}
/*
* See header
*/
rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
{
struct stat stb;
FILE *file;
char *buffer;
chunk_t chunk;
rsa_public_key_info_t key_info = {CHUNK_INITIALIZER, CHUNK_INITIALIZER};
der_decoder_t *dd;
status_t status;
rsa_public_key_t *public_key = NULL;
if (stat(filename, &stb) == -1)
{
return NULL;
}
buffer = alloca(stb.st_size);
file = fopen(filename, "r");
if (file == NULL)
{
return NULL;
}
if (fread(buffer, stb.st_size, 1, file) != 1)
{
return NULL;
}
chunk.ptr = buffer;
chunk.len = stb.st_size;
/* parse public key info first */
dd = der_decoder_create(rsa_public_key_info_rules);
status = dd->decode(dd, chunk, &key_info);
dd->destroy(dd);
allocator_free_chunk(&key_info.algorithm_oid);
if (status == SUCCESS)
{
public_key = rsa_public_key_create_from_chunk(chunk);
}
allocator_free_chunk(&key_info.public_key);
return public_key;
}
+153
View File
@@ -0,0 +1,153 @@
/**
* @file rsa_public_key.h
*
* @brief Interface of rsa_public_key_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef RSA_PUBLIC_KEY_H_
#define RSA_PUBLIC_KEY_H_
#include <gmp.h>
#include <types.h>
#include <definitions.h>
typedef struct rsa_public_key_t rsa_public_key_t;
/**
* @brief RSA public key with associated functions.
*
* Currently only supports signature verification using
* the EMSA encoding (see PKCS1)
*
* @b Constructors:
* - rsa_public_key_create_from_chunk()
* - rsa_public_key_create_from_file()
* - rsa_private_key_t.get_public_key()
*
* @see rsa_private_key_t
*
* @todo Implement getkey() and savekey()
*
* @ingroup rsa
*/
struct rsa_public_key_t {
/**
* @brief Verify a EMSA-PKCS1 encodined 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 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) (rsa_public_key_t *this, chunk_t data, chunk_t signature);
/**
* @brief Gets the key.
*
* Currently uses a proprietary format which is only inteded
* for testing. This should be replaced with a proper
* ASN1 encoded key format, when charon gets the ASN1
* capabilities.
*
* @param this calling object
* @param key key (in a propriarity format)
* @return
* - SUCCESS
* - INVALID_STATE, if key not set
*/
status_t (*get_key) (rsa_public_key_t *this, chunk_t *key);
/**
* @brief Saves a key to a file.
*
* Not implemented!
*
* @param this calling object
* @param file file to which the key should be written.
* @return NOT_SUPPORTED
*/
status_t (*save_key) (rsa_public_key_t *this, char *file);
/**
* @brief Get the modulus of the key.
*
* @param this calling object
* @return modulus (n) of the key
*/
mpz_t *(*get_modulus) (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) (rsa_public_key_t *this);
/**
* @brief Destroys the public key.
*
* @param this public key to destroy
*/
void (*destroy) (rsa_public_key_t *this);
};
/**
* @brief Load an RSA public key from a chunk.
*
* Load a key from a chunk, encoded in the more frequently
* used PublicKeyInfo struct (ASN1 DER encoded).
*
* @param chunk chunk containing the DER encoded key
* @return loaded rsa_public_key_t, or NULL
*
* @todo Check OID in PublicKeyInfo
*
* @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
*
* @todo Implement PEM file loading
*
* @ingroup rsa
*/
rsa_public_key_t *rsa_public_key_create_from_file(char *filename);
#endif /*RSA_PUBLIC_KEY_H_*/
@@ -0,0 +1,23 @@
# Copyright (C) 2005 Jan Hutter, 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.
#
SIGNERS_DIR= $(CRYPTO_DIR)signers/
LIB_OBJS+= $(BUILD_DIR)signer.o
$(BUILD_DIR)signer.o : $(SIGNERS_DIR)signer.c $(SIGNERS_DIR)signer.h
$(CC) $(CFLAGS) -c -o $@ $<
LIB_OBJS+= $(BUILD_DIR)hmac_signer.o
$(BUILD_DIR)hmac_signer.o : $(SIGNERS_DIR)hmac_signer.c $(SIGNERS_DIR)hmac_signer.h
$(CC) $(CFLAGS) -c -o $@ $<
+168
View File
@@ -0,0 +1,168 @@
/**
* @file hmac_signer.c
*
* @brief Implementation of hmac_signer_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 "hmac_signer.h"
#include <utils/allocator.h>
#include <crypto/prfs/hmac_prf.h>
/**
* This class represents a hmac signer with 12 byte (96 bit) output.
*/
#define BLOCK_SIZE 12
typedef struct private_hmac_signer_t private_hmac_signer_t;
/**
* Private data structure with signing context.
*/
struct private_hmac_signer_t {
/**
* Public interface of hmac_signer_t.
*/
hmac_signer_t public;
/*
* Assigned hmac function.
*/
prf_t *hmac_prf;
};
/**
* Implementation of signer_t.get_signature.
*/
static void get_signature (private_hmac_signer_t *this, chunk_t data, u_int8_t *buffer)
{
u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
/* copy mac aka signature :-) */
memcpy(buffer,full_mac,BLOCK_SIZE);
}
/**
* Implementation of signer_t.allocate_signature.
*/
static void allocate_signature (private_hmac_signer_t *this, chunk_t data, chunk_t *chunk)
{
chunk_t signature;
u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
signature.ptr = allocator_alloc(BLOCK_SIZE);
signature.len = BLOCK_SIZE;
/* copy signature */
memcpy(signature.ptr,full_mac,BLOCK_SIZE);
*chunk = signature;
}
/**
* Implementation of signer_t.verify_signature.
*/
static bool verify_signature (private_hmac_signer_t *this, chunk_t data, chunk_t signature)
{
u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
if (signature.len != BLOCK_SIZE)
{
return FALSE;
}
/* compare mac aka signature :-) */
if (memcmp(signature.ptr,full_mac,BLOCK_SIZE) == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
/**
* Implementation of signer_t.get_key_size.
*/
static size_t get_key_size (private_hmac_signer_t *this)
{
/* for HMAC signer, IKEv2 uses block size as key size */
return this->hmac_prf->get_block_size(this->hmac_prf);
}
/**
* Implementation of signer_t.get_block_size.
*/
static size_t get_block_size (private_hmac_signer_t *this)
{
return BLOCK_SIZE;
}
/**
* Implementation of signer_t.set_key.
*/
static void set_key (private_hmac_signer_t *this, chunk_t key)
{
this->hmac_prf->set_key(this->hmac_prf,key);
}
/**
* Implementation of signer_t.destroy.
*/
static status_t destroy(private_hmac_signer_t *this)
{
this->hmac_prf->destroy(this->hmac_prf);
allocator_free(this);
return SUCCESS;
}
/*
* Described in header
*/
hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm)
{
private_hmac_signer_t *this = allocator_alloc_thing(private_hmac_signer_t);
this->hmac_prf = (prf_t *) hmac_prf_create(hash_algoritm);
if (this->hmac_prf == NULL)
{
/* algorithm not supported */
allocator_free(this);
return NULL;
}
/* interface functions */
this->public.signer_interface.get_signature = (void (*) (signer_t*, chunk_t, u_int8_t*))get_signature;
this->public.signer_interface.allocate_signature = (void (*) (signer_t*, chunk_t, chunk_t*))allocate_signature;
this->public.signer_interface.verify_signature = (bool (*) (signer_t*, chunk_t, chunk_t))verify_signature;
this->public.signer_interface.get_key_size = (size_t (*) (signer_t*))get_key_size;
this->public.signer_interface.get_block_size = (size_t (*) (signer_t*))get_block_size;
this->public.signer_interface.set_key = (void (*) (signer_t*,chunk_t))set_key;
this->public.signer_interface.destroy = (void (*) (signer_t*))destroy;
return &(this->public);
}
+58
View File
@@ -0,0 +1,58 @@
/**
* @file hmac_signer.h
*
* @brief Interface of hmac_signer_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef HMAC_SIGNER_H_
#define HMAC_SIGNER_H_
#include <crypto/signers/signer.h>
#include <crypto/hashers/hasher.h>
typedef struct hmac_signer_t hmac_signer_t;
/**
* @brief Implementation of signer_t interface using the
* HMAC algorithm in combination with either MD5 or SHA1.
*
* @ingroup signers
*/
struct hmac_signer_t {
/**
* generic signer_t interface for this signer
*/
signer_t signer_interface;
};
/**
* @brief Creates a new hmac_signer_t.
*
* @param hash_algoritm Hash algorithm to use with signer
* @return
* - hmac_signer_t
* - NULL if hash algorithm not supported
*
* @ingroup signers
*/
hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm);
#endif /*HMAC_SIGNER_H_*/
+59
View File
@@ -0,0 +1,59 @@
/**
* @file signer.c
*
* @brief Implementation of generic signer_t constructor.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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 "signer.h"
#include <crypto/signers/hmac_signer.h>
/**
* String mappings for integrity_algorithm_t.
*/
mapping_t integrity_algorithm_m[] = {
{AUTH_UNDEFINED, "AUTH_UNDEFINED"},
{AUTH_HMAC_MD5_96, "AUTH_HMAC_MD5_96"},
{AUTH_HMAC_SHA1_96, "AUTH_HMAC_SHA1_96"},
{AUTH_DES_MAC, "AUTH_DES_MAC"},
{AUTH_KPDK_MD5, "AUTH_KPDK_MD5"},
{AUTH_AES_XCBC_96, "AUTH_AES_XCBC_96"},
{MAPPING_END, NULL}
};
/*
* 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));
}
case AUTH_HMAC_MD5_96:
{
return ((signer_t *) hmac_signer_create(HASH_MD5));
}
default:
return NULL;
}
}
+147
View File
@@ -0,0 +1,147 @@
/**
* @file signer.h
*
* @brief Interface for signer_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, 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.
*/
#ifndef SIGNER_H_
#define SIGNER_H_
#include <types.h>
#include <definitions.h>
typedef enum integrity_algorithm_t integrity_algorithm_t;
/**
* @brief Integrity algorithm, as in IKEv2 RFC 3.3.2.
*
* Currently only the following algorithms are implemented and therefore supported:
* - AUTH_HMAC_MD5_96
* - AUTH_HMAC_SHA1_96
*
* @ingroup signers
*/
enum integrity_algorithm_t {
AUTH_UNDEFINED = 1024,
/**
* Implemented in class hmac_signer_t.
*/
AUTH_HMAC_MD5_96 = 1,
/**
* Implemented in class hmac_signer_t.
*/
AUTH_HMAC_SHA1_96 = 2,
AUTH_DES_MAC = 3,
AUTH_KPDK_MD5 = 4,
AUTH_AES_XCBC_96 = 5
};
/**
* String mappings for integrity_algorithm_t.
*/
extern mapping_t integrity_algorithm_m[];
typedef struct signer_t signer_t;
/**
* @brief Generig interface for a symmetric signature algorithm.
*
* @b Constructors:
* - signer_create()
* - hmac_signer_create()
*
* @todo Implement more integrity algorithms
*
* @ingroup signers
*/
struct signer_t {
/**
* @brief Generate a signature.
*
* @param this calling object
* @param data a chunk containing the data to sign
* @param[out] 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.
*
* @param this calling object
* @param data a chunk containing the data to sign
* @param[out] chunk chunk which will hold the allocated signature
*/
void (*allocate_signature) (signer_t *this, chunk_t data, chunk_t *chunk);
/**
* @brief 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
*/
bool (*verify_signature) (signer_t *this, chunk_t data, chunk_t signature);
/**
* @brief Get the block size of this signature algorithm.
*
* @param this calling object
* @return block size in bytes
*/
size_t (*get_block_size) (signer_t *this);
/**
* @brief Get the key size of the signature algorithm.
*
* @param this calling object
* @return key size in bytes
*/
size_t (*get_key_size) (signer_t *this);
/**
* @brief Set the key for this object.
*
* @param this calling object
* @param key key to set
*/
void (*set_key) (signer_t *this, chunk_t key);
/**
* @brief Destroys a signer_t object.
*
* @param this calling 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_*/