stl_string calc_mac (DnsRR &tsig_rr, message_buff msg, stl_string sign_key, message_buff *extra) { struct hmac_md5_ctx md5; unsigned char md5res [MD5_DIGEST_SIZE]; memset (&md5, 0, sizeof (hmac_md5_ctx)); unsigned char *digestpos = rr_getdata (tsig_rr.RDATA, DNS_TYPE_TSIG, 3); uint16_t digestlen = uint16_value (digestpos); // print_buff (sign_key.size(), (unsigned char*)sign_key.c_str()); hmac_md5_set_key(&md5, sign_key.size(), (uint8_t *)sign_key.c_str()); // printf ("Begin MAC calculation\n"); /* original MAC */ if (extra && extra->len) hmac_md5_update(&md5, extra->len, extra->msg); /* message */ hmac_md5_update(&md5, 10, msg.msg); hmac_md5_update(&md5, 2, uint16_buff (uint16_value (msg.msg + 10) - 1)); hmac_md5_update(&md5, msg.len - 12, msg.msg + 12); /* tsig rr */ stl_string canname = tsig_rr.NAME.canonical(); hmac_md5_update(&md5, canname.size(), (const uint8_t *)canname.c_str()); hmac_md5_update(&md5, 2, uint16_buff (QCLASS_ANY)); hmac_md5_update(&md5, 4, uint32_buff (0)); /* start of TSIG rrdata */ domainname dom = domainname (true, tsig_rr.RDATA); canname = dom.canonical(); hmac_md5_update (&md5, canname.size(), (const uint8_t*)canname.c_str()); hmac_md5_update(&md5, 8, digestpos - 8); /* rest, excluding original ID */ hmac_md5_update(&md5, tsig_rr.RDLENGTH - (digestpos - tsig_rr.RDATA) - digestlen - 4, digestpos + digestlen + 4); hmac_md5_digest(&md5, MD5_DIGEST_SIZE, md5res); // printf ("End MAC calculation\n"); // print_buff (MD5_DIGEST_SIZE, md5res); stl_string ret; ret.append ((char*)md5res, MD5_DIGEST_SIZE); return ret; }
term_t cbif_md5_mac_n3(proc_t *proc, term_t *regs) { term_t Key = regs[0]; term_t Data = regs[1]; term_t Size = regs[2]; if (!is_list(Key) && !is_boxed_binary(Key)) badarg(Key); if (!is_list(Data) && !is_boxed_binary(Data)) badarg(Data); if (!is_int(Size)) badarg(Size); int trunc_size = int_value(Size); if (trunc_size < 1 || trunc_size > MD5_DIGEST_SIZE) badarg(Size); int key_size = iolist_size(Key); if (key_size < 0) badarg(Key); assert(key_size <= 65536); // TODO: use heap_tmp_buf for a longer Key uint8_t key_buf[key_size]; iolist_flatten(Key, key_buf); int data_size = iolist_size(Data); if (data_size < 0) badarg(Data); assert(data_size <= 65536); // TODO: use heap_tmp_buf for larger Data uint8_t data_buf[data_size]; iolist_flatten(Data, data_buf); struct hmac_md5_ctx ctx; hmac_md5_set_key(&ctx, key_size, key_buf); hmac_md5_update(&ctx, data_size, data_buf); uint8_t *ptr; term_t mac = heap_make_bin(&proc->hp, trunc_size, &ptr); hmac_md5_digest(&ctx, trunc_size, ptr); return mac; }