return ok;
}
+static bool_t rsa_sig_unpick(void *sst, struct buffer_if *msg,
+ struct alg_msg_data *sig)
+{
+ uint8_t *lp = buf_unprepend(msg, 2);
+ if (!lp) return False;
+ sig->siglen = get_uint16(lp);
+ sig->sigstart = buf_unprepend(msg, sig->siglen);
+ if (!sig->sigstart) return False;
+
+ /* In `rsa_sig_check' below, we assume that we can write a nul
+ * terminator following the signature. Make sure there's enough space.
+ */
+ if (msg->start >= msg->base + msg->alloclen)
+ return False;
+
+ return True;
+}
+
static sig_checksig_fn rsa_sig_check;
static bool_t rsa_sig_check(void *sst, uint8_t *data, int32_t datalen,
- cstring_t signature)
+ const struct alg_msg_data *sig)
{
struct rsapub *st=sst;
MP_INT a, b, c;
emsa_pkcs1(&st->n, &a, data, datalen);
- mpz_set_str(&b, signature, 16);
+ /* Terminate signature with a '0' - already checked that this will fit */
+ int save = sig->sigstart[sig->siglen];
+ sig->sigstart[sig->siglen] = 0;
+ mpz_set_str(&b, sig->sigstart, 16);
+ sig->sigstart[sig->siglen] = save;
mpz_powm(&c, &b, &st->e, &st->n);
st->cl.apply=NULL;
st->cl.interface=&st->ops;
st->ops.st=st;
+ st->ops.unpick=rsa_sig_unpick;
st->ops.check=rsa_sig_check;
st->loc=loc;
struct buffer_if;
+struct alg_msg_data {
+ uint8_t *sigstart;
+ int32_t siglen;
+};
+
/* PURE closure requires no interface */
/* RESOLVER interface */
/* SIGPUBKEY interface */
+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,
- cstring_t signature);
+ const struct alg_msg_data *sig);
struct sigpubkey_if {
void *st;
+ sig_unpick_fn *unpick;
sig_checksig_fn *check;
};
int32_t pklen;
char *pk;
int32_t hashlen;
- int32_t siglen;
- char *sig;
+ struct alg_msg_data sig;
};
static int32_t wait_timeout(struct site *st) {
CHECK_AVAIL(msg,m->pklen);
m->pk=buf_unprepend(msg,m->pklen);
m->hashlen=msg->start-m->hashstart;
- CHECK_AVAIL(msg,2);
- m->siglen=buf_unprepend_uint16(msg);
- CHECK_AVAIL(msg,m->siglen);
- m->sig=buf_unprepend(msg,m->siglen);
- CHECK_EMPTY(msg);
- /* In `process_msg3_msg4' below, we assume that we can write a nul
- * terminator following the signature. Make sure there's enough space.
- */
- if (msg->start >= msg->base + msg->alloclen)
+ if (!st->pubkey->unpick(st->pubkey->st,msg,&m->sig)) {
return False;
+ }
+
+ CHECK_EMPTY(msg);
return True;
}
hst=st->hash->init();
st->hash->update(hst,m->hashstart,m->hashlen);
st->hash->final(hst,hash);
- /* Terminate signature with a '0' - already checked that this will fit */
- m->sig[m->siglen]=0;
- if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m->sig)) {
+ if (!st->pubkey->check(st->pubkey->st,
+ hash,st->hash->len,
+ &m->sig)) {
slog(st,LOG_SEC,"msg3/msg4 signature failed check!");
free(hash);
return False;