int knot_query_add_rrset_authority(knot_packet_t *query, const knot_rrset_t *rrset) { if (query == NULL || rrset == NULL) { return KNOT_EINVAL; } if (query->ns_rrsets == query->max_ns_rrsets) { size_t oldsize = query->max_ns_rrsets * sizeof(knot_rrset_t *); ++query->max_ns_rrsets; size_t newsize = query->max_ns_rrsets * sizeof(knot_rrset_t *); const knot_rrset_t ** na = malloc(newsize); if (na == 0) { query->max_ns_rrsets = 0; return KNOT_ENOMEM; } else { memcpy(na, query->authority, oldsize); free(query->authority); query->authority = na; } } /* Append to packet. */ query->authority[query->ns_rrsets] = rrset; /* Write to wire. */ uint8_t *startp = query->wireformat + query->size; uint8_t *endp = query->wireformat + query->max_size; assert(endp - startp > query->opt_rr.size + query->tsig_size); // reserve space for OPT RR /*! \todo Why here??? */ endp -= query->opt_rr.size; /* Reserve space for TSIG RR */ endp -= query->tsig_size; size_t written = 0; uint16_t rr_count = 0; int ret = knot_rrset_to_wire(rrset, startp, &written, query->max_size, &rr_count, NULL); if (ret != KNOT_EOK) { return ret; } query->size += written; ++query->ns_rrsets; ++query->header.nscount; return KNOT_EOK; }
_public_ int knot_sig0_sign(uint8_t *wire, size_t *wire_size, size_t wire_max_size, knot_dnssec_key_t *key) { knot_rrset_t *sig_rrset = sig0_create_rrset(); if (!sig_rrset) { return KNOT_ENOMEM; } // SIG(0) headers without signature uint8_t *sig_rdata = sig0_create_rdata(sig_rrset, key); if (!sig_rdata) { knot_rrset_free(&sig_rrset, NULL); return KNOT_ENOMEM; } // convert to wire uint8_t *wire_end = wire + *wire_size; size_t wire_avail_size = wire_max_size - *wire_size; size_t wire_sig_size = 0; int result = knot_rrset_to_wire(sig_rrset, wire_end, wire_avail_size, NULL); knot_rrset_free(&sig_rrset, NULL); if (result < 0) { return result; } wire_sig_size = result; // create signature result = sig0_write_signature(wire, *wire_size, wire_sig_size, key); if (result != KNOT_EOK) { return result; } uint16_t wire_arcount = knot_wire_get_arcount(wire); knot_wire_set_arcount(wire, wire_arcount + 1); *wire_size += wire_sig_size; return KNOT_EOK; }
int knot_tsig_append(uint8_t *msg, size_t *msg_len, size_t msg_max_len, const knot_rrset_t *tsig_rr) { size_t tsig_wire_len = 0; uint16_t rr_count = 0; /* Write RRSet to wire */ int ret = KNOT_ERROR; ret = knot_rrset_to_wire(tsig_rr, msg + *msg_len, &tsig_wire_len, msg_max_len - *msg_len, &rr_count, NULL); if (ret != KNOT_EOK) { dbg_tsig("TSIG: rrset_to_wire = %s\n", knot_strerror(ret)); return ret; } *msg_len += tsig_wire_len; knot_wire_set_arcount(msg, knot_wire_get_arcount(msg) + 1); return KNOT_EOK; }
/*! * \brief Add covered RRs to signing context. * * Requires all DNAMEs in canonical form and all RRs ordered canonically. * * \param ctx Signing context. * \param covered Covered RRs. * * \return Error code, KNOT_EOK if successful. */ static int sign_ctx_add_records(dnssec_sign_ctx_t *ctx, const knot_rrset_t *covered, uint32_t orig_ttl, int trim_labels) { // huge block of rrsets can be optionally created static uint8_t wire_buffer[KNOT_WIRE_MAX_PKTSIZE]; int written = knot_rrset_to_wire(covered, wire_buffer, sizeof(wire_buffer), NULL); if (written < 0) { return written; } /* Set original ttl. */ int ret = adjust_wire_ttl(wire_buffer, written, orig_ttl); if (ret != 0) { return ret; } /* RFC4035 5.3.2 * Remove leftmost labels and replace them with '*.'. */ uint8_t *beginp = wire_buffer; if (trim_labels > 0) { for (int i = 0; i < trim_labels; ++i) { assert(beginp[0]); beginp = (uint8_t *) knot_wire_next_label(beginp, NULL); } *(--beginp) = '*'; *(--beginp) = 1; } dnssec_binary_t wire_binary = { .size = written - (beginp - wire_buffer), .data = beginp }; return dnssec_sign_add(ctx, &wire_binary); } /*! * \brief Add all data covered by signature into signing context. * * RFC 4034: The signature covers RRSIG RDATA field (excluding the signature) * and all matching RR records, which are ordered canonically. * * Requires all DNAMEs in canonical form and all RRs ordered canonically. * * \param ctx Signing context. * \param rrsig_rdata RRSIG RDATA with populated fields except signature. * \param covered Covered RRs. * * \return Error code, KNOT_EOK if successful. */ /* TODO -- Taken from knot/src/knot/dnssec/rrset-sign.c. Re-write for better fit needed. */ static int sign_ctx_add_data(dnssec_sign_ctx_t *ctx, const uint8_t *rrsig_rdata, const knot_rrset_t *covered, uint32_t orig_ttl, int trim_labels) { int result = sign_ctx_add_self(ctx, rrsig_rdata); if (result != KNOT_EOK) { return result; } return sign_ctx_add_records(ctx, covered, orig_ttl, trim_labels); }
int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len, const uint8_t *prev_digest, size_t prev_digest_len, uint8_t *digest, size_t *digest_len, const knot_tsig_key_t *key, uint8_t *to_sign, size_t to_sign_len) { if (!msg || !msg_len || !key || !digest || !digest_len) { return KNOT_EINVAL; } uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE]; size_t digest_tmp_len = 0; knot_rrset_t *tmp_tsig = knot_rrset_new(key->name, KNOT_RRTYPE_TSIG, KNOT_CLASS_ANY, NULL); if (!tmp_tsig) { return KNOT_ENOMEM; } /* Create rdata for TSIG RR. */ tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm), knot_tsig_digest_length(key->algorithm), 0); tsig_rdata_store_current_time(tmp_tsig); tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT); /* Create wire to be signed. */ size_t wire_len = prev_digest_len + to_sign_len + KNOT_TSIG_TIMERS_LENGTH + 2; uint8_t *wire = malloc(wire_len); if (!wire) { ERR_ALLOC_FAILED; knot_rrset_free(&tmp_tsig, NULL); return KNOT_ENOMEM; } memset(wire, 0, wire_len); /* Write previous digest length. */ knot_wire_write_u16(wire, prev_digest_len); /* Write previous digest. */ memcpy(wire + 2, prev_digest, sizeof(uint8_t) * prev_digest_len); /* Write original message. */ memcpy(wire + prev_digest_len + 2, to_sign, to_sign_len); /* Write timers. */ knot_tsig_wire_write_timers(wire + prev_digest_len + to_sign_len + 2, tmp_tsig); dbg_tsig_detail("Previous digest: \n"); dbg_tsig_hex_detail((char *)prev_digest, prev_digest_len); dbg_tsig_detail("Timers: \n"); dbg_tsig_hex_detail((char *)(wire + prev_digest_len + *msg_len), KNOT_TSIG_TIMERS_LENGTH); int ret = KNOT_ERROR; ret = knot_tsig_compute_digest(wire, wire_len, digest_tmp, &digest_tmp_len, key); /* No matter how the function did, this data is no longer needed. */ free(wire); if (ret != KNOT_EOK) { knot_rrset_free(&tmp_tsig, NULL); *digest_len = 0; return ret; } if (digest_tmp_len > *digest_len) { knot_rrset_free(&tmp_tsig, NULL); *digest_len = 0; return KNOT_ESPACE; } /* Set the MAC. */ tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp); /* Set original id. */ tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg)); /* Set other data. */ tsig_rdata_set_other_data(tmp_tsig, 0, NULL); dbg_tsig_verb("Message max length: %zu, message length: %zu\n", msg_max_len, *msg_len); size_t tsig_wire_size = 0; uint16_t rr_count = 0; ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len, &tsig_wire_size, msg_max_len - *msg_len, &rr_count, NULL); if (ret != KNOT_EOK) { knot_rrset_free(&tmp_tsig, NULL); *digest_len = 0; return ret; } /* This should not happen, at least one rr has to be converted. */ if (rr_count == 0) { knot_rrset_free(&tmp_tsig, NULL); return KNOT_EINVAL; } knot_rrset_free(&tmp_tsig, NULL); *msg_len += tsig_wire_size; uint16_t arcount = knot_wire_get_arcount(msg); knot_wire_set_arcount(msg, ++arcount); memcpy(digest, digest_tmp, digest_tmp_len); *digest_len = digest_tmp_len; return KNOT_EOK; }
int knot_tsig_sign(uint8_t *msg, size_t *msg_len, size_t msg_max_len, const uint8_t *request_mac, size_t request_mac_len, uint8_t *digest, size_t *digest_len, const knot_tsig_key_t *key, uint16_t tsig_rcode, uint64_t request_time_signed) { if (!msg || !msg_len || !key || digest == NULL || digest_len == NULL) { return KNOT_EINVAL; } knot_rrset_t *tmp_tsig = knot_rrset_new(key->name, KNOT_RRTYPE_TSIG, KNOT_CLASS_ANY, NULL); if (!tmp_tsig) { dbg_tsig("TSIG: tmp_tsig = NULL\n"); return KNOT_ENOMEM; } /* Create rdata for TSIG RR. */ uint16_t rdata_rcode = 0; if (tsig_rcode == KNOT_RCODE_BADTIME) rdata_rcode = tsig_rcode; tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm), knot_tsig_digest_length(key->algorithm), rdata_rcode); /* Distinguish BADTIME response. */ if (tsig_rcode == KNOT_RCODE_BADTIME) { /* Set client's time signed into the time signed field. */ tsig_rdata_set_time_signed(tmp_tsig, request_time_signed); /* Store current time into Other data. */ uint8_t time_signed[6]; time_t curr_time = time(NULL); uint64_t time64 = curr_time; knot_wire_write_u48(time_signed, time64); tsig_rdata_set_other_data(tmp_tsig, 6, time_signed); } else { tsig_rdata_store_current_time(tmp_tsig); /* Set other len. */ tsig_rdata_set_other_data(tmp_tsig, 0, 0); } tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT); /* Set original ID */ tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg)); uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE]; size_t digest_tmp_len = 0; int ret = KNOT_ERROR; ret = knot_tsig_create_sign_wire(msg, *msg_len, /*msg_max_len,*/ request_mac, request_mac_len, digest_tmp, &digest_tmp_len, tmp_tsig, key); if (ret != KNOT_EOK) { dbg_tsig("TSIG: could not create wire or sign wire: %s\n", knot_strerror(ret)); knot_rrset_free(&tmp_tsig, NULL); return ret; } /* Set the digest. */ size_t tsig_wire_len = 0; dbg_tsig("TSIG: msg_len=%zu, msg_max_len=%zu, tsig_max_len=%zu\n", *msg_len, msg_max_len, tsig_wire_len); uint16_t rr_count = 0; tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp); /* Write RRSet to wire */ ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len, &tsig_wire_len, msg_max_len - *msg_len, &rr_count, NULL); if (ret != KNOT_EOK) { dbg_tsig("TSIG: rrset_to_wire = %s\n", knot_strerror(ret)); *digest_len = 0; knot_rrset_free(&tmp_tsig, NULL); return ret; } knot_rrset_free(&tmp_tsig, NULL); dbg_tsig("TSIG: written TSIG RR (wire len %zu)\n", tsig_wire_len); *msg_len += tsig_wire_len; uint16_t arcount = knot_wire_get_arcount(msg); knot_wire_set_arcount(msg, ++arcount); // everything went ok, save the digest to the output parameter memcpy(digest, digest_tmp, digest_tmp_len); *digest_len = digest_tmp_len; return KNOT_EOK; }
//short size = knot_response_rrset_size(rrset, &resp->compression); dbg_response_exec( char *name = knot_dname_to_str(rrset->owner); dbg_response_verb("\nAdding RRSet with owner %s and type %u: \n", name, rrset->type); free(name); ); uint8_t *pos = resp->wireformat + resp->size; size_t size = max_size; compression_param_t param; param.compressed_dnames = resp->compression; param.wire_pos = resp->size; param.wire = resp->wireformat; uint16_t rr_count = 0; int ret = knot_rrset_to_wire(rrset, pos, &size, max_size, &rr_count, ¶m); if (ret != KNOT_EOK) { dbg_response("Failed to convert RRSet to wire. (%s).\n,", knot_strerror(ret)); } if (rr_count > 0) { rrsets[(*rrset_count)++] = rrset; resp->size += size; dbg_response_verb("RRset added, size: %zu, RRs: %d, total " "size of response: %zu\n\n", size, rr_count, resp->size); } else if (tc) { dbg_response_verb("Setting TC bit.\n"); knot_wire_flags_set_tc(&resp->header.flags1);
_public_ int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr, uint16_t flags) { if (pkt == NULL || rr == NULL) { return KNOT_EINVAL; } /* Reserve memory for RR descriptors. */ int ret = pkt_rr_array_alloc(pkt, pkt->rrset_count + 1); if (ret != KNOT_EOK) { return ret; } knot_rrinfo_t *rrinfo = &pkt->rr_info[pkt->rrset_count]; memset(rrinfo, 0, sizeof(knot_rrinfo_t)); rrinfo->pos = pkt->size; rrinfo->flags = flags; rrinfo->compress_ptr[0] = compr_hint; memcpy(pkt->rr + pkt->rrset_count, rr, sizeof(knot_rrset_t)); /* Check for double insertion. */ if ((flags & KNOT_PF_CHECKDUP) && pkt_contains(pkt, rr)) { return KNOT_EOK; /*! \todo return rather a number of added RRs */ } uint8_t *pos = pkt->wire + pkt->size; size_t maxlen = pkt_remaining(pkt); /* Create compression context. */ knot_compr_t compr; compr.wire = pkt->wire; compr.rrinfo = rrinfo; compr.suffix.pos = KNOT_WIRE_HEADER_SIZE; compr.suffix.labels = knot_dname_labels(compr.wire + compr.suffix.pos, compr.wire); /* Write RRSet to wireformat. */ ret = knot_rrset_to_wire(rr, pos, maxlen, &compr); if (ret < 0) { /* Truncate packet if required. */ if (ret == KNOT_ESPACE && !(flags & KNOT_PF_NOTRUNC)) { knot_wire_set_tc(pkt->wire); } return ret; } size_t len = ret; uint16_t rr_added = rr->rrs.rr_count; /* Keep reference to special types. */ if (rr->type == KNOT_RRTYPE_OPT) { pkt->opt_rr = &pkt->rr[pkt->rrset_count]; } if (rr_added > 0) { pkt->rrset_count += 1; pkt->sections[pkt->current].count += 1; pkt->size += len; pkt_rr_wirecount_add(pkt, pkt->current, rr_added); } return KNOT_EOK; }