A little background: Among the many ways a signature can fail to
verify is the user trying to verify with the wrong public key. In a
setup like signify where users may be expected (required) at times to
specify the public key, I expect this to be one of the leading failure
modes. (Somewhere on this list is also using the wrong private key to
create the signature.)

This can be a frustrating error because the only message you get back
is "signature failed". The obvious solution is to encode some
identifier information into the key and signature files. That provides
a quick check where we can easily say "this public key belongs to X,
but the signature was created by Y".

Why doesn't signify do this? Because that identity isn't trusted. Just
because a public key says it came from root@openbsd doesn't mean it
did. I didn't want to open up a social engineering avenue whereby
somebody provides a user with a backdoor pkg and matching public key,
allegedly from root@openbsd. "Hey, openbsd is using a new key now, but
as you can see, it comes from them." Nothing in a signify key or
signature should be mistaken as a voucher for its own integrity.

As a concession to usability, I did include a comment line in the
files. If you accidentally mix up some key files, for whatever reason,
maybe that can help set you straight. The signify tool itself ignores
this line, as documented. Now we're back to asking, can this be used
to trick the user? I was hoping that users would know the comment
isn't to be trusted, but that may be asking too much.

To that end, I think the comment should be marked as untrusted, and
signify should even check that it says untrusted. Hopefully this makes
it a little harder to con somebody into believing the comment actually
should be trusted. Is this really necessary? Honestly, I think so. The
weakest link here is an adversary's ability to trick the user into using
the wrong key; I don't want to assist them in any way.

(I'm also open to reconsidering whether keys should include
identifiers. Perhaps a random id created during key generation? Just
enough to say "you're using the wrong key.")

Index: signify.c
===================================================================
RCS file: /cvs/src/usr.bin/signify/signify.c,v
retrieving revision 1.12
diff -u -p -r1.12 signify.c
--- signify.c   6 Jan 2014 01:50:54 -0000       1.12
+++ signify.c   30 Dec 2013 16:14:25 -0000
@@ -38,6 +38,9 @@
 #define PKALG "Ed"
 #define KDFALG "BK"
 
+#define COMMENTHDR "untrusted comment:"
+#define COMMENTHDRLEN 18
+
 struct enckey {
        uint8_t pkalg[2];
        uint8_t kdfalg[2];
@@ -118,8 +121,9 @@ readb64file(const char *filename, void *
        if (rv == -1)
                err(1, "read from %s", filename);
        commentend = strchr(b64, '\n');
-       if (!commentend)
-               errx(1, "no newline in %s", filename);
+       if (!commentend || commentend - b64 <= COMMENTHDRLEN ||
+           memcmp(b64, COMMENTHDR, COMMENTHDRLEN))
+               errx(1, "invalid comment in %s", filename);
        rv = b64_pton(commentend + 1, buf, len);
        if (rv != len)
                errx(1, "invalid b64 encoding in %s", filename);
@@ -172,7 +176,8 @@ writeb64file(const char *filename, const
        int fd, rv;
 
        fd = xopen(filename, O_CREAT|O_EXCL|O_NOFOLLOW|O_RDWR, mode);
-       snprintf(header, sizeof(header), "signify -- %s\n", comment);
+       snprintf(header, sizeof(header), "%s signify %s\n", COMMENTHDR,
+           comment);
        writeall(fd, header, strlen(header), filename);
        if ((rv = b64_ntop(buf, len, b64, sizeof(b64)-1)) == -1)
                errx(1, "b64 encode failed");





Reply via email to