From 5f9236521f5add49669a97875b7d26cf35b28963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= Date: Fri, 22 Jun 2018 14:05:18 +0200 Subject: [PATCH 1/2] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 3fd542379fa381b54381e07d6625ce53f9f9b1f0 Author: Petr Menšík Date: Thu Jun 21 12:00:35 2018 +0200 Revert "4450. [port] Provide more nuanced HSM support which better matches" This reverts commit f3b4d031c1f714ff6e862670663aa5a18650951e. Revert PK11_MD5_DISABLED also from remaining files. Keep documentation changes. commit f90934f734796595135cdd7a5008555a615dfe8e Author: Petr Menšík Date: Wed Jun 20 19:31:19 2018 +0200 Fix rndc-confgen default algorithm, report true algorithm in usage. commit dd53212c12c6943a21a3c24d60995edd19e1d9f7 Author: Petr Menšík Date: Fri Feb 23 21:21:30 2018 +0100 Cleanup only if initialization was successful commit f163ea51c46bb22bf264a1ac983e2027e43845fa Author: Petr Menšík Date: Mon Feb 5 12:19:28 2018 +0100 Ensure dst backend is initialized first even before hmac algorithms. commit 58751b60bd39168b7c8f817ede70473842432081 Author: Petr Menšík Date: Mon Feb 5 12:17:54 2018 +0100 Skip initialization of MD5 based algorithms if not available. commit 0572b98430d3c80f4a0b0c592b1e3bf7fde9b768 Author: Petr Menšík Date: Mon Feb 5 10:21:27 2018 +0100 Change secalgs skipping to be more safe commit 994f497a032930fce1370d507a265fbb293c66f4 Author: Petr Menšík Date: Wed Jan 31 18:26:11 2018 +0100 Skip MD5 algorithm also in case of NULL name commit abd82fbd2507c4b8f20e1ade202fd66d224fd646 Author: Petr Menšík Date: Wed Jan 31 16:54:29 2018 +0100 Revert part of commit 1b5c641416eb6de7fc232fc89d31a40a4d439f3d related to SHA1. commit b3c832d53a14a0779f598869bb99685c8e4b2bc0 Author: Petr Menšík Date: Wed Jan 31 11:38:12 2018 +0100 Make MD5 behave like unknown algorithm in TSIG. commit a64a3d6962ee93d6f8699b29bd6507dba0c244ed Author: Petr Menšík Date: Tue Nov 28 20:14:37 2017 +0100 Select token with most supported functions, instead of demanding it must support all functions Initialize PKCS#11 always until successfully initialized commit db118c6368668099ea1b6e75860cc12e178afa3b Author: Petr Menšík Date: Mon Jan 22 16:17:44 2018 +0100 Handle MD5 unavailability from DST commit 8f8824dca2f5b4d5a3a176d31ac3ee612321c4e3 Author: Petr Menšík Date: Mon Jan 22 14:11:16 2018 +0100 Check runtime flag from library and applications, fail gracefully. commit bd431384af7dcde8827e670c8749517ad677a967 Author: Petr Menšík Date: Mon Jan 22 08:39:08 2018 +0100 Modify libraries to use isc_md5_available() if PK11_MD5_DISABLE is not defined. TODO: pk11.c should accept slot without MD5 support. commit 160b13979ef3d0e92d2dd52d0987a3ec979be6cf Author: Petr Menšík Date: Mon Jan 22 07:21:04 2018 +0100 Add runtime detection whether MD5 is useable. commit 23b27ce0f2ad496c331ae40349cc1074a1b11804 Author: Mark Andrews Date: Fri Aug 19 08:25:54 2016 +1000 4450. [port] Provide more nuanced HSM support which better matches the specific PKCS11 providers capabilities. [RT #42458] (cherry picked from commit 8ee6f289d87851a5b898b24a64587f0e6bc225bc) Fix compiler warnings --- bin/confgen/keygen.c | 10 +++++- bin/confgen/rndc-confgen.c | 12 ++++--- bin/confgen/rndc-confgen.docbook | 3 +- bin/dig/dig.c | 5 ++- bin/dig/dig.docbook | 6 ++-- bin/dig/dighost.c | 14 ++++++-- bin/dnssec/dnssec-keyfromlabel.c | 9 +++++ bin/dnssec/dnssec-keygen.c | 19 +++++++++-- bin/named/config.c | 23 +++++++++++-- bin/nsupdate/nsupdate.c | 20 +++++++---- bin/nsupdate/nsupdate.docbook | 9 ++++- bin/rndc/rndc.c | 3 +- bin/tests/hashes/t_hashes.c | 20 ++++++----- lib/bind9/check.c | 8 +++++ lib/dns/dst_api.c | 23 +++++++++---- lib/dns/dst_internal.h | 3 +- lib/dns/dst_parse.c | 12 ++++++- lib/dns/hmac_link.c | 2 +- lib/dns/opensslrsa_link.c | 4 +++ lib/dns/pkcs11rsa_link.c | 25 ++++++++++++-- lib/dns/rcode.c | 19 +++++++++-- lib/dns/tests/tsig_test.c | 1 + lib/dns/tkey.c | 9 +++++ lib/dns/tsec.c | 8 ++++- lib/dns/tsig.c | 22 +++++------- lib/isc/include/isc/md5.h | 3 ++ lib/isc/md5.c | 59 ++++++++++++++++++++++++++++++++ lib/isc/pk11.c | 72 +++++++++++++++++++++++++++++++--------- lib/isccc/cc.c | 48 ++++++++++++++++----------- 29 files changed, 373 insertions(+), 98 deletions(-) diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c index d0cdafed36..4eb027e723 100644 --- a/bin/confgen/keygen.c +++ b/bin/confgen/keygen.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -69,7 +70,7 @@ alg_totext(dns_secalg_t alg) { */ dns_secalg_t alg_fromtext(const char *name) { - if (strcmp(name, "hmac-md5") == 0) + if (strcmp(name, "hmac-md5") == 0 && isc_md5_available()) return DST_ALG_HMACMD5; if (strcmp(name, "hmac-sha1") == 0) return DST_ALG_HMACSHA1; @@ -126,6 +127,13 @@ generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, switch (alg) { case DST_ALG_HMACMD5: + if (isc_md5_available() == ISC_FALSE) { + fatal("unsupported algorithm %d\n", alg); + } else if (keysize < 1 || keysize > 512) { + fatal("keysize %d out of range (must be 1-512)\n", + keysize); + } + break; case DST_ALG_HMACSHA1: case DST_ALG_HMACSHA224: case DST_ALG_HMACSHA256: diff --git a/bin/confgen/rndc-confgen.c b/bin/confgen/rndc-confgen.c index 3fd54fe2bb..c48a38f094 100644 --- a/bin/confgen/rndc-confgen.c +++ b/bin/confgen/rndc-confgen.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,7 @@ const char *progname; isc_boolean_t verbose = ISC_FALSE; -const char *keyfile, *keydef; +const char *keyfile, *keydef, *algdef; ISC_PLATFORM_NORETURN_PRE static void usage(int status) ISC_PLATFORM_NORETURN_POST; @@ -79,7 +80,7 @@ Usage:\n\ %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ [-s addr] [-t chrootdir] [-u user]\n\ -a: generate just the key clause and write it to keyfile (%s)\n\ - -A alg: algorithm (default hmac-md5)\n\ + -A alg: algorithm (default %s)\n\ -b bits: from 1 through 512, default 256; total length of the secret\n\ -c keyfile: specify an alternate key file (requires -a)\n\ -k keyname: the name as it will be used in named.conf and rndc.conf\n\ @@ -88,7 +89,7 @@ Usage:\n\ -s addr: the address to which rndc should connect\n\ -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ -u user: set the keyfile owner to \"user\" (requires -a)\n", - progname, keydef); + progname, keydef, algdef); exit (status); } @@ -124,9 +125,12 @@ main(int argc, char **argv) { progname = program; keyname = DEFAULT_KEYNAME; - alg = DST_ALG_HMACMD5; serveraddr = DEFAULT_SERVER; port = DEFAULT_PORT; + alg = DST_ALG_HMACSHA256; + if (isc_md5_available()) + alg = DST_ALG_HMACMD5; + algdef = alg_totext(alg); isc_commandline_errprint = ISC_FALSE; diff --git a/bin/confgen/rndc-confgen.docbook b/bin/confgen/rndc-confgen.docbook index f367b94aae..add8d7357f 100644 --- a/bin/confgen/rndc-confgen.docbook +++ b/bin/confgen/rndc-confgen.docbook @@ -136,7 +136,8 @@ Specifies the algorithm to use for the TSIG key. Available choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, - hmac-sha384 and hmac-sha512. The default is hmac-md5. + hmac-sha384 and hmac-sha512. The default is hmac-md5 or + if MD5 was disabled hmac-sha256. diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 634ccfbfbf..4db0e6430f 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1426,7 +1427,9 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, ptr = ptr2; ptr2 = ptr3; } else { - hmacname = DNS_TSIG_HMACMD5_NAME; + hmacname = DNS_TSIG_HMACSHA256_NAME; + if (isc_md5_available()) + hmacname = DNS_TSIG_HMACMD5_NAME; digestbits = 0; } strncpy(keynametext, ptr, sizeof(keynametext)); diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook index 028f0fcd73..6ee5bd90bc 100644 --- a/bin/dig/dig.docbook +++ b/bin/dig/dig.docbook @@ -309,9 +309,11 @@ responses using transaction signatures (TSIG), specify a TSIG key file using the option. You can also specify the TSIG key itself on the command line using the option; - hmac is the type of the TSIG, default HMAC-MD5, + hmac is the type of the TSIG, name is the name of the TSIG key and - key is the actual key. The key is a + key is the actual key. If hmac + is not specified, the default is hmac-md5 + or if MD5 was disabled hmac-sha256. The key is a base-64 encoded string, typically generated by diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 3a066c68c9..3998a81a5d 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -81,6 +81,7 @@ #include #include #include +#include #include #ifdef DIG_SIGCHASE #include @@ -1025,9 +1026,10 @@ parse_hmac(const char *hmac) { digestbits = 0; - if (strcasecmp(buf, "hmac-md5") == 0) { + if (strcasecmp(buf, "hmac-md5") == 0 && isc_md5_available()) { hmacname = DNS_TSIG_HMACMD5_NAME; - } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { + } else if (strncasecmp(buf, "hmac-md5-", 9) == 0 && + isc_md5_available()) { hmacname = DNS_TSIG_HMACMD5_NAME; digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); } else if (strcasecmp(buf, "hmac-sha1") == 0) { @@ -1145,7 +1147,13 @@ setup_file_key(void) { switch (dst_key_alg(dstkey)) { case DST_ALG_HMACMD5: - hmacname = DNS_TSIG_HMACMD5_NAME; + if (isc_md5_available()) { + hmacname = DNS_TSIG_HMACMD5_NAME; + } else { + printf(";; Couldn't create key %s: bad algorithm\n", + keynametext); + goto failure; + } break; case DST_ALG_HMACSHA1: hmacname = DNS_TSIG_HMACSHA1_NAME; diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c index cc212e1ed1..a5854a1f4c 100644 --- a/bin/dnssec/dnssec-keyfromlabel.c +++ b/bin/dnssec/dnssec-keyfromlabel.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -379,6 +380,11 @@ main(int argc, char **argv) { if (freeit != NULL) free(freeit); return (1); + } else if (strcasecmp(algname, "RSAMD5") == 0 && isc_md5_available() == ISC_FALSE) { + fprintf(stderr, "The use of RSAMD5 was disabled\n"); + if (freeit != NULL) + free(freeit); + return (1); } else { r.base = algname; r.length = strlen(algname); @@ -412,6 +418,9 @@ main(int argc, char **argv) { fatal("invalid type %s", type); } + if (alg == DST_ALG_RSAMD5 && isc_md5_available() == ISC_FALSE) + fatal("Key uses disabled RSAMD5"); + if (nametype == NULL) { if ((options & DST_TYPE_KEY) != 0) /* KEY */ fatal("no nametype specified"); diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index 97b96ee1dc..c147bb4e6c 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -548,9 +549,21 @@ main(int argc, char **argv) { "\"-a RSAMD5\"\n"); INSIST(freeit == NULL); return (1); - } else if (strcasecmp(algname, "HMAC-MD5") == 0) - alg = DST_ALG_HMACMD5; - else if (strcasecmp(algname, "HMAC-SHA1") == 0) + } else if (strcasecmp(algname, "HMAC-MD5") == 0) { + if (isc_md5_available()) { + alg = DST_ALG_HMACMD5; + } else { + fprintf(stderr, + "The use of HMAC-MD5 was disabled\n"); + INSIST(freeit == NULL); + return (1); + } + } else if (strcasecmp(algname, "RSAMD5") == 0 && + isc_md5_available() == ISC_FALSE) { + fprintf(stderr, "The use of RSAMD5 was disabled\n"); + INSIST(freeit == NULL); + return (1); + } else if (strcasecmp(algname, "HMAC-SHA1") == 0) alg = DST_ALG_HMACSHA1; else if (strcasecmp(algname, "HMAC-SHA224") == 0) alg = DST_ALG_HMACSHA224; diff --git a/bin/named/config.c b/bin/named/config.c index 818ed3797a..22d8a85405 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -828,6 +829,19 @@ ns_config_getkeyalgorithm(const char *str, dns_name_t **name, return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits)); } +static inline int +algorithms_start() { + if (isc_md5_available() == ISC_FALSE) { + int i = 0; + while (algorithms[i].str != NULL && + algorithms[i].hmac == hmacmd5) { + i++; + } + return i; + } + return 0; +} + isc_result_t ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, unsigned int *typep, isc_uint16_t *digestbits) @@ -837,7 +851,7 @@ ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, isc_uint16_t bits; isc_result_t result; - for (i = 0; algorithms[i].str != NULL; i++) { + for (i = algorithms_start(); algorithms[i].str != NULL; i++) { len = strlen(algorithms[i].str); if (strncasecmp(algorithms[i].str, str, len) == 0 && (str[len] == '\0' || @@ -859,7 +873,12 @@ ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, if (name != NULL) { switch (algorithms[i].hmac) { - case hmacmd5: *name = dns_tsig_hmacmd5_name; break; + case hmacmd5: + if (isc_md5_available()) { + *name = dns_tsig_hmacmd5_name; break; + } else { + return (ISC_R_NOTFOUND); + } case hmacsha1: *name = dns_tsig_hmacsha1_name; break; case hmacsha224: *name = dns_tsig_hmacsha224_name; break; case hmacsha256: *name = dns_tsig_hmacsha256_name; break; diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 644e3d9fc0..336597a95d 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -440,9 +441,10 @@ parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) { strncpy(buf, hmacstr, len); buf[len] = 0; - if (strcasecmp(buf, "hmac-md5") == 0) { + if (strcasecmp(buf, "hmac-md5") == 0 && isc_md5_available()) { *hmac = DNS_TSIG_HMACMD5_NAME; - } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { + } else if (strncasecmp(buf, "hmac-md5-", 9) == 0 && + isc_md5_available()) { *hmac = DNS_TSIG_HMACMD5_NAME; result = isc_parse_uint16(&digestbits, &buf[9], 10); if (result != ISC_R_SUCCESS || digestbits > 128) @@ -538,7 +540,9 @@ setup_keystr(void) { secretstr = n + 1; digestbits = parse_hmac(&hmacname, keystr, s - keystr); } else { - hmacname = DNS_TSIG_HMACMD5_NAME; + hmacname = DNS_TSIG_HMACSHA256_NAME; + if (isc_md5_available()) + hmacname = DNS_TSIG_HMACMD5_NAME; name = keystr; n = s; } @@ -670,7 +674,8 @@ setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { switch (dst_key_alg(dstkey)) { case DST_ALG_HMACMD5: - hmacname = DNS_TSIG_HMACMD5_NAME; + if (isc_md5_available()) + hmacname = DNS_TSIG_HMACMD5_NAME; break; case DST_ALG_HMACSHA1: hmacname = DNS_TSIG_HMACSHA1_NAME; @@ -1462,8 +1467,11 @@ evaluate_key(char *cmdline) { if (n != NULL) { digestbits = parse_hmac(&hmacname, namestr, n - namestr); namestr = n + 1; - } else - hmacname = DNS_TSIG_HMACMD5_NAME; + } else { + hmacname = DNS_TSIG_HMACSHA256_NAME; + if (isc_md5_available()) + hmacname = DNS_TSIG_HMACMD5_NAME; + } isc_buffer_init(&b, namestr, strlen(namestr)); isc_buffer_add(&b, strlen(namestr)); diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook index bbcc68110f..7d8e78f894 100644 --- a/bin/nsupdate/nsupdate.docbook +++ b/bin/nsupdate/nsupdate.docbook @@ -158,6 +158,9 @@ hmac:keyname:secret. keyname is the name of the key, and secret is the base64 encoded shared secret. + If hmac is not specified, + the default is hmac-md5 + or if MD5 was disabled hmac-sha256. Use of the option is discouraged because the shared secret is supplied as a command line argument in clear text. This may be visible in the output from @@ -371,13 +374,17 @@ key - name + hmac:name secret Specifies that all updates are to be TSIG-signed using the keyname keysecret pair. + If hmac is specified, then it sets the + signing algorithm in use; the default is + hmac-md5 or if MD5 was disabled + hmac-sha256. The key command overrides any key specified on the command line via or . diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 81e629f15c..0fd192d3a5 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -607,7 +608,7 @@ parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, secretstr = cfg_obj_asstring(secretobj); algorithmstr = cfg_obj_asstring(algorithmobj); - if (strcasecmp(algorithmstr, "hmac-md5") == 0) + if (strcasecmp(algorithmstr, "hmac-md5") == 0 && isc_md5_available()) algorithm = ISCCC_ALG_HMACMD5; else if (strcasecmp(algorithmstr, "hmac-sha1") == 0) algorithm = ISCCC_ALG_HMACSHA1; diff --git a/bin/tests/hashes/t_hashes.c b/bin/tests/hashes/t_hashes.c index 47d08c572d..965271ad67 100644 --- a/bin/tests/hashes/t_hashes.c +++ b/bin/tests/hashes/t_hashes.c @@ -353,8 +353,10 @@ t_hashes(IN *in, OUT *out_sha1, OUT *out_sha224, OUT *out_md5) t_hash("SHA1", (HASH_INIT)isc_sha1_init, (UPDATE)isc_sha1_update, (FINAL)isc_sha1_final, in, out_sha1); t_sha224(in, out_sha224); - t_hash("md5", (HASH_INIT)isc_md5_init, (UPDATE)isc_md5_update, - (FINAL)isc_md5_final, in, out_md5); + if (isc_md5_available()) { + t_hash("md5", (HASH_INIT)isc_md5_init, (UPDATE)isc_md5_update, + (FINAL)isc_md5_final, in, out_md5); + } } @@ -435,12 +437,14 @@ t1(void) t_hashes(&abc, &abc_sha1, &abc_sha224, &abc_md5); t_hashes(&abc_blah, &abc_blah_sha1, &abc_blah_sha224, &abc_blah_md5); - /* - * three HMAC-md5 examples from RFC 2104 - */ - t_md5hmac(&rfc2104_1, &rfc2104_1_hmac); - t_md5hmac(&rfc2104_2, &rfc2104_2_hmac); - t_md5hmac(&rfc2104_3, &rfc2104_3_hmac); + if (isc_md5_available()) { + /* + * three HMAC-md5 examples from RFC 2104 + */ + t_md5hmac(&rfc2104_1, &rfc2104_1_hmac); + t_md5hmac(&rfc2104_2, &rfc2104_2_hmac); + t_md5hmac(&rfc2104_3, &rfc2104_3_hmac); + } /* * four HMAC-SHA tests from RFC 4634 starting on page 86 diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 5131b521f4..00c4b3e509 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1895,6 +1896,13 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) { } algorithm = cfg_obj_asstring(algobj); + /* Skip hmac-md5* algorithms */ + if (isc_md5_available() == ISC_FALSE && + strncasecmp(algorithm, "hmac-md5", 8) == 0) { + cfg_obj_log(algobj, logctx, ISC_LOG_ERROR, + "disabled algorithm '%s'", algorithm); + return (ISC_R_DISABLED); + } for (i = 0; algorithms[i].name != NULL; i++) { len = strlen(algorithms[i].name); if (strncasecmp(algorithms[i].name, algorithm, len) == 0 && diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index e71f2026e5..e6375cf406 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -202,6 +202,12 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, dst_result_register(); memset(dst_t_func, 0, sizeof(dst_t_func)); + +#ifdef OPENSSL + RETERR(dst__openssl_init(engine)); +#elif PKCS11CRYPTO + RETERR(dst__pkcs11_init(mctx, engine)); +#endif RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5])); RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1])); RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224])); @@ -209,7 +215,6 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384])); RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512])); #ifdef OPENSSL - RETERR(dst__openssl_init(engine)); RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5], DST_ALG_RSAMD5)); RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1], @@ -233,12 +238,16 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); #endif #elif PKCS11CRYPTO - RETERR(dst__pkcs11_init(mctx, engine)); - RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5])); - RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1])); - RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1])); - RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256])); - RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512])); + RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5], + DST_ALG_RSAMD5)); + RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1], + DST_ALG_RSASHA1)); + RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1], + DST_ALG_NSEC3RSASHA1)); + RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256], + DST_ALG_RSASHA256)); + RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512], + DST_ALG_RSASHA512)); RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_DSA])); RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); RETERR(dst__pkcs11dh_init(&dst_t_func[DST_ALG_DH])); diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h index b15135e634..66d322a278 100644 --- a/lib/dns/dst_internal.h +++ b/lib/dns/dst_internal.h @@ -232,7 +232,8 @@ isc_result_t dst__hmacsha384_init(struct dst_func **funcp); isc_result_t dst__hmacsha512_init(struct dst_func **funcp); isc_result_t dst__opensslrsa_init(struct dst_func **funcp, unsigned char algorithm); -isc_result_t dst__pkcs11rsa_init(struct dst_func **funcp); +isc_result_t dst__pkcs11rsa_init(struct dst_func **funcp, + unsigned char algorithm); isc_result_t dst__openssldsa_init(struct dst_func **funcp); isc_result_t dst__pkcs11dsa_init(struct dst_func **funcp); isc_result_t dst__openssldh_init(struct dst_func **funcp); diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c index ec622d9603..0e889cc740 100644 --- a/lib/dns/dst_parse.c +++ b/lib/dns/dst_parse.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -353,6 +354,10 @@ check_data(const dst_private_t *priv, const unsigned int alg, /* XXXVIX this switch statement is too sparse to gen a jump table. */ switch (alg) { case DST_ALG_RSAMD5: + if (isc_md5_available()) + return (check_rsa(priv, external)); + else + return (DST_R_UNSUPPORTEDALG); case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: case DST_ALG_RSASHA256: @@ -369,7 +374,10 @@ check_data(const dst_private_t *priv, const unsigned int alg, case DST_ALG_ECDSA384: return (check_ecdsa(priv, external)); case DST_ALG_HMACMD5: - return (check_hmac_md5(priv, old)); + if (isc_md5_available()) + return (check_hmac_md5(priv, old)); + else + return (DST_R_UNSUPPORTEDALG); case DST_ALG_HMACSHA1: return (check_hmac_sha(priv, HMACSHA1_NTAGS, alg)); case DST_ALG_HMACSHA224: @@ -587,6 +595,8 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, goto fail; } + if (isc_md5_available() == ISC_FALSE && alg == DST_ALG_RSA) + alg = DST_ALG_RSASHA1; check = check_data(priv, alg, ISC_TRUE, external); if (check < 0) { ret = DST_R_INVALIDPRIVATEKEY; diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c index 3ac01a8c20..6b6801af1c 100644 --- a/lib/dns/hmac_link.c +++ b/lib/dns/hmac_link.c @@ -340,7 +340,7 @@ static dst_func_t hmacmd5_functions = { isc_result_t dst__hmacmd5_init(dst_func_t **funcp) { REQUIRE(funcp != NULL); - if (*funcp == NULL) + if (*funcp == NULL && isc_md5_available()) *funcp = &hmacmd5_functions; return (ISC_R_SUCCESS); } diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index 53c6d4bdd9..08291af016 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -1484,6 +1484,10 @@ dst__opensslrsa_init(dst_func_t **funcp, unsigned char algorithm) { if (*funcp == NULL) { switch (algorithm) { + case DST_ALG_RSAMD5: + if (isc_md5_available()) + *funcp = &opensslrsa_functions; + break; case DST_ALG_RSASHA256: #if defined(HAVE_EVP_SHA256) || !USE_EVP *funcp = &opensslrsa_functions; diff --git a/lib/dns/pkcs11rsa_link.c b/lib/dns/pkcs11rsa_link.c index 010d4b64fc..6b556bcd11 100644 --- a/lib/dns/pkcs11rsa_link.c +++ b/lib/dns/pkcs11rsa_link.c @@ -89,6 +89,9 @@ pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { key->key_alg == DST_ALG_RSASHA256 || key->key_alg == DST_ALG_RSASHA512); + if (key->key_alg == DST_ALG_RSAMD5 && isc_md5_available() == ISC_FALSE) + return (ISC_R_FAILURE); + rsa = key->keydata.pkey; pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, @@ -216,6 +219,8 @@ pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { switch (dctx->key->key_alg) { case DST_ALG_RSAMD5: + if (isc_md5_available() == ISC_FALSE) + return (ISC_R_FAILURE); mech.mechanism = CKM_MD5_RSA_PKCS; break; case DST_ALG_RSASHA1: @@ -297,6 +302,9 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits, key->key_alg == DST_ALG_RSASHA256 || key->key_alg == DST_ALG_RSASHA512); + if (key->key_alg == DST_ALG_RSAMD5 && isc_md5_available() == ISC_FALSE) + return (ISC_R_FAILURE); + rsa = key->keydata.pkey; pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, @@ -350,6 +358,8 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits, switch (dctx->key->key_alg) { case DST_ALG_RSAMD5: + if (isc_md5_available() == ISC_FALSE) + return (ISC_R_FAILURE); mech.mechanism = CKM_MD5_RSA_PKCS; break; case DST_ALG_RSASHA1: @@ -1565,11 +1575,20 @@ static dst_func_t pkcs11rsa_functions = { }; isc_result_t -dst__pkcs11rsa_init(dst_func_t **funcp) { +dst__pkcs11rsa_init(dst_func_t **funcp, unsigned char algorithm) { REQUIRE(funcp != NULL); - if (*funcp == NULL) - *funcp = &pkcs11rsa_functions; + if (*funcp == NULL) { + switch (algorithm) { + case DST_ALG_RSAMD5: + if (isc_md5_available()) + *funcp = &pkcs11rsa_functions; + break; + default: + *funcp = &pkcs11rsa_functions; + break; + } + } return (ISC_R_SUCCESS); } diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c index 091b3c70fb..c1251225d5 100644 --- a/lib/dns/rcode.c +++ b/lib/dns/rcode.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -310,17 +311,31 @@ dns_cert_totext(dns_cert_t cert, isc_buffer_t *target) { return (dns_mnemonic_totext(cert, target, certs)); } +static inline struct tbl * +secalgs_tbl_start() { + struct tbl *algs = secalgs; + + if (isc_md5_available() == ISC_FALSE) { + while (algs->name != NULL && + algs->value == DNS_KEYALG_RSAMD5) + ++algs; + } + return algs; +} + isc_result_t dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) { unsigned int value; - RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff)); + + RETERR(dns_mnemonic_fromtext(&value, source, + secalgs_tbl_start(), 0xff)); *secalgp = value; return (ISC_R_SUCCESS); } isc_result_t dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) { - return (dns_mnemonic_totext(secalg, target, secalgs)); + return (dns_mnemonic_totext(secalg, target, secalgs_tbl_start())); } void diff --git a/lib/dns/tests/tsig_test.c b/lib/dns/tests/tsig_test.c index 956e4a0469..c4b2f84837 100644 --- a/lib/dns/tests/tsig_test.c +++ b/lib/dns/tests/tsig_test.c @@ -10,6 +10,7 @@ #include #include +#include #include #include diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index 7343b4c26f..59a78c8dca 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -230,6 +230,9 @@ compute_secret(isc_buffer_t *shared, isc_region_t *queryrandomness, unsigned char digests[32]; unsigned int i; + if (isc_md5_available() == ISC_FALSE) + return (ISC_R_NOTIMPLEMENTED); + isc_buffer_usedregion(shared, &r); /* @@ -298,6 +301,12 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, return (DNS_R_REFUSED); } + if (isc_md5_available() == ISC_FALSE) { + tkey_log("process_dhtkey: MD5 was disabled"); + tkeyout->error = dns_tsigerror_badalg; + return (ISC_R_SUCCESS); + } + if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) { tkey_log("process_dhtkey: algorithms other than " "hmac-md5 are not supported"); diff --git a/lib/dns/tsec.c b/lib/dns/tsec.c index bfa6195d0d..fad645668c 100644 --- a/lib/dns/tsec.c +++ b/lib/dns/tsec.c @@ -18,6 +18,7 @@ #include +#include #include #include @@ -66,7 +67,12 @@ dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key, case dns_tsectype_tsig: switch (dst_key_alg(key)) { case DST_ALG_HMACMD5: - algname = dns_tsig_hmacmd5_name; + if (isc_md5_available()) { + algname = dns_tsig_hmacmd5_name; + } else { + isc_mem_put(mctx, tsec, sizeof(*tsec)); + return (DNS_R_BADALG); + } break; case DST_ALG_HMACSHA1: algname = dns_tsig_hmacsha1_name; diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 325c901f93..804ef821f0 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -316,7 +317,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, goto cleanup_key; (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); - if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { + if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && isc_md5_available()) { tkey->algorithm = DNS_TSIG_HMACMD5_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) { ret = DNS_R_BADALG; @@ -539,7 +540,7 @@ destroyring(dns_tsig_keyring_t *ring) { static unsigned int dst_alg_fromname(dns_name_t *algorithm) { - if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { + if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && isc_md5_available()) { return (DST_ALG_HMACMD5); } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { return (DST_ALG_HMACSHA1); @@ -724,7 +725,7 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, if (length > 0) REQUIRE(secret != NULL); - if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { + if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && isc_md5_available()) { if (secret != NULL) { isc_buffer_t b; @@ -1322,7 +1323,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, ret = dst_key_sigsize(key, &siglen); if (ret != ISC_R_SUCCESS) return (ret); - if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || + if ((alg == DST_ALG_HMACMD5 && isc_md5_available()) || + alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) { @@ -1484,9 +1486,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, } if ( -#ifndef PK11_MD5_DISABLE - alg == DST_ALG_HMACMD5 || -#endif + (alg == DST_ALG_HMACMD5 && isc_md5_available()) || alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) @@ -1626,9 +1626,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { if (ret != ISC_R_SUCCESS) goto cleanup_querystruct; if ( -#ifndef PK11_MD5_DISABLE - alg == DST_ALG_HMACMD5 || -#endif + (alg == DST_ALG_HMACMD5 && isc_md5_available()) || alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || @@ -1801,9 +1799,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { if (ret != ISC_R_SUCCESS) goto cleanup_context; if ( -#ifndef PK11_MD5_DISABLE - alg == DST_ALG_HMACMD5 || -#endif + (alg == DST_ALG_HMACMD5 && isc_md5_available()) || alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || diff --git a/lib/isc/include/isc/md5.h b/lib/isc/include/isc/md5.h index a2e00b382a..d4c2b8ab48 100644 --- a/lib/isc/include/isc/md5.h +++ b/lib/isc/include/isc/md5.h @@ -83,6 +83,9 @@ isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len); void isc_md5_final(isc_md5_t *ctx, unsigned char *digest); +isc_boolean_t +isc_md5_available(void); + ISC_LANG_ENDDECLS #endif /* ISC_MD5_H */ diff --git a/lib/isc/md5.c b/lib/isc/md5.c index 2e3cf9a4a3..a5113df4b8 100644 --- a/lib/isc/md5.c +++ b/lib/isc/md5.c @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -51,6 +52,9 @@ #ifdef ISC_PLATFORM_OPENSSLHASH +static isc_once_t available_once = ISC_ONCE_INIT; +static isc_boolean_t available = ISC_FALSE; + void isc_md5_init(isc_md5_t *ctx) { EVP_DigestInit(ctx, EVP_md5()); @@ -71,8 +75,33 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { EVP_DigestFinal(ctx, digest, NULL); } +static void +do_detect_available() { + isc_md5_t local; + isc_md5_t *ctx = &local; + unsigned char digest[ISC_MD5_DIGESTLENGTH]; + + ctx->ctx = EVP_MD_CTX_new(); + RUNTIME_CHECK(ctx->ctx != NULL); + available = ISC_TF(EVP_DigestInit(ctx->ctx, EVP_md5()) == 1); + if (available) + (void)EVP_DigestFinal(ctx->ctx, digest, NULL); + EVP_MD_CTX_free(ctx->ctx); + ctx->ctx = NULL; +} + +isc_boolean_t +isc_md5_available() { + RUNTIME_CHECK(isc_once_do(&available_once, do_detect_available) + == ISC_R_SUCCESS); + return available; +} + #elif PKCS11CRYPTO +static isc_once_t available_once = ISC_ONCE_INIT; +static isc_boolean_t available = ISC_FALSE; + void isc_md5_init(isc_md5_t *ctx) { CK_RV rv; @@ -115,6 +144,31 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { pk11_return_session(ctx); } +static void +do_detect_available() { + isc_md5_t local; + isc_md5_t *ctx = &local; + CK_RV rv; + CK_MECHANISM mech = { CKM_MD5, NULL, 0 }; + + if (pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, + ISC_FALSE, NULL, 0) == ISC_R_SUCCESS) + { + rv = pkcs_C_DigestInit(ctx->session, &mech); + isc_md5_invalidate(ctx); + available = (ISC_TF(rv == CKR_OK)); + } else { + available = ISC_FALSE; + } +} + +isc_boolean_t +isc_md5_available() { + RUNTIME_CHECK(isc_once_do(&available_once, do_detect_available) + == ISC_R_SUCCESS); + return available; +} + #else static void @@ -324,4 +378,9 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(isc_md5_t)); /* In case it's sensitive */ } + +isc_boolean_t +isc_md5_available() { + return ISC_TRUE; +} #endif diff --git a/lib/isc/pk11.c b/lib/isc/pk11.c index de4479b7b0..6cce70f0cf 100644 --- a/lib/isc/pk11.c +++ b/lib/isc/pk11.c @@ -139,6 +139,8 @@ #define PK11_NO_LOGERR 1 #endif +LIBISC_EXTERNAL_DATA isc_boolean_t pk11_verbose_init = ISC_FALSE; + static isc_once_t once = ISC_ONCE_INIT; static isc_mem_t *pk11_mctx = NULL; static isc_int32_t allocsize = 0; @@ -283,13 +285,12 @@ pk11_initialize(isc_mem_t *mctx, const char *engine) { LOCK(&alloclock); if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0)) isc_mem_attach(mctx, &pk11_mctx); + UNLOCK(&alloclock); + + LOCK(&sessionlock); if (initialized) { - UNLOCK(&alloclock); - return (ISC_R_SUCCESS); - } else { - LOCK(&sessionlock); - initialized = ISC_TRUE; - UNLOCK(&alloclock); + result = ISC_R_SUCCESS; + goto unlock; } ISC_LIST_INIT(tokens); @@ -327,6 +328,7 @@ pk11_initialize(isc_mem_t *mctx, const char *engine) { } #endif #endif /* PKCS11CRYPTO */ + initialized = ISC_TRUE; result = ISC_R_SUCCESS; unlock: UNLOCK(&sessionlock); @@ -363,9 +365,14 @@ pk11_finalize(void) { pk11_mem_put(token, sizeof(*token)); token = next; } + LOCK(&alloclock); if (pk11_mctx != NULL) isc_mem_detach(&pk11_mctx); + UNLOCK(&alloclock); + + LOCK(&sessionlock); initialized = ISC_FALSE; + UNLOCK(&sessionlock); return (ret); } @@ -655,6 +662,15 @@ token_login(pk11_session_t *sp) { return (ret); } +#define PK11_TRACE(fmt) \ + if (pk11_verbose_init) fprintf(stderr, fmt) +#define PK11_TRACE1(fmt, arg) \ + if (pk11_verbose_init) fprintf(stderr, fmt, arg) +#define PK11_TRACE2(fmt, arg1, arg2) \ + if (pk11_verbose_init) fprintf(stderr, fmt, arg1, arg2) +#define PK11_TRACEM(mech) \ + if (pk11_verbose_init) fprintf(stderr, #mech ": 0x%lx\n", rv) + static void choose_slots(void) { CK_MECHANISM_INFO mechInfo; @@ -665,6 +681,8 @@ choose_slots(void) { CK_ULONG slotCount; pk11_token_t *token; unsigned int i; + unsigned int best_rsa_algorithms = 0; + unsigned int best_digest_algorithms = 0; slotCount = 0; PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount)); @@ -676,6 +694,8 @@ choose_slots(void) { PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount)); for (i = 0; i < slotCount; i++) { + unsigned int rsa_algorithms = 0; + unsigned int digest_algorithms = 0; slot = slotList[i]; rv = pkcs_C_GetTokenInfo(slot, &tokenInfo); @@ -708,8 +728,11 @@ choose_slots(void) { &mechInfo); if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0) || - ((mechInfo.flags & CKF_VERIFY) == 0)) - goto try_dsa; + ((mechInfo.flags & CKF_VERIFY) == 0)) { + PK11_TRACEM(CKM_MD5_RSA_PKCS); + } + else + ++rsa_algorithms; rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS, &mechInfo); if ((rv != CKR_OK) || @@ -729,8 +752,14 @@ choose_slots(void) { ((mechInfo.flags & CKF_VERIFY) == 0)) goto try_dsa; token->operations |= 1 << OP_RSA; - if (best_rsa_token == NULL) + if (best_rsa_token == NULL) { best_rsa_token = token; + best_rsa_algorithms = rsa_algorithms; + } else if (rsa_algorithms > best_rsa_algorithms) { + pk11_mem_put(best_rsa_token, sizeof(*best_rsa_token)); + best_rsa_token = token; + best_rsa_algorithms = rsa_algorithms; + } try_dsa: rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_PARAMETER_GEN, @@ -773,8 +802,11 @@ choose_slots(void) { try_digest: rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5, &mechInfo); - if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) - continue; + if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) { + PK11_TRACEM(CKM_MD5); + } + else + ++digest_algorithms; rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1, &mechInfo); if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) continue; @@ -792,13 +824,15 @@ choose_slots(void) { continue; #ifdef PKCS11CRYPTOWITHHMAC rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_HMAC, &mechInfo); - if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) - continue; + if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) { + PK11_TRACEM(CKM_MD5_HMAC); + } + else + ++digest_algorithms; #endif rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1_HMAC, &mechInfo); if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) continue; - rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224_HMAC, &mechInfo); if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) continue; rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_HMAC, &mechInfo); @@ -811,8 +845,14 @@ choose_slots(void) { if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) continue; token->operations |= 1 << OP_DIGEST; - if (digest_token == NULL) - digest_token = token; + if (digest_token == NULL) { + digest_token = token; + best_digest_algorithms = digest_algorithms; + } else if (digest_algorithms > best_digest_algorithms) { + pk11_mem_put(digest_token, sizeof(*digest_token)); + digest_token = token; + best_digest_algorithms = digest_algorithms; + } /* ECDSA requires digest */ rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_KEY_PAIR_GEN, diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c index 9428374cc1..ca3cff27c9 100644 --- a/lib/isccc/cc.c +++ b/lib/isccc/cc.c @@ -254,11 +254,15 @@ sign(unsigned char *data, unsigned int length, unsigned char *hmac, switch (algorithm) { case ISCCC_ALG_HMACMD5: - isc_hmacmd5_init(&ctx.hmd5, secret->rstart, - REGION_SIZE(*secret)); - isc_hmacmd5_update(&ctx.hmd5, data, length); - isc_hmacmd5_sign(&ctx.hmd5, digest); - source.rend = digest + ISC_MD5_DIGESTLENGTH; + if (isc_md5_available()) { + isc_hmacmd5_init(&ctx.hmd5, secret->rstart, + REGION_SIZE(*secret)); + isc_hmacmd5_update(&ctx.hmd5, data, length); + isc_hmacmd5_sign(&ctx.hmd5, digest); + source.rend = digest + ISC_MD5_DIGESTLENGTH; + } else { + return (ISC_R_FAILURE); + } break; case ISCCC_ALG_HMACSHA1: @@ -329,14 +333,14 @@ isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target, { unsigned char *hmac_rstart, *signed_rstart; isc_result_t result; + const isc_boolean_t md5 = ISC_TF(algorithm == ISCCC_ALG_HMACMD5); - if (algorithm == ISCCC_ALG_HMACMD5) { - if (REGION_SIZE(*target) < 4 + sizeof(auth_hmd5)) - return (ISC_R_NOSPACE); - } else { - if (REGION_SIZE(*target) < 4 + sizeof(auth_hsha)) - return (ISC_R_NOSPACE); - } + if (md5 && isc_md5_available() == ISC_FALSE) + return (ISC_R_NOTIMPLEMENTED); + if (REGION_SIZE(*target) < 4 + ((md5) ? + sizeof(auth_hmd5) : + sizeof(auth_hsha))) + return (ISC_R_NOSPACE); /* * Emit protocol version. @@ -348,7 +352,7 @@ isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target, * We'll replace the zeros with the real signature once * we know what it is. */ - if (algorithm == ISCCC_ALG_HMACMD5) { + if (md5) { hmac_rstart = target->rstart + HMD5_OFFSET; PUT_MEM(auth_hmd5, sizeof(auth_hmd5), target->rstart); } else { @@ -404,7 +408,7 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, _auth = isccc_alist_lookup(alist, "_auth"); if (!isccc_alist_alistp(_auth)) return (ISC_R_FAILURE); - if (algorithm == ISCCC_ALG_HMACMD5) + if (algorithm == ISCCC_ALG_HMACMD5 && isc_md5_available()) hmac = isccc_alist_lookup(_auth, "hmd5"); else hmac = isccc_alist_lookup(_auth, "hsha"); @@ -417,12 +421,16 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, target.rstart = digestb64; switch (algorithm) { case ISCCC_ALG_HMACMD5: - isc_hmacmd5_init(&ctx.hmd5, secret->rstart, - REGION_SIZE(*secret)); - isc_hmacmd5_update(&ctx.hmd5, data, length); - isc_hmacmd5_sign(&ctx.hmd5, digest); - source.rend = digest + ISC_MD5_DIGESTLENGTH; - break; + if (isc_md5_available()) { + isc_hmacmd5_init(&ctx.hmd5, secret->rstart, + REGION_SIZE(*secret)); + isc_hmacmd5_update(&ctx.hmd5, data, length); + isc_hmacmd5_sign(&ctx.hmd5, digest); + source.rend = digest + ISC_MD5_DIGESTLENGTH; + break; + } else { + return (ISC_R_FAILURE); + } case ISCCC_ALG_HMACSHA1: isc_hmacsha1_init(&ctx.hsha, secret->rstart, -- 2.14.4