]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
hmac-md5 support in key generation and reading
authorJelte Jansen <jelte@NLnetLabs.nl>
Wed, 31 Oct 2007 15:05:55 +0000 (15:05 +0000)
committerJelte Jansen <jelte@NLnetLabs.nl>
Wed, 31 Oct 2007 15:05:55 +0000 (15:05 +0000)
fixed random seeder init function

dnssec.c
examples/ldns-keygen.1
examples/ldns-keygen.c
host2str.c
keys.c
ldns/dnssec.h
ldns/keys.h

index 6558e6b4283e10d8453e0d225ccf50557de3fb30..d9a1760bcd445814ce2570f42f43a15bee9d56bc 100644 (file)
--- a/dnssec.c
+++ b/dnssec.c
@@ -937,7 +937,9 @@ ldns_calc_keytag(const ldns_rr *key)
 printf("calc keytag for key at %p:\n", key);
 ldns_rr_print(stdout, key);
 */
-       if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) {
+       if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY &&
+           ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY
+          ) {
                return 0;
        }
 
@@ -3470,36 +3472,33 @@ ldns_rr_list_print(stdout, signed_zone_rrs);
  * apps must call this 
  */
 ldns_status 
-ldns_init_random(FILE *fd, uint16_t bytes
+ldns_init_random(FILE *fd) 
 {
-       FILE *rand;
-       uint8_t *buf;
-
-       buf = LDNS_XMALLOC(uint8_t, bytes);
-       if (!buf) {
-               return LDNS_STATUS_ERR;;
-       }
+       /* if fp is given, seed srand with data from file
+          otherwise use /dev/urandom */
+       FILE *rand_f;
+       unsigned int seed;
+       size_t read;
+       
        if (!fd) {
-               if ((rand = fopen("/dev/urandom", "r")) == NULL) {
-                       LDNS_FREE(buf);
+               if ((rand_f = fopen("/dev/urandom", "r")) == NULL) {
                        return LDNS_STATUS_ERR;
                }
        } else {
-               rand = fd;
+               rand_f = fd;
        }
-
-       if ((fread(buf, sizeof(uint8_t), (size_t)bytes, rand) != bytes)) {
-               LDNS_FREE(buf);
-               if (!fd) {
-                       fclose(rand);
-               }
+          
+       read = fread(&seed, sizeof(seed), 1, rand_f);
+       if (read == 0) {
                return LDNS_STATUS_ERR;
+       } else {
+               srand(seed);
        }
+       
        if (!fd) {
-               fclose(rand);
+               fclose(rand_f);
        }
-       RAND_seed((const void *)buf, (int)bytes);
-       LDNS_FREE(buf);
+
        return LDNS_STATUS_OK;
 }
 
index 080361a51d92af5e4db4ecd2235cadccb5d49fab..91fb6389b4825b98d94e206d535ebc164ff1e18c 100644 (file)
@@ -19,12 +19,16 @@ It prints out the basename for these files: K<name>+<alg>+<id>
 .SH OPTIONS
 .TP
 \fB-R\fR
-Generate a RSA key. 
+Generate an RSA key. 
 
 .TP
 \fB-D\fR
 Generate a DSA key.
 
+.TP
+\fB-D\fR
+Generate an HMAC-MD5 key.
+
 .TP
 \fB-k\fR 
 When given generate a key signing key. This just sets the flag field to
@@ -36,8 +40,8 @@ Use this many bits for the key length.
 
 .TP
 \fb-r \fIdevice\fR
-Make ldns-keygen use this file for its random data. This will default
-to /dev/random.
+Make ldns-keygen use this file to seed the random generator with. This will
+default to /dev/random.
 
 .TP
 \fb-v\fR
index 1c850d17d5a70a0822093523b99de95d3179a3e6..0b341548af95c0145c9d122445ad5db16bc094ad 100644 (file)
@@ -17,15 +17,17 @@ usage(FILE *fp, char *prog) {
        fprintf(fp, "%s [-D|-R] [-b bits] [-r /dev/random] [-v] domain\n", prog);
        fprintf(fp, "  generate a new key pair for domain\n");
        fprintf(fp, "  -D\tgenerate a DSA key\n");
-       fprintf(fp, "  -R\tgenerate a RSA key\n");
+       fprintf(fp, "  -R\tgenerate an RSA key\n");
+       fprintf(fp, "  -H\tgenerate an HMAC-MD5 key (for TSIG)\n");
        fprintf(fp, "  -k\tset the flags to 257; key signing key\n");
        fprintf(fp, "  -b <bits>\tspecify the keylength\n");
        fprintf(fp, "  -r <random>\tspecify a random device (defaults to /dev/random)\n");
+       fprintf(fp, "\t\tto seed the random generator with\n");
        fprintf(fp, "  -v\t\tshow the version and exit\n");
        fprintf(fp, "  The following files will be created:\n");
        fprintf(fp, "    K<name>+<alg>+<id>.key\tPublic key in RR format\n");
        fprintf(fp, "    K<name>+<alg>+<id>.private\tPrivate key in key format\n");
-       fprintf(fp, "    K<name>+<alg>+<id>.ds\tDS in RR format\n");
+       fprintf(fp, "    K<name>+<alg>+<id>.ds\tDS in RR format (only for DNSSEC keys)\n");
        fprintf(fp, "  The base name (K<name>+<alg>+<id> will be printed to stdout\n");
 }
 
@@ -56,22 +58,28 @@ main(int argc, char *argv[])
        random = NULL;
        ksk = false; /* don't create a ksk per default */
        
-       while ((c = getopt(argc, argv, "DRkb:r:v")) != -1) {
+       while ((c = getopt(argc, argv, "DRHkb:r:v")) != -1) {
                switch (c) {
                case 'D':
                        if (algorithm != 0) {
-                               fprintf(stderr, "%s: %s", prog, "Only one -D or -A is allowed\n");
+                               fprintf(stderr, "%s: %s", prog, "Only one of -D, -A or -H is allowed\n");
                                exit(EXIT_FAILURE);
                        }
                        algorithm = LDNS_SIGN_DSA;
                        break;
                case 'R':
                        if (algorithm != 0) {
-                               fprintf(stderr, "%s: %s", prog, "Only one -D or -A is allowed\n");
+                               fprintf(stderr, "%s: %s", prog, "Only one of -D, -A or -H is allowed\n");
                                exit(EXIT_FAILURE);
                        }
                        algorithm = LDNS_SIGN_RSASHA1;
                        break;
+                case 'H':
+                       if (algorithm != 0) {
+                               fprintf(stderr, "%s: %s", prog, "Only one of -D, -A or -H is allowed\n");
+                       }
+                       algorithm = LDNS_SIGN_HMACMD5;
+                       break;
                case 'b':
                        bits = (uint16_t) atoi(optarg);
                        if (bits == 0) {
@@ -110,12 +118,18 @@ main(int argc, char *argv[])
                exit(EXIT_FAILURE);
        } 
        free(prog);
-
-       (void)ldns_init_random(random, def_bits * 8 * 2); /* I hope this is enough? */
-       if (random) {
-               fclose(random);
+       
+       if (!random) {
+               random = fopen("/dev/random", "r");
+               if (!random) {
+                       fprintf(stderr, "Cannot open random file %s: %s\n", optarg, strerror(errno));
+                       exit(EXIT_FAILURE);
+               }
        }
 
+       (void)ldns_init_random(random);
+       fclose(random);
+
        /* create an rdf from the domain name */
        domain = ldns_dname_new_frm_str(argv[0]);
 
@@ -182,23 +196,24 @@ main(int argc, char *argv[])
        }
        
        /* print the DS to .ds */
-       filename = LDNS_XMALLOC(char, strlen(owner) + 16);
-       snprintf(filename, strlen(owner) + 15, "K%s+%03u+%05u.ds", owner, algorithm, (unsigned int) ldns_key_keytag(key));
-       file = fopen(filename, "w");
-       if (!file) {
-               fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
-               ldns_key_deep_free(key);
-               free(owner);
-               ldns_rr_free(pubkey);
-               ldns_rr_free(ds);
-               LDNS_FREE(filename);
-               exit(EXIT_FAILURE);
-       } else {
-               ldns_rr_print(file, ds);
-               fclose(file);
-               LDNS_FREE(filename);
-       }
-       
+       if (algorithm != LDNS_SIGN_HMACMD5) {
+               filename = LDNS_XMALLOC(char, strlen(owner) + 16);
+               snprintf(filename, strlen(owner) + 15, "K%s+%03u+%05u.ds", owner, algorithm, (unsigned int) ldns_key_keytag(key));
+               file = fopen(filename, "w");
+               if (!file) {
+                       fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
+                       ldns_key_deep_free(key);
+                       free(owner);
+                       ldns_rr_free(pubkey);
+                       ldns_rr_free(ds);
+                       LDNS_FREE(filename);
+                       exit(EXIT_FAILURE);
+               } else {
+                       ldns_rr_print(file, ds);
+                       fclose(file);
+                       LDNS_FREE(filename);
+               }
+       }       
 #if 0
        /* TEMP: create PEM format too */
        filename = LDNS_XMALLOC(char, strlen(owner) + 17);
index 6898c34f87c5591b84d61c95fbfdf3a8bf4a0fda..3528043f84c1b68ccc50485d2f88f4df9fbd21be 100644 (file)
@@ -1370,7 +1370,17 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
                                break;
                        case LDNS_SIGN_HMACMD5:
                                /* is the filefmt specified for TSIG.. don't know */
-                               goto error;
+                               ldns_buffer_printf(output, "Private-key-format: v1.2\n");
+                               ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n");
+                               ldns_buffer_printf(output, "Key: ");
+                               i = ldns_key_hmac_size(k);
+                               b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, ldns_key_hmac_key(k));
+                               if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+                                       goto error;
+                               }
+                               ldns_rdf_deep_free(b64_bignum);
+                               ldns_buffer_printf(output, "\n"); 
+                               break;
                }
 #endif /* HAVE_SSL */
        } else {
diff --git a/keys.c b/keys.c
index 77d6884e5983774af65893f0c37cd32ce6204390..8443d769a23f110f129e9cf20e842a0bb7a51d56 100644 (file)
--- a/keys.c
+++ b/keys.c
@@ -96,6 +96,8 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
        ldns_rr *key_rr;
        RSA *rsa;
        DSA *dsa;
+       unsigned char *hmac;
+       size_t hmac_size;
 
        k = ldns_key_new();
 
@@ -131,7 +133,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
        }
 
        if (strncmp(d, "1 RSA", 2) == 0) {
-               alg = LDNS_SIGN_RSAMD5; /* md5, really?? */
+               alg = LDNS_SIGN_RSAMD5;
        }
        if (strncmp(d, "3 DSA", 2) == 0) {
                alg = LDNS_SIGN_DSA; 
@@ -145,13 +147,13 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
        if (strncmp(d, "133 RSASHA1", 4) == 0) {
                alg = LDNS_RSASHA1_NSEC3;
        }
+       if (strncmp(d, "157 HMAC-MD5", 4) == 0) {
+               alg = LDNS_SIGN_HMACMD5;
+       }
 
        LDNS_FREE(d);
 
        switch(alg) {
-               case 0:
-               default:
-                       return LDNS_STATUS_SYNTAX_ALG_ERR;
                case LDNS_SIGN_RSAMD5:
                case LDNS_SIGN_RSASHA1:
                case LDNS_RSASHA1_NSEC3:
@@ -167,6 +169,16 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                        ldns_key_set_dsa_key(k, dsa);
                        DSA_free(dsa);
                        break;
+               case LDNS_SIGN_HMACMD5:
+                       ldns_key_set_algorithm(k, alg);
+                       hmac = ldns_key_new_frm_fp_hmac_l(fp, line_nr, &hmac_size);
+                       ldns_key_set_hmac_size(k, hmac_size);
+                       ldns_key_set_hmac_key(k, hmac);
+                       break;
+               case 0:
+               default:
+                       return LDNS_STATUS_SYNTAX_ALG_ERR;
+                       break;
        }
 
        key_rr = ldns_key2rr(k);
@@ -406,12 +418,49 @@ error:
        return NULL;
 }
 
+unsigned char *
+ldns_key_new_frm_fp_hmac(FILE *f, size_t *hmac_size)
+{
+       return ldns_key_new_frm_fp_hmac_l(f, NULL, hmac_size);
+}
+
+unsigned char *
+ldns_key_new_frm_fp_hmac_l(FILE *f, int *line_nr, size_t *hmac_size)
+{
+       int i;
+       char *d;
+       unsigned char *buf;
+
+       line_nr = line_nr;
+
+       d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
+       buf = LDNS_XMALLOC(unsigned char, LDNS_MAX_LINELEN);
+       
+       if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+               goto error;
+       }
+       i = b64_pton((const char*)d, buf, b64_ntop_calculate_size(strlen(d)));
+
+       *hmac_size = i;
+       return buf;
+       
+       error:
+       LDNS_FREE(d);
+       LDNS_FREE(buf);
+       *hmac_size = 0;
+       return NULL;
+}
+
+
 ldns_key *
 ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
 {
        ldns_key *k;
        DSA *d;
        RSA *r;
+       int i;
+       uint16_t offset;
+       unsigned char *hmac;
 
        k = ldns_key_new();
        if (!k) {
@@ -440,7 +489,25 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
                        ldns_key_set_dsa_key(k, d);
                        break;
                case LDNS_SIGN_HMACMD5:
-                       /* do your hmac thing here */
+                       k->_key.key = NULL;
+                       size = size / 8;
+                       ldns_key_set_hmac_size(k, size);
+                        
+                       hmac = LDNS_XMALLOC(unsigned char, size);
+                       offset = 0;
+                       while (offset + sizeof(i) < size) {
+                         i = rand();
+                         memcpy(&hmac[offset], &i, sizeof(i));
+                         offset += sizeof(i);
+                       }
+                       if (offset < size) {
+                         i = rand();
+                         memcpy(&hmac[offset], &i, size - offset);
+                       }
+
+                       ldns_key_set_hmac_key(k, hmac);
+                       
+                       ldns_key_set_flags(k, 0);
                        break;
        }
        ldns_key_set_algorithm(k, alg);
@@ -497,7 +564,13 @@ ldns_key_set_dsa_key(ldns_key *k, DSA *d)
 void
 ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac)
 {
-       k->_key.hmac = hmac;
+       k->_key.hmac.key = hmac;
+}
+
+void
+ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size)
+{
+       k->_key.hmac.size = hmac_size;
 }
 
 void
@@ -574,7 +647,13 @@ ldns_key_dsa_key(const ldns_key *k)
 unsigned char *
 ldns_key_hmac_key(const ldns_key *k)
 {
-       return k->_key.hmac;
+       return k->_key.hmac.key;
+}
+
+size_t
+ldns_key_hmac_size(const ldns_key *k)
+{
+       return k->_key.hmac.size;
 }
 
 uint32_t
@@ -754,7 +833,14 @@ ldns_key2rr(const ldns_key *k)
                return NULL;
        }
 
-       ldns_rr_set_type(pubkey, LDNS_RR_TYPE_DNSKEY);
+       switch (ldns_key_algorithm(k)) {
+       case LDNS_SIGN_HMACMD5:
+               ldns_rr_set_type(pubkey, LDNS_RR_TYPE_KEY);
+               break;
+       default:
+               ldns_rr_set_type(pubkey, LDNS_RR_TYPE_DNSKEY);
+               break;
+        }
        /* zero-th rdf - flags */
        ldns_rr_push_rdf(pubkey,
                        ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 
@@ -824,11 +910,17 @@ ldns_key2rr(const ldns_key *k)
                        break;
                case LDNS_SIGN_HMACMD5:
                        /* tja */
+                       ldns_rr_push_rdf(pubkey,
+                                         ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_SIGN_HMACMD5));
+                        size = ldns_key_hmac_size(k);
+                        bin = LDNS_XREALLOC(bin, unsigned char, size);
+                        memcpy(bin, ldns_key_hmac_key(k), size);
                        break;
        }
        /* fourth the key bin material */
        /* MIEK, not sure about this +1. I've re-added it--needs checking */
-       keybin = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, size + 1, bin);
+       /* TODO: and i've removed it again, it's certainly wrong for HMAC */
+       keybin = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, size, bin);
        LDNS_FREE(bin);
        ldns_rr_push_rdf(pubkey, keybin);
        return pubkey;
@@ -868,6 +960,9 @@ ldns_key_deep_free(ldns_key *key)
        if (ldns_key_evp_key(key)) {
                EVP_PKEY_free(ldns_key_evp_key(key));
        }
+       if (ldns_key_hmac_key(key)) {
+               free(ldns_key_hmac_key(key));
+       }       
        LDNS_FREE(key);
 }
 
index d620ab5650ba0a26b5654487a098d989d3d2a20f..c7ff722f242a42b1fee0928ea634c38b5f58ed17 100644 (file)
@@ -600,12 +600,14 @@ ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list);
 ldns_zone *ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt);
  
 /**
- * Initialize the random function. This calls OpenSSL
- * \param[in] fd a file providing entropy data
+ * Initialize the random function. This calls the OpenSSL srand() function
+ * If the file descriptor is specified, the random generator is seeded with
+ * data from that file. If not, /dev/urandom is used.
+ * \param[in] fd a file providing entropy data for the seed
  * \param[in] bytes number of bytes for the seed
  * \return LDNS_STATUS_OK if init succeeds
  */
-ldns_status ldns_init_random(FILE *fd, uint16_t bytes);
+ldns_status ldns_init_random(FILE *fd);
 
 /**
  * Tries to build an authentication chain from the given keys down to the queried domain.
index fbf3e4046520b961e7a103814c0a237038f279aa..e949a4b6f247c2dbe3f59765e857451d0fbcc549 100644 (file)
@@ -71,7 +71,7 @@ enum ldns_enum_signing_algorithm
        LDNS_SIGN_DSA            = LDNS_DSA,
        LDNS_SIGN_RSASHA1_NSEC3  = LDNS_RSASHA1_NSEC3,
        LDNS_SIGN_DSA_NSEC3      = LDNS_DSA_NSEC3,      
-       LDNS_SIGN_HMACMD5        = 150  /* not official! */
+       LDNS_SIGN_HMACMD5        = 157  /* not official! This type is for TSIG, not DNSSEC */
 };
 typedef enum ldns_enum_signing_algorithm ldns_signing_algorithm;
 
@@ -89,13 +89,16 @@ struct ldns_struct_key {
        ldns_signing_algorithm _alg;
        /** Storage pointers for the types of keys supported */
        /* TODO remove unions? */
-       union {
+       struct {
 #ifdef HAVE_SSL
 #ifndef S_SPLINT_S
                 EVP_PKEY *key;
 #endif
 #endif /* HAVE_SSL */
-               unsigned char *hmac;
+               struct {
+                       unsigned char *key;
+                       size_t size;
+               } hmac;
        } _key;
        /** Depending on the key we can have extra data */
        union {
@@ -184,7 +187,7 @@ ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldn
 
 
 /**
- * frm_fp helper function. This function parsed the
+ * frm_fp helper function. This function parses the
  * remainder of the (RSA) priv. key file generated from bind9
  * \param[in] fp the file to parse
  * \return NULL on failure otherwise a RSA structure
@@ -194,7 +197,7 @@ RSA *ldns_key_new_frm_fp_rsa(FILE *fp);
 
 #ifdef HAVE_SSL
 /**
- * frm_fp helper function. This function parsed the
+ * frm_fp helper function. This function parses the
  * remainder of the (RSA) priv. key file generated from bind9
  * \param[in] fp the file to parse
  * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
@@ -205,8 +208,8 @@ RSA *ldns_key_new_frm_fp_rsa_l(FILE *fp, int *line_nr);
 
 #ifdef HAVE_SSL
 /**
- * frm_fp helper function. This function parsed the
- * remainder of the (DSA) priv. key file generated from bind9
+ * frm_fp helper function. This function parses the
+ * remainder of the (DSA) priv. key file
  * \param[in] fp the file to parse
  * \return NULL on failure otherwise a RSA structure
  */
@@ -215,8 +218,8 @@ DSA *ldns_key_new_frm_fp_dsa(FILE *fp);
 
 #ifdef HAVE_SSL
 /**
- * frm_fp helper function. This function parsed the
- * remainder of the (DSA) priv. key file generated from bind9
+ * frm_fp helper function. This function parses the
+ * remainder of the (DSA) priv. key file
  * \param[in] fp the file to parse
  * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
  * \return NULL on failure otherwise a RSA structure
@@ -224,6 +227,31 @@ DSA *ldns_key_new_frm_fp_dsa(FILE *fp);
 DSA *ldns_key_new_frm_fp_dsa_l(FILE *fp, int *line_nr);
 #endif /* HAVE_SSL */
 
+#ifdef HAVE_SSL
+/**
+ * frm_fp helper function. This function parses the
+ * remainder of the (HMAC-MD5) key file
+ * This function allocated a buffer that needs to be freed
+ * \param[in] fp the file to parse
+ * \param[out] hmac_size the number of bits in the resulting buffer
+ * \return NULL on failure otherwise a newly allocated char buffer
+ */
+unsigned char *ldns_key_new_frm_fp_hmac(FILE *fp, size_t *hmac_size);
+#endif
+
+#ifdef HAVE_SSL
+/**
+ * frm_fp helper function. This function parses the
+ * remainder of the (HMAC-MD5) key file
+ * This function allocated a buffer that needs to be freed
+ * \param[in] fp the file to parse
+ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+ * \param[out] hmac_size the number of bits in the resulting buffer
+ * \return NULL on failure otherwise a newly allocated char buffer
+ */
+unsigned char *ldns_key_new_frm_fp_hmac_l(FILE *fp, int *line_nr, size_t *hmac_size);
+#endif /* HAVE_SSL */
+
 /* acces write functions */
 /**
  * Set the key's algorithm
@@ -254,9 +282,15 @@ void ldns_key_set_dsa_key(ldns_key *k, DSA *d);
 /**
  * Set the key's hmac data
  * \param[in] k the key
- * \param[in] hmac the hmac data
+ * \param[in] hmac_size in nr of bytes
  */
 void ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac);
+/**
+ * Set the key's hmac size
+ * \param[in] k the key
+ * \param[in] hmac the hmac data
+ */
+void ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size);
 /**
  * Set the key's original ttl
  * \param[in] k the key
@@ -357,6 +391,12 @@ ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k);
  * \return the hmac key
  */
 unsigned char *ldns_key_hmac_key(const ldns_key *k);
+/**
+ * return the hmac key size
+ * \param[in] k the key size
+ * \return the hmac key size
+ */
+size_t ldns_key_hmac_size(const ldns_key *k);
 /**
  * return the original ttl of the key
  * \param[in] k the key