1 #define _POSIX_C_SOURCE 200809L
3 /* general zpm sign function */
5 /* read key, export key, import key, sign, export signature, import
6 * signature, verify signature
9 /* import and export is base64 encoded */
14 * -e extract public key
18 * -p read key from file
19 * -P read public key from argument to -P
20 * -S read secret key from argument
21 * -m message from argument
22 * -h message is hex encoded
25 /* chacha20 encryption: 256 bit key = 32 bytes */
32 #include <sys/types.h>
38 /* linux specific for getrandom */
39 #include <sys/random.h>
43 #include "crypto/chacha.h"
44 #include "lib/blake2.h"
46 char *readpass(char *prompt);
61 #define HUMANREADABLE 0x2
70 /* possible additional types:
72 * revocation certificate
75 /* timestamps are 8 byte little endian integers of seconds since
76 * the epoch. or unix time, or some such. Times are a mess.
77 * Unix time is leap second unaware, and ambiguous during leap seconds.
78 * UTC requires a database of leap seconds for past time, and the
79 * specified second in the future possibly changes.
80 * TAI is good, but currently 37 seconds behind UTC, which is just weird
83 /* size of structs would have to be increased for 57/64 byte keys
84 * and key*2 size signatures
87 /* need 25 more bytes for ed448 */
89 char magic[4]; /* "ZPMS" */
90 uint8_t version; /* 0x01 */
91 uint8_t type; /* 0x01 */
92 uint8_t encryption; /* 0x01 == chacha */
93 uint8_t reserved1; /* MBZ */
94 char key[32]; /* private key data */
95 int64_t created; /* time in unix epoch seconds, little endian */
96 int64_t expires; /* time in unix epoch seconds, little endian, = is none, could do uint64max */
97 char salt[8]; /* password salt, nist wants 16, but we're not using nist approved hash algorithms anyway. */
98 char reserved2[64]; /* could put the pubkey here could have 16 bytes of IV for chacha to encrypt. */
99 char id[120]; /* 1 byte len, id bytes, zero bytes remainder */
100 char trailer[8]; /* room for a pointer */
104 char magic[4]; /* "ZPMS" */
105 uint8_t version; /* 0x01 */
106 uint8_t type; /* 0x02 */
107 uint8_t reserved0; /* MBZ */
108 uint8_t reserved1; /* MBZ */
109 char key[32]; /* public key data */
110 int64_t created; /* time in unix epoch seconds, little endian */
111 int64_t expires; /* time in unix epoch seconds, little endian */
112 char reserved2[8]; /* MBZ */
113 char signature[64]; /* self sig data */
114 char id[120]; /* 1 byte len, id bytes, zero bytes remainder */
115 char trailer[8]; /* room for a pointer */
119 char magic[4]; /* "ZPMS" */
120 uint8_t version; /* 0x01 */
121 uint8_t type; /* 0x03 */
122 uint8_t reserved0; /* MBZ */ /* trust level? revokable? */
123 uint8_t reserved1; /* MBZ */
124 char key[32]; /* signing public key data?, can be zero */
125 int64_t signtime; /* time in unix epoch seconds, little endian */
126 int64_t expires; /* time in unix epoch seconds, little endian */
127 char reserved2[8]; /* MBZ */
128 char signature[64]; /* sig data */
129 char reserved3[120]; /* some indication of what you're signing ? */
130 /* 512 bits is 64 bytes, could put the hash of the data signed */
131 char trailer[8]; /* room for a pointer */
135 char magic[4]; /* "ZPMS" */
136 uint8_t version; /* 0x01 */
138 uint8_t encryption; /* trust level for pk? revokable for sig? */
139 uint8_t reserved1; /* MBZ */
140 char key[32]; /* signing public key data?, can be zero */
141 /* should these be signed? */
142 int64_t created; /* time in unix epoch seconds */
143 int64_t expires; /* time in unix epoch seconds */
144 char salt[8]; /* reserved for pk and sig, could be IV for sig */
145 char signature[64]; /* sig data, reserved for sk */
146 char id[120]; /* signing hash for sig? otherwise reserved for sig */
147 /* 512 bits is 64 bytes, could put the hash of the data signed */
148 char trailer[8]; /* room for a pointer */
151 struct signing_context {
155 char *keyfile, *keystring, *keyid, *keyprefix, *passphrase;
156 unsigned char passkey[32];
159 void putsle8(unsigned char *dst, int64_t inval) {
161 union { uint64_t out; int64_t in; } uv;
167 for (i=0; i<8; i++) {
173 int64_t getsle8(unsigned char *dst) {
176 union { int64_t out; uint64_t in; } uv;
178 for (i=0; i<8; i++) {
179 val += (uint64_t)dst[i] << (8*i);
187 void seckey_bytea(unsigned char *bytes, struct secret_key *sk) {
188 memset(bytes, 0, 256);
189 memcpy(bytes, "ZPMS", 4);
190 bytes[4] = sk->version;
192 bytes[6] = sk->encryption;
194 memcpy(bytes + 8, sk->key, 32);
195 putsle8(bytes+40, sk->created);
196 putsle8(bytes+48, sk->expires);
197 /* @56 8 salt, not implemented */
198 /* memcpy(bytes + 64, sk->reserved2, 64); should probably put the pk */
199 memcpy(bytes + 128, sk->id, 120);
203 void bytea_seckey(struct secret_key *sk, unsigned char *bytes) {
204 memcpy(sk->magic, bytes, 4);
205 sk->version = bytes[4];
207 sk->encryption = bytes[6];
209 memcpy(sk->key, bytes + 8, 32);
210 sk->created = getsle8(bytes+40);
211 sk->expires = getsle8(bytes+48);
212 memset(sk->salt, 0, 8); /* salt not implemented */
213 memset(sk->reserved2, 0, 64); /* salt not implemented */
214 memcpy(sk->id, bytes + 128, 120);
215 memset(sk->trailer, 0, 8);
218 int create_key(struct secret_key *sk, int generate) {
219 memcpy(sk->magic, "ZPMS", 4);
220 sk->version = VERSION;
221 sk->type = SECRET_KEY;
226 /* a private key is just 32 random bytes */
227 getrandom(sk->key, sizeof sk->key, 0);
230 sk->created = time(NULL);
231 sk->expires = INT64_MAX;
232 memset(sk->salt, 0, 8);
233 memset(sk->reserved2, 0, 64);
234 memset(sk->id, 0, 120);
235 memset(sk->trailer, 0, 8);
237 ed25519_genpub(sk->reserved2, sk->key);
241 /* hash password into 32 bytes for chacha encryption */
242 int collect_key(unsigned char *key, const char *pass) {
243 struct blake2b_state__ h;
245 pass = readpass("Passphrase: ");
252 blake2b_init(&h, 32);
253 blake2b_update(&h, pass, strlen(pass));
254 blake2b_final(&h, key, 32);
258 int encrypt_key(struct secret_key *sk, unsigned char *key) {
261 if (sk->encryption) {
265 /* TODO chacha encrypt sk->key */
266 for (i=0; i < 32; i++) {
267 sk->key[i] ^= key[i];
274 int encrypt_sk(struct secret_key *sk, unsigned char *pass) {
275 unsigned char key[32];
277 if (sk->encryption == 1) {
281 collect_key(key, pass);
282 encrypt_key(sk, key);
285 memset(pass, 0, strlen(pass));
290 int decrypt_sk(struct secret_key *sk, unsigned char *pass) {
291 unsigned char key[32];
294 if (sk->encryption == 0) {
298 collect_key(key, pass);
300 for (i=0; i < 32; i++) {
301 sk->key[i] ^= key[i];
305 memset(pass, 0, strlen(pass));
312 int decrypt_key(struct secret_key *sk, unsigned char *key) {
315 if (sk->encryption == 0) {
319 /* TODO chacha decrypt sk->key */
320 for (i=0; i < 32; i++) {
321 sk->key[i] ^= key[i];
328 void pubkey_init(struct public_key *pk) {
329 memcpy(pk->magic, "ZPMS", 4);
330 pk->version = VERSION;
331 pk->type = PUBLIC_KEY;
334 memset(pk->key, 0, sizeof pk->key);
337 memset(pk->reserved2, 0, 8);
338 memset(pk->signature, 0, 64);
339 memset(pk->id, 0, 120);
340 memset(pk->trailer, 0, 8);
343 void pubkey_bytea(unsigned char *bytes, struct public_key *pk) {
344 memset(bytes, 0, 256);
345 memcpy(bytes, "ZPMS", 4);
346 bytes[4] = pk->version;
349 memcpy(bytes + 8, pk->key, 32);
350 putsle8(bytes+40, pk->created);
351 putsle8(bytes+48, pk->expires);
353 memcpy(bytes + 64, pk->signature, 64);
354 memcpy(bytes + 128, pk->id, 120);
358 void bytea_pubkey(struct public_key *pk, unsigned char *bytes) {
359 memcpy(pk->magic, bytes, 4);
360 pk->version = bytes[4];
364 memcpy(pk->key, bytes + 8, 32);
365 pk->created = getsle8(bytes+40);
366 pk->expires = getsle8(bytes+48);
367 memset(pk->reserved2, 0, 8);
368 memcpy(pk->signature, bytes + 64, 64);
369 memcpy(pk->id, bytes + 128, 120);
370 memset(pk->trailer, 0, 8);
373 int derive_pubkey(struct public_key *pk, struct secret_key *sk) {
376 memcpy(pk->magic, "ZPMS", 4);
377 pk->version = VERSION;
378 pk->type = PUBLIC_KEY;
381 ed25519_genpub(pk->key, sk->key);
382 pk->created = sk->created;
383 pk->expires = sk->expires;
384 memset(pk->reserved2, 0, 8);
385 memset(pk->signature, 0, 64);
386 memset(pk->id, 0, 120);
387 strncpy(pk->id, sk->id, 119);
388 memset(pk->trailer, 0, 8);
390 /* serialize and sign */
391 pubkey_bytea(bytes, pk);
392 ed25519_sign(pk->signature, sk->key, pk->key, bytes, 256);
397 void bytea_signature(struct signature *sig, unsigned char *bytes) {
398 memcpy(sig->magic, bytes, 4);
399 sig->version = bytes[4];
400 sig->type = bytes[5];
403 memcpy(sig->key, bytes + 8, 32);
404 sig->signtime = getsle8(bytes+40);
405 sig->expires = getsle8(bytes+48);
406 memset(sig->reserved2, 0, 8);
407 memcpy(sig->signature, bytes + 64, 64);
408 memcpy(sig->reserved3, bytes + 128, 120);
409 memset(sig->trailer, 0, 8);
412 void signature_bytea(unsigned char *bytes, struct signature *sig) {
413 memset(bytes, 0, 256);
414 memcpy(bytes, "ZPMS", 4);
415 bytes[4] = sig->version;
416 bytes[5] = sig->type;
418 memcpy(bytes + 8, sig->key, 32);
419 putsle8(bytes+40, sig->signtime);
420 putsle8(bytes+48, sig->expires);
422 memcpy(bytes + 64, sig->signature, 64);
428 struct signature sig;
429 struct public_key pk;
430 struct secret_key sk;
434 int object_type(union signobject *obj) {
435 return obj ? obj->sk.type : 0;
438 void sighash(unsigned char *dst, struct signature *sig, unsigned char *data,
440 unsigned char signtime[8], expires[8];
443 /* need to put these in as little endian */
444 putsle8(signtime, sig->signtime);
445 putsle8(expires, sig->expires);
448 sha512_add(&hash, signtime, sizeof signtime);
449 sha512_add(&hash, expires, sizeof expires);
450 sha512_add(&hash, data, len);
451 sha512_final(&hash, dst);
454 void init_signature(struct signature *sig) {
455 memcpy(sig->magic, "ZPMS", 4);
456 sig->version = VERSION;
457 sig->type = SIGNATURE;
460 memset(sig->key, 0, sizeof sig->key);
463 memset(sig->reserved2, 0, 8);
464 memset(sig->signature, 0, 64);
465 memset(sig->reserved3, 0, 120);
466 memset(sig->trailer, 0, 8);
469 int create_signature(struct signature *sig, struct secret_key *sk,
470 int baresign, unsigned char *data, size_t len) {
471 unsigned char messagehash[64];
473 if (!sk || !data || !sig) {
477 memcpy(sig->magic, "ZPMS", 4);
478 sig->version = VERSION;
479 sig->type = SIGNATURE;
482 ed25519_genpub(sig->key, sk->key);
487 memset(sig->reserved2, 0, 8);
488 memset(sig->signature, 0, 64);
489 memset(sig->reserved3, 0, 120);
490 memset(sig->trailer, 0, 8);
493 sighash(messagehash, sig, data, len);
495 len = sizeof messagehash;
498 ed25519_sign(sig->signature, sk->key, sig->key, data, len);
503 //#define MARK do { fprintf(stderr, "%s %s:%d\n", __FILE__, __func__, __LINE__); } while (0)
505 static char hexchars[] = "0123456789abcdefABCDEF";
507 static void hex(char *dst, uint8_t *src, size_t len) {
509 dst[0] = hexchars[(src[0]>>4)&0xf];
510 dst[1] = hexchars[src[0]&0xf];
516 /* always 512 bytes dst, 248 bytes src, last 8 bytes
517 * are ignored and set to zero, last 4 bytes not output
519 void serialize(uint8_t *dst, unsigned char *src) {
521 uint8_t byte, hi, lo;
523 for (i = 0; i < 248; i++) {
527 if (i % 32 == 0 && i > 0) {
531 *dst++ = hexchars[hi];
532 *dst++ = hexchars[lo];
534 for (; i < 252; i++) {
541 int hexval(int digit) {
542 if (digit >= '0' && digit <= '9') {
544 } else if (digit == 'A' || digit == 'a') {
546 } else if (digit == 'B' || digit == 'b') {
548 } else if (digit == 'C' || digit == 'c') {
550 } else if (digit == 'D' || digit == 'd') {
552 } else if (digit == 'E' || digit == 'e') {
554 } else if (digit == 'F' || digit == 'f') {
561 /* convert at most dlen hex bytes from srclen, returns
562 * number of bytes read, src may contain zero bytes,
563 * so use strlen in the caller if needed
565 size_t hex2bin(uint8_t *dst, size_t dlen, char *src, size_t slen) {
569 for (i = 0; i < slen && n < dlen; i++) {
570 if (!isxdigit(src[i])) {
574 val = hexval(src[i++]) << 4;
575 /* look for next hex digit */
576 while (i < slen && !isxdigit(src[i])) {
579 if (i == slen || !isxdigit(src[i])) {
580 break; /* tests redundant, but make code clearer */
582 val += hexval(src[i]); /* low nibble */
589 /* read in up to 248 bytes, set remaining to zero
590 * returns byte 5 if the bytes begin with "ZPMS" and 248 bytes were converted
591 * src must be at least 512 bytes
593 int deserialize(void *obj, uint8_t *src, size_t slen) {
597 bytes = hex2bin(buf, 248, src, slen);
599 for (i = bytes; i < 256; i++) {
603 if (bytes == 248 && memcmp(buf, "ZPMS", 4) == 0) {
611 bytea_seckey(obj, buf);
612 memset(buf, 0, sizeof buf);
615 bytea_pubkey(obj, buf);
618 bytea_signature(obj, buf);
628 void *map(char *file, size_t *size) {
633 fd = open(file, O_RDONLY);
644 m = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
645 if (m == MAP_FAILED) {
654 /* read 512 bytes from fd, returns -1 for error, 512 for full read,
655 * < 512 for end of file
657 ssize_t read512(int fd, void *dst) {
661 bytes = read(fd, dst + 512 - need, need);
673 int read_item(int fd, void *item) {
678 bytes = read512(fd, buffer);
682 type = deserialize(item, buffer, sizeof buffer);
686 int write_secret_key(int fd, struct secret_key *sk, int outputflags) {
688 char serialized[512];
691 if (outputflags & RAW) {
692 hex(serialized, sk->key, 32);
695 seckey_bytea(skh, sk);
696 serialize(serialized, skh);
697 outlen = sizeof serialized;
700 write(fd, serialized, outlen);
702 memset(skh, 0, sizeof skh);
703 memset(serialized, 0, sizeof serialized);
708 int write_public_key(int fd, struct public_key *pk, int outputflags) {
710 char serialized[512];
713 if (outputflags & RAW) {
714 hex(serialized, pk->key, 32);
717 pubkey_bytea(skh, pk);
718 serialize(serialized, skh);
719 outlen = sizeof serialized;
722 write(fd, serialized, outlen);
724 memset(skh, 0, sizeof skh);
725 memset(serialized, 0, sizeof serialized);
730 int write_signature(int fd, struct signature *sig, int outputflags) {
732 char serialized[512];
735 if (outputflags & RAW) {
736 hex(serialized, sig->signature, 64);
739 signature_bytea(skh, sig);
740 serialize(serialized, skh);
741 outlen = sizeof serialized;
744 write(fd, serialized, outlen);
746 memset(skh, 0, sizeof skh);
747 memset(serialized, 0, sizeof serialized);
752 int write_object(int fd, void *o, int outputflags) {
754 char serialized[512];
757 union signobject *obj = o;
759 type = ((struct secret_key *)obj)->type;
761 if (outputflags & RAW) {
763 case 0x01: hex(serialized, obj->sk.key, 32);
766 case 0x02: hex(serialized, obj->pk.key, 32);
769 case 0x03: hex(serialized, obj->sig.signature, 64);
778 case 0x01: seckey_bytea(bytes, &obj->sk); break;
779 case 0x02: pubkey_bytea(bytes, &obj->pk); break;
780 case 0x03: signature_bytea(bytes, &obj->sig); break;
781 memset(bytes, 0, sizeof bytes);
784 serialize(serialized, bytes);
787 write(fd, serialized, outlen);
788 memset(serialized, 0, outlen);
793 /* TODO work on strings, not file output */
794 void write_to_512(int fd, int output) {
796 memset(trailer, '-', 64);
799 while (output < 512) {
800 int shortfall = 512 - output;
801 if (shortfall >= 65) {
802 write(fd, trailer, 65);
806 write(fd, trailer + (65-shortfall), shortfall);
811 int dump_signature(int fd, struct signature *sig) {
812 char as_str[1024], key[64], sigstr[128];
814 int64_t curtime = time(0);
816 hex(key, sig->key, 32);
817 hex(sigstr, sig->signature, 64);
819 output = sprintf(as_str, "Type: %s\nSigned: %ld\n%s: %ld\nPublic Key: %s\nSignature:\n%.64s\n%.64s\n",
822 curtime > sig->expires ? "Expired" : "Expires",
825 write(fd, as_str, strlen(as_str));
826 write_to_512(fd, output);
831 int dump_public_key(int fd, struct public_key *pk) {
832 char as_str[1024], key[64], sig[128];
834 int64_t curtime = time(0);
836 hex(key, pk->key, 32);
837 hex(sig, pk->signature, 64);
839 output = sprintf(as_str, "Type: %s\nId: \"%s\"\nCreated: %ld\n%s: %ld\nKey: %.64s\nSignature:\n%.64s\n%.64s\n",
842 curtime > pk->expires ? "Expired" : "Expires",
845 write(fd, as_str, strlen(as_str));
846 write_to_512(fd, output);
851 int dump_secret_key(int fd, struct secret_key *sk) {
855 int64_t curtime = time(0);
858 hex(key, sk->key, 32);
859 if (sk->expires == INT64_MAX) {
860 sprintf(exprep, "never");
862 sprintf(exprep, "%ld", sk->expires);
865 output = sprintf(as_str, "Type: %s\nEncrypted: %s\nId: \"%s\"\nCreated: %ld\n%s: %s\nKey: %.64s\n",
867 sk->encryption ? "yes" : "no",
869 curtime > sk->expires ? "Expired" : "Expires",
871 write(fd, as_str, strlen(as_str));
872 write_to_512(fd, output);
877 int dump_object(int fd, void *obj) {
879 switch (((struct secret_key *)obj)->type) {
880 case 0x01: rv = dump_secret_key(fd, obj); break;
881 case 0x02: rv = dump_public_key(fd, obj); break;
882 case 0x03: rv = dump_signature(fd, obj); break;
883 default: rv = 0; break;
888 /* returns a malloced keyfile name. no check is made to see if the
889 * file actually exists
891 char *find_keyfile(char *file) {
896 } else if (getenv("ZPM_KEYFILE")) {
897 f = strdup(getenv("ZPM_KEYFILE"));
899 char *home = getenv("HOME");
902 need = snprintf(0, 0, "%s/.zpm/key", home);
903 char *freefile = malloc(need + 1);
905 snprintf(freefile, need+1, "%s/.zpm/key", home);
914 int obj_id_match(union signobject *obj, char *id) {
919 switch(object_type(obj)) {
921 return !strcmp(obj->sk.id, id);
924 return !strcmp(obj->pk.id, id);
934 int key_id_match(struct secret_key *sk, char *id) {
938 /* TODO look for substring */
939 return !strcmp(sk->id, id);
942 /* try to populate a secret key structure.
944 * direct specified string, won't have any additional info added
945 * string from ZPM_KEY
946 * file, if id, try to match
947 * file from ZPM_KEYFILE
950 * if direct from string, encrypted? assume no. need option then.
953 /* can probably just call read_item */
954 int read_object(int fd, union signobject *obj) {
958 bytes = read512(fd, buf);
963 return deserialize(obj, buf, bytes);
966 int find_secret_key(struct secret_key *sk, char *id, char *file, char *direct) {
971 if (direct || (direct = getenv("ZPM_KEY"))) {
972 /* TODO check strlen == 64 */
973 len = strlen(direct);
974 if (len < 2 * sizeof sk->key) {
977 memset(sk->key, 0, sizeof sk->key);
978 bytes = hex2bin(sk->key, sizeof sk->key, direct, len);
979 if (bytes != sizeof sk->key) {
985 path = find_keyfile(file);
990 fd = open(path, O_RDONLY);
996 int64_t curtime = time(0);
999 type = read_object(fd, (union signobject *)sk);
1000 if (type != SECRET_KEY) {
1003 if (curtime > sk->expires) {
1006 if (!id || key_id_match(sk, id)) {
1010 } while (type != 0);
1017 int open_output(char *path) {
1020 if (path && strcmp(path, "-") != 0) {
1021 fd = open(path, O_WRONLY|O_CREAT, 0600);
1027 void set_key_id(struct secret_key *sk, char *id) {
1028 memset(sk->id, 0, 120);
1030 strncpy(sk->id, id, 119);
1034 void set_pub_id(struct public_key *sk, char *id) {
1035 memset(sk->id, 0, 120);
1037 strncpy(sk->id, id, 119);
1041 int object_filter(union signobject *obj, int type, char *id, char *prefix) {
1045 otype = object_type(obj);
1051 if (type && otype != type) {
1055 if (otype != SECRET_KEY) {
1061 if (!key_id_match(&obj->sk, id)) {
1068 len = strlen(prefix);
1069 len = hex2bin(buf, sizeof buf, prefix, len);
1070 if (memcmp(obj->sk.key, buf, len) != 0) {
1078 /* read or construct a secret key */
1079 int find_key(struct secret_key *sk, struct signing_context *ctx) {
1080 char *keystring, *keyfile, *idstring, *keyprefix;
1083 keystring = ctx->keystring;
1084 keyfile = ctx->keyfile;
1085 idstring = ctx->keyid;
1086 keyprefix = ctx->keyprefix;
1088 //fprintf(stderr, "looking for key, str = \"%s\", file = \"%s\", id = \"%s\", prefix = \"%s\"\n", keystring, keyfile, idstring, keyprefix);
1091 len = strlen(keystring);
1095 hex2bin(sk->key, sizeof sk->key, keystring, len);
1097 set_key_id(sk, idstring);
1100 char *keyringfile = find_keyfile(keyfile);
1104 int keyring = open(keyringfile, O_RDONLY);
1105 union signobject obj;
1107 while ((rv = read_object(keyring, &obj))) {
1108 if (rv != SECRET_KEY) {
1111 if (object_filter(&obj, SECRET_KEY, idstring, keyprefix)) {
1121 if (sk->encryption && ctx->passphrase) {
1122 collect_key(ctx->passkey, ctx->passphrase);
1123 decrypt_key(sk, ctx->passkey);
1129 /* flags: 1 = hex encoded, 2 = input is path */
1130 char *create_message(char *in, size_t *len, int flags) {
1135 } else if (flags == 1) {
1137 msg = malloc(*len/2 + 2);
1138 *len = hex2bin(msg, *len, in, *len);
1144 /* would need to read from stdin and buffer */
1151 char *construct_message(char *ms, char *path, size_t *mlen, int flags) {
1152 char *msg = 0, *mapped = 0;
1159 mapped = msg = map(path, mlen);
1163 /* input is hex encoded */
1165 new = malloc(*mlen/2+1);
1166 *mlen = hex2bin(new, *mlen/2+1, msg, *mlen);
1173 /* TODO should use mlock()ed memory for the secret key */
1175 #if _POSIX_ADVISORY_INFO > 0
1176 long pagesize = sysconf(_SC_PAGESIZE);
1177 int rv = posix_memalign(&sk, pagesize, sizeof *sk);
1179 mlock(sk, sizeof sk);
1180 /* not able to lock, use stack memory */
1182 /* not able to allocate, use stack memory */
1184 /* TODO if the allocate or lock fails, try mlockall(),
1185 * if that fails, abort or perhaps continue if insecure mode */
1186 /* TODO also mlock buffers */
1190 /* if flags == 0, then need to hash the message and the signature info
1191 * before verifying, otherwise, bare sign, so just verify
1193 int verify(struct signature *sig, char *message, size_t mlen, int flags) {
1197 sighash(hash, sig, message, mlen);
1202 return ed25519_verify(sig->signature, sig->key, message, mlen);
1205 int generate_key(struct secret_key *sk, char *keystring, char *idstring) {
1213 len = strlen(keystring);
1217 hex2bin(sk->key, sizeof sk->key, keystring, len);
1224 strncpy(sk->id, idstring, 119);
1230 int list_object(int fd, union signobject *obj) {
1231 if (fd >= 0 && obj) {
1232 dump_object(fd, obj);
1237 /* TODO can be just a find_key and take an arg */
1238 int find_public_key(struct public_key *pk, char *id, char *pstr, char *pfile) {
1239 char *path = 0, buf[32];
1240 int fd, bytes, type = 0;
1243 if (!pstr && !pfile) {
1244 pstr = getenv("ZPM_PUBLIC_KEY");
1248 /* TODO check strlen == 64 */
1251 type = deserialize(pk, pstr, len);
1252 } else if (len >= 64) {
1253 bytes = hex2bin(buf, sizeof buf, pstr, len);
1256 memcpy(pk->key, buf, 32);
1264 path = find_keyfile(pfile);
1269 fd = open(path, O_RDONLY);
1275 int64_t curtime = time(0);
1278 type = read_object(fd, (union signobject *)pk);
1279 if (type != PUBLIC_KEY) {
1282 if (curtime > pk->expires) {
1286 if (!id || obj_id_match((union signobject *)pk, id)) {
1290 } while (type != 0);
1297 int find_signature(struct signature *sig, char *sigstring, char *sigfile) {
1304 len = strlen(sigstring);
1306 type = deserialize(sig, sigstring, len);
1307 } else if (len >= 128) {
1308 len = hex2bin(buf, sizeof buf, sigstring, len);
1310 init_signature(sig);
1311 memcpy(sig->signature, buf, 64);
1315 } else if (sigfile) {
1316 mapped = map(sigfile, &len);
1317 if (mapped && len >= 512) {
1318 type = deserialize(sig, mapped, len);
1323 munmap(mapped, len);
1328 int object_match(union signobject *a, union signobject *b) {
1336 if (object_type(a) != object_type(b)) {
1340 if (object_type(a) == PUBLIC_KEY) {
1341 return memcmp(a->pk.key, b->pk.key, 32) == 0;
1342 } else if (object_type(a) == SECRET_KEY) {
1343 return memcmp(a->sk.key, b->sk.key, 32) == 0;
1344 } else if (object_type(a) == SIGNATURE) {
1345 if (memcmp(a->sig.key, b->sig.key, 32) != 0) {
1348 return memcmp(a->sig.signature, b->sig.signature, 64) == 0;
1354 /* return true if we find something that matches obj */
1355 int find_object(int fd, union signobject *lookfor) {
1356 union signobject obj;
1357 while (read_object(fd, &obj) > 0) {
1358 if (object_match(lookfor, &obj)) {
1365 #include <sys/time.h>
1366 #include <sys/resource.h>
1368 int main(int ac, char *av[]) {
1370 * M = message, P = public key, K = secret key, S = signature
1371 * T = timestamp, E = expires, I = identity, H = message hash
1372 * C = ciphertext, W = password
1374 struct signing_context ctx = { 0 };
1376 unsigned char *message = 0;
1378 char *messagefile = 0;
1379 char *messagestring = 0;
1381 char *timestring = 0, *expirestring = 0;
1382 int64_t timestamp = 0, expires = INT64_MAX;
1384 char *passphrase = 0;
1385 unsigned char passkey[32];
1387 char *keyid = 0, *keyprefix = 0;
1388 struct secret_key sk = { 0 };
1389 char *keyfile = 0, *keystring = 0;
1391 struct public_key pk = { 0 };
1392 char *pubfile = 0, *pubstring = 0;
1394 struct signature sig = { 0 };
1395 char *sigfile = 0, *sigstring = 0;
1397 char *encfile = 0, *encstring = 0;
1399 int output = 1; /* file descriptor */
1404 int hexencoded = 0, outputflags = 0;
1405 int debug = 0, quiet = 0, bareinput = 0;
1406 int outputmsghash = 0;
1410 #if _POSIX_ADVISORY_INFO > 0
1411 fprintf(stderr, "locking memory\n");
1413 getrlimit(RLIMIT_MEMLOCK, &lim);
1414 fprintf(stderr, "memlock limit %llu/%llu\n", lim.rlim_cur, lim.rlim_max);
1415 struct public_key *pkp;
1416 posix_memalign(&pkp,
1417 rv = mlockall(MCL_CURRENT|MCL_FUTURE); /* can't happen, have to just
1418 lock sk and maybe ctx */
1420 perror("unable to lock memory");
1425 while ((option = getopt(ac, av, "vsgelxyirdHo:hbT:E:n:w:m:N:k:K:p:P:f:F:c:C:")) != -1) {
1428 case 'v': mode = VERIFY; break;
1429 case 's': mode = SIGN; break;
1430 case 'g': mode = KEYGEN; break;
1431 case 'e': mode = EXTRACT; break;
1432 case 'l': mode = LIST; break;
1433 case 'x': mode = ENCRYPT; break;
1434 case 'y': mode = DECRYPT; break;
1435 case 'i': mode = IMPORT; break;
1437 * remove pw, add pw, export, delete
1438 * need a manage mode to delete
1443 case 't': trust = strtoul(optarg, 0, 10); break;
1446 case 'r': outputflags |= RAW; break;
1447 case 'd': debug++; break;
1448 case 'H': outputmsghash = 1; break;
1449 case 'o': outfile = optarg; break;
1450 case 'q': quiet++; break;
1453 case 'h': hexencoded = 1; break;
1454 case 'b': bareinput = 1; break;
1455 case 'T': timestring = optarg; break; /* T */
1456 case 'E': expirestring = optarg; break; /* E */
1457 case 'n': keyid = optarg; break; /* I */
1458 case 'w': passphrase = optarg; break; /* W */
1459 case 'm': messagestring = optarg; break; /* M */
1460 case 'N': keyprefix = optarg; break; /* K ish */
1461 case 'k': keyfile = optarg; break; /* K */
1462 case 'K': keystring = optarg; break; /* K */
1463 case 'p': pubfile = optarg; break; /* P */
1464 case 'P': pubstring = optarg; break; /* P */
1465 case 'f': sigfile = optarg; break; /* S */
1466 case 'F': sigstring = optarg; break; /* S */
1467 case 'c': encfile = optarg; break; /* C */
1468 case 'C': encstring = optarg; break; /* C */
1479 * M = message, P = public key, K = secret key, S = signature
1480 * T = timestamp, E = expires, I = identity, H = message hash
1481 * C = ciphertext, W = password
1483 * -sb bare data sign (M, K) -> S
1484 * -s full data sign ( (M,T,E) -> H, K) -> S
1485 * -s key sign ( (P,T,E) -> H, K) -> S
1486 * -e extract (K) -> P
1487 * -g generate (T, E, I) -> K (default to keyring append)
1488 * -g generate (K, T, E, I) -> K (default to keyring append)
1489 * self sign ( (K->P,T,E,I) -> H, M) -> S
1490 * import (K/P/S) -> keyring file append, stdout daft, unless redir
1491 * show (K/P/S) -> output input
1492 * -l list keys (K/P/S) -> key list, get from -k
1493 * -v verify (M, S) -> boolean, via exit value, no output
1494 * -x encrypt (M, K, T, E, P...) -> C
1495 * -y decrypt (C, K) -> M
1496 * -H generate signing hash for message or key
1498 * output style: serialized, -d human readable, -r raw
1499 * input style: serialized, -b bare, -h hexencoded
1501 * possible inputs: M K T E P I S C
1502 * M -> from -m, non-option arg, stdin
1503 * K -> from -K, ZPM_KEY, -k, ZPM_KEYFILE, ~/.zpm/key
1505 * S -> from -F, -f, second arg?
1506 * C -> from -C, -c, non-option arg, stdin
1507 * T -> from -T, time(NULL)
1508 * E -> from -E, never/-1
1509 * I -> from -n, ZPM_KEYID, K, S, null
1510 * W -> from -w, ZPM_PASS, ~/.zpm/pass, terminal
1514 timestamp = strtoull(timestring, 0, 10);
1516 timestamp = time(NULL);
1520 expires = strtoull(expirestring, 0, 10);
1523 ctx.keystring = keystring;
1524 ctx.keyfile = keyfile;
1526 ctx.keyprefix = keyprefix;
1527 ctx.passphrase = passphrase;
1529 if (mode == KEYGEN) {
1530 rv = generate_key(&sk, keystring, keyid);
1534 sk.created = timestamp;
1535 sk.expires = expires;
1536 } else if (mode == SIGN) {
1537 char *firstarg = av[argn];
1538 rv = find_key(&sk, &ctx);
1540 fprintf(stderr, "unable to find signing key\n");
1543 char *message = construct_message(messagestring, firstarg, &mlen, hexencoded);
1544 // dump_secret_key(2, &sk);
1545 sig.signtime = timestamp;
1546 sig.expires = expires;
1547 rv = create_signature(&sig, &sk, bareinput, message, mlen);
1551 // dump_signature(2, &sig);
1552 } else if (mode == SIGNKEY) {
1553 find_key(&sk, &ctx);
1554 find_public_key(&pk, keyid, pubstring, pubfile);
1555 /* TODO construct a message out of a public key */
1557 sig.signtime = timestamp;
1558 sig.expires = expires;
1559 rv = create_signature(&sig, &sk, 0, message, mlen);
1563 } else if (mode == EXTRACT) {
1564 rv = find_key(&sk, &ctx);
1566 decrypt_sk(&sk, passphrase);
1571 derive_pubkey(&pk, &sk);
1572 } else if (mode == VERIFY) {
1573 rv = find_signature(&sig, sigstring, sigfile);
1574 if (rv == SIGNATURE) {
1575 /* if you've specified the public key in a verify op,
1576 * you probably know what you're doing
1578 if (pubstring || pubfile) {
1579 rv = find_public_key(&pk, keyid, pubstring, pubfile);
1580 if (rv == PUBLIC_KEY) {
1581 memcpy(sig.key, pk.key, 32);
1584 //dump_signature(2, &sig);
1586 message = construct_message(messagestring, av[argn], &mlen, hexencoded);
1587 rv = verify(&sig, message, mlen, bareinput);
1591 } else if (mode == LIST) {
1592 union signobject obj;
1593 char *keyringfile = find_keyfile(keyfile);
1595 fprintf(stderr, "can't find keyring file\n");
1598 int keyring = open(keyringfile, O_RDWR|O_APPEND);
1599 if (keyring == -1) {
1600 fprintf(stderr, "can't open keyring file %s\n", keyringfile);
1604 while ((rv = read_object(keyring, &obj))) {
1605 list_object(output, &obj);
1608 } else if (mode == IMPORT) {
1610 union signobject obj;
1611 char *keyringfile = find_keyfile(keyfile);
1612 int keyring = open(keyringfile, O_RDWR|O_APPEND);
1613 if (keyring == -1) {
1614 fprintf(stderr, "%s ", keyringfile);
1618 for (i = argn; i < ac; i++) {
1619 fd = open(av[i], O_RDONLY);
1621 fprintf(stderr, "%s ", av[i]);
1627 while ((rv = read_object(fd, &obj))) {
1628 fprintf(stderr, "importing type %d\n", object_type(&obj));
1629 /* TODO probably a more efficient way to do
1630 * this. Perhaps read in the keyring to
1632 lseek(keyring, 0, SEEK_SET);
1633 if (!find_object(keyring, &obj)) {
1634 write_object(keyring, &obj, outputflags);
1640 } else if (mode == ENCRYPT) {
1641 fprintf(stderr, "encryption not supported\n");
1643 } else if (mode == DECRYPT) {
1644 fprintf(stderr, "decryption not supported\n");
1649 * now, do the action
1652 if (mode == KEYGEN) {
1654 outfile = find_keyfile(keyfile);
1656 if (outfile && strcmp(outfile, "-") != 0) {
1657 output = open(outfile, O_RDWR|O_CREAT|O_APPEND, 0600);
1659 /* TODO encrypt key */
1661 fprintf(stderr, "encrypting key\n");
1662 collect_key(passkey, passphrase);
1663 encrypt_key(&sk, passkey);
1664 //memset(passphrase, 0, strlen(passphrase));
1665 memset(passkey, 0, 32);
1667 // dump_secret_key(2, &sk);
1668 write_secret_key(output, &sk, outputflags);
1669 } else if (mode == SIGN || mode == SIGNKEY) {
1670 if (outfile && strcmp(outfile, "-") != 0) {
1671 output = open(outfile, O_RDWR|O_CREAT|O_APPEND, 0600);
1673 //dump_signature(2, &sig);
1674 write_signature(output, &sig, outputflags);
1675 } else if (mode == EXTRACT) {
1676 if (outfile && strcmp(outfile, "-") != 0) {
1677 output = open(outfile, O_RDWR|O_CREAT|O_APPEND, 0600);
1679 // dump_public_key(2, &pk);
1680 write_public_key(output, &pk, outputflags);
1681 } else if (mode == VERIFY) {
1683 } else if (mode == LIST) {
1685 } else if (mode == IMPORT) {
1687 } else if (mode == ENCRYPT) {
1688 fprintf(stderr, "encryption not supported\n");
1690 } else if (mode == DECRYPT) {
1691 fprintf(stderr, "decryption not supported\n");
1695 if (message && messagefile) {
1696 munmap(message, mlen);
1699 memset(sk.key, 0, sizeof sk.key);