From a76ff60d7afae2c15385711bb5e070285e8732cc Mon Sep 17 00:00:00 2001 From: "git@daemon.de" Date: Tue, 12 Nov 2013 16:58:59 +0100 Subject: [PATCH] added pcptext_infile(), used with pcp1 -t -I $file, which determines filetype by content. minor debugging changes. --- ChangeLog | 35 ++++++++++++- src/encryption.c | 4 +- src/keymgmt.c | 56 ++++++++++++--------- src/keymgmt.h | 1 + src/keyprint.c | 116 ++++++++++++++++++++++++++++++++++++++++++++ src/keyprint.h | 1 + src/pcp.c | 7 ++- tests/unittests.cfg | 24 +++++++++ 8 files changed, 216 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 610786e..3a14bb6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,43 @@ +0.1.5 Fixed a segmentation fault when using pcp1 -t on a + public key. I added a double free() there by purpose + to test segfault catching I added in unittest.pl + and forgot to remove it. The good news is, that + I found the double free() immediately thanks to the + segfault catching of unittest.pl :) + + Fixed use of unencrypted secret keys, added proper + unittests for this case. Note: a secret key will + be stored unencrypted if the user doesn't enter + a password when asked. In addition to the fix I + added a question if the user is sure about what + he does. + + Moved config.h to include/pcp/ so it will be + installed as well. Removed the conditional include + of config.h in platform.h, that was stupid. + + Added generation of a pkg-config configuration + in libpcp/libpcp1.pc.in. + + Added -O support to -k. So now you can generate + a new secret key and export it directly into a + file. In this case the key will not be stored to + the vault. + + The -t option now accepts an inputfile (-I) and + determines what kind of file that might be and + if it finds out, prints some info about it to + stdout. Useful if you've got a z85 encoded file + without headers and comments and don't know what + it is. + 0.1.4 Changed key format (again), now the main secret is the ED25519 secret key, which will be encrypted. Everything else will be derived from that. Thanks to S.Neives and "CodesInChaos" from the libsodium mailinglist for clarifying it and helping me to understand it. - + 0.1.3 Added signature support using ED25519. Key format has changed it now contains the ed25519 diff --git a/src/encryption.c b/src/encryption.c index d40be0e..bcd397f 100644 --- a/src/encryption.c +++ b/src/encryption.c @@ -255,9 +255,9 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, char *recipi if(debug) { fprintf(stderr, "Using secret key:\n"); - pcpkey_printshortinfo(secret); + pcp_dumpkey(secret); fprintf(stderr, "Using publickey:\n"); - pcppubkey_printshortinfo(public); + pcp_dumppubkey(public); } unsigned char *input = NULL; diff --git a/src/keymgmt.c b/src/keymgmt.c index 4157b2a..1ecd1b7 100644 --- a/src/keymgmt.c +++ b/src/keymgmt.c @@ -64,9 +64,9 @@ int pcp_storekey (pcp_key_t *key) { -void pcp_keygen(char *passwd) { +void pcp_keygen(char *passwd, char *outfile) { pcp_key_t *k = pcpkey_new (); - pcp_key_t *key; + pcp_key_t *key = NULL; char *owner = pcp_getstdin("Enter the name of the key owner"); memcpy(k->owner, owner, strlen(owner) + 1); @@ -102,9 +102,18 @@ void pcp_keygen(char *passwd) { } if(key != NULL) { - if(pcp_storekey(key) == 0) { - fprintf(stderr, "Generated new secret key:\n"); + fprintf(stderr, "Generated new secret key:\n"); + if(outfile != NULL) { + pcp_exportsecretkey(key, outfile); pcpkey_printshortinfo(key); + fprintf(stderr, "key stored to file %s, vault unaltered\n", outfile); + memset(key, 0, sizeof(pcp_key_t)); + free(key); + } + else { + if(pcp_storekey(key) == 0) { + pcpkey_printshortinfo(key); + } } } @@ -216,28 +225,29 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile) { } if(key != NULL) { - FILE *out; - if(outfile == NULL) { - out = stdout; - } - else { - if((out = fopen(outfile, "wb+")) == NULL) { - fatal("Could not create output file %s", outfile); - out = NULL; - } - } - - if(out != NULL) { - if(debug) - pcp_dumpkey(key); - else - pcpkey_print(key, out); - } - - free(key); + pcp_exportsecretkey(key, outfile); } } +void pcp_exportsecretkey(pcp_key_t *key, char *outfile) { + FILE *out; + if(outfile == NULL) { + out = stdout; + } + else { + if((out = fopen(outfile, "wb+")) == NULL) { + fatal("Could not create output file %s", outfile); + out = NULL; + } + } + + if(out != NULL) { + if(debug) + pcp_dumpkey(key); + else + pcpkey_print(key, out); + } +} pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd) { if(recipient != NULL) { diff --git a/src/keymgmt.h b/src/keymgmt.h index 8525aec..56c93e4 100644 --- a/src/keymgmt.h +++ b/src/keymgmt.h @@ -45,6 +45,7 @@ int pcp_storekey (pcp_key_t *key); void pcp_keygen(); void pcp_listkeys(); void pcp_exportsecret(char *keyid, int useid, char *outfile); +void pcp_exportsecretkey(pcp_key_t *key, char *outfile); pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd); void pcp_exportpublic(char *keyid, char *recipient, char *passwd, char *outfile); char *pcp_normalize_id(char *keyid); diff --git a/src/keyprint.c b/src/keyprint.c index 2859f68..5192b97 100644 --- a/src/keyprint.c +++ b/src/keyprint.c @@ -23,6 +23,122 @@ #include "keyprint.h" +int pcptext_infile(char *infile) { + FILE *in; + int insize; + + if((in = fopen(infile, "rb")) == NULL) { + fatal("Could not open input file %s\n", infile); + goto errtinf1; + } + + fseek(in, 0, SEEK_END); + insize = ftell(in); + fseek(in, 0, SEEK_SET); + + if(insize == 40) { + fprintf(stdout, "%s seems to be an empty vault file\n", infile); + goto tdone; + } + + // maybe a vault? + vault_t *v = pcpvault_init(infile); + if(v != NULL) { + fprintf(stdout, "%s is a vault file\n", infile); + pcptext_vault(v); + goto tdone; + } + + // try z85ing it + char *z85 = pcp_readz85file(in); + if(z85 == NULL) { + fprintf(stdout, "Can't handle %s - unknown file type.\n", infile); + goto errtinf1; + } + + size_t clen; + unsigned char *bin = pcp_z85_decode((char *)z85, &clen); + free(z85); + + if(bin == NULL) { + fprintf(stdout, "%s isn't properly Z85 encoded - unknown file type.\n", infile); + goto errtinf1; + } + + if(clen == sizeof(pcp_key_t)) { + // secret key? + pcp_key_t *key = (pcp_key_t *)bin; + key2native(key); + if(pcp_sanitycheck_key(key) == 0) { + fprintf(stdout, "%s is a secret key file:\n", infile); + pcpkey_print(key, stdout); + free(key); + goto tdone; + } + else { + fprintf(stdout, "%s looks like a secret key but failed sanity checking.\n", infile); + free(key); + goto errtinf1; + } + } + + if(clen == sizeof(pcp_pubkey_t)) { + // public key? + pcp_pubkey_t *key = (pcp_pubkey_t *)bin; + pubkey2native(key); + if(pcp_sanitycheck_pub(key) == 0) { + fprintf(stdout, "%s is a public key file:\n", infile); + pcppubkey_print(key, stdout); + free(key); + goto tdone; + } + else { + fprintf(stdout, "%s looks like a publickey but failed sanity checking.\n", infile); + free(key); + goto errtinf1; + } + } + + if(clen == sizeof(pcp_sig_t)) { + // a signature? + pcp_sig_t *sig = (pcp_sig_t *)bin; + sig2native(sig); + if(sig->version == PCP_SIG_VERSION) { + // looks valid + fprintf(stdout, "%s is an ed25519 signature file:\n", infile); + struct tm *c; + time_t t = (time_t)sig->ctime; + c = localtime(&t); + fprintf(stdout, "Signed by key: 0x%s\n", sig->id); + fprintf(stdout, "Creation Time: %04d-%02d-%02dT%02d:%02d:%02d\n", + c->tm_year+1900, c->tm_mon+1, c->tm_mday, + c->tm_hour, c->tm_min, c->tm_sec); + fprintf(stdout, " Signature: "); + pcpprint_bin(stdout, sig->edsig, crypto_sign_BYTES); + fprintf(stdout, "\n"); + free(sig); + goto tdone; + } + else { + fprintf(stdout, "%s looks like a ed255 signature but failed sanity checking.\n", infile); + free(sig); + goto errtinf1; + } + } + + // still there? + fprintf(stdout, "%s looks Z85 encoded but otherwise unknown and is possibly encrypted.\n", infile); + + tdone: + fatals_reset(); + return 0; + + errtinf1: + fatals_reset(); + return 1; +} + + void pcptext_key(char *keyid) { pcp_key_t *s = pcpkey_exists(keyid); if(s != NULL) { diff --git a/src/keyprint.h b/src/keyprint.h index 2b55af0..4d28a99 100644 --- a/src/keyprint.h +++ b/src/keyprint.h @@ -42,6 +42,7 @@ void pcppubkey_printlineinfo(pcp_pubkey_t *key); void pcptext_key(char *keyid); void pcptext_vault(vault_t *vault); +int pcptext_infile(char *infile); void pcpexport_yaml(char *outfile); void pcpprint_bin(FILE *out, unsigned char *data, size_t len); diff --git a/src/pcp.c b/src/pcp.c index a4580ec..4702c5f 100644 --- a/src/pcp.c +++ b/src/pcp.c @@ -234,7 +234,7 @@ int main (int argc, char **argv) { if(vault != NULL) { switch (mode) { case PCP_MODE_KEYGEN: - pcp_keygen(xpass); + pcp_keygen(xpass, outfile); if(xpass != NULL) free(xpass); break; @@ -309,9 +309,12 @@ int main (int argc, char **argv) { break; case PCP_MODE_TEXT: - if(! useid) { + if(! useid && infile == NULL) { pcptext_vault(vault); } + else if(infile != NULL) { + pcptext_infile(infile); + } else { id = pcp_normalize_id(keyid); if(id != NULL) { diff --git a/tests/unittests.cfg b/tests/unittests.cfg index 32e3737..68518da 100644 --- a/tests/unittests.cfg +++ b/tests/unittests.cfg @@ -209,6 +209,30 @@ dxmorg@florida.cops.gov +# +# check usage of unencrypted secret key + + cmd = (echo dau; echo foo; echo yes) | $pcp -V vcl -k -x "" + expect = /added to/ + + + + cmd = $pcp -V vcl -y + expect = /encrypted: no/ + + + + prepare = $pcp -V vcl -I key-bobby-pub -P + cmd = echo HALLO | $pcp -V vcl -e -O testencrypted -i ${idbobby} + expect = /success/ + + + + prepare = $pcp -V vcl -p | $pcp -V vb -P + cmd = $pcp -V vb -d -I testencrypted -x b + expect = /HALLO/ + + # # signature test