chiark / gitweb /
site: Change `struct msg m' to `struct msg m[1]'
[secnet.git] / site.c
diff --git a/site.c b/site.c
index 9e93ef12e8d07353bea4e90d6ce0e49ad2287cf5..897366cf27817d67d778f08bdbd28e03d32d9e03 100644 (file)
--- 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;
@@ -534,8 +533,7 @@ struct msg {
     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) {
@@ -615,9 +613,7 @@ 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, sig;
+    string_t dhpub;
     unsigned minor;
 
     st->retries=st->setup_retries;
@@ -656,15 +652,16 @@ 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);
-    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)
@@ -741,17 +738,12 @@ static bool_t unpick_msg(struct site *st, uint32_t type,
     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;
 }
@@ -828,16 +820,16 @@ static bool_t generate_msg2(struct site *st)
 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 */
 
@@ -868,7 +860,7 @@ kind##_found:                                                               \
 
 #undef CHOOSE_CRYPTO
 
-    memcpy(st->remoteN,m.nR,NONCELEN);
+    memcpy(st->remoteN,m->nR,NONCELEN);
     return True;
 }
 
@@ -886,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);
-    /* 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;
 
@@ -911,7 +894,7 @@ static bool_t process_msg3_msg4(struct site *st, struct msg *m)
 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) {
@@ -919,17 +902,17 @@ static bool_t process_msg3(struct site *st, struct buffer_if *msg3,
        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;
     }
 
@@ -938,11 +921,11 @@ static bool_t process_msg3(struct site *st, struct buffer_if *msg3,
     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;                                           \
@@ -952,7 +935,7 @@ kind##_found:                                                               \
 
 #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
@@ -963,15 +946,15 @@ kind##_found:                                                             \
      * 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;
 }
@@ -986,23 +969,23 @@ static bool_t generate_msg4(struct site *st)
 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;
 }
@@ -1840,12 +1823,12 @@ static bool_t setup_late_msg_ok(struct site *st,
      * 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);
@@ -2199,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)