public
Last active

List ciphers and other details from GnuTLS priority string

  • Download Gist
gnutls-priority.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
/*
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]);
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.