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;
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) {
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, sig;
+ string_t dhpub;
unsigned minor;
st->retries=st->setup_retries;
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);
- sig=st->privkey->sign(st->privkey->st,hash,st->hash->len);
- buf_append_string(&st->buffer,sig);
- free(sig);
- free(hash);
+
+ bool_t ok=st->privkey->sign(st->privkey->st,
+ st->buffer.start,
+ st->buffer.size,
+ &st->buffer);
+ if (!ok) goto fail;
return True;
+
+ fail:
+ return False;
}
static bool_t unpick_name(struct buffer_if *msg, struct parsedname *nm)
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;
}
static bool_t process_msg2(struct site *st, struct buffer_if *msg2,
const struct comm_addr *src)
{
- struct msg m;
+ struct msg m[1];
cstring_t err;
- if (!unpick_msg(st,LABEL_MSG2,msg2,&m)) return False;
- if (!check_msg(st,LABEL_MSG2,&m,&err)) {
+ if (!unpick_msg(st,LABEL_MSG2,msg2,m)) return False;
+ if (!check_msg(st,LABEL_MSG2,m,&err)) {
slog(st,LOG_SEC,"msg2: %s",err);
return False;
}
- st->setup_session_id=m.source;
- st->remote_capabilities=m.remote_capabilities;
+ st->setup_session_id=m->source;
+ st->remote_capabilities=m->remote_capabilities;
/* Select the transform to use */
#undef CHOOSE_CRYPTO
- memcpy(st->remoteN,m.nR,NONCELEN);
+ memcpy(st->remoteN,m->nR,NONCELEN);
return True;
}
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);
- /* 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,
+ 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;
static bool_t process_msg3(struct site *st, struct buffer_if *msg3,
const struct comm_addr *src, uint32_t msgtype)
{
- struct msg m;
+ struct msg m[1];
cstring_t err;
switch (msgtype) {
default: assert(0);
}
- if (!unpick_msg(st,msgtype,msg3,&m)) return False;
- if (!check_msg(st,msgtype,&m,&err)) {
+ if (!unpick_msg(st,msgtype,msg3,m)) return False;
+ if (!check_msg(st,msgtype,m,&err)) {
slog(st,LOG_SEC,"msg3: %s",err);
return False;
}
- uint32_t capab_adv_late = m.remote_capabilities
+ uint32_t capab_adv_late = m->remote_capabilities
& ~st->remote_capabilities & st->early_capabilities;
if (capab_adv_late) {
slog(st,LOG_SEC,"msg3 impermissibly adds early capability flag(s)"
" %#"PRIx32" (was %#"PRIx32", now %#"PRIx32")",
- capab_adv_late, st->remote_capabilities, m.remote_capabilities);
+ capab_adv_late, st->remote_capabilities, m->remote_capabilities);
return False;
}
int i; \
for (i=0; i<st->n##kind##s; i++) { \
iface=st->kind##s[i]; \
- if (iface->capab_bit == m.capab_##kind##num) \
+ if (iface->capab_bit == m->capab_##kind##num) \
goto kind##_found; \
} \
slog(st,LOG_SEC,"peer chose unknown-to-us " what " %d!", \
- m.capab_##kind##num); \
+ m->capab_##kind##num); \
return False; \
kind##_found: \
st->chosen_##kind=iface; \
#undef CHOSE_CRYPTO
- if (!process_msg3_msg4(st,&m))
+ if (!process_msg3_msg4(st,m))
return False;
/* Update our idea of the remote site's capabilities, now that we've
* doesn't change any of the bits we relied upon in the past, but it may
* also have set additional capability bits. We simply throw those away
* now, and use the authentic capabilities from this MSG3. */
- st->remote_capabilities=m.remote_capabilities;
+ st->remote_capabilities=m->remote_capabilities;
/* Terminate their DH public key with a '0' */
- m.pk[m.pklen]=0;
+ m->pk[m->pklen]=0;
/* Invent our DH secret key */
st->random->generate(st->random->st,st->dh->len,st->dhsecret);
/* Generate the shared key and set up the transform */
- if (!set_new_transform(st,m.pk)) return False;
+ if (!set_new_transform(st,m->pk)) return False;
return True;
}
static bool_t process_msg4(struct site *st, struct buffer_if *msg4,
const struct comm_addr *src)
{
- struct msg m;
+ struct msg m[1];
cstring_t err;
- if (!unpick_msg(st,LABEL_MSG4,msg4,&m)) return False;
- if (!check_msg(st,LABEL_MSG4,&m,&err)) {
+ if (!unpick_msg(st,LABEL_MSG4,msg4,m)) return False;
+ if (!check_msg(st,LABEL_MSG4,m,&err)) {
slog(st,LOG_SEC,"msg4: %s",err);
return False;
}
- if (!process_msg3_msg4(st,&m))
+ if (!process_msg3_msg4(st,m))
return False;
/* Terminate their DH public key with a '0' */
- m.pk[m.pklen]=0;
+ m->pk[m->pklen]=0;
/* Generate the shared key and set up the transform */
- if (!set_new_transform(st,m.pk)) return False;
+ if (!set_new_transform(st,m->pk)) return False;
return True;
}
* late. Maybe they came via a different path. All we do is make
* a note of the sending address, iff they look like they are part
* of the current key setup attempt. */
- struct msg m;
- if (!named_for_us(st,buf_in,msgtype,&m))
+ struct msg m[1];
+ if (!named_for_us(st,buf_in,msgtype,m))
/* named_for_us calls unpick_msg which gets the nonces */
return False;
- if (!consttime_memeq(m.nR,st->remoteN,NONCELEN) ||
- !consttime_memeq(m.nL,st->localN, NONCELEN))
+ if (!consttime_memeq(m->nR,st->remoteN,NONCELEN) ||
+ !consttime_memeq(m->nL,st->localN, NONCELEN))
/* spoof ? from stale run ? who knows */
return False;
transport_setup_msgok(st,source);
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)