Skip to content

Instantly share code, notes, and snippets.

@stbuehler
Created October 26, 2013 09:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stbuehler/7167426 to your computer and use it in GitHub Desktop.
Save stbuehler/7167426 to your computer and use it in GitHub Desktop.
Generate javascript tables for gnutls and official TLS ciphersuites
<?xml version="1.0" encoding="UTF-8"?>
<!-- saxonb-xslt http://www.iana.org/assignments/tls-parameters/tls-parameters.xml registry-ciphers.xslt > registry-ciphers.js -->
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:iana="http://www.iana.org/assignments"
>
<xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8"/>
<xsl:variable name='nl'><xsl:text>&#xa;</xsl:text></xsl:variable>
<xsl:variable name='sep'><xsl:text>,</xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:text>var registry_ciphersuites = {&#xa;</xsl:text>
<xsl:for-each select="iana:registry/iana:registry[@id='tls-parameters-4']/iana:record">
<xsl:variable name="xref"><xsl:for-each select="iana:xref[@type='rfc']"><xsl:value-of select="@data"/></xsl:for-each></xsl:variable>
<xsl:if test="matches(iana:value, '^0x[0-9A-Z]{2},0x[0-9A-Z]{2}$')">
<xsl:value-of select="concat('&#x9;',substring(iana:value,1,4),substring(iana:value,8,2),': &quot;',normalize-space(iana:description),'&quot;,',$nl)" />
</xsl:if>
</xsl:for-each>
<xsl:text>};&#xa;</xsl:text>
</xsl:template>
</xsl:stylesheet>
#/bin/sh
# ./scan-gnutls.sh > gnutls-ciphers.js
echo 'var gnutls_ciphersuites = {'
gcc -E ciphersuites.c -I.. -DHAVE_LIBNETTLE -I../../gl -DENABLE_DHE -DENABLE_ECDHE -DENABLE_PSK -DENABLE_ANON -DENABLE_SRP \
| awk '/^static const gnutls_cipher_suite_entry cs_algorithms/, /;/ { print; }' \
| grep '{' | head -n-1 | tail -n+2 \
| sed -r -e 's#\{ *0x(..), *0x(..) *\}#0x\1\2#;s# *\{ *"#"#;s#\}##;s#, +# #g' \
-e 's#GNUTLS_VERSION_UNKNOWN#unknown#' \
-e 's#GNUTLS_DTLS_VERSION_MIN#GNUTLS_DTLS1_0#;s#GNUTLS_TLS1 #GNUTLS_TLS1_0 #' \
-e 's#TLS([0-9])_([0-9])#TLS\1.\2#g;s#GNUTLS_SSL3#SSL3.0#;s#_#-#g;s#GNUTLS-(CIPHER|KX|MAC)-##g;s#GNUTLS-##g' \
| gawk --non-decimal-data '{ if ($5 == "AEAD") { mac = $8; } else { mac = $5; }; sub("UMAC-", "UMAC", mac); sub("DIG-", "", mac); if (mac == "SHA1") { mac = "SHA"; } \
cipher = $3; sub("ARCFOUR", "RC4", cipher); sub("3DES-CBC", "3DES-EDE-CBC", cipher); \
kx = $4; if (sub("ANON-", "", kx)) { kx = kx "-anon"; }; sub("SRP", "SRP-SHA", kx); \
name = "TLS_" kx "_WITH_" cipher "_" mac; gsub("-", "_", name); printf ("%d# \"%s\": { id: %s, name: \"%s\", gnutlsname: %s, cipher: \"%s\", kx: \"%s\", mac: \"%s\", min_version: \"%s\", min_dtls_version: \"%s\", prf: \"%s\" },\n", $2, name, $2, name, $1, $3, $4, $5, $6, $7, $8) }' \
| sort -n \
| cut -d'#' -f2- \
| column -t \
| sed -e 's#: #: #g;s#, #, #g;s#{ #{ #g;s#^# #'
echo '};'
/* run with nodejs */
var fs = require('fs');
var vm = require('vm');
function include(path) {
var code = fs.readFileSync(path, 'utf-8');
vm.runInThisContext(code, path);
}
include('./gnutls-ciphers.js');
include('./registry-ciphers.js');
(function() {
// var s = "NORMAL:-VERS-SSL3.0:-CIPHER-ALL:-SHA1:-MD5:+SHA1:+AES-256-GCM:+AES-256-CBC:+CAMELLIA-256-CBC:%SERVER_PRECEDENCE";
// console.log("Test: ", require('util').inspect(priority_config(priority(s)), false, 10));
// console.log("Test: ", require('util').inspect(priority_ciphersuites(priority(s)), false, 10));
// check whether gnutls ciphersuite names match the kx/cipher/mac/prf combination
for (var i in gnutls_ciphersuites) {
if (!gnutls_ciphersuites.hasOwnProperty(i)) continue;
var cs = gnutls_ciphersuites[i];
var mac = cs.mac;
if (mac == "AEAD") mac = cs.prf.replace("DIG-", "");
mac = mac.replace("UMAC-", "UMAC");
var cipher = cs.cipher.replace("3DES-CBC", "3DES-EDE-CBC");
var kx = cs.kx.replace("ANON-DH", "DH-ANON").replace("ANON-ECDH", "ECDH-ANON").replace("SRP", "SRP-SHA");
if (kx + "-" + cipher + "-" + mac != cs.gnutlsname) {
console.log("Broken: ", kx + "-" + cipher + "-" + mac, " ", cs.gnutlsname);
}
if (cs.name !== i) {
console.log("Name doesn't match index:", cs.name, i);
}
if (!registry_ciphersuites[cs.id]) {
if (cipher.match(/SALSA20/)) {
var warned_salsa20;
if (!warned_salsa20) {
/* warn only once */
console.log("Unofficial SALSA20 ciphers");
warned_salsa20 = 1;
}
} else {
console.log("Unofficial cipher:", cs.name, cs.id);
}
} else if (registry_ciphersuites[cs.id] !== cs.name) {
console.log("Name doesn't match official name for id:", cs.name, registry_ciphersuites[cs.id], cs.id);
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment