From: Jelte Jansen Date: Thu, 24 May 2007 12:53:00 +0000 (+0000) Subject: merges crypto_evp_api branch back to trunk X-Git-Tag: ldns-1.3.0_pre_20070822~61 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d019c2e5175b76385b3eecd093aa7787faa81746;p=thirdparty%2Fldns.git merges crypto_evp_api branch back to trunk --- diff --git a/dnssec.c b/dnssec.c index 9a1bcb44..a51f067a 100644 --- a/dnssec.c +++ b/dnssec.c @@ -22,6 +22,7 @@ * crypto... */ #include +#include #include #include #include @@ -62,7 +63,7 @@ ldns_calc_keytag(const ldns_rr *key) } ldns_buffer_free(keybuf); ac16 = ntohs(ac16); - return (uint16_t) ac16; + return (uint16_t) ac16; } else { for (i = 0; (size_t)i < keysize; ++i) { ac32 += (i & 1) ? *ldns_buffer_at(keybuf, i) : @@ -335,6 +336,7 @@ ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, return ldns_verify_rrsig_dsa(rawsig_buf, verify_buf, key_buf); break; case LDNS_RSASHA1: + /*return ldns_verify_rrsig_rsasha1(rawsig_buf, verify_buf, key_buf);*/ return ldns_verify_rrsig_rsasha1(rawsig_buf, verify_buf, key_buf); break; case LDNS_RSAMD5: @@ -411,23 +413,23 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis now = time(NULL); if (expiration - inception < 0) { - /* bad sig, expiration before inception?? Tsssg */ + /* bad sig, expiration before inception?? Tsssg */ ldns_buffer_free(rawsig_buf); ldns_buffer_free(verify_buf); return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION; - } - if (now - inception < 0) { - /* bad sig, inception date has passed */ + } + if (now - inception < 0) { + /* bad sig, inception date has passed */ ldns_buffer_free(rawsig_buf); ldns_buffer_free(verify_buf); return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED; - } - if (expiration - now < 0) { - /* bad sig, expiration date has passed */ + } + if (expiration - now < 0) { + /* bad sig, expiration date has passed */ ldns_buffer_free(rawsig_buf); ldns_buffer_free(verify_buf); return LDNS_STATUS_CRYPTO_SIG_EXPIRED; - } + } /* create a buffer with b64 signature rdata */ if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { @@ -444,7 +446,7 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { if (label_count < ldns_dname_label_count( - ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) { + ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) { (void) ldns_str2rdf_dname(&wildcard_name, "*"); wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i))); while (label_count < ldns_dname_label_count(wildcard_chopped)) { @@ -457,7 +459,7 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i))); ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), wildcard_name); - + } ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl); /* convert to lowercase */ @@ -485,7 +487,7 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis current_key = ldns_rr_list_rr(keys, i); /* before anything, check if the keytags match */ if (ldns_calc_keytag(current_key) == - ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))) { + ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))) { key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); /* put the key-data in a buffer, that's the third rdf, with @@ -573,18 +575,18 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) now = time(NULL); if (expiration - inception < 0) { - /* bad sig, expiration before inception?? Tsssg */ + /* bad sig, expiration before inception?? Tsssg */ return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION; - } - if (now - inception < 0) { - /* bad sig, inception date has passed */ + } + if (now - inception < 0) { + /* bad sig, inception date has passed */ return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED; - } + } - if (expiration - now < 0) { - /* bad sig, expiration date has passed */ + if (expiration - now < 0) { + /* bad sig, expiration date has passed */ return LDNS_STATUS_CRYPTO_SIG_EXPIRED; - } + } /* clone the rrset so that we can fiddle with it */ rrset_clone = ldns_rr_list_clone(rrset); @@ -635,7 +637,7 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { if (label_count < ldns_dname_label_count( - ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) { + ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) { (void) ldns_str2rdf_dname(&wildcard_name, "*"); wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i))); while (label_count < ldns_dname_label_count(wildcard_chopped)) { @@ -648,7 +650,7 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i))); ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), wildcard_name); - + } ldns_rr_set_ttl( ldns_rr_list_rr(rrset_clone, i), @@ -677,8 +679,8 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) } if (ldns_calc_keytag(key) - == - ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) + == + ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) ) { key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); @@ -716,75 +718,49 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) } ldns_status -ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) +ldns_verify_rrsig_evp(ldns_buffer *sig, ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type) { - DSA *dsakey; - DSA_SIG *dsasig; - BIGNUM *R; - BIGNUM *S; - uint8_t t; - int result; + EVP_MD_CTX ctx; + int res; - unsigned char *sha1_hash; - - dsakey = ldns_key_buf2dsa(key); - if (!dsakey) { - return LDNS_STATUS_ERR; - } - - /* extract the R and S field from the sig buffer */ - t = *(ldns_buffer_at(sig, 0)); - R = BN_new(); - (void) BN_bin2bn((unsigned char*)ldns_buffer_at(sig, 1), SHA_DIGEST_LENGTH, R); - S = BN_new(); - (void) BN_bin2bn((unsigned char*)ldns_buffer_at(sig, 21), SHA_DIGEST_LENGTH, S); - - dsasig = DSA_SIG_new(); - if (!dsasig) { - return LDNS_STATUS_MEM_ERR; + EVP_MD_CTX_init(&ctx); + + EVP_VerifyInit(&ctx, digest_type); + EVP_VerifyUpdate(&ctx, ldns_buffer_begin(rrset), ldns_buffer_position(rrset)); + res = EVP_VerifyFinal(&ctx, (unsigned char *) ldns_buffer_begin(sig), ldns_buffer_position(sig), key); + + if (res == 1) { + return LDNS_STATUS_OK; + } else if (res == 0) { + return LDNS_STATUS_CRYPTO_BOGUS; } + return LDNS_STATUS_OK; +} - dsasig->r = R; - dsasig->s = S; - sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(rrset), ldns_buffer_position(rrset), NULL); - if (!sha1_hash) { - return LDNS_STATUS_ERR; - } +ldns_status +ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) +{ + EVP_PKEY *evp_key; + ldns_status result; - result = DSA_do_verify(sha1_hash, SHA_DIGEST_LENGTH, dsasig, dsakey); + evp_key = EVP_PKEY_new(); + EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa(key)); + result = ldns_verify_rrsig_evp(sig, rrset, evp_key, EVP_sha1()); + EVP_PKEY_free(evp_key); + return result; - if (result == 1) { - return LDNS_STATUS_OK; - } else { - return LDNS_STATUS_CRYPTO_BOGUS; - } } ldns_status ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) { - RSA *rsakey; - unsigned char *sha1_hash; + EVP_PKEY *evp_key; ldns_status result; - rsakey = ldns_key_buf2rsa(key); - if (!rsakey) { - result = LDNS_STATUS_ERR; - } else { - sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(rrset), ldns_buffer_position(rrset), NULL); - if (!sha1_hash) { - return LDNS_STATUS_ERR; - } - if (RSA_verify(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH, - (unsigned char*)ldns_buffer_begin(sig), - (unsigned int)ldns_buffer_position(sig), rsakey) == 1) { - result = LDNS_STATUS_OK; - } else { - result = LDNS_STATUS_CRYPTO_BOGUS; - } - } - - RSA_free(rsakey); + evp_key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa(key)); + result = ldns_verify_rrsig_evp(sig, rrset, evp_key, EVP_sha1()); + EVP_PKEY_free(evp_key); return result; } @@ -793,26 +769,15 @@ ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key ldns_status ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) { - RSA *rsakey; - unsigned char *md5_hash; + EVP_PKEY *evp_key; + ldns_status result; - rsakey = ldns_key_buf2rsa(key); - if (!rsakey) { - return LDNS_STATUS_ERR; - } - md5_hash = MD5((unsigned char*)ldns_buffer_begin(rrset), - (unsigned int)ldns_buffer_position(rrset), NULL); - if (!md5_hash) { - return LDNS_STATUS_ERR; - } - if (RSA_verify(NID_md5, md5_hash, MD5_DIGEST_LENGTH, - (unsigned char*)ldns_buffer_begin(sig), - (unsigned int)ldns_buffer_position(sig), rsakey) == 1) { - return LDNS_STATUS_OK; - } else { - return LDNS_STATUS_CRYPTO_BOGUS; - } - return true; + evp_key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa(key)); + result = ldns_verify_rrsig_evp(sig, rrset, evp_key, EVP_md5()); + EVP_PKEY_free(evp_key); + + return result; } #ifdef HAVE_SSL @@ -901,21 +866,21 @@ ldns_key_buf2rsa(ldns_buffer *key) ldns_rr * ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) { - ldns_rdf *tmp; - ldns_rr *ds; - uint16_t keytag; - uint8_t sha1hash; - uint8_t *digest; - ldns_buffer *data_buf; - - if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) { - return NULL; - } + ldns_rdf *tmp; + ldns_rr *ds; + uint16_t keytag; + uint8_t sha1hash; + uint8_t *digest; + ldns_buffer *data_buf; - ds = ldns_rr_new(); - if (!ds) { - return NULL; - } + if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) { + return NULL; + } + + ds = ldns_rr_new(); + if (!ds) { + return NULL; + } ldns_rr_set_type(ds, LDNS_RR_TYPE_DS); ldns_rr_set_owner(ds, ldns_rdf_clone( ldns_rr_owner(key))); @@ -937,28 +902,28 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) break; } - data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); - if (!data_buf) { + data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!data_buf) { LDNS_FREE(digest); ldns_rr_free(ds); - return NULL; - } + return NULL; + } - /* keytag */ - keytag = htons(ldns_calc_keytag((ldns_rr*)key)); - tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16, sizeof(uint16_t), &keytag); - ldns_rr_push_rdf(ds, tmp); + /* keytag */ + keytag = htons(ldns_calc_keytag((ldns_rr*)key)); + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16, sizeof(uint16_t), &keytag); + ldns_rr_push_rdf(ds, tmp); - /* copy the algorithm field */ - ldns_rr_push_rdf(ds, ldns_rdf_clone( ldns_rr_rdf(key, 2))); /* second rfd */ + /* copy the algorithm field */ + ldns_rr_push_rdf(ds, ldns_rdf_clone( ldns_rr_rdf(key, 2))); /* second rfd */ - /* digest hash type */ - sha1hash = (uint8_t)h; - tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, sizeof(uint8_t), &sha1hash); - ldns_rr_push_rdf(ds, tmp); + /* digest hash type */ + sha1hash = (uint8_t)h; + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, sizeof(uint8_t), &sha1hash); + ldns_rr_push_rdf(ds, tmp); - /* digest */ - /* owner name */ + /* digest */ + /* owner name */ if (ldns_rdf2buffer_wire(data_buf, ldns_rr_owner(key)) != LDNS_STATUS_OK) { LDNS_FREE(digest); ldns_buffer_free(data_buf); @@ -966,7 +931,7 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) return NULL; } - /* all the rdata's */ + /* all the rdata's */ if (ldns_rr_rdata2buffer_wire(data_buf, (ldns_rr*)key) != LDNS_STATUS_OK) { LDNS_FREE(digest); ldns_buffer_free(data_buf); @@ -976,8 +941,8 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) switch(h) { case LDNS_SHA1: (void) SHA1((unsigned char *) ldns_buffer_begin(data_buf), - ldns_buffer_position(data_buf), - (unsigned char*) digest); + ldns_buffer_position(data_buf), + (unsigned char*) digest); tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, SHA_DIGEST_LENGTH, digest); @@ -990,7 +955,7 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) LDNS_FREE(digest); ldns_buffer_free(data_buf); - return ds; + return ds; } /* @@ -1059,9 +1024,9 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) /* sign all RRs with keys that have ZSKbit, !SEPbit. sign DNSKEY RRs with keys that have ZSKbit&SEPbit */ if ( - ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY && - (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY) || - ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)) == LDNS_RR_TYPE_DNSKEY) + ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY && + (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY) || + ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)) == LDNS_RR_TYPE_DNSKEY) ) { current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG); @@ -1138,13 +1103,13 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) switch(ldns_key_algorithm(current_key)) { case LDNS_SIGN_DSA: - b64rdf = ldns_sign_public_dsa(sign_buf, ldns_key_dsa_key(current_key)); + b64rdf = ldns_sign_public_evp(sign_buf, ldns_key_evp_key(current_key), EVP_sha1()); break; case LDNS_SIGN_RSASHA1: - b64rdf = ldns_sign_public_rsasha1(sign_buf, ldns_key_rsa_key(current_key)); + b64rdf = ldns_sign_public_evp(sign_buf, ldns_key_evp_key(current_key), EVP_sha1()); break; case LDNS_SIGN_RSAMD5: - b64rdf = ldns_sign_public_rsamd5(sign_buf, ldns_key_rsa_key(current_key)); + b64rdf = ldns_sign_public_evp(sign_buf, ldns_key_evp_key(current_key), EVP_md5()); break; default: /* do _you_ know this alg? */ @@ -1161,8 +1126,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) ldns_rr_list_push_rr(signatures, current_sig); } ldns_buffer_free(sign_buf); /* restart for the next key */ - } - ldns_rr_list_deep_free(rrset_clone); + } + ldns_rr_list_deep_free(rrset_clone); return signatures; } @@ -1216,6 +1181,43 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) return sigdata_rdf; } +ldns_rdf * +ldns_sign_public_evp(ldns_buffer *to_sign, EVP_PKEY *key, const EVP_MD *digest_type) +{ + unsigned int siglen; + ldns_rdf *sigdata_rdf; + ldns_buffer *b64sig; + EVP_MD_CTX ctx; + const EVP_MD *md_type; + + siglen = 0; + b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!b64sig) { + return NULL; + } + + /* initializes a signing context */ + md_type = digest_type; + if(!md_type) { + printf("Unknown message digest"); + exit(1); + } + + EVP_MD_CTX_init(&ctx); + EVP_SignInit(&ctx, md_type); + + EVP_SignUpdate(&ctx, (unsigned char*)ldns_buffer_begin(to_sign), ldns_buffer_position(to_sign)); + + EVP_SignFinal(&ctx, (unsigned char*)ldns_buffer_begin(b64sig), &siglen, key); + + sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, + ldns_buffer_begin(b64sig)); + ldns_buffer_free(b64sig); + EVP_MD_CTX_cleanup(&ctx); + return sigdata_rdf; +} + + ldns_rdf * ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key) { @@ -1315,7 +1317,7 @@ ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs) i_rr = ldns_rr_list_rr(rrs, i); if (ldns_rdf_compare(cur_owner, - ldns_rr_owner(i_rr)) == 0) { + ldns_rr_owner(i_rr)) == 0) { /* add type to bitmap */ i_type = ldns_rr_get_type(i_rr); if ((i_type / 8) + 1 > bm_len) { @@ -1407,7 +1409,7 @@ ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type) if (bitmap[i] == window_block_nr) { /* this is the right window, check the bit */ if ((uint8_t) (type / 8) < bitmap[i + 1] && - ldns_get_bit(&bitmap[i + 1 + (type / 8)], (size_t) (7 - (type % 8)))) { + ldns_get_bit(&bitmap[i + 1 + (type / 8)], (size_t) (7 - (type % 8)))) { return true; } else { return false; @@ -1434,7 +1436,7 @@ ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name) ldns_dname_compare(name, nsec_next) < 0); return (ldns_dname_compare(nsec_owner, name) <= 0 && - ldns_dname_compare(name, nsec_next) < 0); + ldns_dname_compare(name, nsec_next) < 0); } /* sig may be null - if so look in the packet */ @@ -1536,8 +1538,8 @@ ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list) ldns_rr_list_push_rr(orig_zone_rrs, ldns_rr_clone(ldns_zone_soa(zone))); /* canon now, needed for correct nsec creation */ - /* - for (i = 0; i < ldns_rr_list_rr_count(orig_zone_rrs); i++) { + /* + for (i = 0; i < ldns_rr_list_rr_count(orig_zone_rrs); i++) { ldns_rr2canonical(ldns_rr_list_rr(orig_zone_rrs, i)); } */ @@ -1596,14 +1598,14 @@ ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list) /* if we have KSKs, use them for DNSKEYS, otherwise make them selfsigned (?) */ - /* don't sign sigs, delegations, and glue */ + /* don't sign sigs, delegations, and glue */ if (cur_rrset_type != LDNS_RR_TYPE_RRSIG && - ((ldns_dname_is_subdomain(cur_dname, ldns_rr_owner(ldns_zone_soa(signed_zone))) - && cur_rrset_type != LDNS_RR_TYPE_NS - ) || - ldns_rdf_compare(cur_dname, ldns_rr_owner(ldns_zone_soa(signed_zone))) == 0 - ) && - !(ldns_rr_list_contains_rr(glue_rrs, ldns_rr_list_rr(cur_rrset, 0))) + ((ldns_dname_is_subdomain(cur_dname, ldns_rr_owner(ldns_zone_soa(signed_zone))) + && cur_rrset_type != LDNS_RR_TYPE_NS + ) || + ldns_rdf_compare(cur_dname, ldns_rr_owner(ldns_zone_soa(signed_zone))) == 0 + ) && + !(ldns_rr_list_contains_rr(glue_rrs, ldns_rr_list_rr(cur_rrset, 0))) ) { cur_rrsigs = ldns_sign_public(cur_rrset, key_list); @@ -1665,4 +1667,11 @@ ldns_init_random(FILE *fd, uint16_t bytes) LDNS_FREE(buf); return LDNS_STATUS_OK; } + +/* taken from the ENGINE man page */ +/* +int ldns_load_engine_fn(const char *engine_id, const char **pre_cmds, int pre_num, const char **post_cmds, int post_num) +{ + ENGINE *e +*/ #endif /* HAVE_SSL */ diff --git a/error.c b/error.c index af67039a..8476df62 100644 --- a/error.c +++ b/error.c @@ -53,6 +53,7 @@ ldns_lookup_table ldns_error_str[] = { { LDNS_STATUS_CRYPTO_TSIG_BOGUS, "Bogus TSIG signature" }, { LDNS_STATUS_CRYPTO_TSIG_ERR, "Could not create TSIG signature" }, { LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION, "DNSSEC signature has expiration date earlier than inception date" }, + { LDNS_STATUS_ENGINE_KEY_NOT_LOADED, "Unable to load private key from engine" }, { LDNS_STATUS_RES_NO_NS, "No nameservers defined in the resolver" }, { LDNS_STATUS_RES_QUERY, "No correct query given to resolver" }, { LDNS_STATUS_WIRE_INCOMPLETE_HEADER, "header section incomplete" }, diff --git a/examples/configure.ac b/examples/configure.ac index cffcb571..67a9624b 100644 --- a/examples/configure.ac +++ b/examples/configure.ac @@ -43,6 +43,48 @@ $3 fi ]) +# Checks for libraries. +# Check for SSL, original taken from +# http://www.gnu.org/software/ac-archive/htmldoc/check_ssl.html and +# modified for NSD and +# copied again for use in ldns +AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname], + [enable SSL (will check /usr/local/ssl + /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr/sfw /usr)]),[ + ],[ + withval="yes" + ]) + if test x_$withval != x_no; then + AC_MSG_CHECKING(for SSL) + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr/sfw /usr" + fi + for dir in $withval; do + ssldir="$dir" + if test -f "$dir/include/openssl/ssl.h"; then + found_ssl="yes"; + AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.]) + CPPFLAGS="$CPPFLAGS -I$ssldir/include"; + break; + fi + done + if test x_$found_ssl != x_yes; then + AC_MSG_ERROR(Cannot find the SSL libraries in $withval) + else + AC_MSG_RESULT(found in $ssldir) + HAVE_SSL=yes + LDFLAGS="$LDFLAGS -L$ssldir/lib -lcrypto"; + RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib" + AC_CHECK_LIB(crypto, HMAC_CTX_init,, [ + AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required]) + ]) + fi + AC_SUBST(HAVE_SSL) + AC_SUBST(RUNTIME_PATH) + fi + + + dnl routine to help check for needed compiler flags. # if the given code compiles without the flag, execute argument 4 # if the given code only compiles with the flag, execute argument 3 diff --git a/examples/ldns-signzone.c b/examples/ldns-signzone.c index b7c9722c..41decf2d 100644 --- a/examples/ldns-signzone.c +++ b/examples/ldns-signzone.c @@ -14,6 +14,11 @@ #include #include +#include + +#include +#include + #define MAX_FILENAME_LEN 250 @@ -26,11 +31,22 @@ usage(FILE *fp, const char *prog) { fprintf(fp, " -i \tinception date\n"); fprintf(fp, " -o \torigin for the zone\n"); fprintf(fp, " -v\t\tprint version and exit\n"); + fprintf(fp, " -E \tuse as the crypto engine for signing\n"); + fprintf(fp, " \tThis can have a lot of extra options, see -E help for more info\n"); + fprintf(fp, " -k ,\tuse key id with algorithm int from engine\n"); + fprintf(fp, " -K ,\tuse key id with algorithm int from engine as KSK\n"); + fprintf(fp, "\t\tif no key is given (but an external one is used through the engine support, it might be necessary to provide the right algorithm number.\n"); fprintf(fp, " keys must be specified by their base name: K++\n"); fprintf(fp, " both a .key and .private file must present\n"); fprintf(fp, " A date can be a timestamp (seconds since the epoch), or of\n the form \n"); } +void +usage_openssl(FILE *fp, const char *prog) { + fprintf(fp, "Special commands for openssl engines:\n"); + fprintf(fp, "-c \tOpenSSL config file\n"); +} + void check_tm(struct tm tm) { if (tm.tm_year < 70) { @@ -72,6 +88,7 @@ main(int argc, char *argv[]) int line_nr = 0; int c; int argi; + ENGINE *engine = NULL; ldns_zone *orig_zone; ldns_rr_list *orig_rrs = NULL; @@ -84,12 +101,19 @@ main(int argc, char *argv[]) ldns_key *key = NULL; ldns_rr *pubkey; ldns_key_list *keys; + size_t key_i; ldns_status s; char *outputfile_name = NULL; FILE *outputfile; + /* tmp vars for engine keys */ + char *eng_key_l; + size_t eng_key_id_len; + char *eng_key_id; + int eng_key_algo; + /* we need to know the origin before reading ksk's, * so keep an array of filenames until we know it */ @@ -105,7 +129,11 @@ main(int argc, char *argv[]) inception = 0; expiration = 0; - while ((c = getopt(argc, argv, "e:f:i:o:v")) != -1) { + keys = ldns_key_list_new(); + +/* OPENSSL_config(NULL);*/ + + while ((c = getopt(argc, argv, "e:f:i:o:vE:ak:K:")) != -1) { switch (c) { case 'e': /* try to parse YYYYMMDD first, @@ -169,6 +197,84 @@ main(int argc, char *argv[]) printf("zone signer version %s (ldns version %s)\n", LDNS_VERSION, ldns_version()); exit(EXIT_SUCCESS); break; + case 'E': + if (strncmp("help", optarg, 5) == 0) { + printf("help\n"); + exit(EXIT_SUCCESS); + } + ENGINE_load_openssl(); + ENGINE_load_builtin_engines(); + ENGINE_load_dynamic(); + ENGINE_load_cryptodev(); + engine = ENGINE_by_id(optarg); + if (!engine) { + printf("No such engine: %s\n", optarg); + engine = ENGINE_get_first(); + printf("Available engines:\n"); + while (engine) { + printf("%s\n", ENGINE_get_id(engine)); + engine = ENGINE_get_next(engine); + } + exit(EXIT_FAILURE); + } else { + if (!ENGINE_init(engine)) { + printf("The engine couldn't initialize\n"); + exit(EXIT_FAILURE); + } + ENGINE_set_default_RSA(engine); + ENGINE_set_default_DSA(engine); + ENGINE_set_default(engine, 0); + } + break; + case 'k': + eng_key_l = index(optarg, ','); + if (eng_key_l && strlen(eng_key_l) > 1) { + if (eng_key_l > optarg) { + eng_key_id_len = (size_t) (eng_key_l - optarg); + eng_key_id = malloc(eng_key_id_len + 1); + memcpy(eng_key_id, optarg, eng_key_id_len); + eng_key_id[eng_key_id_len] = '\0'; + } else { + /* no id given, use default from engine */ + eng_key_id = NULL; + } + + eng_key_algo = atoi(eng_key_l + 1); + + printf("Engine key id: %s, algo %d\n", eng_key_id, eng_key_algo); + + if (expiration != 0) { + ldns_key_set_expiration(key, expiration); + } + if (inception != 0) { + ldns_key_set_inception(key, inception); + } + + s = ldns_key_new_frm_engine(&key, engine, eng_key_id, eng_key_algo); + if (s == LDNS_STATUS_OK) { + ldns_key_list_push_key(keys, key); + /*printf("Added key at %p:\n", key);*/ + /*ldns_key_print(stdout, key);*/ + } else { + printf("Error reading key '%s' from engine: %s\n", eng_key_id, ldns_get_errorstr_by_id(s)); + printf("The available key id's are:\n"); + printf("TODO\n"); + exit(EXIT_FAILURE); + } + + if (eng_key_id) { + free(eng_key_id); + } + } else { + printf("Error: bad engine key specification (should be: -k ,)).\n"); + exit(EXIT_FAILURE); + } + + break; + case 'K': + printf("Not implemented yet\n"); + exit(EXIT_FAILURE); + break; default: usage(stderr, prog); exit(EXIT_SUCCESS); @@ -178,7 +284,8 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (argc < 2) { + if (argc < 1) { + printf("Error: not enough arguments\n"); usage(stdout, prog); exit(EXIT_FAILURE); } else { @@ -218,8 +325,6 @@ main(int argc, char *argv[]) origin = ldns_rr_owner(orig_soa); } - keys = ldns_key_list_new(); - /* read the ZSKs */ argi = 1; while (argi < argc) { @@ -247,6 +352,7 @@ main(int argc, char *argv[]) LDNS_FREE(keyfile_name); keyfile_name = LDNS_XMALLOC(char, strlen(keyfile_name_base) + 5); snprintf(keyfile_name, strlen(keyfile_name_base) + 5, "%s.key", keyfile_name_base); + fprintf(stderr, "trying to read %s\n", keyfile_name); keyfile = fopen(keyfile_name, "r"); line_nr = 0; if (!keyfile) { @@ -261,9 +367,9 @@ main(int argc, char *argv[]) ldns_key_list_push_key(keys, key); ldns_zone_push_rr(orig_zone, ldns_rr_clone(pubkey)); ldns_rr_free(pubkey); + fclose(keyfile); } LDNS_FREE(keyfile_name); - } else { fprintf(stderr, "Error reading key from %s at line %d\n", argv[argi], line_nr); } @@ -277,6 +383,20 @@ main(int argc, char *argv[]) usage(stderr, prog); exit(EXIT_FAILURE); } + + /* walk through the keys, and add pubkeys to the orig zone */ + for (key_i = 0; key_i < ldns_key_list_key_count(keys); key_i++) { + key = ldns_key_list_key(keys, key_i); + if (!ldns_key_pubkey_owner(key)) { + ldns_key_set_pubkey_owner(key, ldns_rdf_clone(origin)); + pubkey = ldns_key2rr(key); + ldns_key_set_flags(key, ldns_rdf2native_int16(ldns_rr_rdf(pubkey, 0))); + ldns_key_set_keytag(key, ldns_calc_keytag(pubkey)); + ldns_zone_push_rr(orig_zone, pubkey); + printf("Derived DNSKEY RR:\n"); + ldns_rr_print(stdout, pubkey); + } + } signed_zone = ldns_zone_sign(orig_zone, keys); @@ -284,7 +404,7 @@ main(int argc, char *argv[]) outputfile_name = LDNS_XMALLOC(char, MAX_FILENAME_LEN); snprintf(outputfile_name, MAX_FILENAME_LEN, "%s.signed", zonefile_name); } - + if (signed_zone) { outputfile = fopen(outputfile_name, "w"); if (!outputfile) { @@ -304,6 +424,8 @@ main(int argc, char *argv[]) LDNS_FREE(outputfile_name); + CRYPTO_cleanup_all_ex_data(); + free(prog); - exit(EXIT_SUCCESS); + exit(EXIT_SUCCESS); } diff --git a/host2str.c b/host2str.c index 5252f3e9..de6e5145 100644 --- a/host2str.c +++ b/host2str.c @@ -1065,10 +1065,14 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) { ldns_status status = LDNS_STATUS_OK; unsigned char *bignum; + #ifdef HAVE_SSL /* not used when ssl is not defined */ ldns_rdf *b64_bignum = NULL; uint16_t i; + + RSA *rsa; + DSA *dsa; #endif /* HAVE_SSL */ if (!k) { @@ -1087,6 +1091,8 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) case LDNS_SIGN_RSAMD5: /* copied by looking at dnssec-keygen output */ /* header */ + rsa = ldns_key_rsa_key(k); + ldns_buffer_printf(output,"Private-key-format: v1.2\n"); if (ldns_key_algorithm(k) == LDNS_SIGN_RSAMD5) { ldns_buffer_printf(output,"Algorithm: 1 (RSA)\n"); @@ -1097,7 +1103,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) /* print to buf, convert to bin, convert to b64, * print to buf */ ldns_buffer_printf(output, "Modulus: "); - i = (uint16_t)BN_bn2bin(ldns_key_rsa_key(k)->n, bignum); + i = (uint16_t)BN_bn2bin(rsa->n, bignum); if (i > LDNS_MAX_KEYLEN) { goto error; } @@ -1107,9 +1113,8 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } ldns_rdf_deep_free(b64_bignum); ldns_buffer_printf(output, "\n"); - ldns_buffer_printf(output, "PublicExponent: "); - i = (uint16_t)BN_bn2bin(ldns_key_rsa_key(k)->e, bignum); + i = (uint16_t)BN_bn2bin(rsa->e, bignum); if (i > LDNS_MAX_KEYLEN) { goto error; } @@ -1121,142 +1126,190 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "PrivateExponent: "); - i = (uint16_t)BN_bn2bin(ldns_key_rsa_key(k)->d, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (rsa->d) { + i = (uint16_t)BN_bn2bin(rsa->d, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); - + ldns_buffer_printf(output, "Prime1: "); - i = (uint16_t)BN_bn2bin(ldns_key_rsa_key(k)->p, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (rsa->p) { + i = (uint16_t)BN_bn2bin(rsa->p, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "Prime2: "); - i = (uint16_t)BN_bn2bin(ldns_key_rsa_key(k)->q, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (rsa->q) { + i = (uint16_t)BN_bn2bin(rsa->q, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "Exponent1: "); - i = (uint16_t)BN_bn2bin(ldns_key_rsa_key(k)->dmp1, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (rsa->dmp1) { + i = (uint16_t)BN_bn2bin(rsa->dmp1, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "Exponent2: "); - i = (uint16_t)BN_bn2bin(ldns_key_rsa_key(k)->dmq1, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (rsa->dmq1) { + i = (uint16_t)BN_bn2bin(rsa->dmq1, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "Coefficient: "); - i = (uint16_t)BN_bn2bin(ldns_key_rsa_key(k)->iqmp, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (rsa->iqmp) { + i = (uint16_t)BN_bn2bin(rsa->iqmp, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); + + RSA_free(rsa); break; case LDNS_SIGN_DSA: + dsa = ldns_key_dsa_key(k); + ldns_buffer_printf(output,"Private-key-format: v1.2\n"); ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n"); /* print to buf, convert to bin, convert to b64, * print to buf */ ldns_buffer_printf(output, "Prime(p): "); - i = (uint16_t)BN_bn2bin(ldns_key_dsa_key(k)->p, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (dsa->p) { + i = (uint16_t)BN_bn2bin(dsa->p, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "Subprime(q): "); - i = (uint16_t)BN_bn2bin(ldns_key_dsa_key(k)->q, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (dsa->q) { + i = (uint16_t)BN_bn2bin(dsa->q, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "Base(g): "); - i = (uint16_t)BN_bn2bin(ldns_key_dsa_key(k)->g, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (dsa->g) { + i = (uint16_t)BN_bn2bin(dsa->g, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "Private_value(x): "); - i = (uint16_t)BN_bn2bin(ldns_key_dsa_key(k)->priv_key, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (dsa->priv_key) { + i = (uint16_t)BN_bn2bin(dsa->priv_key, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); ldns_buffer_printf(output, "Public_value(y): "); - i = (uint16_t)BN_bn2bin(ldns_key_dsa_key(k)->pub_key, bignum); - if (i > LDNS_MAX_KEYLEN) { - goto error; - } - b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); - if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { - goto error; + if (dsa->pub_key) { + i = (uint16_t)BN_bn2bin(dsa->pub_key, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); } - ldns_rdf_deep_free(b64_bignum); - ldns_buffer_printf(output, "\n"); break; case LDNS_SIGN_HMACMD5: /* is the filefmt specified for TSIG.. don't know */ diff --git a/keys.c b/keys.c index 53f3aab7..116176fb 100644 --- a/keys.c +++ b/keys.c @@ -16,6 +16,7 @@ #ifdef HAVE_SSL #include +#include #endif /* HAVE_SSL */ ldns_lookup_table ldns_signing_algorithms[] = { @@ -56,11 +57,10 @@ ldns_key_new() ldns_key_set_inception(newkey, 0); ldns_key_set_expiration(newkey, 0); ldns_key_set_pubkey_owner(newkey, NULL); - ldns_key_set_rsa_key(newkey, NULL); - ldns_key_set_dsa_key(newkey, NULL); ldns_key_set_hmac_key(newkey, NULL); return newkey; } +return NULL; } ldns_status @@ -69,6 +69,24 @@ ldns_key_new_frm_fp(ldns_key **k, FILE *fp) return ldns_key_new_frm_fp_l(k, fp, NULL); } +#ifdef HAVE_SSL +ldns_status +ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm alg) +{ + ldns_key *k; + + k = ldns_key_new(); + k->_key.key = ENGINE_load_private_key(e, key_id, UI_OpenSSL(), NULL); + ldns_key_set_algorithm(k, alg); + if (!k->_key.key) { + return LDNS_STATUS_ENGINE_KEY_NOT_LOADED; + } else { + *key = k; + return LDNS_STATUS_OK; + } +} +#endif + ldns_status ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) { @@ -76,6 +94,8 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) char *d; ldns_signing_algorithm alg; ldns_rr *key_rr; + RSA *rsa; + DSA *dsa; k = ldns_key_new(); @@ -128,20 +148,23 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) return LDNS_STATUS_SYNTAX_ALG_ERR; case LDNS_SIGN_RSAMD5: case LDNS_SIGN_RSASHA1: - ldns_key_set_algorithm(k, alg); - ldns_key_set_rsa_key(k, ldns_key_new_frm_fp_rsa_l(fp, line_nr)); - + rsa = ldns_key_new_frm_fp_rsa_l(fp, line_nr); + ldns_key_set_rsa_key(k, rsa); + RSA_free(rsa); break; case LDNS_SIGN_DSA: ldns_key_set_algorithm(k, alg); - ldns_key_set_dsa_key(k, ldns_key_new_frm_fp_dsa_l(fp, line_nr)); + dsa = ldns_key_new_frm_fp_dsa_l(fp, line_nr); + ldns_key_set_dsa_key(k, dsa); + DSA_free(dsa); break; } key_rr = ldns_key2rr(k); ldns_key_set_keytag(k, ldns_calc_keytag(key_rr)); ldns_rr_free(key_rr); + if (key) { *key = k; return LDNS_STATUS_OK; @@ -393,6 +416,7 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) if (RSA_check_key(r) != 1) { return NULL; } + ldns_key_set_rsa_key(k, r); break; case LDNS_SIGN_DSA: @@ -438,16 +462,26 @@ ldns_key_set_flags(ldns_key *k, uint16_t f) k->_extra.dnssec.flags = f; } +void +ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e) +{ + k->_key.key = e; +} + void ldns_key_set_rsa_key(ldns_key *k, RSA *r) { - k->_key.rsa = r; + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_set1_RSA(key, r); + k->_key.key = key; } void ldns_key_set_dsa_key(ldns_key *k, DSA *d) { - k->_key.dsa = d; + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_set1_DSA(key, d); + k->_key.key = key; } void @@ -509,16 +543,22 @@ ldns_key_algorithm(const ldns_key *k) return k->_alg; } +EVP_PKEY * +ldns_key_evp_key(const ldns_key *k) +{ + return k->_key.key; +} + RSA * ldns_key_rsa_key(const ldns_key *k) { - return k->_key.rsa; + return EVP_PKEY_get1_RSA(k->_key.key); } DSA * ldns_key_dsa_key(const ldns_key *k) { - return k->_key.dsa; + return EVP_PKEY_get1_DSA(k->_key.key); } unsigned char * @@ -691,6 +731,8 @@ ldns_key2rr(const ldns_key *k) ldns_rdf *keybin; unsigned char *bin; uint16_t size; + RSA *rsa = NULL; + DSA *dsa = NULL; pubkey = ldns_rr_new(); if (!k) { @@ -720,22 +762,40 @@ ldns_key2rr(const ldns_key *k) case LDNS_SIGN_RSAMD5: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_RSAMD5)); - if (!ldns_key_rsa2bin(bin, ldns_key_rsa_key(k), &size)) { + rsa = ldns_key_rsa_key(k); + if (!rsa) { return NULL; + } else { + if (!ldns_key_rsa2bin(bin, rsa, &size)) { + return NULL; + } + RSA_free(rsa); } break; case LDNS_SIGN_RSASHA1: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_RSASHA1)); - if (!ldns_key_rsa2bin(bin, ldns_key_rsa_key(k), &size)) { + rsa = ldns_key_rsa_key(k); + if (!rsa) { return NULL; + } else { + if (!ldns_key_rsa2bin(bin, rsa, &size)) { + return NULL; + } + RSA_free(rsa); } break; case LDNS_SIGN_DSA: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA)); - if (!ldns_key_dsa2bin(bin, ldns_key_dsa_key(k), &size)) { + rsa = ldns_key_dsa_key(k); + if (!rsa) { return NULL; + } else { + if (!ldns_key_dsa2bin(bin, dsa, &size)) { + return NULL; + } + DSA_free(dsa); } break; case LDNS_SIGN_HMACMD5: @@ -762,6 +822,7 @@ ldns_key_deep_free(ldns_key *key) if (ldns_key_pubkey_owner(key)) { ldns_rdf_deep_free(ldns_key_pubkey_owner(key)); } +/* switch(ldns_key_algorithm(key)) { case LDNS_SIGN_RSASHA1: case LDNS_SIGN_RSAMD5: @@ -777,6 +838,10 @@ ldns_key_deep_free(ldns_key *key) case LDNS_SIGN_HMACMD5: break; } +*/ + if (ldns_key_evp_key(key)) { + EVP_PKEY_free(ldns_key_evp_key(key)); + } LDNS_FREE(key); } diff --git a/ldns/dnssec.h b/ldns/dnssec.h index 0e4c26fb..de0cade1 100644 --- a/ldns/dnssec.h +++ b/ldns/dnssec.h @@ -24,6 +24,7 @@ #ifdef HAVE_SSL #include +#include #endif /* HAVE_SSL */ #include #include @@ -86,6 +87,19 @@ ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const */ ldns_status ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key); +/** + * verifies a buffer with signature data for a buffer with rrset data + * with an EVP_PKEY + * + * \param[in] sig the signature data + * \param[in] rrset the rrset data, sorted and processed for verification + * \param[in] key the EVP key structure + * \param[in] digest_type The digest type of the signature + */ +#ifdef HAVE_SSL +ldns_status ldns_verify_rrsig_evp(ldns_buffer *sig, ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type); +#endif + /** * verifies a buffer with signature data (DSA) for a buffer with rrset data * with a buffer with key data. @@ -161,6 +175,7 @@ ldns_rr_list *ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys); * \return a ldns_rdf with the signed data */ ldns_rdf *ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key); +ldns_rdf *ldns_sign_public_evp(ldns_buffer *to_sign, EVP_PKEY *key, const EVP_MD *digest_type); /** * Sign a buffer with the RSA key (hash with MD5) * \param[in] to_sign buffer with the data @@ -229,7 +244,7 @@ ldns_status ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_li * \return the signed zone */ ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list); - + /** * Initialize the random function. This calls OpenSSL * \param[in] fd a file providing entropy data diff --git a/ldns/error.h b/ldns/error.h index 0e01f1a0..a3a86761 100644 --- a/ldns/error.h +++ b/ldns/error.h @@ -60,6 +60,7 @@ enum ldns_enum_status LDNS_STATUS_CRYPTO_TSIG_ERR, LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION, LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR, + LDNS_STATUS_ENGINE_KEY_NOT_LOADED, LDNS_STATUS_RES_NO_NS, LDNS_STATUS_RES_QUERY, LDNS_STATUS_WIRE_INCOMPLETE_HEADER, diff --git a/ldns/keys.h b/ldns/keys.h index eeced611..757d0384 100644 --- a/ldns/keys.h +++ b/ldns/keys.h @@ -87,8 +87,7 @@ struct ldns_struct_key { /* TODO remove unions? */ union { #ifdef HAVE_SSL - RSA *rsa; - DSA *dsa; + EVP_PKEY *key; #endif /* HAVE_SSL */ unsigned char *hmac; } _key; @@ -171,6 +170,13 @@ ldns_status ldns_key_new_frm_fp(ldns_key **k, FILE *fp); ldns_status ldns_key_new_frm_fp_l(ldns_key **k, FILE *fp, int *line_nr); #ifdef HAVE_SSL +/** + * Read the key with the given id from the given engine and store it + * in the given ldns_key structure. The algorithm type is set + */ +ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm); + + /** * frm_fp helper function. This function parsed the * remainder of the (RSA) priv. key file generated from bind9 @@ -220,6 +226,12 @@ DSA *ldns_key_new_frm_fp_dsa_l(FILE *fp, int *line_nr); */ void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l); #ifdef HAVE_SSL +/** + * Set the key's evp key + * \param[in] k the key + * \param[in] e the evp key + */ +void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e); /** * Set the key's rsa data * \param[in] k the key @@ -312,6 +324,12 @@ ldns_key *ldns_key_list_key(const ldns_key_list *key, size_t nr); * \return the RSA * structure in the key */ RSA *ldns_key_rsa_key(const ldns_key *k); +/** + * returns the (openssl) EVP struct contained in the key + * \param[in] k the key to look in + * \return the RSA * structure in the key + */ +EVP_PKEY *ldns_key_evp_key(const ldns_key *k); #endif /* HAVE_SSL */ /**