version 1.12, 2014/01/06 01:50:54 |
version 1.13, 2014/01/08 03:57:57 |
|
|
|
|
#define PKALG "Ed" |
#define PKALG "Ed" |
#define KDFALG "BK" |
#define KDFALG "BK" |
|
#define FPLEN 8 |
|
|
|
#define COMMENTHDR "untrusted comment:" |
|
#define COMMENTHDRLEN 18 |
|
|
struct enckey { |
struct enckey { |
uint8_t pkalg[2]; |
uint8_t pkalg[2]; |
uint8_t kdfalg[2]; |
uint8_t kdfalg[2]; |
uint32_t kdfrounds; |
uint32_t kdfrounds; |
uint8_t salt[16]; |
uint8_t salt[16]; |
uint8_t checksum[8]; |
uint8_t checksum[8]; |
|
uint8_t fingerprint[FPLEN]; |
uint8_t seckey[SECRETBYTES]; |
uint8_t seckey[SECRETBYTES]; |
}; |
}; |
|
|
struct pubkey { |
struct pubkey { |
uint8_t pkalg[2]; |
uint8_t pkalg[2]; |
|
uint8_t fingerprint[FPLEN]; |
uint8_t pubkey[PUBLICBYTES]; |
uint8_t pubkey[PUBLICBYTES]; |
}; |
}; |
|
|
struct sig { |
struct sig { |
uint8_t pkalg[2]; |
uint8_t pkalg[2]; |
|
uint8_t fingerprint[FPLEN]; |
uint8_t sig[SIGBYTES]; |
uint8_t sig[SIGBYTES]; |
}; |
}; |
|
|
|
|
if (rv == -1) |
if (rv == -1) |
err(1, "read from %s", filename); |
err(1, "read from %s", filename); |
commentend = strchr(b64, '\n'); |
commentend = strchr(b64, '\n'); |
if (!commentend) |
if (!commentend || commentend - b64 <= COMMENTHDRLEN || |
errx(1, "no newline in %s", filename); |
memcmp(b64, COMMENTHDR, COMMENTHDRLEN)) |
|
errx(1, "invalid comment in %s; must start with '%s'", |
|
filename, COMMENTHDR); |
rv = b64_pton(commentend + 1, buf, len); |
rv = b64_pton(commentend + 1, buf, len); |
if (rv != len) |
if (rv != len) |
errx(1, "invalid b64 encoding in %s", filename); |
errx(1, "invalid b64 encoding in %s", filename); |
|
|
int fd, rv; |
int fd, rv; |
|
|
fd = xopen(filename, O_CREAT|O_EXCL|O_NOFOLLOW|O_RDWR, mode); |
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); |
writeall(fd, header, strlen(header), filename); |
if ((rv = b64_ntop(buf, len, b64, sizeof(b64)-1)) == -1) |
if ((rv = b64_ntop(buf, len, b64, sizeof(b64)-1)) == -1) |
errx(1, "b64 encode failed"); |
errx(1, "b64 encode failed"); |
|
|
} |
} |
|
|
static void |
static void |
verifymsg(uint8_t *pubkey, uint8_t *msg, unsigned long long msglen, |
|
uint8_t *sig) |
|
{ |
|
uint8_t *sigbuf, *dummybuf; |
|
unsigned long long siglen, dummylen; |
|
|
|
siglen = SIGBYTES + msglen; |
|
sigbuf = xmalloc(siglen); |
|
dummybuf = xmalloc(siglen); |
|
memcpy(sigbuf, sig, SIGBYTES); |
|
memcpy(sigbuf + SIGBYTES, msg, msglen); |
|
if (crypto_sign_ed25519_open(dummybuf, &dummylen, sigbuf, siglen, |
|
pubkey) == -1) |
|
errx(1, "signature failed"); |
|
free(sigbuf); |
|
free(dummybuf); |
|
} |
|
|
|
static void |
|
generate(const char *pubkeyfile, const char *seckeyfile, int rounds) |
generate(const char *pubkeyfile, const char *seckeyfile, int rounds) |
{ |
{ |
uint8_t digest[SHA512_DIGEST_LENGTH]; |
uint8_t digest[SHA512_DIGEST_LENGTH]; |
struct pubkey pubkey; |
struct pubkey pubkey; |
struct enckey enckey; |
struct enckey enckey; |
uint8_t xorkey[sizeof(enckey.seckey)]; |
uint8_t xorkey[sizeof(enckey.seckey)]; |
|
uint8_t fingerprint[FPLEN]; |
SHA2_CTX ctx; |
SHA2_CTX ctx; |
int i; |
int i; |
|
|
crypto_sign_ed25519_keypair(pubkey.pubkey, enckey.seckey); |
crypto_sign_ed25519_keypair(pubkey.pubkey, enckey.seckey); |
|
arc4random_buf(fingerprint, sizeof(fingerprint)); |
|
|
SHA512Init(&ctx); |
SHA512Init(&ctx); |
SHA512Update(&ctx, enckey.seckey, sizeof(enckey.seckey)); |
SHA512Update(&ctx, enckey.seckey, sizeof(enckey.seckey)); |
|
|
memcpy(enckey.pkalg, PKALG, 2); |
memcpy(enckey.pkalg, PKALG, 2); |
memcpy(enckey.kdfalg, KDFALG, 2); |
memcpy(enckey.kdfalg, KDFALG, 2); |
enckey.kdfrounds = htonl(rounds); |
enckey.kdfrounds = htonl(rounds); |
|
memcpy(enckey.fingerprint, fingerprint, FPLEN); |
arc4random_buf(enckey.salt, sizeof(enckey.salt)); |
arc4random_buf(enckey.salt, sizeof(enckey.salt)); |
kdf(enckey.salt, sizeof(enckey.salt), rounds, xorkey, sizeof(xorkey)); |
kdf(enckey.salt, sizeof(enckey.salt), rounds, xorkey, sizeof(xorkey)); |
memcpy(enckey.checksum, digest, sizeof(enckey.checksum)); |
memcpy(enckey.checksum, digest, sizeof(enckey.checksum)); |
|
|
memset(&enckey, 0, sizeof(enckey)); |
memset(&enckey, 0, sizeof(enckey)); |
|
|
memcpy(pubkey.pkalg, PKALG, 2); |
memcpy(pubkey.pkalg, PKALG, 2); |
|
memcpy(pubkey.fingerprint, fingerprint, FPLEN); |
writeb64file(pubkeyfile, "public key", &pubkey, |
writeb64file(pubkeyfile, "public key", &pubkey, |
sizeof(pubkey), 0666); |
sizeof(pubkey), 0666); |
} |
} |
|
|
msg = readmsg(inputfile, &msglen); |
msg = readmsg(inputfile, &msglen); |
|
|
signmsg(enckey.seckey, msg, msglen, sig.sig); |
signmsg(enckey.seckey, msg, msglen, sig.sig); |
|
memcpy(sig.fingerprint, enckey.fingerprint, FPLEN); |
memset(&enckey, 0, sizeof(enckey)); |
memset(&enckey, 0, sizeof(enckey)); |
|
|
memcpy(sig.pkalg, PKALG, 2); |
memcpy(sig.pkalg, PKALG, 2); |
|
|
} |
} |
|
|
static void |
static void |
|
verifymsg(uint8_t *pubkey, uint8_t *msg, unsigned long long msglen, |
|
uint8_t *sig) |
|
{ |
|
uint8_t *sigbuf, *dummybuf; |
|
unsigned long long siglen, dummylen; |
|
|
|
siglen = SIGBYTES + msglen; |
|
sigbuf = xmalloc(siglen); |
|
dummybuf = xmalloc(siglen); |
|
memcpy(sigbuf, sig, SIGBYTES); |
|
memcpy(sigbuf + SIGBYTES, msg, msglen); |
|
if (crypto_sign_ed25519_open(dummybuf, &dummylen, sigbuf, siglen, |
|
pubkey) == -1) |
|
errx(1, "signature verification failed"); |
|
free(sigbuf); |
|
free(dummybuf); |
|
} |
|
|
|
|
|
static void |
verify(const char *pubkeyfile, const char *inputfile, const char *sigfile) |
verify(const char *pubkeyfile, const char *inputfile, const char *sigfile) |
{ |
{ |
struct sig sig; |
struct sig sig; |
|
|
|
|
readb64file(pubkeyfile, &pubkey, sizeof(pubkey)); |
readb64file(pubkeyfile, &pubkey, sizeof(pubkey)); |
readb64file(sigfile, &sig, sizeof(sig)); |
readb64file(sigfile, &sig, sizeof(sig)); |
|
|
|
if (memcmp(pubkey.fingerprint, sig.fingerprint, FPLEN)) |
|
errx(1, "verification failed: checked against wrong key"); |
|
|
msg = readmsg(inputfile, &msglen); |
msg = readmsg(inputfile, &msglen); |
|
|