Files
libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.c
T
2008-11-16 09:38:45 +00:00

1497 lines
40 KiB
C

/*
* Copyright (C) 2000, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of GNUTLS.
*
* The GNUTLS library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA
*
*/
#include "gnutls_int.h"
#include "gnutls_algorithms.h"
#include "gnutls_errors.h"
#include "gnutls_cert.h"
/* x509 */
#include "common.h"
/* Cred type mappings to KX algorithms
* FIXME: The mappings are not 1-1. Some KX such as SRP_RSA require
* more than one credentials type.
*/
typedef struct
{
enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm;
enum MHD_GNUTLS_CredentialsType client_type;
enum MHD_GNUTLS_CredentialsType server_type; /* The type of credentials a server
* needs to set */
} MHD_gnutls_cred_map;
static const MHD_gnutls_cred_map MHD_gtls_cred_mappings[] = {
{MHD_GNUTLS_KX_RSA,
MHD_GNUTLS_CRD_CERTIFICATE,
MHD_GNUTLS_CRD_CERTIFICATE},
{MHD_GNUTLS_KX_RSA_EXPORT,
MHD_GNUTLS_CRD_CERTIFICATE,
MHD_GNUTLS_CRD_CERTIFICATE},
{MHD_GNUTLS_KX_DHE_DSS,
MHD_GNUTLS_CRD_CERTIFICATE,
MHD_GNUTLS_CRD_CERTIFICATE},
{MHD_GNUTLS_KX_DHE_RSA,
MHD_GNUTLS_CRD_CERTIFICATE,
MHD_GNUTLS_CRD_CERTIFICATE},
{0,
0,
0}
};
#define GNUTLS_KX_MAP_LOOP(b) \
const MHD_gnutls_cred_map *p; \
for(p = MHD_gtls_cred_mappings; p->algorithm != 0; p++) { b ; }
#define GNUTLS_KX_MAP_ALG_LOOP_SERVER(a) \
GNUTLS_KX_MAP_LOOP( if(p->server_type == type) { a; break; })
#define GNUTLS_KX_MAP_ALG_LOOP_CLIENT(a) \
GNUTLS_KX_MAP_LOOP( if(p->client_type == type) { a; break; })
/* KX mappings to PK algorithms */
typedef struct
{
enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm;
enum MHD_GNUTLS_PublicKeyAlgorithm pk_algorithm;
enum encipher_type encipher_type; /* CIPHER_ENCRYPT if this algorithm is to be used
* for encryption, CIPHER_SIGN if signature only,
* CIPHER_IGN if this does not apply at all.
*
* This is useful to certificate cipher suites, which check
* against the certificate key usage bits.
*/
} MHD_gnutls_pk_map;
/* This table maps the Key exchange algorithms to
* the certificate algorithms. Eg. if we have
* RSA algorithm in the certificate then we can
* use GNUTLS_KX_RSA or GNUTLS_KX_DHE_RSA.
*/
static const MHD_gnutls_pk_map MHD_gtls_pk_mappings[] = {
{MHD_GNUTLS_KX_RSA,
MHD_GNUTLS_PK_RSA,
CIPHER_ENCRYPT},
{MHD_GNUTLS_KX_RSA_EXPORT,
MHD_GNUTLS_PK_RSA,
CIPHER_SIGN},
{MHD_GNUTLS_KX_DHE_RSA,
MHD_GNUTLS_PK_RSA,
CIPHER_SIGN},
{MHD_GNUTLS_KX_SRP_RSA,
MHD_GNUTLS_PK_RSA,
CIPHER_SIGN},
{0,
0,
0}
};
#define GNUTLS_PK_MAP_LOOP(b) \
const MHD_gnutls_pk_map *p; \
for(p = MHD_gtls_pk_mappings; p->kx_algorithm != 0; p++) { b }
#define GNUTLS_PK_MAP_ALG_LOOP(a) \
GNUTLS_PK_MAP_LOOP( if(p->kx_algorithm == kx_algorithm) { a; break; })
/* TLS Versions */
typedef struct
{
const char *name;
enum MHD_GNUTLS_Protocol id; /* gnutls internal version number */
int major; /* defined by the protocol */
int minor; /* defined by the protocol */
int supported; /* 0 not supported, > 0 is supported */
} MHD_gnutls_version_entry;
static const MHD_gnutls_version_entry MHD_gtls_sup_versions[] = {
{"SSL3.0",
MHD_GNUTLS_PROTOCOL_SSL3,
3,
0,
1},
{"TLS1.0",
MHD_GNUTLS_PROTOCOL_TLS1_0,
3,
1,
1},
{"TLS1.1",
MHD_GNUTLS_PROTOCOL_TLS1_1,
3,
2,
1},
{"TLS1.2",
MHD_GNUTLS_PROTOCOL_TLS1_2,
3,
3,
1},
{0,
0,
0,
0,
0}
};
/* Keep the contents of this struct the same as the previous one. */
static const enum MHD_GNUTLS_Protocol MHD_gtls_supported_protocols[] =
{ MHD_GNUTLS_PROTOCOL_SSL3,
MHD_GNUTLS_PROTOCOL_TLS1_0,
MHD_GNUTLS_PROTOCOL_TLS1_1,
MHD_GNUTLS_PROTOCOL_TLS1_2,
0
};
#define GNUTLS_VERSION_LOOP(b) \
const MHD_gnutls_version_entry *p; \
for(p = MHD_gtls_sup_versions; p->name != NULL; p++) { b ; }
#define GNUTLS_VERSION_ALG_LOOP(a) \
GNUTLS_VERSION_LOOP( if(p->id == version) { a; break; })
struct MHD_gnutls_cipher_entry
{
const char *name;
enum MHD_GNUTLS_CipherAlgorithm id;
uint16_t blocksize;
uint16_t keysize;
cipher_type_t block;
uint16_t iv;
int export_flag; /* 0 non export */
};
typedef struct MHD_gnutls_cipher_entry MHD_gnutls_cipher_entry;
/* Note that all algorithms are in CBC or STREAM modes.
* Do not add any algorithms in other modes (avoid modified algorithms).
* View first: "The order of encryption and authentication for
* protecting communications" by Hugo Krawczyk - CRYPTO 2001
*/
static const MHD_gnutls_cipher_entry MHD_gtls_algorithms[] = {
{"AES-256-CBC",
MHD_GNUTLS_CIPHER_AES_256_CBC,
16,
32,
CIPHER_BLOCK,
16,
0},
{"AES-128-CBC",
MHD_GNUTLS_CIPHER_AES_128_CBC,
16,
16,
CIPHER_BLOCK,
16,
0},
{"3DES-CBC",
MHD_GNUTLS_CIPHER_3DES_CBC,
8,
24,
CIPHER_BLOCK,
8,
0},
{"DES-CBC",
MHD_GNUTLS_CIPHER_DES_CBC,
8,
8,
CIPHER_BLOCK,
8,
0},
{"ARCFOUR-128",
MHD_GNUTLS_CIPHER_ARCFOUR_128,
1,
16,
CIPHER_STREAM,
0,
0},
{"ARCFOUR-40",
MHD_GNUTLS_CIPHER_ARCFOUR_40,
1,
5,
CIPHER_STREAM,
0,
1},
{"RC2-40",
MHD_GNUTLS_CIPHER_RC2_40_CBC,
8,
5,
CIPHER_BLOCK,
8,
1},
{"NULL",
MHD_GNUTLS_CIPHER_NULL,
1,
0,
CIPHER_STREAM,
0,
0},
{0,
0,
0,
0,
0,
0,
0}
};
/* Keep the contents of this struct the same as the previous one. */
static const enum MHD_GNUTLS_CipherAlgorithm MHD_gtls_supported_ciphers[] =
{ MHD_GNUTLS_CIPHER_AES_256_CBC,
MHD_GNUTLS_CIPHER_AES_128_CBC,
MHD_GNUTLS_CIPHER_3DES_CBC,
MHD_GNUTLS_CIPHER_DES_CBC,
MHD_GNUTLS_CIPHER_ARCFOUR_128,
MHD_GNUTLS_CIPHER_ARCFOUR_40,
MHD_GNUTLS_CIPHER_RC2_40_CBC,
MHD_GNUTLS_CIPHER_NULL,
0
};
#define GNUTLS_LOOP(b) \
const MHD_gnutls_cipher_entry *p; \
for(p = MHD_gtls_algorithms; p->name != NULL; p++) { b ; }
#define GNUTLS_ALG_LOOP(a) \
GNUTLS_LOOP( if(p->id == algorithm) { a; break; } )
struct MHD_gnutls_hash_entry
{
const char *name;
const char *oid;
enum MHD_GNUTLS_HashAlgorithm id;
size_t key_size; /* in case of mac */
};
typedef struct MHD_gnutls_hash_entry MHD_gnutls_hash_entry;
static const MHD_gnutls_hash_entry MHD_gtls_hash_algorithms[] = {
{"SHA1",
HASH_OID_SHA1,
MHD_GNUTLS_MAC_SHA1,
20},
{"MD5",
HASH_OID_MD5,
MHD_GNUTLS_MAC_MD5,
16},
{"SHA256",
HASH_OID_SHA256,
MHD_GNUTLS_MAC_SHA256,
32},
{"NULL",
NULL,
MHD_GNUTLS_MAC_NULL,
0},
{0,
0,
0,
0}
};
/* Keep the contents of this struct the same as the previous one. */
static const enum MHD_GNUTLS_HashAlgorithm MHD_gtls_supported_macs[] =
{ MHD_GNUTLS_MAC_SHA1,
MHD_GNUTLS_MAC_MD5,
MHD_GNUTLS_MAC_SHA256,
MHD_GNUTLS_MAC_NULL,
0
};
#define GNUTLS_HASH_LOOP(b) \
const MHD_gnutls_hash_entry *p; \
for(p = MHD_gtls_hash_algorithms; p->name != NULL; p++) { b ; }
#define GNUTLS_HASH_ALG_LOOP(a) \
GNUTLS_HASH_LOOP( if(p->id == algorithm) { a; break; } )
/* Compression Section */
#define GNUTLS_COMPRESSION_ENTRY(name, id, wb, ml, cl) \
{ #name, name, id, wb, ml, cl}
#define MAX_COMP_METHODS 5
const int MHD__gnutls_comp_algorithms_size = MAX_COMP_METHODS;
/* the compression entry is defined in MHD_gnutls_algorithms.h */
MHD_gnutls_compression_entry
MHD__gnutls_compression_algorithms[MAX_COMP_METHODS] =
{ GNUTLS_COMPRESSION_ENTRY (MHD_GNUTLS_COMP_NULL, 0x00, 0, 0, 0),
#ifdef HAVE_LIBZ
/* draft-ietf-tls-compression-02 */
GNUTLS_COMPRESSION_ENTRY (MHD_GNUTLS_COMP_DEFLATE, 0x01, 15, 8, 3),
#endif
{0,
0,
0,
0,
0,
0}
};
static const enum MHD_GNUTLS_CompressionMethod
MHD_gtls_supported_compressions[] =
{
#ifdef HAVE_LIBZ
MHD_GNUTLS_COMP_DEFLATE,
#endif
MHD_GNUTLS_COMP_NULL,
0
};
#define GNUTLS_COMPRESSION_LOOP(b) \
const MHD_gnutls_compression_entry *p; \
for(p = MHD__gnutls_compression_algorithms; p->name != NULL; p++) { b ; }
#define GNUTLS_COMPRESSION_ALG_LOOP(a) \
GNUTLS_COMPRESSION_LOOP( if(p->id == algorithm) { a; break; } )
#define GNUTLS_COMPRESSION_ALG_LOOP_NUM(a) \
GNUTLS_COMPRESSION_LOOP( if(p->num == num) { a; break; } )
/* Key Exchange Section */
extern MHD_gtls_mod_auth_st MHD_gtls_rsa_auth_struct;
extern MHD_gtls_mod_auth_st MHD_rsa_export_auth_struct;
extern MHD_gtls_mod_auth_st MHD_gtls_dhe_rsa_auth_struct;
extern MHD_gtls_mod_auth_st MHD_gtls_dhe_dss_auth_struct;
extern MHD_gtls_mod_auth_st srp_auth_struct;
extern MHD_gtls_mod_auth_st psk_auth_struct;
extern MHD_gtls_mod_auth_st dhe_psk_auth_struct;
extern MHD_gtls_mod_auth_st srp_rsa_auth_struct;
extern MHD_gtls_mod_auth_st srp_dss_auth_struct;
typedef struct MHD_gtls_kx_algo_entry
{
const char *name;
enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm;
MHD_gtls_mod_auth_st *auth_struct;
int needs_dh_params;
int needs_rsa_params;
} MHD_gtls_kx_algo_entry_t;
static const MHD_gtls_kx_algo_entry_t MHD_gtls_kx_algorithms[] = {
{"RSA",
MHD_GNUTLS_KX_RSA,
&MHD_gtls_rsa_auth_struct,
0,
0},
{"RSA-EXPORT",
MHD_GNUTLS_KX_RSA_EXPORT,
&MHD_rsa_export_auth_struct,
0,
1 /* needs RSA params */ },
{"DHE-RSA",
MHD_GNUTLS_KX_DHE_RSA,
&MHD_gtls_dhe_rsa_auth_struct,
1,
0},
{"DHE-DSS",
MHD_GNUTLS_KX_DHE_DSS,
&MHD_gtls_dhe_dss_auth_struct,
1,
0},
{0,
0,
0,
0,
0}
};
/* Keep the contents of this struct the same as the previous one. */
static const enum MHD_GNUTLS_KeyExchangeAlgorithm MHD_gtls_supported_kxs[] =
{
MHD_GNUTLS_KX_RSA,
MHD_GNUTLS_KX_RSA_EXPORT,
MHD_GNUTLS_KX_DHE_RSA,
MHD_GNUTLS_KX_DHE_DSS,
0
};
#define GNUTLS_KX_LOOP(b) \
const MHD_gtls_kx_algo_entry_t *p; \
for(p = MHD_gtls_kx_algorithms; p->name != NULL; p++) { b ; }
#define GNUTLS_KX_ALG_LOOP(a) \
GNUTLS_KX_LOOP( if(p->algorithm == algorithm) { a; break; } )
/* Cipher SUITES */
#define GNUTLS_CIPHER_SUITE_ENTRY( name, block_algorithm, kx_algorithm, mac_algorithm, version ) \
{ #name, {name}, block_algorithm, kx_algorithm, mac_algorithm, version }
typedef struct
{
const char *name;
cipher_suite_st id;
enum MHD_GNUTLS_CipherAlgorithm block_algorithm;
enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm;
enum MHD_GNUTLS_HashAlgorithm mac_algorithm;
enum MHD_GNUTLS_Protocol version; /* this cipher suite is supported
* from 'version' and above;
*/
} MHD_gtls_cipher_suite_entry;
/* RSA with NULL cipher and MD5 MAC
* for test purposes.
*/
#define GNUTLS_RSA_NULL_MD5 { 0x00, 0x01 }
/* PSK (not in TLS 1.0)
* draft-ietf-tls-psk:
*/
#define GNUTLS_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8A }
#define GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8B }
#define GNUTLS_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x8C }
#define GNUTLS_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x8D }
#define GNUTLS_DHE_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8E }
#define GNUTLS_DHE_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8F }
#define GNUTLS_DHE_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x90 }
#define GNUTLS_DHE_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x91 }
/* SRP (rfc5054)
*/
#define GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1A }
#define GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1B }
#define GNUTLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1 { 0xC0, 0x1C }
#define GNUTLS_SRP_SHA_AES_128_CBC_SHA1 { 0xC0, 0x1D }
#define GNUTLS_SRP_SHA_RSA_AES_128_CBC_SHA1 { 0xC0, 0x1E }
#define GNUTLS_SRP_SHA_DSS_AES_128_CBC_SHA1 { 0xC0, 0x1F }
#define GNUTLS_SRP_SHA_AES_256_CBC_SHA1 { 0xC0, 0x20 }
#define GNUTLS_SRP_SHA_RSA_AES_256_CBC_SHA1 { 0xC0, 0x21 }
#define GNUTLS_SRP_SHA_DSS_AES_256_CBC_SHA1 { 0xC0, 0x22 }
/* RSA
*/
#define GNUTLS_RSA_ARCFOUR_SHA1 { 0x00, 0x05 }
#define GNUTLS_RSA_ARCFOUR_MD5 { 0x00, 0x04 }
#define GNUTLS_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x0A }
#define GNUTLS_RSA_EXPORT_ARCFOUR_40_MD5 { 0x00, 0x03 }
/* rfc3268:
*/
#define GNUTLS_RSA_AES_128_CBC_SHA1 { 0x00, 0x2F }
#define GNUTLS_RSA_AES_256_CBC_SHA1 { 0x00, 0x35 }
/* rfc4132 */
#define GNUTLS_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x41 }
#define GNUTLS_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x84 }
/* DHE DSS
*/
#define GNUTLS_DHE_DSS_3DES_EDE_CBC_SHA1 { 0x00, 0x13 }
/* draft-ietf-tls-56-bit-ciphersuites-01:
*/
#define GNUTLS_DHE_DSS_ARCFOUR_SHA1 { 0x00, 0x66 }
/* rfc3268:
*/
#define GNUTLS_DHE_DSS_AES_256_CBC_SHA1 { 0x00, 0x38 }
#define GNUTLS_DHE_DSS_AES_128_CBC_SHA1 { 0x00, 0x32 }
/* rfc4132 */
#define GNUTLS_DHE_DSS_CAMELLIA_128_CBC_SHA1 { 0x00,0x44 }
#define GNUTLS_DHE_DSS_CAMELLIA_256_CBC_SHA1 { 0x00,0x87 }
/* DHE RSA
*/
#define GNUTLS_DHE_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x16 }
/* rfc3268:
*/
#define GNUTLS_DHE_RSA_AES_128_CBC_SHA1 { 0x00, 0x33 }
#define GNUTLS_DHE_RSA_AES_256_CBC_SHA1 { 0x00, 0x39 }
/* rfc4132 */
#define GNUTLS_DHE_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x45 }
#define GNUTLS_DHE_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x88 }
#define CIPHER_SUITES_COUNT sizeof(MHD_gtls_cs_algorithms)/sizeof(MHD_gtls_cipher_suite_entry)-1
static const MHD_gtls_cipher_suite_entry MHD_gtls_cs_algorithms[] = {
/* SRP */
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1,
MHD_GNUTLS_CIPHER_3DES_CBC, MHD_GNUTLS_KX_SRP,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_AES_128_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_128_CBC, MHD_GNUTLS_KX_SRP,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_AES_256_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_256_CBC, MHD_GNUTLS_KX_SRP,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1,
MHD_GNUTLS_CIPHER_3DES_CBC,
MHD_GNUTLS_KX_SRP_DSS,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1,
MHD_GNUTLS_CIPHER_3DES_CBC,
MHD_GNUTLS_KX_SRP_RSA,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_AES_128_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_128_CBC,
MHD_GNUTLS_KX_SRP_DSS,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_AES_128_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_128_CBC,
MHD_GNUTLS_KX_SRP_RSA,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_AES_256_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_256_CBC,
MHD_GNUTLS_KX_SRP_DSS,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_AES_256_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_256_CBC,
MHD_GNUTLS_KX_SRP_RSA,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
/* DHE_DSS */
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_ARCFOUR_SHA1,
MHD_GNUTLS_CIPHER_ARCFOUR_128,
MHD_GNUTLS_KX_DHE_DSS,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_TLS1_0),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_3DES_EDE_CBC_SHA1,
MHD_GNUTLS_CIPHER_3DES_CBC,
MHD_GNUTLS_KX_DHE_DSS,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_128_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_128_CBC,
MHD_GNUTLS_KX_DHE_DSS,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_256_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_256_CBC,
MHD_GNUTLS_KX_DHE_DSS,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
/* DHE_RSA */
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_3DES_EDE_CBC_SHA1,
MHD_GNUTLS_CIPHER_3DES_CBC,
MHD_GNUTLS_KX_DHE_RSA,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_128_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_128_CBC,
MHD_GNUTLS_KX_DHE_RSA,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_256_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_256_CBC,
MHD_GNUTLS_KX_DHE_RSA,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
/* RSA */
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_MD5,
MHD_GNUTLS_CIPHER_NULL,
MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_MD5,
MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_EXPORT_ARCFOUR_40_MD5,
MHD_GNUTLS_CIPHER_ARCFOUR_40,
MHD_GNUTLS_KX_RSA_EXPORT, MHD_GNUTLS_MAC_MD5,
MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_SHA1,
MHD_GNUTLS_CIPHER_ARCFOUR_128,
MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_SHA1,
MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_MD5,
MHD_GNUTLS_CIPHER_ARCFOUR_128,
MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_MD5,
MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_3DES_EDE_CBC_SHA1,
MHD_GNUTLS_CIPHER_3DES_CBC,
MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_SHA1,
MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_128_CBC, MHD_GNUTLS_KX_RSA,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_256_CBC_SHA1,
MHD_GNUTLS_CIPHER_AES_256_CBC, MHD_GNUTLS_KX_RSA,
MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
{0,
{
{0,
0}},
0,
0,
0,
0}
};
#define GNUTLS_CIPHER_SUITE_LOOP(b) \
const MHD_gtls_cipher_suite_entry *p; \
for(p = MHD_gtls_cs_algorithms; p->name != NULL; p++) { b ; }
#define GNUTLS_CIPHER_SUITE_ALG_LOOP(a) \
GNUTLS_CIPHER_SUITE_LOOP( if( (p->id.suite[0] == suite->suite[0]) && (p->id.suite[1] == suite->suite[1])) { a; break; } )
/* Generic Functions */
int
MHD_gtls_mac_priority (MHD_gtls_session_t session,
enum MHD_GNUTLS_HashAlgorithm algorithm)
{ /* actually returns the priority */
unsigned int i;
for (i = 0; i < session->internals.priorities.mac.num_algorithms; i++)
{
if (session->internals.priorities.mac.priority[i] == algorithm)
return i;
}
return -1;
}
int
MHD_gnutls_mac_is_ok (enum MHD_GNUTLS_HashAlgorithm algorithm)
{
ssize_t ret = -1;
GNUTLS_HASH_ALG_LOOP (ret = p->id);
if (ret >= 0)
ret = 0;
else
ret = 1;
return ret;
}
/**
* MHD__gnutls_compression_get_name - Returns a string with the name of the specified compression algorithm
* @algorithm: is a Compression algorithm
*
* Returns: a pointer to a string that contains the name of the
* specified compression algorithm, or %NULL.
**/
const char *
MHD_gtls_compression_get_name (enum MHD_GNUTLS_CompressionMethod algorithm)
{
const char *ret = NULL;
/* avoid prefix */
GNUTLS_COMPRESSION_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_COMP_") - 1);
return ret;
}
/**
* MHD_gtls_compression_get_id - Returns the gnutls id of the specified in string algorithm
* @algorithm: is a compression method name
*
* The names are compared in a case insensitive way.
*
* Returns: an id of the specified in a string compression method, or
* %GNUTLS_COMP_UNKNOWN on error.
*
**/
enum MHD_GNUTLS_CompressionMethod
MHD_gtls_compression_get_id (const char *name)
{
enum MHD_GNUTLS_CompressionMethod ret = MHD_GNUTLS_COMP_UNKNOWN;
GNUTLS_COMPRESSION_LOOP (if
(strcasecmp
(p->name + sizeof ("GNUTLS_COMP_") - 1,
name) == 0) ret = p->id)
;
return ret;
}
/* return the tls number of the specified algorithm */
int
MHD_gtls_compression_get_num (enum MHD_GNUTLS_CompressionMethod algorithm)
{
int ret = -1;
/* avoid prefix */
GNUTLS_COMPRESSION_ALG_LOOP (ret = p->num);
return ret;
}
int
MHD_gtls_compression_get_wbits (enum MHD_GNUTLS_CompressionMethod algorithm)
{
int ret = -1;
/* avoid prefix */
GNUTLS_COMPRESSION_ALG_LOOP (ret = p->window_bits);
return ret;
}
int
MHD_gtls_compression_get_mem_level (enum MHD_GNUTLS_CompressionMethod
algorithm)
{
int ret = -1;
/* avoid prefix */
GNUTLS_COMPRESSION_ALG_LOOP (ret = p->mem_level);
return ret;
}
int
MHD_gtls_compression_get_comp_level (enum MHD_GNUTLS_CompressionMethod
algorithm)
{
int ret = -1;
/* avoid prefix */
GNUTLS_COMPRESSION_ALG_LOOP (ret = p->comp_level);
return ret;
}
/* returns the gnutls internal ID of the TLS compression
* method num
*/
enum MHD_GNUTLS_CompressionMethod
MHD_gtls_compression_get_id_from_int (int num)
{
enum MHD_GNUTLS_CompressionMethod ret = -1;
/* avoid prefix */
GNUTLS_COMPRESSION_ALG_LOOP_NUM (ret = p->id);
return ret;
}
int
MHD_gtls_compression_is_ok (enum MHD_GNUTLS_CompressionMethod algorithm)
{
ssize_t ret = -1;
GNUTLS_COMPRESSION_ALG_LOOP (ret = p->id);
if (ret >= 0)
ret = 0;
else
ret = 1;
return ret;
}
/* CIPHER functions */
int
MHD_gtls_cipher_get_block_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
{
size_t ret = 0;
GNUTLS_ALG_LOOP (ret = p->blocksize);
return ret;
}
/* returns the priority */
int
MHD_gtls_cipher_priority (MHD_gtls_session_t session,
enum MHD_GNUTLS_CipherAlgorithm algorithm)
{
unsigned int i;
for (i = 0; i < session->internals.priorities.cipher.num_algorithms; i++)
{
if (session->internals.priorities.cipher.priority[i] == algorithm)
return i;
}
return -1;
}
int
MHD_gtls_cipher_is_block (enum MHD_GNUTLS_CipherAlgorithm algorithm)
{
size_t ret = 0;
GNUTLS_ALG_LOOP (ret = p->block);
return ret;
}
/**
* MHD__gnutls_cipher_get_key_size - Returns the length of the cipher's key size
* @algorithm: is an encryption algorithm
*
* Returns: length (in bytes) of the given cipher's key size, o 0 if
* the given cipher is invalid.
**/
size_t
MHD__gnutls_cipher_get_key_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
{ /* In bytes */
size_t ret = 0;
GNUTLS_ALG_LOOP (ret = p->keysize);
return ret;
}
int
MHD_gtls_cipher_get_iv_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
{ /* In bytes */
size_t ret = 0;
GNUTLS_ALG_LOOP (ret = p->iv);
return ret;
}
int
MHD_gtls_cipher_get_export_flag (enum MHD_GNUTLS_CipherAlgorithm algorithm)
{ /* In bytes */
size_t ret = 0;
GNUTLS_ALG_LOOP (ret = p->export_flag);
return ret;
}
int
MHD_gtls_cipher_is_ok (enum MHD_GNUTLS_CipherAlgorithm algorithm)
{
ssize_t ret = -1;
GNUTLS_ALG_LOOP (ret = p->id);
if (ret >= 0)
ret = 0;
else
ret = 1;
return ret;
}
/* Key EXCHANGE functions */
MHD_gtls_mod_auth_st *
MHD_gtls_kx_auth_struct (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
{
MHD_gtls_mod_auth_st *ret = NULL;
GNUTLS_KX_ALG_LOOP (ret = p->auth_struct);
return ret;
}
int
MHD_gtls_kx_priority (MHD_gtls_session_t session,
enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
{
unsigned int i;
for (i = 0; i < session->internals.priorities.kx.num_algorithms; i++)
{
if (session->internals.priorities.kx.priority[i] == algorithm)
return i;
}
return -1;
}
int
MHD_gtls_kx_is_ok (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
{
ssize_t ret = -1;
GNUTLS_KX_ALG_LOOP (ret = p->algorithm);
if (ret >= 0)
ret = 0;
else
ret = 1;
return ret;
}
int
MHD_gtls_kx_needs_rsa_params (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
{
ssize_t ret = 0;
GNUTLS_KX_ALG_LOOP (ret = p->needs_rsa_params);
return ret;
}
int
MHD_gtls_kx_needs_dh_params (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
{
ssize_t ret = 0;
GNUTLS_KX_ALG_LOOP (ret = p->needs_dh_params);
return ret;
}
/* Version */
int
MHD_gtls_version_priority (MHD_gtls_session_t session,
enum MHD_GNUTLS_Protocol version)
{ /* actually returns the priority */
unsigned int i;
if (session->internals.priorities.protocol.priority == NULL)
{
MHD_gnutls_assert ();
return -1;
}
for (i = 0; i < session->internals.priorities.protocol.num_algorithms; i++)
{
if (session->internals.priorities.protocol.priority[i] == version)
return i;
}
return -1;
}
enum MHD_GNUTLS_Protocol
MHD_gtls_version_max (MHD_gtls_session_t session)
{ /* returns the maximum version supported */
unsigned int i, max = 0x00;
if (session->internals.priorities.protocol.priority == NULL)
{
return MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN;
}
else
for (i = 0; i < session->internals.priorities.protocol.num_algorithms;
i++)
{
if (session->internals.priorities.protocol.priority[i] > max)
max = session->internals.priorities.protocol.priority[i];
}
if (max == 0x00)
return MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN; /* unknown version */
return max;
}
int
MHD_gtls_version_get_minor (enum MHD_GNUTLS_Protocol version)
{
int ret = -1;
GNUTLS_VERSION_ALG_LOOP (ret = p->minor);
return ret;
}
enum MHD_GNUTLS_Protocol
MHD_gtls_version_get (int major, int minor)
{
int ret = -1;
GNUTLS_VERSION_LOOP (if ((p->major == major) && (p->minor == minor))
ret = p->id)
;
return ret;
}
int
MHD_gtls_version_get_major (enum MHD_GNUTLS_Protocol version)
{
int ret = -1;
GNUTLS_VERSION_ALG_LOOP (ret = p->major);
return ret;
}
/* Version Functions */
int
MHD_gtls_version_is_supported (MHD_gtls_session_t session,
const enum MHD_GNUTLS_Protocol version)
{
int ret = 0;
GNUTLS_VERSION_ALG_LOOP (ret = p->supported);
if (ret == 0)
return 0;
if (MHD_gtls_version_priority (session, version) < 0)
return 0; /* disabled by the user */
else
return 1;
}
enum MHD_GNUTLS_CredentialsType
MHD_gtls_map_kx_get_cred (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm,
int server)
{
enum MHD_GNUTLS_CredentialsType ret = -1;
if (server)
{
GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret = p->server_type)
;
}
else
{
GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret = p->client_type)
;
}
return ret;
}
/* Cipher Suite's functions */
enum MHD_GNUTLS_CipherAlgorithm
MHD_gtls_cipher_suite_get_cipher_algo (const cipher_suite_st * suite)
{
int ret = 0;
GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->block_algorithm);
return ret;
}
enum MHD_GNUTLS_Protocol
MHD_gtls_cipher_suite_get_version (const cipher_suite_st * suite)
{
int ret = 0;
GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->version);
return ret;
}
enum MHD_GNUTLS_KeyExchangeAlgorithm
MHD_gtls_cipher_suite_get_kx_algo (const cipher_suite_st * suite)
{
int ret = 0;
GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->kx_algorithm);
return ret;
}
enum MHD_GNUTLS_HashAlgorithm
MHD_gtls_cipher_suite_get_mac_algo (const cipher_suite_st * suite)
{ /* In bytes */
int ret = 0;
GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->mac_algorithm);
return ret;
}
const char *
MHD_gtls_cipher_suite_get_name (cipher_suite_st * suite)
{
const char *ret = NULL;
/* avoid prefix */
GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_") - 1);
return ret;
}
static inline int
MHD__gnutls_cipher_suite_is_ok (cipher_suite_st * suite)
{
size_t ret;
const char *name = NULL;
GNUTLS_CIPHER_SUITE_ALG_LOOP (name = p->name);
if (name != NULL)
ret = 0;
else
ret = 1;
return ret;
}
#define SWAP(x, y) memcpy(tmp,x,size); \
memcpy(x,y,size); \
memcpy(y,tmp,size);
#define MAX_ELEM_SIZE 4
static inline int
MHD__gnutls_partition (MHD_gtls_session_t session,
void *_base,
size_t nmemb,
size_t size,
int (*compar) (MHD_gtls_session_t,
const void *, const void *))
{
uint8_t *base = _base;
uint8_t tmp[MAX_ELEM_SIZE];
uint8_t ptmp[MAX_ELEM_SIZE];
unsigned int pivot;
unsigned int i, j;
unsigned int full;
i = pivot = 0;
j = full = (nmemb - 1) * size;
memcpy (ptmp, &base[0], size); /* set pivot item */
while (i < j)
{
while ((compar (session, &base[i], ptmp) <= 0) && (i < full))
{
i += size;
}
while ((compar (session, &base[j], ptmp) >= 0) && (j > 0))
j -= size;
if (i < j)
{
SWAP (&base[j], &base[i]);
}
}
if (j > pivot)
{
SWAP (&base[pivot], &base[j]);
pivot = j;
}
else if (i < pivot)
{
SWAP (&base[pivot], &base[i]);
pivot = i;
}
return pivot / size;
}
static void
MHD__gnutls_qsort (MHD_gtls_session_t session,
void *_base,
size_t nmemb,
size_t size,
int (*compar) (MHD_gtls_session_t, const void *,
const void *))
{
unsigned int pivot;
char *base = _base;
size_t snmemb = nmemb;
if (snmemb <= 1)
return;
pivot = MHD__gnutls_partition (session, _base, nmemb, size, compar);
MHD__gnutls_qsort (session, base, pivot < nmemb ? pivot + 1
: pivot, size, compar);
MHD__gnutls_qsort (session, &base[(pivot + 1) * size], nmemb - pivot - 1,
size, compar);
}
/* a compare function for KX algorithms (using priorities).
* For use with qsort
*/
static int
MHD__gnutls_compare_algo (MHD_gtls_session_t session,
const void *i_A1, const void *i_A2)
{
enum MHD_GNUTLS_KeyExchangeAlgorithm kA1 =
MHD_gtls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A1);
enum MHD_GNUTLS_KeyExchangeAlgorithm kA2 =
MHD_gtls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A2);
enum MHD_GNUTLS_CipherAlgorithm cA1 =
MHD_gtls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A1);
enum MHD_GNUTLS_CipherAlgorithm cA2 =
MHD_gtls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A2);
enum MHD_GNUTLS_HashAlgorithm mA1 =
MHD_gtls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A1);
enum MHD_GNUTLS_HashAlgorithm mA2 =
MHD_gtls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A2);
int p1 = (MHD_gtls_kx_priority (session, kA1) + 1) * 64;
int p2 = (MHD_gtls_kx_priority (session, kA2) + 1) * 64;
p1 += (MHD_gtls_cipher_priority (session, cA1) + 1) * 8;
p2 += (MHD_gtls_cipher_priority (session, cA2) + 1) * 8;
p1 += MHD_gtls_mac_priority (session, mA1);
p2 += MHD_gtls_mac_priority (session, mA2);
if (p1 > p2)
{
return 1;
}
else
{
if (p1 == p2)
{
return 0;
}
return -1;
}
}
int
MHD_gtls_supported_ciphersuites_sorted (MHD_gtls_session_t session,
cipher_suite_st ** ciphers)
{
int count;
count = MHD_gtls_supported_ciphersuites (session, ciphers);
if (count <= 0)
{
MHD_gnutls_assert ();
return count;
}
MHD__gnutls_qsort (session, *ciphers, count, sizeof (cipher_suite_st),
MHD__gnutls_compare_algo);
return count;
}
int
MHD_gtls_supported_ciphersuites (MHD_gtls_session_t session,
cipher_suite_st ** _ciphers)
{
unsigned int i, ret_count, j;
unsigned int count = CIPHER_SUITES_COUNT;
cipher_suite_st *tmp_ciphers;
cipher_suite_st *ciphers;
enum MHD_GNUTLS_Protocol version;
if (count == 0)
{
return 0;
}
tmp_ciphers = MHD_gnutls_alloca (count * sizeof (cipher_suite_st));
if (tmp_ciphers == NULL)
return GNUTLS_E_MEMORY_ERROR;
ciphers = MHD_gnutls_malloc (count * sizeof (cipher_suite_st));
if (ciphers == NULL)
{
MHD_gnutls_afree (tmp_ciphers);
return GNUTLS_E_MEMORY_ERROR;
}
version = MHD__gnutls_protocol_get_version (session);
for (i = 0; i < count; i++)
{
memcpy (&tmp_ciphers[i], &MHD_gtls_cs_algorithms[i].id,
sizeof (cipher_suite_st));
}
for (i = j = 0; i < count; i++)
{
/* remove private cipher suites, if requested.
*/
if (tmp_ciphers[i].suite[0] == 0xFF && session->internals.enable_private
== 0)
continue;
/* remove cipher suites which do not support the
* protocol version used.
*/
if (MHD_gtls_cipher_suite_get_version (&tmp_ciphers[i]) > version)
continue;
if (MHD_gtls_kx_priority (session,
MHD_gtls_cipher_suite_get_kx_algo
(&tmp_ciphers[i])) < 0)
continue;
if (MHD_gtls_mac_priority (session,
MHD_gtls_cipher_suite_get_mac_algo
(&tmp_ciphers[i])) < 0)
continue;
if (MHD_gtls_cipher_priority (session,
MHD_gtls_cipher_suite_get_cipher_algo
(&tmp_ciphers[i])) < 0)
continue;
memcpy (&ciphers[j], &tmp_ciphers[i], sizeof (cipher_suite_st));
j++;
}
ret_count = j;
#if 0 /* expensive */
if (ret_count > 0 && ret_count != count)
{
ciphers =
MHD_gtls_realloc_fast (ciphers, ret_count * sizeof (cipher_suite_st));
}
else
{
if (ret_count != count)
{
MHD_gnutls_free (ciphers);
ciphers = NULL;
}
}
#endif
MHD_gnutls_afree (tmp_ciphers);
/* This function can no longer return 0 cipher suites.
* It returns an error code instead.
*/
if (ret_count == 0)
{
MHD_gnutls_assert ();
MHD_gnutls_free (ciphers);
return GNUTLS_E_NO_CIPHER_SUITES;
}
*_ciphers = ciphers;
return ret_count;
}
/* For compression */
#define MIN_PRIVATE_COMP_ALGO 0xEF
/* returns the TLS numbers of the compression methods we support
*/
#define SUPPORTED_COMPRESSION_METHODS session->internals.priorities.compression.num_algorithms
int
MHD_gtls_supported_compression_methods (MHD_gtls_session_t session,
uint8_t ** comp)
{
unsigned int i, j;
*comp =
MHD_gnutls_malloc (sizeof (uint8_t) * SUPPORTED_COMPRESSION_METHODS);
if (*comp == NULL)
return GNUTLS_E_MEMORY_ERROR;
for (i = j = 0; i < SUPPORTED_COMPRESSION_METHODS; i++)
{
int tmp =
MHD_gtls_compression_get_num (session->internals.
priorities.compression.priority[i]);
/* remove private compression algorithms, if requested.
*/
if (tmp == -1 || (tmp >= MIN_PRIVATE_COMP_ALGO
&& session->internals.enable_private == 0))
{
MHD_gnutls_assert ();
continue;
}
(*comp)[j] = (uint8_t) tmp;
j++;
}
if (j == 0)
{
MHD_gnutls_assert ();
MHD_gnutls_free (*comp);
*comp = NULL;
return GNUTLS_E_NO_COMPRESSION_ALGORITHMS;
}
return j;
}
static const enum MHD_GNUTLS_CertificateType
MHD_gtls_supported_certificate_types[] =
{ MHD_GNUTLS_CRT_X509,
0
};
/* returns the enum MHD_GNUTLS_PublicKeyAlgorithm which is compatible with
* the given enum MHD_GNUTLS_KeyExchangeAlgorithm.
*/
enum MHD_GNUTLS_PublicKeyAlgorithm
MHD_gtls_map_pk_get_pk (enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm)
{
enum MHD_GNUTLS_PublicKeyAlgorithm ret = -1;
GNUTLS_PK_MAP_ALG_LOOP (ret = p->pk_algorithm) return ret;
}
/* Returns the encipher type for the given key exchange algorithm.
* That one of CIPHER_ENCRYPT, CIPHER_SIGN, CIPHER_IGN.
*
* ex. GNUTLS_KX_RSA requires a certificate able to encrypt... so returns CIPHER_ENCRYPT.
*/
enum encipher_type
MHD_gtls_kx_encipher_type (enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm)
{
int ret = CIPHER_IGN;
GNUTLS_PK_MAP_ALG_LOOP (ret = p->encipher_type) return ret;
}
/* signature algorithms;
*/
struct MHD_gnutls_sign_entry
{
const char *name;
const char *oid;
MHD_gnutls_sign_algorithm_t id;
enum MHD_GNUTLS_PublicKeyAlgorithm pk;
enum MHD_GNUTLS_HashAlgorithm mac;
};
typedef struct MHD_gnutls_sign_entry MHD_gnutls_sign_entry;
static const MHD_gnutls_sign_entry MHD_gtls_sign_algorithms[] = {
{"RSA-SHA",
SIG_RSA_SHA1_OID,
GNUTLS_SIGN_RSA_SHA1,
MHD_GNUTLS_PK_RSA,
MHD_GNUTLS_MAC_SHA1},
{"RSA-SHA256",
SIG_RSA_SHA256_OID,
GNUTLS_SIGN_RSA_SHA256,
MHD_GNUTLS_PK_RSA,
MHD_GNUTLS_MAC_SHA256},
{"RSA-MD5",
SIG_RSA_MD5_OID,
GNUTLS_SIGN_RSA_MD5,
MHD_GNUTLS_PK_RSA,
MHD_GNUTLS_MAC_MD5},
{"GOST R 34.10-2001",
SIG_GOST_R3410_2001_OID,
0,
0,
0},
{"GOST R 34.10-94",
SIG_GOST_R3410_94_OID,
0,
0,
0},
{0,
0,
0,
0,
0}
};
#define GNUTLS_SIGN_LOOP(b) \
do { \
const MHD_gnutls_sign_entry *p; \
for(p = MHD_gtls_sign_algorithms; p->name != NULL; p++) { b ; } \
} while (0)
#define GNUTLS_SIGN_ALG_LOOP(a) \
GNUTLS_SIGN_LOOP( if(p->id && p->id == sign) { a; break; } )
/* pk algorithms;
*/
struct MHD_gnutls_pk_entry
{
const char *name;
const char *oid;
enum MHD_GNUTLS_PublicKeyAlgorithm id;
};
typedef struct MHD_gnutls_pk_entry MHD_gnutls_pk_entry;
static const MHD_gnutls_pk_entry MHD_gtls_pk_algorithms[] = {
{"RSA",
PK_PKIX1_RSA_OID,
MHD_GNUTLS_PK_RSA},
{"GOST R 34.10-2001",
PK_GOST_R3410_2001_OID,
0},
{"GOST R 34.10-94",
PK_GOST_R3410_94_OID,
0},
{0,
0,
0}
};
enum MHD_GNUTLS_PublicKeyAlgorithm
MHD_gtls_x509_oid2pk_algorithm (const char *oid)
{
enum MHD_GNUTLS_PublicKeyAlgorithm ret = MHD_GNUTLS_PK_UNKNOWN;
const MHD_gnutls_pk_entry *p;
for (p = MHD_gtls_pk_algorithms; p->name != NULL; p++)
if (strcmp (p->oid, oid) == 0)
{
ret = p->id;
break;
}
return ret;
}