00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "gnutls_int.h"
00026 #include "gnutls_algorithms.h"
00027 #include "gnutls_errors.h"
00028 #include "gnutls_cert.h"
00029
00030 #include "common.h"
00031
00032
00033
00034
00035
00036 typedef struct
00037 {
00038 enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm;
00039 enum MHD_GNUTLS_CredentialsType client_type;
00040 enum MHD_GNUTLS_CredentialsType server_type;
00041
00042 } MHD_gnutls_cred_map;
00043
00044 static const MHD_gnutls_cred_map MHD_gtls_cred_mappings[] = {
00045 {MHD_GNUTLS_KX_RSA,
00046 MHD_GNUTLS_CRD_CERTIFICATE,
00047 MHD_GNUTLS_CRD_CERTIFICATE},
00048 {MHD_GNUTLS_KX_RSA_EXPORT,
00049 MHD_GNUTLS_CRD_CERTIFICATE,
00050 MHD_GNUTLS_CRD_CERTIFICATE},
00051 {0,
00052 0,
00053 0}
00054 };
00055
00056 #define GNUTLS_KX_MAP_LOOP(b) \
00057 const MHD_gnutls_cred_map *p; \
00058 for(p = MHD_gtls_cred_mappings; p->algorithm != 0; p++) { b ; }
00059
00060 #define GNUTLS_KX_MAP_ALG_LOOP_SERVER(a) \
00061 GNUTLS_KX_MAP_LOOP( if(p->server_type == type) { a; break; })
00062
00063 #define GNUTLS_KX_MAP_ALG_LOOP_CLIENT(a) \
00064 GNUTLS_KX_MAP_LOOP( if(p->client_type == type) { a; break; })
00065
00066
00067 typedef struct
00068 {
00069 enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm;
00070 enum MHD_GNUTLS_PublicKeyAlgorithm pk_algorithm;
00071 enum encipher_type encipher_type;
00072
00073
00074
00075
00076
00077
00078 } MHD_gnutls_pk_map;
00079
00080
00081
00082
00083
00084
00085 static const MHD_gnutls_pk_map MHD_gtls_pk_mappings[] = {
00086 {MHD_GNUTLS_KX_RSA,
00087 MHD_GNUTLS_PK_RSA,
00088 CIPHER_ENCRYPT},
00089 {MHD_GNUTLS_KX_RSA_EXPORT,
00090 MHD_GNUTLS_PK_RSA,
00091 CIPHER_SIGN},
00092 {0,
00093 0,
00094 0}
00095 };
00096
00097 #define GNUTLS_PK_MAP_LOOP(b) \
00098 const MHD_gnutls_pk_map *p; \
00099 for(p = MHD_gtls_pk_mappings; p->kx_algorithm != 0; p++) { b }
00100
00101 #define GNUTLS_PK_MAP_ALG_LOOP(a) \
00102 GNUTLS_PK_MAP_LOOP( if(p->kx_algorithm == kx_algorithm) { a; break; })
00103
00104
00105
00106 typedef struct
00107 {
00108 const char *name;
00109 enum MHD_GNUTLS_Protocol id;
00110 int major;
00111 int minor;
00112 int supported;
00113 } MHD_gnutls_version_entry;
00114
00115 static const MHD_gnutls_version_entry MHD_gtls_sup_versions[] = {
00116 {"SSL3.0",
00117 MHD_GNUTLS_PROTOCOL_SSL3,
00118 3,
00119 0,
00120 1},
00121 {"TLS1.0",
00122 MHD_GNUTLS_PROTOCOL_TLS1_0,
00123 3,
00124 1,
00125 1},
00126 {"TLS1.1",
00127 MHD_GNUTLS_PROTOCOL_TLS1_1,
00128 3,
00129 2,
00130 1},
00131 {"TLS1.2",
00132 MHD_GNUTLS_PROTOCOL_TLS1_2,
00133 3,
00134 3,
00135 1},
00136 {0,
00137 0,
00138 0,
00139 0,
00140 0}
00141 };
00142
00143
00144 static const enum MHD_GNUTLS_Protocol MHD_gtls_supported_protocols[] =
00145 { MHD_GNUTLS_PROTOCOL_SSL3,
00146 MHD_GNUTLS_PROTOCOL_TLS1_0,
00147 MHD_GNUTLS_PROTOCOL_TLS1_1,
00148 MHD_GNUTLS_PROTOCOL_TLS1_2,
00149 0
00150 };
00151
00152 #define GNUTLS_VERSION_LOOP(b) \
00153 const MHD_gnutls_version_entry *p; \
00154 for(p = MHD_gtls_sup_versions; p->name != NULL; p++) { b ; }
00155
00156 #define GNUTLS_VERSION_ALG_LOOP(a) \
00157 GNUTLS_VERSION_LOOP( if(p->id == version) { a; break; })
00158
00159 struct MHD_gnutls_cipher_entry
00160 {
00161 const char *name;
00162 enum MHD_GNUTLS_CipherAlgorithm id;
00163 uint16_t blocksize;
00164 uint16_t keysize;
00165 cipher_type_t block;
00166 uint16_t iv;
00167 int export_flag;
00168 };
00169 typedef struct MHD_gnutls_cipher_entry MHD_gnutls_cipher_entry;
00170
00171
00172
00173
00174
00175
00176 static const MHD_gnutls_cipher_entry MHD_gtls_algorithms[] = {
00177 {"AES-256-CBC",
00178 MHD_GNUTLS_CIPHER_AES_256_CBC,
00179 16,
00180 32,
00181 CIPHER_BLOCK,
00182 16,
00183 0},
00184 {"AES-128-CBC",
00185 MHD_GNUTLS_CIPHER_AES_128_CBC,
00186 16,
00187 16,
00188 CIPHER_BLOCK,
00189 16,
00190 0},
00191 {"3DES-CBC",
00192 MHD_GNUTLS_CIPHER_3DES_CBC,
00193 8,
00194 24,
00195 CIPHER_BLOCK,
00196 8,
00197 0},
00198 {"ARCFOUR-128",
00199 MHD_GNUTLS_CIPHER_ARCFOUR_128,
00200 1,
00201 16,
00202 CIPHER_STREAM,
00203 0,
00204 0},
00205 {"NULL",
00206 MHD_GNUTLS_CIPHER_NULL,
00207 1,
00208 0,
00209 CIPHER_STREAM,
00210 0,
00211 0},
00212 {0,
00213 0,
00214 0,
00215 0,
00216 0,
00217 0,
00218 0}
00219 };
00220
00221
00222 static const enum MHD_GNUTLS_CipherAlgorithm MHD_gtls_supported_ciphers[] =
00223 { MHD_GNUTLS_CIPHER_AES_256_CBC,
00224 MHD_GNUTLS_CIPHER_AES_128_CBC,
00225 MHD_GNUTLS_CIPHER_3DES_CBC,
00226 MHD_GNUTLS_CIPHER_ARCFOUR_128,
00227 MHD_GNUTLS_CIPHER_NULL,
00228 0
00229 };
00230
00231 #define GNUTLS_LOOP(b) \
00232 const MHD_gnutls_cipher_entry *p; \
00233 for(p = MHD_gtls_algorithms; p->name != NULL; p++) { b ; }
00234
00235 #define GNUTLS_ALG_LOOP(a) \
00236 GNUTLS_LOOP( if(p->id == algorithm) { a; break; } )
00237
00238 struct MHD_gnutls_hash_entry
00239 {
00240 const char *name;
00241 const char *oid;
00242 enum MHD_GNUTLS_HashAlgorithm id;
00243 size_t key_size;
00244 };
00245 typedef struct MHD_gnutls_hash_entry MHD_gnutls_hash_entry;
00246
00247 static const MHD_gnutls_hash_entry MHD_gtls_hash_algorithms[] = {
00248 {"SHA1",
00249 HASH_OID_SHA1,
00250 MHD_GNUTLS_MAC_SHA1,
00251 20},
00252 {"MD5",
00253 HASH_OID_MD5,
00254 MHD_GNUTLS_MAC_MD5,
00255 16},
00256 {"SHA256",
00257 HASH_OID_SHA256,
00258 MHD_GNUTLS_MAC_SHA256,
00259 32},
00260 {"NULL",
00261 NULL,
00262 MHD_GNUTLS_MAC_NULL,
00263 0},
00264 {0,
00265 0,
00266 0,
00267 0}
00268 };
00269
00270
00271 static const enum MHD_GNUTLS_HashAlgorithm MHD_gtls_supported_macs[] =
00272 { MHD_GNUTLS_MAC_SHA1,
00273 MHD_GNUTLS_MAC_MD5,
00274 MHD_GNUTLS_MAC_SHA256,
00275 MHD_GNUTLS_MAC_NULL,
00276 0
00277 };
00278
00279 #define GNUTLS_HASH_LOOP(b) \
00280 const MHD_gnutls_hash_entry *p; \
00281 for(p = MHD_gtls_hash_algorithms; p->name != NULL; p++) { b ; }
00282
00283 #define GNUTLS_HASH_ALG_LOOP(a) \
00284 GNUTLS_HASH_LOOP( if(p->id == algorithm) { a; break; } )
00285
00286
00287 #define GNUTLS_COMPRESSION_ENTRY(name, id, wb, ml, cl) \
00288 { #name, name, id, wb, ml, cl}
00289
00290 #define MAX_COMP_METHODS 5
00291 const int MHD__gnutls_comp_algorithms_size = MAX_COMP_METHODS;
00292
00293
00294
00295 MHD_gnutls_compression_entry
00296 MHD__gnutls_compression_algorithms[MAX_COMP_METHODS] =
00297 {
00298 GNUTLS_COMPRESSION_ENTRY (MHD_GNUTLS_COMP_NULL, 0x00, 0, 0, 0),
00299 {
00300 0, 0, 0, 0, 0, 0}
00301 };
00302
00303 static const enum MHD_GNUTLS_CompressionMethod
00304 MHD_gtls_supported_compressions[] =
00305 {
00306 MHD_GNUTLS_COMP_NULL,
00307 0
00308 };
00309
00310 #define GNUTLS_COMPRESSION_LOOP(b) \
00311 const MHD_gnutls_compression_entry *p; \
00312 for(p = MHD__gnutls_compression_algorithms; p->name != NULL; p++) { b ; }
00313 #define GNUTLS_COMPRESSION_ALG_LOOP(a) \
00314 GNUTLS_COMPRESSION_LOOP( if(p->id == algorithm) { a; break; } )
00315 #define GNUTLS_COMPRESSION_ALG_LOOP_NUM(a) \
00316 GNUTLS_COMPRESSION_LOOP( if(p->num == num) { a; break; } )
00317
00318
00319 extern MHD_gtls_mod_auth_st MHD_gtls_rsa_auth_struct;
00320 extern MHD_gtls_mod_auth_st MHD_rsa_export_auth_struct;
00321 extern MHD_gtls_mod_auth_st MHD_gtls_dhe_rsa_auth_struct;
00322 extern MHD_gtls_mod_auth_st MHD_gtls_dhe_dss_auth_struct;
00323 extern MHD_gtls_mod_auth_st srp_auth_struct;
00324 extern MHD_gtls_mod_auth_st psk_auth_struct;
00325 extern MHD_gtls_mod_auth_st dhe_psk_auth_struct;
00326 extern MHD_gtls_mod_auth_st srp_rsa_auth_struct;
00327 extern MHD_gtls_mod_auth_st srp_dss_auth_struct;
00328
00329 typedef struct MHD_gtls_kx_algo_entry
00330 {
00331 const char *name;
00332 enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm;
00333 MHD_gtls_mod_auth_st *auth_struct;
00334 int needs_dh_params;
00335 int needs_rsa_params;
00336 } MHD_gtls_kx_algo_entry_t;
00337
00338 static const MHD_gtls_kx_algo_entry_t MHD_gtls_kx_algorithms[] = {
00339 {"RSA",
00340 MHD_GNUTLS_KX_RSA,
00341 &MHD_gtls_rsa_auth_struct,
00342 0,
00343 0},
00344 {"RSA-EXPORT",
00345 MHD_GNUTLS_KX_RSA_EXPORT,
00346 &MHD_rsa_export_auth_struct,
00347 0,
00348 1 },
00349 {0,
00350 0,
00351 0,
00352 0,
00353 0}
00354 };
00355
00356
00357 static const enum MHD_GNUTLS_KeyExchangeAlgorithm MHD_gtls_supported_kxs[] =
00358 {
00359 MHD_GNUTLS_KX_RSA,
00360 MHD_GNUTLS_KX_RSA_EXPORT,
00361 0
00362 };
00363
00364 #define GNUTLS_KX_LOOP(b) \
00365 const MHD_gtls_kx_algo_entry_t *p; \
00366 for(p = MHD_gtls_kx_algorithms; p->name != NULL; p++) { b ; }
00367
00368 #define GNUTLS_KX_ALG_LOOP(a) \
00369 GNUTLS_KX_LOOP( if(p->algorithm == algorithm) { a; break; } )
00370
00371
00372 #define GNUTLS_CIPHER_SUITE_ENTRY( name, block_algorithm, kx_algorithm, mac_algorithm, version ) \
00373 { #name, {name}, block_algorithm, kx_algorithm, mac_algorithm, version }
00374
00375 typedef struct
00376 {
00377 const char *name;
00378 cipher_suite_st id;
00379 enum MHD_GNUTLS_CipherAlgorithm block_algorithm;
00380 enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm;
00381 enum MHD_GNUTLS_HashAlgorithm mac_algorithm;
00382 enum MHD_GNUTLS_Protocol version;
00383
00384
00385 } MHD_gtls_cipher_suite_entry;
00386
00387
00388
00389
00390 #define GNUTLS_RSA_NULL_MD5 { 0x00, 0x01 }
00391
00392
00393
00394
00395 #define GNUTLS_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8A }
00396 #define GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8B }
00397 #define GNUTLS_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x8C }
00398 #define GNUTLS_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x8D }
00399
00400 #define GNUTLS_DHE_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8E }
00401 #define GNUTLS_DHE_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8F }
00402 #define GNUTLS_DHE_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x90 }
00403 #define GNUTLS_DHE_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x91 }
00404
00405
00406
00407 #define GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1A }
00408 #define GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1B }
00409 #define GNUTLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1 { 0xC0, 0x1C }
00410
00411 #define GNUTLS_SRP_SHA_AES_128_CBC_SHA1 { 0xC0, 0x1D }
00412 #define GNUTLS_SRP_SHA_RSA_AES_128_CBC_SHA1 { 0xC0, 0x1E }
00413 #define GNUTLS_SRP_SHA_DSS_AES_128_CBC_SHA1 { 0xC0, 0x1F }
00414
00415 #define GNUTLS_SRP_SHA_AES_256_CBC_SHA1 { 0xC0, 0x20 }
00416 #define GNUTLS_SRP_SHA_RSA_AES_256_CBC_SHA1 { 0xC0, 0x21 }
00417 #define GNUTLS_SRP_SHA_DSS_AES_256_CBC_SHA1 { 0xC0, 0x22 }
00418
00419
00420
00421 #define GNUTLS_RSA_ARCFOUR_SHA1 { 0x00, 0x05 }
00422 #define GNUTLS_RSA_ARCFOUR_MD5 { 0x00, 0x04 }
00423 #define GNUTLS_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x0A }
00424
00425
00426
00427 #define GNUTLS_RSA_AES_128_CBC_SHA1 { 0x00, 0x2F }
00428 #define GNUTLS_RSA_AES_256_CBC_SHA1 { 0x00, 0x35 }
00429
00430
00431 #define GNUTLS_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x41 }
00432 #define GNUTLS_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x84 }
00433
00434
00435
00436
00437 #define GNUTLS_DHE_DSS_3DES_EDE_CBC_SHA1 { 0x00, 0x13 }
00438
00439
00440
00441 #define GNUTLS_DHE_DSS_ARCFOUR_SHA1 { 0x00, 0x66 }
00442
00443
00444
00445 #define GNUTLS_DHE_DSS_AES_256_CBC_SHA1 { 0x00, 0x38 }
00446 #define GNUTLS_DHE_DSS_AES_128_CBC_SHA1 { 0x00, 0x32 }
00447
00448
00449 #define GNUTLS_DHE_DSS_CAMELLIA_128_CBC_SHA1 { 0x00,0x44 }
00450 #define GNUTLS_DHE_DSS_CAMELLIA_256_CBC_SHA1 { 0x00,0x87 }
00451
00452
00453
00454 #define GNUTLS_DHE_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x16 }
00455
00456
00457
00458 #define GNUTLS_DHE_RSA_AES_128_CBC_SHA1 { 0x00, 0x33 }
00459 #define GNUTLS_DHE_RSA_AES_256_CBC_SHA1 { 0x00, 0x39 }
00460
00461
00462 #define GNUTLS_DHE_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x45 }
00463 #define GNUTLS_DHE_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x88 }
00464
00465 #define CIPHER_SUITES_COUNT sizeof(MHD_gtls_cs_algorithms)/sizeof(MHD_gtls_cipher_suite_entry)-1
00466
00467 static const MHD_gtls_cipher_suite_entry MHD_gtls_cs_algorithms[] = {
00468
00469 GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_MD5,
00470 MHD_GNUTLS_CIPHER_NULL,
00471 MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_MD5,
00472 MHD_GNUTLS_PROTOCOL_SSL3),
00473 GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_SHA1,
00474 MHD_GNUTLS_CIPHER_ARCFOUR_128,
00475 MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_SHA1,
00476 MHD_GNUTLS_PROTOCOL_SSL3),
00477 GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_MD5,
00478 MHD_GNUTLS_CIPHER_ARCFOUR_128,
00479 MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_MD5,
00480 MHD_GNUTLS_PROTOCOL_SSL3),
00481 GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_3DES_EDE_CBC_SHA1,
00482 MHD_GNUTLS_CIPHER_3DES_CBC,
00483 MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_SHA1,
00484 MHD_GNUTLS_PROTOCOL_SSL3),
00485 GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_CBC_SHA1,
00486 MHD_GNUTLS_CIPHER_AES_128_CBC, MHD_GNUTLS_KX_RSA,
00487 MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
00488 GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_256_CBC_SHA1,
00489 MHD_GNUTLS_CIPHER_AES_256_CBC, MHD_GNUTLS_KX_RSA,
00490 MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
00491 {0,
00492 {
00493 {0,
00494 0}},
00495 0,
00496 0,
00497 0,
00498 0}
00499 };
00500
00501 #define GNUTLS_CIPHER_SUITE_LOOP(b) \
00502 const MHD_gtls_cipher_suite_entry *p; \
00503 for(p = MHD_gtls_cs_algorithms; p->name != NULL; p++) { b ; }
00504
00505 #define GNUTLS_CIPHER_SUITE_ALG_LOOP(a) \
00506 GNUTLS_CIPHER_SUITE_LOOP( if( (p->id.suite[0] == suite->suite[0]) && (p->id.suite[1] == suite->suite[1])) { a; break; } )
00507
00508
00509
00510 int
00511 MHD_gtls_mac_priority (MHD_gtls_session_t session,
00512 enum MHD_GNUTLS_HashAlgorithm algorithm)
00513 {
00514 unsigned int i;
00515 for (i = 0; i < session->internals.priorities.mac.num_algorithms; i++)
00516 {
00517 if (session->internals.priorities.mac.priority[i] == algorithm)
00518 return i;
00519 }
00520 return -1;
00521 }
00522
00523
00524 int
00525 MHD_gnutls_mac_is_ok (enum MHD_GNUTLS_HashAlgorithm algorithm)
00526 {
00527 ssize_t ret = -1;
00528 GNUTLS_HASH_ALG_LOOP (ret = p->id);
00529 if (ret >= 0)
00530 ret = 0;
00531 else
00532 ret = 1;
00533 return ret;
00534 }
00535
00536
00544 const char *
00545 MHD_gtls_compression_get_name (enum MHD_GNUTLS_CompressionMethod algorithm)
00546 {
00547 const char *ret = NULL;
00548
00549
00550 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_COMP_") - 1);
00551
00552 return ret;
00553 }
00554
00565 enum MHD_GNUTLS_CompressionMethod
00566 MHD_gtls_compression_get_id (const char *name)
00567 {
00568 enum MHD_GNUTLS_CompressionMethod ret = MHD_GNUTLS_COMP_UNKNOWN;
00569
00570 GNUTLS_COMPRESSION_LOOP (if
00571 (strcasecmp
00572 (p->name + sizeof ("GNUTLS_COMP_") - 1,
00573 name) == 0) ret = p->id)
00574 ;
00575
00576 return ret;
00577 }
00578
00579
00580
00581 int
00582 MHD_gtls_compression_get_num (enum MHD_GNUTLS_CompressionMethod algorithm)
00583 {
00584 int ret = -1;
00585
00586
00587 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->num);
00588
00589 return ret;
00590 }
00591
00592 int
00593 MHD_gtls_compression_get_wbits (enum MHD_GNUTLS_CompressionMethod algorithm)
00594 {
00595 int ret = -1;
00596
00597 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->window_bits);
00598 return ret;
00599 }
00600
00601 int
00602 MHD_gtls_compression_get_mem_level (enum MHD_GNUTLS_CompressionMethod
00603 algorithm)
00604 {
00605 int ret = -1;
00606
00607 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->mem_level);
00608 return ret;
00609 }
00610
00611 int
00612 MHD_gtls_compression_get_comp_level (enum MHD_GNUTLS_CompressionMethod
00613 algorithm)
00614 {
00615 int ret = -1;
00616
00617 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->comp_level);
00618 return ret;
00619 }
00620
00621
00622
00623
00624 enum MHD_GNUTLS_CompressionMethod
00625 MHD_gtls_compression_get_id_from_int (int num)
00626 {
00627 enum MHD_GNUTLS_CompressionMethod ret = -1;
00628
00629
00630 GNUTLS_COMPRESSION_ALG_LOOP_NUM (ret = p->id);
00631
00632 return ret;
00633 }
00634
00635 int
00636 MHD_gtls_compression_is_ok (enum MHD_GNUTLS_CompressionMethod algorithm)
00637 {
00638 ssize_t ret = -1;
00639 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->id);
00640 if (ret >= 0)
00641 ret = 0;
00642 else
00643 ret = 1;
00644 return ret;
00645 }
00646
00647
00648 int
00649 MHD_gtls_cipher_get_block_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
00650 {
00651 size_t ret = 0;
00652 GNUTLS_ALG_LOOP (ret = p->blocksize);
00653 return ret;
00654
00655 }
00656
00657
00658 int
00659 MHD_gtls_cipher_priority (MHD_gtls_session_t session,
00660 enum MHD_GNUTLS_CipherAlgorithm algorithm)
00661 {
00662 unsigned int i;
00663 for (i = 0; i < session->internals.priorities.cipher.num_algorithms; i++)
00664 {
00665 if (session->internals.priorities.cipher.priority[i] == algorithm)
00666 return i;
00667 }
00668 return -1;
00669 }
00670
00671 int
00672 MHD_gtls_cipher_is_block (enum MHD_GNUTLS_CipherAlgorithm algorithm)
00673 {
00674 size_t ret = 0;
00675
00676 GNUTLS_ALG_LOOP (ret = p->block);
00677 return ret;
00678
00679 }
00680
00688 size_t
00689 MHD__gnutls_cipher_get_key_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
00690 {
00691 size_t ret = 0;
00692 GNUTLS_ALG_LOOP (ret = p->keysize);
00693 return ret;
00694
00695 }
00696
00697 int
00698 MHD_gtls_cipher_get_iv_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
00699 {
00700 size_t ret = 0;
00701 GNUTLS_ALG_LOOP (ret = p->iv);
00702 return ret;
00703
00704 }
00705
00706 int
00707 MHD_gtls_cipher_get_export_flag (enum MHD_GNUTLS_CipherAlgorithm algorithm)
00708 {
00709 size_t ret = 0;
00710 GNUTLS_ALG_LOOP (ret = p->export_flag);
00711 return ret;
00712
00713 }
00714
00715
00716 int
00717 MHD_gtls_cipher_is_ok (enum MHD_GNUTLS_CipherAlgorithm algorithm)
00718 {
00719 ssize_t ret = -1;
00720 GNUTLS_ALG_LOOP (ret = p->id);
00721 if (ret >= 0)
00722 ret = 0;
00723 else
00724 ret = 1;
00725 return ret;
00726 }
00727
00728
00729 MHD_gtls_mod_auth_st *
00730 MHD_gtls_kx_auth_struct (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
00731 {
00732 MHD_gtls_mod_auth_st *ret = NULL;
00733 GNUTLS_KX_ALG_LOOP (ret = p->auth_struct);
00734 return ret;
00735
00736 }
00737
00738 int
00739 MHD_gtls_kx_priority (MHD_gtls_session_t session,
00740 enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
00741 {
00742 unsigned int i;
00743 for (i = 0; i < session->internals.priorities.kx.num_algorithms; i++)
00744 {
00745 if (session->internals.priorities.kx.priority[i] == algorithm)
00746 return i;
00747 }
00748 return -1;
00749 }
00750
00751
00752 int
00753 MHD_gtls_kx_is_ok (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
00754 {
00755 ssize_t ret = -1;
00756 GNUTLS_KX_ALG_LOOP (ret = p->algorithm);
00757 if (ret >= 0)
00758 ret = 0;
00759 else
00760 ret = 1;
00761 return ret;
00762 }
00763
00764 int
00765 MHD_gtls_kx_needs_rsa_params (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
00766 {
00767 ssize_t ret = 0;
00768 GNUTLS_KX_ALG_LOOP (ret = p->needs_rsa_params);
00769 return ret;
00770 }
00771
00772 int
00773 MHD_gtls_kx_needs_dh_params (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
00774 {
00775 ssize_t ret = 0;
00776 GNUTLS_KX_ALG_LOOP (ret = p->needs_dh_params);
00777 return ret;
00778 }
00779
00780
00781 int
00782 MHD_gtls_version_priority (MHD_gtls_session_t session,
00783 enum MHD_GNUTLS_Protocol version)
00784 {
00785 unsigned int i;
00786
00787 if (session->internals.priorities.protocol.priority == NULL)
00788 {
00789 MHD_gnutls_assert ();
00790 return -1;
00791 }
00792
00793 for (i = 0; i < session->internals.priorities.protocol.num_algorithms; i++)
00794 {
00795 if (session->internals.priorities.protocol.priority[i] == version)
00796 return i;
00797 }
00798 return -1;
00799 }
00800
00801
00802 enum MHD_GNUTLS_Protocol
00803 MHD_gtls_version_max (MHD_gtls_session_t session)
00804 {
00805 unsigned int i, max = 0x00;
00806
00807 if (session->internals.priorities.protocol.priority == NULL)
00808 {
00809 return MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN;
00810 }
00811 else
00812 for (i = 0; i < session->internals.priorities.protocol.num_algorithms;
00813 i++)
00814 {
00815 if (session->internals.priorities.protocol.priority[i] > max)
00816 max = session->internals.priorities.protocol.priority[i];
00817 }
00818
00819 if (max == 0x00)
00820 return MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN;
00821
00822 return max;
00823 }
00824
00825 int
00826 MHD_gtls_version_get_minor (enum MHD_GNUTLS_Protocol version)
00827 {
00828 int ret = -1;
00829
00830 GNUTLS_VERSION_ALG_LOOP (ret = p->minor);
00831 return ret;
00832 }
00833
00834 enum MHD_GNUTLS_Protocol
00835 MHD_gtls_version_get (int major, int minor)
00836 {
00837 int ret = -1;
00838
00839 GNUTLS_VERSION_LOOP (if ((p->major == major) && (p->minor == minor))
00840 ret = p->id)
00841 ;
00842 return ret;
00843 }
00844
00845 int
00846 MHD_gtls_version_get_major (enum MHD_GNUTLS_Protocol version)
00847 {
00848 int ret = -1;
00849
00850 GNUTLS_VERSION_ALG_LOOP (ret = p->major);
00851 return ret;
00852 }
00853
00854
00855
00856 int
00857 MHD_gtls_version_is_supported (MHD_gtls_session_t session,
00858 const enum MHD_GNUTLS_Protocol version)
00859 {
00860 int ret = 0;
00861
00862 GNUTLS_VERSION_ALG_LOOP (ret = p->supported);
00863 if (ret == 0)
00864 return 0;
00865
00866 if (MHD_gtls_version_priority (session, version) < 0)
00867 return 0;
00868 else
00869 return 1;
00870 }
00871
00872 enum MHD_GNUTLS_CredentialsType
00873 MHD_gtls_map_kx_get_cred (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm,
00874 int server)
00875 {
00876 enum MHD_GNUTLS_CredentialsType ret = -1;
00877 if (server)
00878 {
00879 GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret = p->server_type)
00880 ;
00881 }
00882 else
00883 {
00884 GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret = p->client_type)
00885 ;
00886 }
00887
00888 return ret;
00889 }
00890
00891
00892 enum MHD_GNUTLS_CipherAlgorithm
00893 MHD_gtls_cipher_suite_get_cipher_algo (const cipher_suite_st * suite)
00894 {
00895 int ret = 0;
00896 GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->block_algorithm);
00897 return ret;
00898 }
00899
00900 enum MHD_GNUTLS_Protocol
00901 MHD_gtls_cipher_suite_get_version (const cipher_suite_st * suite)
00902 {
00903 int ret = 0;
00904 GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->version);
00905 return ret;
00906 }
00907
00908 enum MHD_GNUTLS_KeyExchangeAlgorithm
00909 MHD_gtls_cipher_suite_get_kx_algo (const cipher_suite_st * suite)
00910 {
00911 int ret = 0;
00912
00913 GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->kx_algorithm);
00914 return ret;
00915
00916 }
00917
00918 enum MHD_GNUTLS_HashAlgorithm
00919 MHD_gtls_cipher_suite_get_mac_algo (const cipher_suite_st * suite)
00920 {
00921 int ret = 0;
00922 GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->mac_algorithm);
00923 return ret;
00924
00925 }
00926
00927 const char *
00928 MHD_gtls_cipher_suite_get_name (cipher_suite_st * suite)
00929 {
00930 const char *ret = NULL;
00931
00932
00933 GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_") - 1);
00934
00935 return ret;
00936 }
00937
00938 static inline int
00939 MHD__gnutls_cipher_suite_is_ok (cipher_suite_st * suite)
00940 {
00941 size_t ret;
00942 const char *name = NULL;
00943
00944 GNUTLS_CIPHER_SUITE_ALG_LOOP (name = p->name);
00945 if (name != NULL)
00946 ret = 0;
00947 else
00948 ret = 1;
00949 return ret;
00950
00951 }
00952
00953 #define SWAP(x, y) memcpy(tmp,x,size); \
00954 memcpy(x,y,size); \
00955 memcpy(y,tmp,size);
00956
00957 #define MAX_ELEM_SIZE 4
00958 static inline int
00959 MHD__gnutls_partition (MHD_gtls_session_t session,
00960 void *_base,
00961 size_t nmemb,
00962 size_t size,
00963 int (*compar) (MHD_gtls_session_t,
00964 const void *, const void *))
00965 {
00966 uint8_t *base = _base;
00967 uint8_t tmp[MAX_ELEM_SIZE];
00968 uint8_t ptmp[MAX_ELEM_SIZE];
00969 unsigned int pivot;
00970 unsigned int i, j;
00971 unsigned int full;
00972
00973 i = pivot = 0;
00974 j = full = (nmemb - 1) * size;
00975
00976 memcpy (ptmp, &base[0], size);
00977
00978 while (i < j)
00979 {
00980 while ((compar (session, &base[i], ptmp) <= 0) && (i < full))
00981 {
00982 i += size;
00983 }
00984 while ((compar (session, &base[j], ptmp) >= 0) && (j > 0))
00985 j -= size;
00986
00987 if (i < j)
00988 {
00989 SWAP (&base[j], &base[i]);
00990 }
00991 }
00992
00993 if (j > pivot)
00994 {
00995 SWAP (&base[pivot], &base[j]);
00996 pivot = j;
00997 }
00998 else if (i < pivot)
00999 {
01000 SWAP (&base[pivot], &base[i]);
01001 pivot = i;
01002 }
01003 return pivot / size;
01004 }
01005
01006 static void
01007 MHD__gnutls_qsort (MHD_gtls_session_t session,
01008 void *_base,
01009 size_t nmemb,
01010 size_t size,
01011 int (*compar) (MHD_gtls_session_t, const void *,
01012 const void *))
01013 {
01014 unsigned int pivot;
01015 char *base = _base;
01016 size_t snmemb = nmemb;
01017
01018 if (snmemb <= 1)
01019 return;
01020 pivot = MHD__gnutls_partition (session, _base, nmemb, size, compar);
01021
01022 MHD__gnutls_qsort (session, base, pivot < nmemb ? pivot + 1
01023 : pivot, size, compar);
01024 MHD__gnutls_qsort (session, &base[(pivot + 1) * size], nmemb - pivot - 1,
01025 size, compar);
01026 }
01027
01028
01029
01030
01031 static int
01032 MHD__gnutls_compare_algo (MHD_gtls_session_t session,
01033 const void *i_A1, const void *i_A2)
01034 {
01035 enum MHD_GNUTLS_KeyExchangeAlgorithm kA1 =
01036 MHD_gtls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A1);
01037 enum MHD_GNUTLS_KeyExchangeAlgorithm kA2 =
01038 MHD_gtls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A2);
01039 enum MHD_GNUTLS_CipherAlgorithm cA1 =
01040 MHD_gtls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A1);
01041 enum MHD_GNUTLS_CipherAlgorithm cA2 =
01042 MHD_gtls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A2);
01043 enum MHD_GNUTLS_HashAlgorithm mA1 =
01044 MHD_gtls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A1);
01045 enum MHD_GNUTLS_HashAlgorithm mA2 =
01046 MHD_gtls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A2);
01047
01048 int p1 = (MHD_gtls_kx_priority (session, kA1) + 1) * 64;
01049 int p2 = (MHD_gtls_kx_priority (session, kA2) + 1) * 64;
01050 p1 += (MHD_gtls_cipher_priority (session, cA1) + 1) * 8;
01051 p2 += (MHD_gtls_cipher_priority (session, cA2) + 1) * 8;
01052 p1 += MHD_gtls_mac_priority (session, mA1);
01053 p2 += MHD_gtls_mac_priority (session, mA2);
01054
01055 if (p1 > p2)
01056 {
01057 return 1;
01058 }
01059 else
01060 {
01061 if (p1 == p2)
01062 {
01063 return 0;
01064 }
01065 return -1;
01066 }
01067 }
01068
01069 int
01070 MHD_gtls_supported_ciphersuites_sorted (MHD_gtls_session_t session,
01071 cipher_suite_st ** ciphers)
01072 {
01073
01074 int count;
01075
01076 count = MHD_gtls_supported_ciphersuites (session, ciphers);
01077 if (count <= 0)
01078 {
01079 MHD_gnutls_assert ();
01080 return count;
01081 }
01082 MHD__gnutls_qsort (session, *ciphers, count, sizeof (cipher_suite_st),
01083 MHD__gnutls_compare_algo);
01084
01085 return count;
01086 }
01087
01088 int
01089 MHD_gtls_supported_ciphersuites (MHD_gtls_session_t session,
01090 cipher_suite_st ** _ciphers)
01091 {
01092
01093 unsigned int i, ret_count, j;
01094 unsigned int count = CIPHER_SUITES_COUNT;
01095 cipher_suite_st *tmp_ciphers;
01096 cipher_suite_st *ciphers;
01097 enum MHD_GNUTLS_Protocol version;
01098
01099 if (count == 0)
01100 {
01101 return 0;
01102 }
01103
01104 tmp_ciphers = MHD_gnutls_alloca (count * sizeof (cipher_suite_st));
01105 if (tmp_ciphers == NULL)
01106 return GNUTLS_E_MEMORY_ERROR;
01107
01108 ciphers = MHD_gnutls_malloc (count * sizeof (cipher_suite_st));
01109 if (ciphers == NULL)
01110 {
01111 MHD_gnutls_afree (tmp_ciphers);
01112 return GNUTLS_E_MEMORY_ERROR;
01113 }
01114
01115 version = MHD__gnutls_protocol_get_version (session);
01116
01117 for (i = 0; i < count; i++)
01118 {
01119 memcpy (&tmp_ciphers[i], &MHD_gtls_cs_algorithms[i].id,
01120 sizeof (cipher_suite_st));
01121 }
01122
01123 for (i = j = 0; i < count; i++)
01124 {
01125
01126
01127 if (tmp_ciphers[i].suite[0] == 0xFF)
01128 continue;
01129
01130
01131
01132
01133 if (MHD_gtls_cipher_suite_get_version (&tmp_ciphers[i]) > version)
01134 continue;
01135
01136 if (MHD_gtls_kx_priority (session,
01137 MHD_gtls_cipher_suite_get_kx_algo
01138 (&tmp_ciphers[i])) < 0)
01139 continue;
01140 if (MHD_gtls_mac_priority (session,
01141 MHD_gtls_cipher_suite_get_mac_algo
01142 (&tmp_ciphers[i])) < 0)
01143 continue;
01144 if (MHD_gtls_cipher_priority (session,
01145 MHD_gtls_cipher_suite_get_cipher_algo
01146 (&tmp_ciphers[i])) < 0)
01147 continue;
01148
01149 memcpy (&ciphers[j], &tmp_ciphers[i], sizeof (cipher_suite_st));
01150 j++;
01151 }
01152
01153 ret_count = j;
01154
01155 MHD_gnutls_afree (tmp_ciphers);
01156
01157
01158
01159
01160 if (ret_count == 0)
01161 {
01162 MHD_gnutls_assert ();
01163 MHD_gnutls_free (ciphers);
01164 return GNUTLS_E_NO_CIPHER_SUITES;
01165 }
01166 *_ciphers = ciphers;
01167 return ret_count;
01168 }
01169
01170
01171
01172 #define MIN_PRIVATE_COMP_ALGO 0xEF
01173
01174
01175
01176 #define SUPPORTED_COMPRESSION_METHODS session->internals.priorities.compression.num_algorithms
01177 int
01178 MHD_gtls_supported_compression_methods (MHD_gtls_session_t session,
01179 uint8_t ** comp)
01180 {
01181 unsigned int i, j;
01182
01183 *comp =
01184 MHD_gnutls_malloc (sizeof (uint8_t) * SUPPORTED_COMPRESSION_METHODS);
01185 if (*comp == NULL)
01186 return GNUTLS_E_MEMORY_ERROR;
01187
01188 for (i = j = 0; i < SUPPORTED_COMPRESSION_METHODS; i++)
01189 {
01190 int tmp =
01191 MHD_gtls_compression_get_num (session->internals.priorities.
01192 compression.priority[i]);
01193
01194
01195
01196 if (tmp == -1 || (tmp >= MIN_PRIVATE_COMP_ALGO))
01197 {
01198 MHD_gnutls_assert ();
01199 continue;
01200 }
01201
01202 (*comp)[j] = (uint8_t) tmp;
01203 j++;
01204 }
01205
01206 if (j == 0)
01207 {
01208 MHD_gnutls_assert ();
01209 MHD_gnutls_free (*comp);
01210 *comp = NULL;
01211 return GNUTLS_E_NO_COMPRESSION_ALGORITHMS;
01212 }
01213 return j;
01214 }
01215
01216 static const enum MHD_GNUTLS_CertificateType
01217 MHD_gtls_supported_certificate_types[] =
01218 { MHD_GNUTLS_CRT_X509,
01219 0
01220 };
01221
01222
01223
01224
01225
01226 enum MHD_GNUTLS_PublicKeyAlgorithm
01227 MHD_gtls_map_pk_get_pk (enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm)
01228 {
01229 enum MHD_GNUTLS_PublicKeyAlgorithm ret = -1;
01230
01231 GNUTLS_PK_MAP_ALG_LOOP (ret = p->pk_algorithm) return ret;
01232 }
01233
01234
01235
01236
01237
01238
01239 enum encipher_type
01240 MHD_gtls_kx_encipher_type (enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm)
01241 {
01242 int ret = CIPHER_IGN;
01243 GNUTLS_PK_MAP_ALG_LOOP (ret = p->encipher_type) return ret;
01244
01245 }
01246
01247
01248
01249 struct MHD_gnutls_sign_entry
01250 {
01251 const char *name;
01252 const char *oid;
01253 MHD_gnutls_sign_algorithm_t id;
01254 enum MHD_GNUTLS_PublicKeyAlgorithm pk;
01255 enum MHD_GNUTLS_HashAlgorithm mac;
01256 };
01257 typedef struct MHD_gnutls_sign_entry MHD_gnutls_sign_entry;
01258
01259 static const MHD_gnutls_sign_entry MHD_gtls_sign_algorithms[] = {
01260 {"RSA-SHA",
01261 SIG_RSA_SHA1_OID,
01262 GNUTLS_SIGN_RSA_SHA1,
01263 MHD_GNUTLS_PK_RSA,
01264 MHD_GNUTLS_MAC_SHA1},
01265 {"RSA-SHA256",
01266 SIG_RSA_SHA256_OID,
01267 GNUTLS_SIGN_RSA_SHA256,
01268 MHD_GNUTLS_PK_RSA,
01269 MHD_GNUTLS_MAC_SHA256},
01270 {"RSA-MD5",
01271 SIG_RSA_MD5_OID,
01272 GNUTLS_SIGN_RSA_MD5,
01273 MHD_GNUTLS_PK_RSA,
01274 MHD_GNUTLS_MAC_MD5},
01275 {"GOST R 34.10-2001",
01276 SIG_GOST_R3410_2001_OID,
01277 0,
01278 0,
01279 0},
01280 {"GOST R 34.10-94",
01281 SIG_GOST_R3410_94_OID,
01282 0,
01283 0,
01284 0},
01285 {0,
01286 0,
01287 0,
01288 0,
01289 0}
01290 };
01291
01292 #define GNUTLS_SIGN_LOOP(b) \
01293 do { \
01294 const MHD_gnutls_sign_entry *p; \
01295 for(p = MHD_gtls_sign_algorithms; p->name != NULL; p++) { b ; } \
01296 } while (0)
01297
01298 #define GNUTLS_SIGN_ALG_LOOP(a) \
01299 GNUTLS_SIGN_LOOP( if(p->id && p->id == sign) { a; break; } )
01300
01301
01302
01303 struct MHD_gnutls_pk_entry
01304 {
01305 const char *name;
01306 const char *oid;
01307 enum MHD_GNUTLS_PublicKeyAlgorithm id;
01308 };
01309 typedef struct MHD_gnutls_pk_entry MHD_gnutls_pk_entry;
01310
01311 static const MHD_gnutls_pk_entry MHD_gtls_pk_algorithms[] = {
01312 {"RSA",
01313 PK_PKIX1_RSA_OID,
01314 MHD_GNUTLS_PK_RSA},
01315 {"GOST R 34.10-2001",
01316 PK_GOST_R3410_2001_OID,
01317 0},
01318 {"GOST R 34.10-94",
01319 PK_GOST_R3410_94_OID,
01320 0},
01321 {0,
01322 0,
01323 0}
01324 };
01325
01326 enum MHD_GNUTLS_PublicKeyAlgorithm
01327 MHD_gtls_x509_oid2pk_algorithm (const char *oid)
01328 {
01329 enum MHD_GNUTLS_PublicKeyAlgorithm ret = MHD_GNUTLS_PK_UNKNOWN;
01330 const MHD_gnutls_pk_entry *p;
01331
01332 for (p = MHD_gtls_pk_algorithms; p->name != NULL; p++)
01333 if (strcmp (p->oid, oid) == 0)
01334 {
01335 ret = p->id;
01336 break;
01337 }
01338
01339 return ret;
01340 }