diff --git a/include/pcp/defines.h b/include/pcp/defines.h index 917b003..a3bc158 100644 --- a/include/pcp/defines.h +++ b/include/pcp/defines.h @@ -118,10 +118,12 @@ typedef enum _PCP_KEY_TYPES { #ifndef PCP_CBC #define PCP_ASYM_CIPHER 5 #define PCP_SYM_CIPHER 23 + #define PCP_ASYM_CIPHER_SIG 24 #define PCP_BLOCK_SIZE 32 * 1024 #else /* CBC mode, use smaller blocks */ #define PCP_ASYM_CIPHER 7 + #define PCP_ASYM_CIPHER_SIG 8 #define PCP_SYM_CIPHER 25 #define PCP_BLOCK_SIZE 1 * 1024 #endif diff --git a/include/pcp/mgmt.h b/include/pcp/mgmt.h index 4cf6b01..ebd069b 100644 --- a/include/pcp/mgmt.h +++ b/include/pcp/mgmt.h @@ -73,13 +73,19 @@ those cipher numbers become official, I'll use them instead of my own. + - We use 64 bit integers for times everywhere (ctime, expire, etc), + to be year 2038 safe. Note, that this is a violation of the + RFC spec. However, said RFC have to be modified to fit 2038 + anc beyond anyways. This applies for the keyfile ctime as + well for the key sig sub fields containing time values. + - The exported public key packet contains a signature. We're filling out all required fields. A signature has a variable number of sig sub packets. We use only these types: - 2 = Signature Creation Time (4 byte) - 3 = Signature Expiration Time (4 byte) - 9 = Key Expiration Time (4 bytes) + 2 = Signature Creation Time (8 byte) + 3 = Signature Expiration Time (8 byte) + 9 = Key Expiration Time (8 bytes) 20 = Notation Data (4 byte flags, N bytes name+value) 27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80 diff --git a/include/pcp/structs.h b/include/pcp/structs.h index 838913c..d70c3be 100644 --- a/include/pcp/structs.h +++ b/include/pcp/structs.h @@ -343,7 +343,7 @@ typedef struct _pcp_stream_t Pcpstream; /* various helper structs for mgmt.c, used internally only */ struct _pcp_rfc_pubkey_header_t { uint8_t version; - uint32_t ctime; + uint64_t ctime; uint8_t cipher; }; diff --git a/libpcp/crypto.c b/libpcp/crypto.c index 909f6f0..289ddf9 100644 --- a/libpcp/crypto.c +++ b/libpcp/crypto.c @@ -197,6 +197,14 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t else if(head[0] == PCP_ASYM_CIPHER) { self = 0; } + else if(head[0] == PCP_ASYM_CIPHER_SIG) { + self = 0; + verify = 1; + } + else { + fatal(ptx, "Unknown file header (got: %02x)\n", head[0]); + goto errdef1; + } } } @@ -323,7 +331,10 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t } /* step 1, file header */ - head[0] = PCP_ASYM_CIPHER; + if(sign) + head[0] = PCP_ASYM_CIPHER_SIG; + else + head[0] = PCP_ASYM_CIPHER; ps_write(out, head, 1); /* fwrite(head, 1, 1, out); */ /* fprintf(stderr, "D: header - 1\n"); */ @@ -454,7 +465,8 @@ size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, byte * out_size += crypto_secretbox_NONCEBYTES + es; if(recsign != NULL) - crypto_generichash_update(st, in_buf, cur_bufsize); + crypto_generichash_update(st, buf_cipher, es); + //crypto_generichash_update(st, in_buf, cur_bufsize); #ifdef PCP_CBC /* make current cipher to next IV, ignore nonce and pad */ @@ -573,7 +585,8 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte * /* fwrite(buf_clear, ciphersize - PCP_CRYPTO_ADD, 1, out); */ if(recverify != NULL) - crypto_generichash_update(st, buf_clear, ciphersize - PCP_CRYPTO_ADD); + crypto_generichash_update(st, buf_cipher, ciphersize); + //crypto_generichash_update(st, buf_clear, ciphersize - PCP_CRYPTO_ADD); free(buf_clear); diff --git a/libpcp/mgmt.c b/libpcp/mgmt.c index 65df0d1..794b2d2 100644 --- a/libpcp/mgmt.c +++ b/libpcp/mgmt.c @@ -120,7 +120,12 @@ int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *su ucfree(notation, nsize); } else { - /* unsupported or ignored sig sub */ + /* unsupported or ignored sig subs: + we (currently) ignore sig ctime, expire and keyexpire, + since the ctime - which is the only one we need internally - + is already known from the key ctime. This may change in + the future though. + */ if(buffer_get_chunk(blob, ignore, subheader->size) == 0) { fatal(ptx, "Invalid 'unsupported' notation, expected %ld bytes, but got 0\n", subheader->size); return 1; @@ -135,6 +140,7 @@ int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t // read hash + sig size_t blobstop = blob->offset; size_t sigsize = crypto_sign_BYTES + crypto_generichash_BYTES_MAX; + size_t phead = (2 * sizeof(uint8_t)) + sizeof(uint64_t); /* rfc_pub_h */ byte *signature = ucmalloc(sigsize); if(buffer_get_chunk(blob, signature, sigsize) == 0) @@ -144,11 +150,11 @@ int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t sk->type = PCP_KEYSIG_NATIVE; /* everything minus version, ctime and cipher, 1st 3 fields */ - sk->size = blobstop - 6; + sk->size = blobstop - phead; memcpy(sk->id, p->id, 17); /* put the whole signature blob into our keysig */ - blob->offset = 6; /* woah, hack :) */ + blob->offset = phead; sk->blob = ucmalloc(sk->size); buffer_get_chunk(blob, sk->blob, sk->size); @@ -262,7 +268,7 @@ pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob) { rfc_pub_sig_s *subheader = ucmalloc(sizeof(rfc_pub_sig_s)); if(buffer_done(blob)) goto be; - p->ctime = buffer_get32na(blob); + p->ctime = buffer_get64na(blob); uint8_t pkcipher = buffer_get8(blob); if(buffer_done(blob)) goto be; @@ -352,7 +358,7 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) { date[19] = '\0'; struct tm c; if(strptime(date, "%Y-%m-%dT%H:%M:%S", &c) == NULL) { - fatal(ptx, "Failed to parse creation time in PBP public key file (<%s>)\n", date); + fatal(ptx, "Failed to parse creation time in PBP public key file\n"); free(date); goto errimp2; } @@ -594,7 +600,7 @@ Buffer *pcp_export_rfc_pub (pcp_key_t *sk) { /* add the header */ buffer_add8(out, PCP_KEY_VERSION); - buffer_add32be(out, sk->ctime); + buffer_add64be(out, sk->ctime); buffer_add8(out, EXP_PK_CIPHER); /* add the keys */ @@ -619,19 +625,19 @@ Buffer *pcp_export_rfc_pub (pcp_key_t *sk) { buffer_add16be(raw, nsubs); /* add sig ctime */ - buffer_add32be(raw, 4); + buffer_add32be(raw, 8); buffer_add8(raw, EXP_SIG_SUB_CTIME); - buffer_add32be(raw, time(0)); + buffer_add64be(raw, time(0)); /* add sig expire time */ - buffer_add32be(raw, 4); + buffer_add32be(raw, 8); buffer_add8(raw, EXP_SIG_SUB_SIGEXPIRE); - buffer_add32be(raw, time(0) + 31536000); + buffer_add64be(raw, time(0) + 31536000); /* add key expire time */ - buffer_add32be(raw, 4); + buffer_add32be(raw, 8); buffer_add8(raw, EXP_SIG_SUB_KEYEXPIRE); - buffer_add32be(raw, sk->ctime + 31536000); + buffer_add64be(raw, sk->ctime + 31536000); size_t notation_size = 0; /* add serial number notation sub */ diff --git a/src/encryption.c b/src/encryption.c index 7324491..937ac61 100644 --- a/src/encryption.c +++ b/src/encryption.c @@ -76,7 +76,7 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i symkey = pcp_scrypt(ptx, passphrase, strlen(passphrase), salt, 90); free(salt); } - else { + else if(head == PCP_ASYM_CIPHER || head == PCP_ASYM_CIPHER_SIG) { /* asymetric mode */ if(useid) { secret = pcphash_keyexists(ptx, id); @@ -108,11 +108,18 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i secret = pcpkey_decrypt(ptx, secret, passphrase); if(secret == NULL) goto errde3; + + if(head == PCP_ASYM_CIPHER_SIG) + verify = 1; } } + else { + fatal(ptx, "Could not determine input file type (got: %02x)\n", head); + goto errde3; + } } else { - fatal(ptx, "Could not determine input file type\n"); + fatal(ptx, "Failed to read from file!\n"); goto errde3; }