From 13b8fbf4548f3457b02afd36e9284d39839d6f85 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 27 Sep 2019 19:09:22 +0100 Subject: [PATCH] sig: Move hashing into algorithm 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 --- 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 5fafdcb..cdeadad 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 73d5b64..df0ab3a 100644 --- a/site.c +++ b/site.c @@ -317,7 +317,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 early_capabilities; @@ -614,8 +613,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; unsigned minor; @@ -655,18 +652,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; } @@ -884,22 +878,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; @@ -2197,7 +2182,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.30.2