+char *fingerprint_ssh2_blob(const void *blob, int bloblen)
+{
+ unsigned char digest[16];
+ char fingerprint_str[16*3];
+ unsigned stringlen;
+ int i;
+
+ MD5Simple(blob, bloblen, digest);
+ for (i = 0; i < 16; i++)
+ sprintf(fingerprint_str + i*3, "%02x%s", digest[i], i==15 ? "" : ":");
+
+ stringlen = GET_32BIT((const unsigned char *)blob);
+ if (stringlen < bloblen-4)
+ return dupprintf("%.*s %s", (int)stringlen, (const char *)blob + 4,
+ fingerprint_str);
+ else
+ return dupstr(fingerprint_str);
+}
+
+static void plog(void *logctx, pageant_logfn_t logfn, const char *fmt, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 3, 4)))
+#endif
+ ;
+
+static void plog(void *logctx, pageant_logfn_t logfn, const char *fmt, ...)
+{
+ /*
+ * This is the wrapper that takes a variadic argument list and
+ * turns it into the va_list that the log function really expects.
+ * It's safe to call this with logfn==NULL, because we
+ * double-check that below; but if you're going to do lots of work
+ * before getting here (such as looping, or hashing things) then
+ * you should probably check logfn manually before doing that.
+ */
+ if (logfn) {
+ va_list ap;
+ va_start(ap, fmt);
+ logfn(logctx, fmt, ap);
+ va_end(ap);
+ }
+}
+
+void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
+ void *logctx, pageant_logfn_t logfn)