$OpenBSD: patch-dnssec_c,v 1.1 2016/01/16 13:15:26 sthen Exp $

Fix ECDSA signature generation, do not omit leading zeroes.
http://git.nlnetlabs.nl/ldns/commit/?h=develop&id=1139fdc7f6d78cc9a93e46d3defcd05d15c45af0

--- dnssec.c.orig	Fri Jan 10 16:04:41 2014
+++ dnssec.c	Fri Jan 15 23:06:29 2016
@@ -1806,7 +1806,8 @@ ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_bu
 #ifdef USE_ECDSA
 #ifndef S_SPLINT_S
 ldns_rdf *
-ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len)
+ldns_convert_ecdsa_rrsig_asn1len2rdf(const ldns_buffer *sig,
+	const long sig_len, int num_bytes)
 {
         ECDSA_SIG* ecdsa_sig;
 	unsigned char *data = (unsigned char*)ldns_buffer_begin(sig);
@@ -1815,16 +1816,22 @@ ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *s
         if(!ecdsa_sig) return NULL;
 
         /* "r | s". */
-        data = LDNS_XMALLOC(unsigned char,
-                BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s));
+        if(BN_num_bytes(ecdsa_sig->r) > num_bytes ||
+		BN_num_bytes(ecdsa_sig->s) > num_bytes) {
+                ECDSA_SIG_free(ecdsa_sig);
+		return NULL; /* numbers too big for passed curve size */
+	}
+        data = LDNS_XMALLOC(unsigned char, num_bytes*2);
         if(!data) {
                 ECDSA_SIG_free(ecdsa_sig);
                 return NULL;
         }
-        BN_bn2bin(ecdsa_sig->r, data);
-        BN_bn2bin(ecdsa_sig->s, data+BN_num_bytes(ecdsa_sig->r));
-	rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)(
-		BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)), data);
+	/* write the bignums (in big-endian) a little offset if the BN code
+	 * wants to write a shorter number of bytes, with zeroes prefixed */
+	memset(data, 0, num_bytes*2);
+        BN_bn2bin(ecdsa_sig->r, data+num_bytes-BN_num_bytes(ecdsa_sig->r));
+        BN_bn2bin(ecdsa_sig->s, data+num_bytes*2-BN_num_bytes(ecdsa_sig->s));
+	rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)(num_bytes*2), data);
         ECDSA_SIG_free(ecdsa_sig);
         return rdf;
 }
