[SECNET RFC PATCH 4/4] sig: Move hashing into algorithm

Ian Jackson ijackson at chiark.greenend.org.uk
Fri Sep 27 19:19:13 BST 2019


I think it should be up to the pk algorithm to decide on the hash
function, at least in the usual case.  When we have key rollover and
proper enrolment, a public key declaration by a site should specify
precisely the validation algorithm including the hash function.

For `rsa' we can't do that because in theory people might have bound
the `hash' config key to something unusual.  So provide a way for that
to work.  The approach is to have site.c (the only caller of the sig
closures) find out whether to do the `hash' config key lookup by
seeing whether the pk algorithm wants it.

Then we can move all the hash-related machinations into rsa.c.  (A
future pk algorithm can do this a lot more simply by calling the
appropriate hash functions directly.)

An effect is to move the allocation of the hash result buffer from
per-packet to initialisation (!)

Signed-off-by: Ian Jackson <ijackson at chiark.greenend.org.uk>
---
 rsa.c    | 40 ++++++++++++++++++++++++++++++++++++++--
 secnet.h |  4 ++++
 site.c   | 32 +++++++++++---------------------
 3 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/rsa.c b/rsa.c
index 49672c2..81754a7 100644
--- a/rsa.c
+++ b/rsa.c
@@ -41,10 +41,16 @@
 
 #define mpp(s,n) do { char *p = mpz_get_str(NULL,16,n); printf("%s 0x%sL\n", s, p); free(p); } while (0)
 
+struct rsacommon {
+    struct hash_if *hashi;
+    uint8_t *hashbuf;
+};
+
 struct rsapriv {
     closure_t cl;
     struct sigprivkey_if ops;
     struct cloc loc;
+    struct rsacommon common;
     MP_INT n;
     MP_INT p, dp;
     MP_INT q, dq;
@@ -54,6 +60,7 @@ struct rsapub {
     closure_t cl;
     struct sigpubkey_if ops;
     struct cloc loc;
+    struct rsacommon common;
     MP_INT e;
     MP_INT n;
 };
@@ -67,6 +74,29 @@ struct rsapub {
 
 static const char *hexchars="0123456789abcdef";
 
+static void rsa_sethash(struct rsacommon *c, struct hash_if *hash)
+{
+    free(c->hashbuf);
+    c->hashbuf=safe_malloc(hash->len, "generate_msg");
+    c->hashi=hash;
+}
+static void rsa_pub_sethash(void *sst, struct hash_if *hash)
+{
+    struct rsapub *st=sst;
+    rsa_sethash(&st->common, hash);
+}
+static void rsa_priv_sethash(void *sst, struct hash_if *hash)
+{
+    struct rsapriv *st=sst;
+    rsa_sethash(&st->common, hash);
+}
+static void rsa_hash(struct rsacommon *c, const uint8_t *buf, int32_t len)
+{
+    void *hst=c->hashi->init();
+    c->hashi->update(hst,buf,len);
+    c->hashi->final(hst,c->hashbuf);
+}
+
 static void emsa_pkcs1(MP_INT *n, MP_INT *m,
 		       const uint8_t *data, int32_t datalen)
 {
@@ -126,8 +156,9 @@ static bool_t rsa_sign(void *sst, uint8_t *data, int32_t datalen,
     mpz_init(&a);
     mpz_init(&b);
 
+    rsa_hash(&st->common,data,datalen);
     /* Construct the message representative. */
-    emsa_pkcs1(&st->n, &a, data, datalen);
+    emsa_pkcs1(&st->n, &a, st->common.hashbuf, st->common.hashi->len);
 
     /*
      * Produce an RSA signature (a^d mod n) using the Chinese
@@ -213,7 +244,8 @@ static bool_t rsa_sig_check(void *sst, uint8_t *data, int32_t datalen,
     mpz_init(&b);
     mpz_init(&c);
 
-    emsa_pkcs1(&st->n, &a, data, datalen);
+    rsa_hash(&st->common,data,datalen);
+    emsa_pkcs1(&st->n, &a, st->common.hashbuf, st->common.hashi->len);
 
     /* Terminate signature with a '0' - already checked that this will fit */
     int save = sig->sigstart[sig->siglen];
@@ -245,6 +277,8 @@ static list_t *rsapub_apply(closure_t *self, struct cloc loc, dict_t *context,
     st->cl.apply=NULL;
     st->cl.interface=&st->ops;
     st->ops.st=st;
+    st->ops.sethash=rsa_pub_sethash;
+    st->common.hashbuf=NULL;
     st->ops.unpick=rsa_sig_unpick;
     st->ops.check=rsa_sig_check;
     st->loc=loc;
@@ -324,6 +358,8 @@ static list_t *rsapriv_apply(closure_t *self, struct cloc loc, dict_t *context,
     st->cl.apply=NULL;
     st->cl.interface=&st->ops;
     st->ops.st=st;
+    st->ops.sethash=rsa_priv_sethash;
+    st->common.hashbuf=NULL;
     st->ops.sign=rsa_sign;
     st->loc=loc;
 
diff --git a/secnet.h b/secnet.h
index 980fff7..5f8f648 100644
--- a/secnet.h
+++ b/secnet.h
@@ -46,6 +46,7 @@
 #define MAX_PEER_ADDRS 5
 /* send at most this many copies; honour at most that many addresses */
 
+struct hash_if;
 struct comm_if;
 struct comm_addr;
 
@@ -418,12 +419,14 @@ struct random_if {
 
 /* SIGPUBKEY interface */
 
+typedef void sig_sethash_fn(void *st, struct hash_if *hash);
 typedef bool_t sig_unpick_fn(void *sst, struct buffer_if *msg,
 			     struct alg_msg_data *sig);
 typedef bool_t sig_checksig_fn(void *st, uint8_t *data, int32_t datalen,
 			       const struct alg_msg_data *sig);
 struct sigpubkey_if {
     void *st;
+    sig_sethash_fn *sethash; /* must be called before check, if non-0 */
     sig_unpick_fn *unpick;
     sig_checksig_fn *check;
 };
@@ -436,6 +439,7 @@ typedef bool_t sig_makesig_fn(void *st, uint8_t *data, int32_t datalen,
 			      struct buffer_if *msg);
 struct sigprivkey_if {
     void *st;
+    sig_sethash_fn *sethash; /* must be called before sign, if non-0 */
     sig_makesig_fn *sign;
 };
 
diff --git a/site.c b/site.c
index 38ab532..be56fae 100644
--- a/site.c
+++ b/site.c
@@ -315,7 +315,6 @@ struct site {
     struct transform_if **transforms;
     int ntransforms;
     struct dh_if *dh;
-    struct hash_if *hash;
 
     uint32_t index; /* Index of this site */
     uint32_t local_capabilities;
@@ -611,8 +610,6 @@ static void append_string_xinfo_done(struct buffer_if *buf,
    out using a transform of config data supplied by netlink */
 static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what)
 {
-    void *hst;
-    uint8_t *hash;
     string_t dhpub;
 
     st->retries=st->setup_retries;
@@ -647,18 +644,15 @@ static bool_t generate_msg(struct site *st, uint32_t type, cstring_t what)
     dhpub=st->dh->makepublic(st->dh->st,st->dhsecret,st->dh->len);
     buf_append_string(&st->buffer,dhpub);
     free(dhpub);
-    hash=safe_malloc(st->hash->len, "generate_msg");
-    hst=st->hash->init();
-    st->hash->update(hst,st->buffer.start,st->buffer.size);
-    st->hash->final(hst,hash);
-    bool_t ok=st->privkey->sign(st->privkey->st,hash,st->hash->len,
+
+    bool_t ok=st->privkey->sign(st->privkey->st,
+				st->buffer.start,
+				st->buffer.size,
 				&st->buffer);
     if (!ok) goto fail;
-    free(hash);
     return True;
 
  fail:
-    free(hash);
     return False;
 }
 
@@ -859,22 +853,13 @@ static bool_t generate_msg3(struct site *st)
 
 static bool_t process_msg3_msg4(struct site *st, struct msg *m)
 {
-    uint8_t *hash;
-    void *hst;
-
     /* Check signature and store g^x mod m */
-    hash=safe_malloc(st->hash->len, "process_msg3_msg4");
-    hst=st->hash->init();
-    st->hash->update(hst,m->hashstart,m->hashlen);
-    st->hash->final(hst,hash);
     if (!st->pubkey->check(st->pubkey->st,
-			   hash,st->hash->len,
+			   m->hashstart,m->hashlen,
 			   &m->sig)) {
 	slog(st,LOG_SEC,"msg3/msg4 signature failed check!");
-	free(hash);
 	return False;
     }
-    free(hash);
 
     st->remote_adv_mtu=m->remote_mtu;
 
@@ -2154,7 +2139,12 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     GET_CLOSURE_LIST("transform",transforms,ntransforms,CL_TRANSFORM);
 
     st->dh=find_cl_if(dict,"dh",CL_DH,True,"site",loc);
-    st->hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc);
+
+    if (st->privkey->sethash || st->pubkey->sethash) {
+	struct hash_if *hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc);
+	if (st->privkey->sethash) st->privkey->sethash(st->privkey->st,hash);
+	if (st->pubkey->sethash) st->pubkey->sethash(st->pubkey->st,hash);
+    }
 
 #define DEFAULT(D) (st->peer_mobile || st->local_mobile	\
                     ? DEFAULT_MOBILE_##D : DEFAULT_##D)
-- 
2.11.0




More information about the sgo-software-discuss mailing list