17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav * tsig.c
37b5038d7SDag-Erling Smørgrav *
47b5038d7SDag-Erling Smørgrav * contains the functions needed for TSIG [RFC2845]
57b5038d7SDag-Erling Smørgrav *
67b5038d7SDag-Erling Smørgrav * (c) 2005-2006 NLnet Labs
77b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license
87b5038d7SDag-Erling Smørgrav */
97b5038d7SDag-Erling Smørgrav
107b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
117b5038d7SDag-Erling Smørgrav
127b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
137b5038d7SDag-Erling Smørgrav
147b5038d7SDag-Erling Smørgrav #include <strings.h>
157b5038d7SDag-Erling Smørgrav
167b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
177b5038d7SDag-Erling Smørgrav #include <openssl/hmac.h>
187b5038d7SDag-Erling Smørgrav #include <openssl/md5.h>
197b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
207b5038d7SDag-Erling Smørgrav
21986ba33cSDag-Erling Smørgrav const char *
ldns_tsig_algorithm(const ldns_tsig_credentials * tc)22986ba33cSDag-Erling Smørgrav ldns_tsig_algorithm(const ldns_tsig_credentials *tc)
237b5038d7SDag-Erling Smørgrav {
247b5038d7SDag-Erling Smørgrav return tc->algorithm;
257b5038d7SDag-Erling Smørgrav }
267b5038d7SDag-Erling Smørgrav
27986ba33cSDag-Erling Smørgrav const char *
ldns_tsig_keyname(const ldns_tsig_credentials * tc)28986ba33cSDag-Erling Smørgrav ldns_tsig_keyname(const ldns_tsig_credentials *tc)
297b5038d7SDag-Erling Smørgrav {
307b5038d7SDag-Erling Smørgrav return tc->keyname;
317b5038d7SDag-Erling Smørgrav }
327b5038d7SDag-Erling Smørgrav
33986ba33cSDag-Erling Smørgrav const char *
ldns_tsig_keydata(const ldns_tsig_credentials * tc)34986ba33cSDag-Erling Smørgrav ldns_tsig_keydata(const ldns_tsig_credentials *tc)
357b5038d7SDag-Erling Smørgrav {
367b5038d7SDag-Erling Smørgrav return tc->keydata;
377b5038d7SDag-Erling Smørgrav }
387b5038d7SDag-Erling Smørgrav
397b5038d7SDag-Erling Smørgrav char *
ldns_tsig_keyname_clone(const ldns_tsig_credentials * tc)40986ba33cSDag-Erling Smørgrav ldns_tsig_keyname_clone(const ldns_tsig_credentials *tc)
417b5038d7SDag-Erling Smørgrav {
427b5038d7SDag-Erling Smørgrav return strdup(tc->keyname);
437b5038d7SDag-Erling Smørgrav }
447b5038d7SDag-Erling Smørgrav
457b5038d7SDag-Erling Smørgrav char *
ldns_tsig_keydata_clone(const ldns_tsig_credentials * tc)46986ba33cSDag-Erling Smørgrav ldns_tsig_keydata_clone(const ldns_tsig_credentials *tc)
477b5038d7SDag-Erling Smørgrav {
487b5038d7SDag-Erling Smørgrav return strdup(tc->keydata);
497b5038d7SDag-Erling Smørgrav }
507b5038d7SDag-Erling Smørgrav
517b5038d7SDag-Erling Smørgrav /*
527b5038d7SDag-Erling Smørgrav * Makes an exact copy of the wire, but with the tsig rr removed
537b5038d7SDag-Erling Smørgrav */
547b5038d7SDag-Erling Smørgrav static uint8_t *
ldns_tsig_prepare_pkt_wire(const uint8_t * wire,size_t wire_len,size_t * result_len)55986ba33cSDag-Erling Smørgrav ldns_tsig_prepare_pkt_wire(const uint8_t *wire, size_t wire_len, size_t *result_len)
567b5038d7SDag-Erling Smørgrav {
577b5038d7SDag-Erling Smørgrav uint8_t *wire2 = NULL;
587b5038d7SDag-Erling Smørgrav uint16_t qd_count;
597b5038d7SDag-Erling Smørgrav uint16_t an_count;
607b5038d7SDag-Erling Smørgrav uint16_t ns_count;
617b5038d7SDag-Erling Smørgrav uint16_t ar_count;
627b5038d7SDag-Erling Smørgrav ldns_rr *rr;
637b5038d7SDag-Erling Smørgrav
647b5038d7SDag-Erling Smørgrav size_t pos;
657b5038d7SDag-Erling Smørgrav uint16_t i;
667b5038d7SDag-Erling Smørgrav
677b5038d7SDag-Erling Smørgrav ldns_status status;
687b5038d7SDag-Erling Smørgrav
697b5038d7SDag-Erling Smørgrav if(wire_len < LDNS_HEADER_SIZE) {
707b5038d7SDag-Erling Smørgrav return NULL;
717b5038d7SDag-Erling Smørgrav }
727b5038d7SDag-Erling Smørgrav /* fake parse the wire */
737b5038d7SDag-Erling Smørgrav qd_count = LDNS_QDCOUNT(wire);
747b5038d7SDag-Erling Smørgrav an_count = LDNS_ANCOUNT(wire);
757b5038d7SDag-Erling Smørgrav ns_count = LDNS_NSCOUNT(wire);
767b5038d7SDag-Erling Smørgrav ar_count = LDNS_ARCOUNT(wire);
777b5038d7SDag-Erling Smørgrav
787b5038d7SDag-Erling Smørgrav if (ar_count > 0) {
797b5038d7SDag-Erling Smørgrav ar_count--;
807b5038d7SDag-Erling Smørgrav } else {
817b5038d7SDag-Erling Smørgrav return NULL;
827b5038d7SDag-Erling Smørgrav }
837b5038d7SDag-Erling Smørgrav
847b5038d7SDag-Erling Smørgrav pos = LDNS_HEADER_SIZE;
857b5038d7SDag-Erling Smørgrav
867b5038d7SDag-Erling Smørgrav for (i = 0; i < qd_count; i++) {
877b5038d7SDag-Erling Smørgrav status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION);
887b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
897b5038d7SDag-Erling Smørgrav return NULL;
907b5038d7SDag-Erling Smørgrav }
917b5038d7SDag-Erling Smørgrav ldns_rr_free(rr);
927b5038d7SDag-Erling Smørgrav }
937b5038d7SDag-Erling Smørgrav
947b5038d7SDag-Erling Smørgrav for (i = 0; i < an_count; i++) {
957b5038d7SDag-Erling Smørgrav status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER);
967b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
977b5038d7SDag-Erling Smørgrav return NULL;
987b5038d7SDag-Erling Smørgrav }
997b5038d7SDag-Erling Smørgrav ldns_rr_free(rr);
1007b5038d7SDag-Erling Smørgrav }
1017b5038d7SDag-Erling Smørgrav
1027b5038d7SDag-Erling Smørgrav for (i = 0; i < ns_count; i++) {
1037b5038d7SDag-Erling Smørgrav status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY);
1047b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
1057b5038d7SDag-Erling Smørgrav return NULL;
1067b5038d7SDag-Erling Smørgrav }
1077b5038d7SDag-Erling Smørgrav ldns_rr_free(rr);
1087b5038d7SDag-Erling Smørgrav }
1097b5038d7SDag-Erling Smørgrav
1107b5038d7SDag-Erling Smørgrav for (i = 0; i < ar_count; i++) {
1117b5038d7SDag-Erling Smørgrav status = ldns_wire2rr(&rr, wire, wire_len, &pos,
1127b5038d7SDag-Erling Smørgrav LDNS_SECTION_ADDITIONAL);
1137b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
1147b5038d7SDag-Erling Smørgrav return NULL;
1157b5038d7SDag-Erling Smørgrav }
1167b5038d7SDag-Erling Smørgrav ldns_rr_free(rr);
1177b5038d7SDag-Erling Smørgrav }
1187b5038d7SDag-Erling Smørgrav
1197b5038d7SDag-Erling Smørgrav *result_len = pos;
1207b5038d7SDag-Erling Smørgrav wire2 = LDNS_XMALLOC(uint8_t, *result_len);
1217b5038d7SDag-Erling Smørgrav if(!wire2) {
1227b5038d7SDag-Erling Smørgrav return NULL;
1237b5038d7SDag-Erling Smørgrav }
1247b5038d7SDag-Erling Smørgrav memcpy(wire2, wire, *result_len);
1257b5038d7SDag-Erling Smørgrav
1267b5038d7SDag-Erling Smørgrav ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count);
1277b5038d7SDag-Erling Smørgrav
1287b5038d7SDag-Erling Smørgrav return wire2;
1297b5038d7SDag-Erling Smørgrav }
1307b5038d7SDag-Erling Smørgrav
1317b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
1327b5038d7SDag-Erling Smørgrav static const EVP_MD *
ldns_digest_function(char * name)1337b5038d7SDag-Erling Smørgrav ldns_digest_function(char *name)
1347b5038d7SDag-Erling Smørgrav {
1357b5038d7SDag-Erling Smørgrav /* these are the mandatory algorithms from RFC4635 */
1367b5038d7SDag-Erling Smørgrav /* The optional algorithms are not yet implemented */
137986ba33cSDag-Erling Smørgrav if (strcasecmp(name, "hmac-sha512.") == 0) {
138986ba33cSDag-Erling Smørgrav #ifdef HAVE_EVP_SHA512
139986ba33cSDag-Erling Smørgrav return EVP_sha512();
140986ba33cSDag-Erling Smørgrav #else
141986ba33cSDag-Erling Smørgrav return NULL;
142986ba33cSDag-Erling Smørgrav #endif
143986ba33cSDag-Erling Smørgrav } else if (strcasecmp(name, "hmac-shac384.") == 0) {
144986ba33cSDag-Erling Smørgrav #ifdef HAVE_EVP_SHA384
145986ba33cSDag-Erling Smørgrav return EVP_sha384();
146986ba33cSDag-Erling Smørgrav #else
147986ba33cSDag-Erling Smørgrav return NULL;
148986ba33cSDag-Erling Smørgrav #endif
149986ba33cSDag-Erling Smørgrav } else if (strcasecmp(name, "hmac-sha256.") == 0) {
1507b5038d7SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256
1517b5038d7SDag-Erling Smørgrav return EVP_sha256();
1527b5038d7SDag-Erling Smørgrav #else
1537b5038d7SDag-Erling Smørgrav return NULL;
1547b5038d7SDag-Erling Smørgrav #endif
15517d15b25SDag-Erling Smørgrav } else if (strcasecmp(name, "hmac-sha1.") == 0) {
1567b5038d7SDag-Erling Smørgrav return EVP_sha1();
15717d15b25SDag-Erling Smørgrav } else if (strcasecmp(name, "hmac-md5.sig-alg.reg.int.") == 0) {
1587b5038d7SDag-Erling Smørgrav return EVP_md5();
1597b5038d7SDag-Erling Smørgrav } else {
1607b5038d7SDag-Erling Smørgrav return NULL;
1617b5038d7SDag-Erling Smørgrav }
1627b5038d7SDag-Erling Smørgrav }
1637b5038d7SDag-Erling Smørgrav #endif
1647b5038d7SDag-Erling Smørgrav
1657b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
1667b5038d7SDag-Erling Smørgrav static ldns_status
ldns_tsig_mac_new(ldns_rdf ** tsig_mac,const uint8_t * pkt_wire,size_t pkt_wire_size,const char * key_data,const ldns_rdf * key_name_rdf,const ldns_rdf * fudge_rdf,const ldns_rdf * algorithm_rdf,const ldns_rdf * time_signed_rdf,const ldns_rdf * error_rdf,const ldns_rdf * other_data_rdf,const ldns_rdf * orig_mac_rdf,int tsig_timers_only)167986ba33cSDag-Erling Smørgrav ldns_tsig_mac_new(ldns_rdf **tsig_mac, const uint8_t *pkt_wire, size_t pkt_wire_size,
168986ba33cSDag-Erling Smørgrav const char *key_data, const ldns_rdf *key_name_rdf, const ldns_rdf *fudge_rdf,
169986ba33cSDag-Erling Smørgrav const ldns_rdf *algorithm_rdf, const ldns_rdf *time_signed_rdf, const ldns_rdf *error_rdf,
170986ba33cSDag-Erling Smørgrav const ldns_rdf *other_data_rdf, const ldns_rdf *orig_mac_rdf, int tsig_timers_only)
1717b5038d7SDag-Erling Smørgrav {
1727b5038d7SDag-Erling Smørgrav ldns_status status;
1737b5038d7SDag-Erling Smørgrav char *wireformat;
1747b5038d7SDag-Erling Smørgrav int wiresize;
1757b5038d7SDag-Erling Smørgrav unsigned char *mac_bytes = NULL;
1767b5038d7SDag-Erling Smørgrav unsigned char *key_bytes = NULL;
1777b5038d7SDag-Erling Smørgrav int key_size;
1787b5038d7SDag-Erling Smørgrav const EVP_MD *digester;
1797b5038d7SDag-Erling Smørgrav char *algorithm_name = NULL;
1807b5038d7SDag-Erling Smørgrav unsigned int md_len = EVP_MAX_MD_SIZE;
1817b5038d7SDag-Erling Smørgrav ldns_rdf *result = NULL;
1827b5038d7SDag-Erling Smørgrav ldns_buffer *data_buffer = NULL;
1837b5038d7SDag-Erling Smørgrav ldns_rdf *canonical_key_name_rdf = NULL;
1847b5038d7SDag-Erling Smørgrav ldns_rdf *canonical_algorithm_rdf = NULL;
1857b5038d7SDag-Erling Smørgrav
1867b5038d7SDag-Erling Smørgrav if (key_name_rdf == NULL || algorithm_rdf == NULL) {
1877b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NULL;
1887b5038d7SDag-Erling Smørgrav }
1897b5038d7SDag-Erling Smørgrav canonical_key_name_rdf = ldns_rdf_clone(key_name_rdf);
1902787e39aSDag-Erling Smørgrav if (canonical_key_name_rdf == NULL) {
1912787e39aSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1922787e39aSDag-Erling Smørgrav }
1937b5038d7SDag-Erling Smørgrav canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf);
1942787e39aSDag-Erling Smørgrav if (canonical_algorithm_rdf == NULL) {
1952787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(canonical_key_name_rdf);
1967b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1977b5038d7SDag-Erling Smørgrav }
1987b5038d7SDag-Erling Smørgrav /*
199*5afab0e5SDag-Erling Smørgrav * prepare the digestible information
2007b5038d7SDag-Erling Smørgrav */
2017b5038d7SDag-Erling Smørgrav data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2027b5038d7SDag-Erling Smørgrav if (!data_buffer) {
2037b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
2047b5038d7SDag-Erling Smørgrav goto clean;
2057b5038d7SDag-Erling Smørgrav }
2067b5038d7SDag-Erling Smørgrav /* if orig_mac is not NULL, add it too */
2077b5038d7SDag-Erling Smørgrav if (orig_mac_rdf) {
2087b5038d7SDag-Erling Smørgrav (void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf);
2097b5038d7SDag-Erling Smørgrav }
2107b5038d7SDag-Erling Smørgrav ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size);
2117b5038d7SDag-Erling Smørgrav if (!tsig_timers_only) {
2127b5038d7SDag-Erling Smørgrav ldns_dname2canonical(canonical_key_name_rdf);
2137b5038d7SDag-Erling Smørgrav (void)ldns_rdf2buffer_wire(data_buffer,
2147b5038d7SDag-Erling Smørgrav canonical_key_name_rdf);
2157b5038d7SDag-Erling Smørgrav ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY);
2167b5038d7SDag-Erling Smørgrav ldns_buffer_write_u32(data_buffer, 0);
2177b5038d7SDag-Erling Smørgrav ldns_dname2canonical(canonical_algorithm_rdf);
2187b5038d7SDag-Erling Smørgrav (void)ldns_rdf2buffer_wire(data_buffer,
2197b5038d7SDag-Erling Smørgrav canonical_algorithm_rdf);
2207b5038d7SDag-Erling Smørgrav }
2217b5038d7SDag-Erling Smørgrav (void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf);
2227b5038d7SDag-Erling Smørgrav (void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf);
2237b5038d7SDag-Erling Smørgrav if (!tsig_timers_only) {
2247b5038d7SDag-Erling Smørgrav (void)ldns_rdf2buffer_wire(data_buffer, error_rdf);
2257b5038d7SDag-Erling Smørgrav (void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf);
2267b5038d7SDag-Erling Smørgrav }
2277b5038d7SDag-Erling Smørgrav
2287b5038d7SDag-Erling Smørgrav wireformat = (char *) data_buffer->_data;
2297b5038d7SDag-Erling Smørgrav wiresize = (int) ldns_buffer_position(data_buffer);
2307b5038d7SDag-Erling Smørgrav
2317b5038d7SDag-Erling Smørgrav algorithm_name = ldns_rdf2str(algorithm_rdf);
2327b5038d7SDag-Erling Smørgrav if(!algorithm_name) {
2337b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
2347b5038d7SDag-Erling Smørgrav goto clean;
2357b5038d7SDag-Erling Smørgrav }
2367b5038d7SDag-Erling Smørgrav
2377b5038d7SDag-Erling Smørgrav /* prepare the key */
2387b5038d7SDag-Erling Smørgrav key_bytes = LDNS_XMALLOC(unsigned char,
2397b5038d7SDag-Erling Smørgrav ldns_b64_pton_calculate_size(strlen(key_data)));
2407b5038d7SDag-Erling Smørgrav if(!key_bytes) {
2417b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
2427b5038d7SDag-Erling Smørgrav goto clean;
2437b5038d7SDag-Erling Smørgrav }
2447b5038d7SDag-Erling Smørgrav key_size = ldns_b64_pton(key_data, key_bytes,
2457b5038d7SDag-Erling Smørgrav ldns_b64_pton_calculate_size(strlen(key_data)));
2467b5038d7SDag-Erling Smørgrav if (key_size < 0) {
2477b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_INVALID_B64;
2487b5038d7SDag-Erling Smørgrav goto clean;
2497b5038d7SDag-Erling Smørgrav }
2507b5038d7SDag-Erling Smørgrav /* hmac it */
2517b5038d7SDag-Erling Smørgrav /* 2 spare bytes for the length */
2527b5038d7SDag-Erling Smørgrav mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2);
2537b5038d7SDag-Erling Smørgrav if(!mac_bytes) {
2547b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
2557b5038d7SDag-Erling Smørgrav goto clean;
2567b5038d7SDag-Erling Smørgrav }
2577b5038d7SDag-Erling Smørgrav memset(mac_bytes, 0, md_len+2);
2587b5038d7SDag-Erling Smørgrav
2597b5038d7SDag-Erling Smørgrav digester = ldns_digest_function(algorithm_name);
2607b5038d7SDag-Erling Smørgrav
2617b5038d7SDag-Erling Smørgrav if (digester) {
2627b5038d7SDag-Erling Smørgrav (void) HMAC(digester, key_bytes, key_size, (void *)wireformat,
2637b5038d7SDag-Erling Smørgrav (size_t) wiresize, mac_bytes + 2, &md_len);
2647b5038d7SDag-Erling Smørgrav
2657b5038d7SDag-Erling Smørgrav ldns_write_uint16(mac_bytes, md_len);
2667b5038d7SDag-Erling Smørgrav result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2,
2677b5038d7SDag-Erling Smørgrav mac_bytes);
2687b5038d7SDag-Erling Smørgrav } else {
2697b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2707b5038d7SDag-Erling Smørgrav goto clean;
2717b5038d7SDag-Erling Smørgrav }
2727b5038d7SDag-Erling Smørgrav *tsig_mac = result;
2737b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_OK;
2747b5038d7SDag-Erling Smørgrav clean:
2757b5038d7SDag-Erling Smørgrav LDNS_FREE(mac_bytes);
2767b5038d7SDag-Erling Smørgrav LDNS_FREE(key_bytes);
2777b5038d7SDag-Erling Smørgrav LDNS_FREE(algorithm_name);
2787b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buffer);
2792787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(canonical_algorithm_rdf);
2802787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(canonical_key_name_rdf);
2817b5038d7SDag-Erling Smørgrav return status;
2827b5038d7SDag-Erling Smørgrav }
2837b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
2847b5038d7SDag-Erling Smørgrav
2857b5038d7SDag-Erling Smørgrav
2867b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
2877b5038d7SDag-Erling Smørgrav bool
ldns_pkt_tsig_verify(ldns_pkt * pkt,const uint8_t * wire,size_t wirelen,const char * key_name,const char * key_data,const ldns_rdf * orig_mac_rdf)288986ba33cSDag-Erling Smørgrav ldns_pkt_tsig_verify(ldns_pkt *pkt, const uint8_t *wire, size_t wirelen, const char *key_name,
289986ba33cSDag-Erling Smørgrav const char *key_data, const ldns_rdf *orig_mac_rdf)
2907b5038d7SDag-Erling Smørgrav {
2917b5038d7SDag-Erling Smørgrav return ldns_pkt_tsig_verify_next(pkt, wire, wirelen, key_name, key_data, orig_mac_rdf, 0);
2927b5038d7SDag-Erling Smørgrav }
2937b5038d7SDag-Erling Smørgrav
2947b5038d7SDag-Erling Smørgrav bool
ldns_pkt_tsig_verify_next(ldns_pkt * pkt,const uint8_t * wire,size_t wirelen,const char * key_name,const char * key_data,const ldns_rdf * orig_mac_rdf,int tsig_timers_only)295986ba33cSDag-Erling Smørgrav ldns_pkt_tsig_verify_next(ldns_pkt *pkt, const uint8_t *wire, size_t wirelen, const char* key_name,
296986ba33cSDag-Erling Smørgrav const char *key_data, const ldns_rdf *orig_mac_rdf, int tsig_timers_only)
2977b5038d7SDag-Erling Smørgrav {
2987b5038d7SDag-Erling Smørgrav ldns_rdf *fudge_rdf;
2997b5038d7SDag-Erling Smørgrav ldns_rdf *algorithm_rdf;
3007b5038d7SDag-Erling Smørgrav ldns_rdf *time_signed_rdf;
3017b5038d7SDag-Erling Smørgrav ldns_rdf *orig_id_rdf;
3027b5038d7SDag-Erling Smørgrav ldns_rdf *error_rdf;
3037b5038d7SDag-Erling Smørgrav ldns_rdf *other_data_rdf;
3047b5038d7SDag-Erling Smørgrav ldns_rdf *pkt_mac_rdf;
3057b5038d7SDag-Erling Smørgrav ldns_rdf *my_mac_rdf;
3067b5038d7SDag-Erling Smørgrav ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
3077b5038d7SDag-Erling Smørgrav uint16_t pkt_id, orig_pkt_id;
3087b5038d7SDag-Erling Smørgrav ldns_status status;
3097b5038d7SDag-Erling Smørgrav
3107b5038d7SDag-Erling Smørgrav uint8_t *prepared_wire = NULL;
3117b5038d7SDag-Erling Smørgrav size_t prepared_wire_size = 0;
3127b5038d7SDag-Erling Smørgrav
3137b5038d7SDag-Erling Smørgrav ldns_rr *orig_tsig = ldns_pkt_tsig(pkt);
3147b5038d7SDag-Erling Smørgrav
3157b5038d7SDag-Erling Smørgrav if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) {
3167b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(key_name_rdf);
3177b5038d7SDag-Erling Smørgrav return false;
3187b5038d7SDag-Erling Smørgrav }
3197b5038d7SDag-Erling Smørgrav algorithm_rdf = ldns_rr_rdf(orig_tsig, 0);
3207b5038d7SDag-Erling Smørgrav time_signed_rdf = ldns_rr_rdf(orig_tsig, 1);
3217b5038d7SDag-Erling Smørgrav fudge_rdf = ldns_rr_rdf(orig_tsig, 2);
3227b5038d7SDag-Erling Smørgrav pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3);
3237b5038d7SDag-Erling Smørgrav orig_id_rdf = ldns_rr_rdf(orig_tsig, 4);
3247b5038d7SDag-Erling Smørgrav error_rdf = ldns_rr_rdf(orig_tsig, 5);
3257b5038d7SDag-Erling Smørgrav other_data_rdf = ldns_rr_rdf(orig_tsig, 6);
3267b5038d7SDag-Erling Smørgrav
3277b5038d7SDag-Erling Smørgrav /* remove temporarily */
3287b5038d7SDag-Erling Smørgrav ldns_pkt_set_tsig(pkt, NULL);
3297b5038d7SDag-Erling Smørgrav /* temporarily change the id to the original id */
3307b5038d7SDag-Erling Smørgrav pkt_id = ldns_pkt_id(pkt);
3317b5038d7SDag-Erling Smørgrav orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf);
3327b5038d7SDag-Erling Smørgrav ldns_pkt_set_id(pkt, orig_pkt_id);
3337b5038d7SDag-Erling Smørgrav
3347b5038d7SDag-Erling Smørgrav prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size);
3357b5038d7SDag-Erling Smørgrav
3367b5038d7SDag-Erling Smørgrav status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size,
3377b5038d7SDag-Erling Smørgrav key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
3387b5038d7SDag-Erling Smørgrav time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only);
3397b5038d7SDag-Erling Smørgrav
3407b5038d7SDag-Erling Smørgrav LDNS_FREE(prepared_wire);
3417b5038d7SDag-Erling Smørgrav
3427b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
3437b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(key_name_rdf);
3447b5038d7SDag-Erling Smørgrav return false;
3457b5038d7SDag-Erling Smørgrav }
3467b5038d7SDag-Erling Smørgrav /* Put back the values */
3477b5038d7SDag-Erling Smørgrav ldns_pkt_set_tsig(pkt, orig_tsig);
3487b5038d7SDag-Erling Smørgrav ldns_pkt_set_id(pkt, pkt_id);
3497b5038d7SDag-Erling Smørgrav
3507b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(key_name_rdf);
3517b5038d7SDag-Erling Smørgrav
352*5afab0e5SDag-Erling Smørgrav if( ldns_rdf_size(pkt_mac_rdf) != ldns_rdf_size(my_mac_rdf)) {
353*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(my_mac_rdf);
354*5afab0e5SDag-Erling Smørgrav return false;
355*5afab0e5SDag-Erling Smørgrav }
356*5afab0e5SDag-Erling Smørgrav /* use time insensitive memory compare */
357*5afab0e5SDag-Erling Smørgrav if(
358*5afab0e5SDag-Erling Smørgrav #ifdef HAVE_CRYPTO_MEMCMP
359*5afab0e5SDag-Erling Smørgrav CRYPTO_memcmp
360*5afab0e5SDag-Erling Smørgrav #else
361*5afab0e5SDag-Erling Smørgrav memcmp
362*5afab0e5SDag-Erling Smørgrav #endif
363*5afab0e5SDag-Erling Smørgrav (ldns_rdf_data(pkt_mac_rdf), ldns_rdf_data(my_mac_rdf),
364*5afab0e5SDag-Erling Smørgrav ldns_rdf_size(my_mac_rdf)) == 0) {
3657b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(my_mac_rdf);
3667b5038d7SDag-Erling Smørgrav return true;
3677b5038d7SDag-Erling Smørgrav } else {
3687b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(my_mac_rdf);
3697b5038d7SDag-Erling Smørgrav return false;
3707b5038d7SDag-Erling Smørgrav }
3717b5038d7SDag-Erling Smørgrav }
3727b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
3737b5038d7SDag-Erling Smørgrav
3747b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
3757b5038d7SDag-Erling Smørgrav ldns_status
ldns_pkt_tsig_sign(ldns_pkt * pkt,const char * key_name,const char * key_data,uint16_t fudge,const char * algorithm_name,const ldns_rdf * query_mac)3767b5038d7SDag-Erling Smørgrav ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data,
377986ba33cSDag-Erling Smørgrav uint16_t fudge, const char *algorithm_name, const ldns_rdf *query_mac)
3787b5038d7SDag-Erling Smørgrav {
3797b5038d7SDag-Erling Smørgrav return ldns_pkt_tsig_sign_next(pkt, key_name, key_data, fudge, algorithm_name, query_mac, 0);
3807b5038d7SDag-Erling Smørgrav }
3817b5038d7SDag-Erling Smørgrav
3827b5038d7SDag-Erling Smørgrav ldns_status
ldns_pkt_tsig_sign_next(ldns_pkt * pkt,const char * key_name,const char * key_data,uint16_t fudge,const char * algorithm_name,const ldns_rdf * query_mac,int tsig_timers_only)3837b5038d7SDag-Erling Smørgrav ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data,
384986ba33cSDag-Erling Smørgrav uint16_t fudge, const char *algorithm_name, const ldns_rdf *query_mac, int tsig_timers_only)
3857b5038d7SDag-Erling Smørgrav {
3867b5038d7SDag-Erling Smørgrav ldns_rr *tsig_rr;
3877b5038d7SDag-Erling Smørgrav ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
3887b5038d7SDag-Erling Smørgrav ldns_rdf *fudge_rdf = NULL;
3897b5038d7SDag-Erling Smørgrav ldns_rdf *orig_id_rdf = NULL;
3907b5038d7SDag-Erling Smørgrav ldns_rdf *algorithm_rdf;
3917b5038d7SDag-Erling Smørgrav ldns_rdf *error_rdf = NULL;
3927b5038d7SDag-Erling Smørgrav ldns_rdf *mac_rdf = NULL;
3937b5038d7SDag-Erling Smørgrav ldns_rdf *other_data_rdf = NULL;
3947b5038d7SDag-Erling Smørgrav
3957b5038d7SDag-Erling Smørgrav ldns_status status = LDNS_STATUS_OK;
3967b5038d7SDag-Erling Smørgrav
3977b5038d7SDag-Erling Smørgrav uint8_t *pkt_wire = NULL;
3987b5038d7SDag-Erling Smørgrav size_t pkt_wire_len;
3997b5038d7SDag-Erling Smørgrav
4007b5038d7SDag-Erling Smørgrav struct timeval tv_time_signed;
4017b5038d7SDag-Erling Smørgrav uint8_t *time_signed = NULL;
4027b5038d7SDag-Erling Smørgrav ldns_rdf *time_signed_rdf = NULL;
4037b5038d7SDag-Erling Smørgrav
4047b5038d7SDag-Erling Smørgrav algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name);
4057b5038d7SDag-Erling Smørgrav if(!key_name_rdf || !algorithm_rdf) {
4067b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
4077b5038d7SDag-Erling Smørgrav goto clean;
4087b5038d7SDag-Erling Smørgrav }
4097b5038d7SDag-Erling Smørgrav
4107b5038d7SDag-Erling Smørgrav /* eww don't have create tsigtime rdf yet :( */
4117b5038d7SDag-Erling Smørgrav /* bleh :p */
4127b5038d7SDag-Erling Smørgrav if (gettimeofday(&tv_time_signed, NULL) == 0) {
4137b5038d7SDag-Erling Smørgrav time_signed = LDNS_XMALLOC(uint8_t, 6);
4147b5038d7SDag-Erling Smørgrav if(!time_signed) {
4157b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
4167b5038d7SDag-Erling Smørgrav goto clean;
4177b5038d7SDag-Erling Smørgrav }
4187b5038d7SDag-Erling Smørgrav ldns_write_uint64_as_uint48(time_signed,
4197b5038d7SDag-Erling Smørgrav (uint64_t)tv_time_signed.tv_sec);
4207b5038d7SDag-Erling Smørgrav } else {
4217b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_INTERNAL_ERR;
4227b5038d7SDag-Erling Smørgrav goto clean;
4237b5038d7SDag-Erling Smørgrav }
4247b5038d7SDag-Erling Smørgrav
4257b5038d7SDag-Erling Smørgrav time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed);
4267b5038d7SDag-Erling Smørgrav if(!time_signed_rdf) {
4277b5038d7SDag-Erling Smørgrav LDNS_FREE(time_signed);
4287b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
4297b5038d7SDag-Erling Smørgrav goto clean;
4307b5038d7SDag-Erling Smørgrav }
4317b5038d7SDag-Erling Smørgrav
4327b5038d7SDag-Erling Smørgrav fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge);
4337b5038d7SDag-Erling Smørgrav
4347b5038d7SDag-Erling Smørgrav orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt));
4357b5038d7SDag-Erling Smørgrav
4367b5038d7SDag-Erling Smørgrav error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0);
4377b5038d7SDag-Erling Smørgrav
4387b5038d7SDag-Erling Smørgrav other_data_rdf = ldns_native2rdf_int16_data(0, NULL);
4397b5038d7SDag-Erling Smørgrav
4407b5038d7SDag-Erling Smørgrav if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) {
4417b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
4427b5038d7SDag-Erling Smørgrav goto clean;
4437b5038d7SDag-Erling Smørgrav }
4447b5038d7SDag-Erling Smørgrav
4457b5038d7SDag-Erling Smørgrav if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) {
4467b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_ERR;
4477b5038d7SDag-Erling Smørgrav goto clean;
4487b5038d7SDag-Erling Smørgrav }
4497b5038d7SDag-Erling Smørgrav
4507b5038d7SDag-Erling Smørgrav status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len,
4517b5038d7SDag-Erling Smørgrav key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
4527b5038d7SDag-Erling Smørgrav time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only);
4537b5038d7SDag-Erling Smørgrav
4547b5038d7SDag-Erling Smørgrav if (!mac_rdf) {
4557b5038d7SDag-Erling Smørgrav goto clean;
4567b5038d7SDag-Erling Smørgrav }
4577b5038d7SDag-Erling Smørgrav
4587b5038d7SDag-Erling Smørgrav LDNS_FREE(pkt_wire);
4597b5038d7SDag-Erling Smørgrav
4607b5038d7SDag-Erling Smørgrav /* Create the TSIG RR */
4617b5038d7SDag-Erling Smørgrav tsig_rr = ldns_rr_new();
4627b5038d7SDag-Erling Smørgrav if(!tsig_rr) {
4637b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
4647b5038d7SDag-Erling Smørgrav goto clean;
4657b5038d7SDag-Erling Smørgrav }
4667b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(tsig_rr, key_name_rdf);
4677b5038d7SDag-Erling Smørgrav ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY);
4687b5038d7SDag-Erling Smørgrav ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG);
4697b5038d7SDag-Erling Smørgrav ldns_rr_set_ttl(tsig_rr, 0);
4707b5038d7SDag-Erling Smørgrav
4717b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(tsig_rr, algorithm_rdf);
4727b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(tsig_rr, time_signed_rdf);
4737b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(tsig_rr, fudge_rdf);
4747b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(tsig_rr, mac_rdf);
4757b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(tsig_rr, orig_id_rdf);
4767b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(tsig_rr, error_rdf);
4777b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(tsig_rr, other_data_rdf);
4787b5038d7SDag-Erling Smørgrav
4797b5038d7SDag-Erling Smørgrav ldns_pkt_set_tsig(pkt, tsig_rr);
4807b5038d7SDag-Erling Smørgrav
4817b5038d7SDag-Erling Smørgrav return status;
4827b5038d7SDag-Erling Smørgrav
4837b5038d7SDag-Erling Smørgrav clean:
4847b5038d7SDag-Erling Smørgrav LDNS_FREE(pkt_wire);
4857b5038d7SDag-Erling Smørgrav ldns_rdf_free(key_name_rdf);
4867b5038d7SDag-Erling Smørgrav ldns_rdf_free(algorithm_rdf);
4877b5038d7SDag-Erling Smørgrav ldns_rdf_free(time_signed_rdf);
4887b5038d7SDag-Erling Smørgrav ldns_rdf_free(fudge_rdf);
4897b5038d7SDag-Erling Smørgrav ldns_rdf_free(orig_id_rdf);
4907b5038d7SDag-Erling Smørgrav ldns_rdf_free(error_rdf);
4917b5038d7SDag-Erling Smørgrav ldns_rdf_free(other_data_rdf);
4927b5038d7SDag-Erling Smørgrav return status;
4937b5038d7SDag-Erling Smørgrav }
4947b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
495