List ciphers and other details from GnuTLS priority string
/* | |
gcc -o gnutls-priority gnutls-priority.c `pkg-config gnutls --cflags --libs` -DTRY_INTERNALS | |
With -DTRY_INTERNALS it will try to show internal stuff, but the internal API might change | |
and the feature break. | |
Example call: | |
./gnutls-priority "NORMAL:-MAC-ALL:+AEAD" | |
also check gnutls-cli -c | |
*/ | |
/* This example code is placed in the public domain. */ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <gnutls/gnutls.h> | |
#define CHECK_RET(func, ret) do { \ | |
if (ret < 0) { \ | |
fprintf(stderr, "%s failed: %s\n", func, gnutls_strerror(ret)); \ | |
exit(1); \ | |
} \ | |
} while (0) | |
#ifdef TRY_INTERNALS | |
/* this is taken from gnutls 3.2.2 (lib/gnutls_int.h), might break with other versions */ | |
typedef struct | |
{ | |
unsigned int priority[GNUTLS_MAX_ALGORITHM_NUM]; | |
unsigned int algorithms; | |
} priority_st; | |
struct gnutls_priority_st | |
{ | |
priority_st cipher; | |
priority_st mac; | |
priority_st kx; | |
priority_st compression; | |
priority_st protocol; | |
priority_st cert_type; | |
priority_st sign_algo; | |
priority_st supported_ecc; | |
/* omitted remaining stuff */ | |
}; | |
#endif | |
static void print_cipher_suite_list(const char* priorities) { | |
size_t i; | |
int ret; | |
unsigned int idx; | |
const char *name; | |
const char *err; | |
unsigned char id[2]; | |
gnutls_protocol_t version; | |
gnutls_priority_t pcache; | |
const unsigned int* list; | |
if (priorities == NULL) return; | |
printf("Cipher suites for %s\n", priorities); | |
ret = gnutls_priority_init(&pcache, priorities, &err); | |
if (ret < 0) { | |
fprintf(stderr, "Syntax error at: %s\n", err); | |
CHECK_RET("gnutls_priority_init", ret); | |
} | |
for (i=0;;i++) { | |
ret = gnutls_priority_get_cipher_suite_index(pcache, i, &idx); | |
if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) break; | |
if (ret == GNUTLS_E_UNKNOWN_CIPHER_SUITE) { | |
/* > It might be that a valid priorities index does not correspond | |
* > to a ciphersuite and in that case GNUTLS_E_UNKNOWN_CIPHER_SUITE | |
* > will be returned. */ | |
/* printf("Unknown cipher suite %i\n", idx); */ | |
continue; | |
} | |
CHECK_RET("gnutls_priority_get_cipher_suite_index", ret); | |
name = gnutls_cipher_suite_info(idx, id, NULL, NULL, NULL, &version); | |
if (name != NULL) { | |
printf("%-50s\t0x%02x, 0x%02x\t%s\n", | |
name, (unsigned char) id[0], (unsigned char) id[1], | |
gnutls_protocol_get_name (version)); | |
} | |
} | |
printf("Certificate types:\n"); | |
ret = gnutls_priority_certificate_type_list(pcache, &list); | |
CHECK_RET("gnutls_priority_certificate_type_list", ret); | |
for (i = 0; i < ret; ++i) { | |
name = gnutls_certificate_type_get_name(list[i]); | |
printf("%20s\t0x%02x\n", name ? name : "<unknown>", list[i]); | |
} | |
printf("Compression methods:\n"); | |
ret = gnutls_priority_compression_list(pcache, &list); | |
CHECK_RET("gnutls_priority_compression_list", ret); | |
for (i = 0; i < ret; ++i) { | |
name = gnutls_compression_get_name(list[i]); | |
printf("%20s\t0x%02x\n", name ? name : "<unknown>", list[i]); | |
} | |
printf("Elliptic curves:\n"); | |
ret = gnutls_priority_ecc_curve_list(pcache, &list); | |
CHECK_RET("gnutls_priority_ecc_curve_list", ret); | |
for (i = 0; i < ret; ++i) { | |
name = gnutls_ecc_curve_get_name(list[i]); | |
printf("%20s\t0x%02x\n", name ? name : "<unknown>", list[i]); | |
} | |
printf("Protocols:\n"); | |
ret = gnutls_priority_protocol_list(pcache, &list); | |
CHECK_RET("gnutls_priority_protocol_list", ret); | |
for (i = 0; i < ret; ++i) { | |
name = gnutls_protocol_get_name(list[i]); | |
printf("%20s\t0x%02x\n", name ? name : "<unknown>", list[i]); | |
} | |
printf("signature algorithms:\n"); | |
ret = gnutls_priority_sign_list(pcache, &list); | |
CHECK_RET("gnutls_priority_sign_list", ret); | |
for (i = 0; i < ret; ++i) { | |
name = gnutls_sign_get_name(list[i]); | |
printf("%20s\t0x%02x\n", name ? name : "<unknown>", list[i]); | |
} | |
#ifdef TRY_INTERNALS | |
/* not official api */ | |
printf("\nStuff from internals\n"); | |
printf("cipher algorithms:\n"); | |
for (i = 0; i < GNUTLS_MAX_ALGORITHM_NUM; ++i) { | |
name = gnutls_cipher_get_name(pcache->cipher.priority[i]); | |
if (i >= pcache->cipher.algorithms) { | |
if (pcache->cipher.priority[i] != 0) { | |
printf("%20s\t0x%02x\tat index %i after list end\n", name ? name : "<unknown>", pcache->cipher.priority[i], i); | |
} | |
} else { | |
printf("%20s\t0x%02x\n", name ? name : "<unknown>", pcache->cipher.priority[i]); | |
} | |
} | |
printf("MAC algorithms:\n"); | |
for (i = 0; i < GNUTLS_MAX_ALGORITHM_NUM; ++i) { | |
name = gnutls_mac_get_name(pcache->mac.priority[i]); | |
if (i >= pcache->mac.algorithms) { | |
if (pcache->mac.priority[i] != 0) { | |
printf("%20s\t0x%02x\tat index %i after list end\n", name ? name : "<unknown>", pcache->mac.priority[i], i); | |
} | |
} else { | |
printf("%20s\t0x%02x\n", name ? name : "<unknown>", pcache->mac.priority[i]); | |
} | |
} | |
printf("key exchange algorithms:\n"); | |
for (i = 0; i < GNUTLS_MAX_ALGORITHM_NUM; ++i) { | |
name = gnutls_kx_get_name(pcache->kx.priority[i]); | |
if (i >= pcache->kx.algorithms) { | |
if (pcache->kx.priority[i] != 0) { | |
printf("%20s\t0x%02x\tat index %i after list end\n", name ? name : "<unknown>", pcache->kx.priority[i], i); | |
} | |
} else { | |
printf("%20s\t0x%02x\n", name ? name : "<unknown>", pcache->kx.priority[i]); | |
} | |
} | |
#endif | |
} | |
int main(int argc, char** argv) { | |
if (argc > 1) print_cipher_suite_list(argv[1]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment