summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFederico Lucifredi <flucifredi@acm.org>2008-01-21 05:32:35 +0000
committerFederico Lucifredi <flucifredi@acm.org>2008-01-21 05:32:35 +0000
commit6197fe64852c19670e10451d29566a4035069930 (patch)
tree6400b0b2bcb2036378e39648c61d5198b3abfbd8
parent0c5214b1797bd794556561e2e69303338d73eec6 (diff)
added RSA-SHA1 signature path.
git-svn-id: file:///home/lennart/svn/public/avahi/branches/federico2@1736 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
-rw-r--r--avahi-core/dns.c101
-rw-r--r--avahi-core/dns.h4
-rw-r--r--avahi-core/domain-util.c29
-rw-r--r--avahi-core/domain-util.h6
4 files changed, 122 insertions, 18 deletions
diff --git a/avahi-core/dns.c b/avahi-core/dns.c
index 3b88a20..61f094b 100644
--- a/avahi-core/dns.c
+++ b/avahi-core/dns.c
@@ -907,12 +907,13 @@ size_t avahi_rdata_serialize(AvahiRecord *record, void *rdata, size_t max_size)
}
/* TODO: should this be located in this file? */
-/* r = avahi_get_local_zsk_pubkey("riker.local", <ttl>) */
-AvahiRecord* avahi_get_local_zsk_pubkey(const unsigned char* keyname, uint32_t ttl){
+/* r = avahi_get_local_zsk_pubkey(<ttl>) */
+AvahiRecord* avahi_get_local_zsk_pubkey(uint32_t ttl){
AvahiRecord *r;
- r = avahi_record_new_full(keyname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_DNSKEY, 0);
+ /* TODO: in merged version into upstream, authority needs to be an external configurable pulled from config file */
+ r = avahi_record_new_full("riker.local", AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_DNSKEY, 0);
if (!r) { /* OOM check */
avahi_log_error("avahi_record_new_full() failed.");
@@ -925,7 +926,7 @@ AvahiRecord* avahi_get_local_zsk_pubkey(const unsigned char* keyname, uint32_t t
r->data.dnskey.protocol = AVAHI_DNSSEC_PROTO; /* used for "compatibility" with KEY record */
- /* TODO: in merged version into upstream, key needs to be an external configurable pulled from /etc */
+ /* TODO: in merged version into upstream, key, algorithm need to be external configurables pulled from config file */
/* in the prototype, we just statically configure */
r->data.dnskey.algorithm = AVAHI_DNSSEC_KEY_SHA1; /* SHA1 is mandatory in the spec, but others do exist */
@@ -938,13 +939,21 @@ AvahiRecord* avahi_get_local_zsk_pubkey(const unsigned char* keyname, uint32_t t
return r;
}
-/* invoke as avahi_dnssec_sign_record(<record>, "reiker.local", <ttl>) */
-AvahiRecord avahi_dnssec_sign_record(AvahiRecord *s, const char *authority, uint32_t ttl){
+/* invoke as avahi_dnssec_sign_record(<record>, <ttl>) */
+AvahiRecord avahi_dnssec_sign_record(AvahiRecord *s, uint32_t ttl){
AvahiRecord *r;
AvahiRecord *key;
int result;
+ char *canonic; /*used in conversions */
+ AvahiDNSPacket *tmp;
+
+ unsigned char signature[EVP_MAX_MD_SIZE]; /*used for signing */
+ HMAC_CTX ctx;
+ unsigned signature_length;
+
+
r = avahi_record_new_full(keyname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_RRSIG, 0);
if (!r) { /* OOM check */
@@ -953,7 +962,7 @@ AvahiRecord avahi_dnssec_sign_record(AvahiRecord *s, const char *authority, uint
}
/* type of covered record */
- r->data.rrsig.type_covered = s->key.clazz;
+ r->data.rrsig.type_covered = s->key.type;
/* SHA1 is mandatory in the spec (MUST), but other options are available */
r->data.rrsig.algorithm = AVAHI_DNSSEC_KEY_SHA1;
@@ -971,15 +980,85 @@ AvahiRecord avahi_dnssec_sign_record(AvahiRecord *s, const char *authority, uint
r->data.rrsig.signature_inception = time(NULL) - AVAHI_DNSSEC_TIME_DRIFT;
/* retrieve RRSIG record representing localhost's trust */
- key = avahi_get_local_zsk_pubkey(authority, ttl);
+ key = avahi_get_local_zsk_pubkey(ttl);
- /* generate keytag of the localhos's pubkey */
+ /* generate keytag of the localhost's pubkey */
r->data.rrsig.keytag = avahi_keytag(key);
+ /* <localhost>+".local", to be retrieved from future *private* crypto config file along with local ZSK keypair */
+ r->data.rrsig.signers_name = avahi_strdup (key->key->name);
+
avahi_free(key);
- /* <localhost>+".local", to be retrieved from future *private* crypto config file along with local ZSK keypair */
- r->data.rrsig.signers_name = avahi_strdup (authority);
+ /* now the signature proper */
+
+ switch (r->data.dnskey.algorithm){
+
+ case AVAHI_DNSSEC_KEY_SHA1 : EVP_SigInit(&ctx, EVP_sha1());
+ break; /* RSA SHA1 is only mandatory in the spec, others exist */
+
+ default: avahi_log_error("Unknown algorithm requested from avahi_dnssec_sign_record()");
+ return NULL;
+ }
+
+ /* generate HASH for signing */
+
+ /*from the RRSIG itself first */
+
+ /* type of RR covered by signature */
+ EVP_SignUpdate(&ctx, avahi_uint16_to_canonical_string(r->data.rrsig.type_covered), 2);
+
+ /* algorithm */
+ EVP_SignUpdate(&ctx, &r->data.rrsig.algorithm, 1);
+
+ /* labels count */
+ EVP_SignUpdate(&ctx, &r->data.rrsig.labels, 1);
+
+ /* original TTL */
+ EVP_SignUpdate(&ctx, avahi_uint32_to_canonical_string(r->data.rrsig.original_ttl), 4);
+
+ /* signature expiration */
+ EVP_SignUpdate(&ctx, avahi_uint32_to_canonical_string(r->data.rrsig.signature_expiration), 4);
+
+ /* signature inception */
+ EVP_SignUpdate(&ctx, avahi_uint32_to_canonical_string(r->data.rrsig.signature_inception), 4);
+
+ /* type of RR covered by signature */
+ EVP_SignUpdate(&ctx, avahi_uint16_to_canonical_string(r->data.rrsig.key_tag), 2);
+
+ /* authority */
+ canonic = avahi_c_to_canonical_string(r->data->signers_name); /* signer's name in canonical wire format (DNS labels) */
+ EVP_SignUpdate(&ctx, canonic, strlen(canonic) +1);
+
+ /* now the DNS record that we are signing, complete and in wire format */
+ tmp = avahi_dns_packet_new_query(0); /* MTU */
+
+ if (!tmp) { /*OOM check */
+ avahi_log_error("avahi_dns_packet_new_query() failed.");
+ assert(tmp);
+ }
+
+ /* no TTL binding, leave record unaltered */
+ result = avahi_dns_packet_append_record(tmp, s, 0, 0);
+
+ if (!result) {
+ avahi_log_error("appending of rdata failed.");
+ assert(result);
+ }
+
+ /* update RRSET we modified - RRSET is arbitrary in this case */
+ avahi_dns_packet_set_field(tmp, AVAHI_DNS_FIELD_ARCOUNT, 1);
+
+ /* now select the right chunk of the packet to get the wire format of the record's RDATA */
+ EVP_SignUpdate(&ctx, AVAHI_DNS_PACKET_DATA(tmp) + AVAHI_DNS_PACKET_HEADER_SIZE, tmp->size - AVAHI_DNS_PACKET_HEADER_SIZE);
+
+ /* now get the signature of the secure hash we just generated*/
+ EVP_SignFinal(&ctx, signature, &signature_length, private_key);
+
+ avahi_free(tmp);
+
+ /*finally, add the signature to the record */
+ r->data.rrsig.signature = avahi_strndup(signature, signature_length);
return r;
}
diff --git a/avahi-core/dns.h b/avahi-core/dns.h
index 01c92aa..baabc8a 100644
--- a/avahi-core/dns.h
+++ b/avahi-core/dns.h
@@ -79,8 +79,8 @@ int avahi_dns_packet_skip(AvahiDnsPacket *p, size_t length);
int avahi_dns_packet_is_empty(AvahiDnsPacket *p);
size_t avahi_dns_packet_space(AvahiDnsPacket *p);
-AvahiRecord* avahi_get_local_zsk_pubkey(const unsigned char* keyname, uint32_t ttl);
-AvahiRecord avahi_dnssec_sign_record(AvahiRecord *s, const char *authority, uint32_t ttl);
+AvahiRecord* avahi_get_local_zsk_pubkey(uint32_t ttl);
+AvahiRecord avahi_dnssec_sign_record(AvahiRecord *s, uint32_t ttl);
AvahiRecord* avahi_get_local_trust_record();
diff --git a/avahi-core/domain-util.c b/avahi-core/domain-util.c
index f4bcdc0..07d1fb1 100644
--- a/avahi-core/domain-util.c
+++ b/avahi-core/domain-util.c
@@ -224,6 +224,25 @@ unsigned char * avahi_c_to_canonical_string(const char* input)
return retval;
}
+unsigned char * avahi_uint16_to_canonical_string(uint16_t v) {
+ uint8_t *c = avahi_malloc(2);
+
+ c[0] = (uint8_t) (v >> 8);
+ c[1] = (uint8_t) v;
+ return c;
+}
+
+unsigned char * avahi_uint32_to_canonical_string(uint32_t v) {
+ uint8_t *c = avahi_malloc(4);
+
+ c[0] = (uint8_t) (v >> 24);
+ c[1] = (uint8_t) (v >> 16);
+ c[2] = (uint8_t) (v >> 8);
+ c[3] = (uint8_t) v;
+
+ return c;
+}
+
uint8_t avahi_count_canonical_labels(const char* input){
char *p;
uint8_t count;
@@ -261,11 +280,11 @@ uint16_t avahi_keytag(AvahiRecord r){
if (r->key.type != AVAHI_DNS_TYPE_RRSIG)
return NULL; /* invalid RRTYPE to generate keytag on */
- p = avahi_dns_packet_new_query(0); /* MTU */
+ tmp = avahi_dns_packet_new_query(0); /* MTU */
- if (!p) { /*OOM check */
- avahi_log_error("avahi_dns_packet_new_update() failed.");
- assert(p);
+ if (!tmp) { /*OOM check */
+ avahi_log_error("avahi_dns_packet_new_query() failed.");
+ assert(tmp);
}
/* no TTL binding, leave record unaltered */
@@ -277,7 +296,7 @@ uint16_t avahi_keytag(AvahiRecord r){
}
/* update RRSET we modified */
- avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_ARCOUNT, 1);
+ avahi_dns_packet_set_field(tmp, AVAHI_DNS_FIELD_ARCOUNT, 1);
/* finally, generate keytag */
/* first arg is rdata address, second arg is rdlength */
diff --git a/avahi-core/domain-util.h b/avahi-core/domain-util.h
index 1e71426..1fdb4f0 100644
--- a/avahi-core/domain-util.h
+++ b/avahi-core/domain-util.h
@@ -45,6 +45,12 @@ int avahi_domain_ends_with(const char *domain, const char *suffix);
/** returns canonical DNS representation of C string representing a domain */
unsigned char * avahi_c_to_canonical_string(const char* input);
+/** returns canonical wire representation of uint16 */
+unsigned char * avahi_uint16_to_canonical_string(uint16_t v);
+
+/** returns canonical wire representation of uint32 */
+unsigned char * avahi_uint32_to_canonical_string(uint32_t v);
+
/** returns the number of labels in a canonical DNS domain */
uint8_t avahi_count_canonical_labels(const char* input);