+static void set_new_transform(struct site *st, char *pk)
+{
+ /* Make room for the shared key */
+ st->sharedsecretlen=st->chosen_transform->keylen?:st->dh->ceil_len;
+ assert(st->sharedsecretlen);
+ if (st->sharedsecretlen > st->sharedsecretallocd) {
+ st->sharedsecretallocd=st->sharedsecretlen;
+ st->sharedsecret=realloc(st->sharedsecret,st->sharedsecretallocd);
+ }
+ if (!st->sharedsecret) fatal_perror("site:sharedsecret");
+
+ /* Generate the shared key */
+ st->dh->makeshared(st->dh->st,st->dhsecret,st->dh->len,pk,
+ st->sharedsecret,st->sharedsecretlen);
+
+ /* Set up the transform */
+ struct transform_if *generator=st->chosen_transform;
+ struct transform_inst_if *generated=generator->create(generator->st);
+ generated->setkey(generated->st,st->sharedsecret,
+ st->sharedsecretlen,st->setup_priority);
+ dispose_transform(&st->new_transform);
+ st->new_transform=generated;
+
+ slog(st,LOG_SETUP_INIT,"key exchange negotiated transform"
+ " %d (capabilities ours=%#"PRIx32" theirs=%#"PRIx32")",
+ st->chosen_transform->capab_transformnum,
+ st->local_capabilities, st->remote_capabilities);
+}
+
+struct xinfoadd {
+ int32_t lenpos, afternul;
+};
+static void append_string_xinfo_start(struct buffer_if *buf,
+ struct xinfoadd *xia,
+ const char *str)
+ /* Helps construct one of the names with additional info as found
+ * in MSG1..4. Call this function first, then append all the
+ * desired extra info (not including the nul byte) to the buffer,
+ * then call append_string_xinfo_done. */
+{
+ xia->lenpos = buf->size;
+ buf_append_string(buf,str);
+ buf_append_uint8(buf,0);
+ xia->afternul = buf->size;
+}
+static void append_string_xinfo_done(struct buffer_if *buf,
+ struct xinfoadd *xia)
+{
+ /* we just need to adjust the string length */
+ if (buf->size == xia->afternul) {
+ /* no extra info, strip the nul too */
+ buf_unappend_uint8(buf);
+ } else {
+ put_uint16(buf->start+xia->lenpos, buf->size-(xia->lenpos+2));
+ }
+}
+