static int sign_ctx_add_self(dnssec_sign_ctx_t *ctx, const uint8_t *rdata) { assert(ctx); assert(rdata); int result; // static header dnssec_binary_t header = { 0 }; header.data = (uint8_t *)rdata; header.size = RRSIG_RDATA_SIGNER_OFFSET; result = dnssec_sign_add(ctx, &header); if (result != DNSSEC_EOK) { return result; } // signer name const uint8_t *rdata_signer = rdata + RRSIG_RDATA_SIGNER_OFFSET; dnssec_binary_t signer = { 0 }; signer.data = knot_dname_copy(rdata_signer, NULL); signer.size = knot_dname_size(signer.data); result = dnssec_sign_add(ctx, &signer); free(signer.data); return result; }
/*! * \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); }
static void test_sign(dnssec_key_t *p11_key, dnssec_key_t *soft_key) { int r; static const dnssec_binary_t input = { .data = (uint8_t *)"So Long, and Thanks for All the Fish.", .size = 37 }; dnssec_binary_t sign = { 0 }; // usage constraints ok(dnssec_key_can_sign(p11_key), MSG_PKCS11 " dnssec_key_can_sign()"); ok(dnssec_key_can_verify(p11_key), MSG_PKCS11 " dnssec_key_can_verify()"); ok(!dnssec_key_can_sign(soft_key), MSG_SOFTWARE " dnssec_key_can_sign()"); ok(dnssec_key_can_verify(soft_key), MSG_SOFTWARE " dnssec_key_can_verify()"); // PKCS #11 key signature dnssec_sign_ctx_t *ctx = NULL; r = dnssec_sign_new(&ctx, p11_key); ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_init() "); r = dnssec_sign_add(ctx, &input); ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_add()"); r = dnssec_sign_write(ctx, &sign); ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_write()"); // PKCS #11 key verification r = dnssec_sign_init(ctx); ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_init()"); r = dnssec_sign_add(ctx, &input); ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_add()"); r = dnssec_sign_verify(ctx, &sign); ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_verify()"); // software verification dnssec_sign_free(ctx); ctx = NULL; r = dnssec_sign_new(&ctx, soft_key); ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_init()"); r = dnssec_sign_add(ctx, &input); ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_add()"); r = dnssec_sign_verify(ctx, &sign); ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_verify()"); dnssec_binary_free(&sign); dnssec_sign_free(ctx); } static void test_key_use(dnssec_keystore_t *store, dnssec_key_algorithm_t algorithm, const char *keyid) { dnssec_key_t *p11_key = NULL; dnssec_key_t *soft_key = NULL; create_dnskeys(store, algorithm, keyid, &p11_key, &soft_key); test_sign(p11_key, soft_key); dnssec_key_free(p11_key); dnssec_key_free(soft_key); }