mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 12:00:56 +01:00
changed secret key export format, now we encrypt the whole thing, and we use an extra passphrase to do so. import wrapper in src/ not implemented yet.
This commit is contained in:
5
TODO
5
TODO
@@ -14,10 +14,6 @@ Implement pbp crypto fix https://github.com/stef/pbp/commit/7d7b7c9ecb7604ad2293
|
|||||||
|
|
||||||
move remaining Export+Import stuff from src => lib.
|
move remaining Export+Import stuff from src => lib.
|
||||||
|
|
||||||
Update pubimport to new format
|
|
||||||
|
|
||||||
Update secret im+ex-port to new format.
|
|
||||||
|
|
||||||
Update pod key format spec.
|
Update pod key format spec.
|
||||||
|
|
||||||
-l show keysig, if any
|
-l show keysig, if any
|
||||||
@@ -26,6 +22,7 @@ vault checksum: add keysigs as well
|
|||||||
|
|
||||||
keysig: fix struct to be even (i.e. type => uint16_t or something) OR add a keysig2blob function
|
keysig: fix struct to be even (i.e. type => uint16_t or something) OR add a keysig2blob function
|
||||||
|
|
||||||
|
Secretkey import: fill in calculated fields (keyid etc), add pcp_importsecret() wrapper to keymgmt.c
|
||||||
|
|
||||||
Python binding, e.g.:
|
Python binding, e.g.:
|
||||||
py % cdll.LoadLibrary("libsodium.so.8")
|
py % cdll.LoadLibrary("libsodium.so.8")
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ extern "C" {
|
|||||||
#include "pcp/config.h"
|
#include "pcp/config.h"
|
||||||
#include "pcp/base85.h"
|
#include "pcp/base85.h"
|
||||||
#include "pcp/buffer.h"
|
#include "pcp/buffer.h"
|
||||||
#include "pcp/config.h"
|
|
||||||
#include "pcp/crypto.h"
|
#include "pcp/crypto.h"
|
||||||
#include "pcp/defines.h"
|
#include "pcp/defines.h"
|
||||||
#include "pcp/digital_crc32.h"
|
#include "pcp/digital_crc32.h"
|
||||||
@@ -17,6 +16,7 @@ extern "C" {
|
|||||||
#include "pcp/jenhash.h"
|
#include "pcp/jenhash.h"
|
||||||
#include "pcp/key.h"
|
#include "pcp/key.h"
|
||||||
#include "pcp/keyhash.h"
|
#include "pcp/keyhash.h"
|
||||||
|
#include "pcp/keysig.h"
|
||||||
#include "pcp/mac.h"
|
#include "pcp/mac.h"
|
||||||
#include "pcp/mem.h"
|
#include "pcp/mem.h"
|
||||||
#include "pcp/mgmt.h"
|
#include "pcp/mgmt.h"
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
#include "jenhash.h"
|
#include "jenhash.h"
|
||||||
#include "scrypt.h"
|
#include "scrypt.h"
|
||||||
|
#include "keysig.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PCP private key structure. Most fields are self explanatory.
|
PCP private key structure. Most fields are self explanatory.
|
||||||
@@ -142,22 +143,6 @@ typedef struct _pcp_rec_t pcp_rec_t;
|
|||||||
|
|
||||||
#define PCP_RAW_KEYSIZE sizeof(pcp_key_t) - sizeof(UT_hash_handle)
|
#define PCP_RAW_KEYSIZE sizeof(pcp_key_t) - sizeof(UT_hash_handle)
|
||||||
#define PCP_RAW_PUBKEYSIZE sizeof(pcp_pubkey_t) - sizeof(UT_hash_handle)
|
#define PCP_RAW_PUBKEYSIZE sizeof(pcp_pubkey_t) - sizeof(UT_hash_handle)
|
||||||
#define PCP_RAW_KEYSIGSIZE sizeof(pcp_keysig_t) - sizeof(UT_hash_handle)
|
|
||||||
|
|
||||||
/* holds a public key signature */
|
|
||||||
struct _pcp_keysig_t {
|
|
||||||
uint8_t type;
|
|
||||||
uint32_t size;
|
|
||||||
char belongs[17];
|
|
||||||
byte checksum[32];
|
|
||||||
byte *blob;
|
|
||||||
UT_hash_handle hh;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _pcp_keysig_t pcp_keysig_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -186,10 +171,6 @@ pcp_key_t *key2native(pcp_key_t *k);
|
|||||||
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k);
|
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k);
|
||||||
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k);
|
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k);
|
||||||
|
|
||||||
pcp_keysig_t *keysig2be(pcp_keysig_t *s);
|
|
||||||
pcp_keysig_t *keysig2native(pcp_keysig_t *s);
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char * pcp_gennonce();
|
unsigned char * pcp_gennonce();
|
||||||
|
|
||||||
void pcpedit_key(char *keyid);
|
void pcpedit_key(char *keyid);
|
||||||
@@ -207,8 +188,5 @@ void *pcp_keyblob(void *k, int type); /* allocates blob */
|
|||||||
int pcp_sanitycheck_pub(pcp_pubkey_t *key);
|
int pcp_sanitycheck_pub(pcp_pubkey_t *key);
|
||||||
int pcp_sanitycheck_key(pcp_key_t *key);
|
int pcp_sanitycheck_key(pcp_key_t *key);
|
||||||
|
|
||||||
/* fetch a keysig from a buffer, usually loaded from vault */
|
|
||||||
pcp_keysig_t *pcp_keysig_new(Buffer *blob);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _HAVE_PCP_KEYPAIR_H */
|
#endif /* _HAVE_PCP_KEYPAIR_H */
|
||||||
|
|||||||
@@ -19,6 +19,9 @@
|
|||||||
You can contact me by mail: <tom AT vondein DOT org>.
|
You can contact me by mail: <tom AT vondein DOT org>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
key management, namely import and export routines.
|
||||||
|
we're working with buffers only, no direct file i/o */
|
||||||
|
|
||||||
#ifndef _HAVE_PCP_MGMT_H
|
#ifndef _HAVE_PCP_MGMT_H
|
||||||
#define _HAVE_PCP_MGMT_H
|
#define _HAVE_PCP_MGMT_H
|
||||||
@@ -33,16 +36,32 @@
|
|||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "ed.h"
|
#include "ed.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
#include "keysig.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "scrypt.h"
|
||||||
|
|
||||||
/* key management api, export, import, yaml and stuff */
|
/* key management api, export, import, yaml and stuff */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* RFC4880 alike public key export with some simplifications:
|
/* RFC4880 alike public key export with some modifications:
|
||||||
|
|
||||||
In sig subpackets we're using fixed sized fields instead
|
- Key material is native to us and not specified in the
|
||||||
of the mess they use in rfc4880. Sorry. We use only these types:
|
rfc for curve25519/ed25519. Therefore we're doing it like
|
||||||
|
so: mp|sp|cp
|
||||||
|
where mp = master keysigning public key (ed25519), 32 bytes
|
||||||
|
sp = signing public key (ed25519), 32 bytes
|
||||||
|
cp = encryption public key (curve25519), 32 bytes
|
||||||
|
|
||||||
|
- The various cipher (algorithm) id's are unspecified for
|
||||||
|
our native ciphers. Therefore I created them, starting at
|
||||||
|
33 (afaik 22 is the last officially assigned one). Once
|
||||||
|
those cipher numbers become official, I'll use them instead
|
||||||
|
of my own.
|
||||||
|
|
||||||
|
- 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)
|
2 = Signature Creation Time (4 byte)
|
||||||
3 = Signature Expiration Time (4 byte)
|
3 = Signature Expiration Time (4 byte)
|
||||||
@@ -50,9 +69,24 @@
|
|||||||
20 = Notation Data (4 byte flags, N bytes name+value)
|
20 = Notation Data (4 byte flags, N bytes name+value)
|
||||||
27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80
|
27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80
|
||||||
|
|
||||||
The actual signature field doesn't contain the 1st 16 bits
|
- We use 3 notation fields:
|
||||||
of the hash, since crypto_sign() created signatures consist
|
* "owner", which contains the owner name, if set
|
||||||
of the hash+signature anyway.
|
* "mail", which contains the emailaddress, if set
|
||||||
|
* "serial", which contains the 32bit serial number
|
||||||
|
|
||||||
|
- The actual signature field consists of the blake2 hash of
|
||||||
|
(mp|sp|cp|keysig) followed by the nacl signature. However, we do
|
||||||
|
not put an extra 16byte value of the hash, since the nacl
|
||||||
|
signature already contains the full hash. So, an implementation
|
||||||
|
could simply pull the fist 16 bytes of said hash to get
|
||||||
|
the same result.
|
||||||
|
|
||||||
|
- The mp keypair will be used for signing. The recipient can
|
||||||
|
verify the signature, since mp is included.
|
||||||
|
|
||||||
|
- While we put expiration dates for the key and the signature
|
||||||
|
into the export as the rfc demands, we ignore them. Key expiring
|
||||||
|
is not implemented in PCP yet.
|
||||||
|
|
||||||
So, a full pubkey export looks like this
|
So, a full pubkey export looks like this
|
||||||
|
|
||||||
@@ -67,9 +101,32 @@
|
|||||||
|
|
||||||
We use big-endian always.
|
We use big-endian always.
|
||||||
|
|
||||||
|
Unlike RC4880 public key exports, we're using Z85 encoding if
|
||||||
|
armoring have been requested by the user. Armored output has
|
||||||
|
a header and a footer line, however they are ignored by the
|
||||||
|
parser and are therefore optional. Newlines, if present, are
|
||||||
|
optional as well.
|
||||||
|
|
||||||
http://tools.ietf.org/html/rfc4880#section-5.2.3
|
http://tools.ietf.org/html/rfc4880#section-5.2.3
|
||||||
|
|
||||||
*/
|
The key sig blob will be saved in the Vault if we import a public key
|
||||||
|
unaltered, so we can verify the signature at will anytime. When exporting
|
||||||
|
a foreign public key, we will just put out that key sig blob to the
|
||||||
|
export untouched.
|
||||||
|
|
||||||
|
Currently PCP only support self-signed public key exports.
|
||||||
|
|
||||||
|
We only support one key signature per key. However, it would be easily
|
||||||
|
possible to support foreign keysigs as well in the future.
|
||||||
|
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Secret key are exported in proprietary format. We just encrypt the
|
||||||
|
whole structure symmetrically and prepend it with a nonce.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* various helper structs, used internally only */
|
||||||
struct _pcp_rfc_pubkey_header_t {
|
struct _pcp_rfc_pubkey_header_t {
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
uint32_t ctime;
|
uint32_t ctime;
|
||||||
@@ -127,24 +184,33 @@ typedef struct _pcp_ks_bundle_t pcp_ks_bundle_t;
|
|||||||
|
|
||||||
/* in armored mode, we're using the usual head+foot */
|
/* in armored mode, we're using the usual head+foot */
|
||||||
#define EXP_PK_HEADER "-----BEGIN ED25519-CURVE29915 PUBLIC KEY-----"
|
#define EXP_PK_HEADER "-----BEGIN ED25519-CURVE29915 PUBLIC KEY-----"
|
||||||
#define EXP_PK_FOOTER "------END ED25519-CURVE29915 PUBLICKEY------"
|
#define EXP_PK_FOOTER "------END ED25519-CURVE29915 PUBLIC KEY------"
|
||||||
|
#define EXP_SK_HEADER "-----BEGIN ED25519-CURVE29915 PRIVATE KEY-----"
|
||||||
|
#define EXP_SK_FOOTER "------END ED25519-CURVE29915 PRIVATE KEY------"
|
||||||
|
|
||||||
|
|
||||||
/* pubkey export formats */
|
/* pubkey export formats */
|
||||||
#define EXP_FORMAT_NATIVE 0x01
|
#define EXP_FORMAT_NATIVE 0x01
|
||||||
#define EXP_FORMAT_PBP 0x03
|
#define EXP_FORMAT_PBP 0x03
|
||||||
|
|
||||||
|
/* export self signed public key from master secret */
|
||||||
/* export public key */
|
|
||||||
Buffer *pcp_export_rfc_pub (pcp_key_t *sk);
|
Buffer *pcp_export_rfc_pub (pcp_key_t *sk);
|
||||||
|
|
||||||
|
/* export foreign public key
|
||||||
|
Buffer *pcp_export_rfc_pub_foreign (pcp_pubkey_t *pub); */
|
||||||
|
|
||||||
/* export public key in pbp format */
|
/* export public key in pbp format */
|
||||||
Buffer *pcp_export_pbp_pub(pcp_key_t *sk);
|
Buffer *pcp_export_pbp_pub(pcp_key_t *sk);
|
||||||
|
|
||||||
|
/* export secret key */
|
||||||
|
Buffer *pcp_export_secret(pcp_key_t *sk, char *passphrase);
|
||||||
|
|
||||||
/* import public keys */
|
/* import public keys */
|
||||||
pcp_ks_bundle_t *pcp_import_pub(unsigned char *raw, size_t rawsize);
|
pcp_ks_bundle_t *pcp_import_pub(unsigned char *raw, size_t rawsize);
|
||||||
pcp_ks_bundle_t *pcp_import_pub_rfc(Buffer *blob);
|
pcp_ks_bundle_t *pcp_import_pub_rfc(Buffer *blob);
|
||||||
pcp_ks_bundle_t *pcp_import_pub_pbp(Buffer *blob);
|
pcp_ks_bundle_t *pcp_import_pub_pbp(Buffer *blob);
|
||||||
|
|
||||||
|
/* import secret key */
|
||||||
|
pcp_key_t *pcp_import_secret(Buffer *cipher, char *passphrase);
|
||||||
|
|
||||||
#endif // _HAVE_PCP_MGMT_H
|
#endif // _HAVE_PCP_MGMT_H
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "keysig.h"
|
||||||
|
|
||||||
struct _vault_t {
|
struct _vault_t {
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|||||||
44
libpcp/key.c
44
libpcp/key.c
@@ -296,28 +296,6 @@ pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
pcp_keysig_t * keysig2be(pcp_keysig_t *s) {
|
|
||||||
#ifdef __CPU_IS_BIG_ENDIAN
|
|
||||||
return s;
|
|
||||||
#else
|
|
||||||
uint32_t size = s->size;
|
|
||||||
unsigned char* p = (unsigned char*)&size;
|
|
||||||
if(p[0] != 0) {
|
|
||||||
s->size = htobe32(s->size);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
pcp_keysig_t *keysig2native(pcp_keysig_t *s) {
|
|
||||||
#ifdef __CPU_IS_BIG_ENDIAN
|
|
||||||
return s;
|
|
||||||
#else
|
|
||||||
s->size = be32toh(s->size);
|
|
||||||
return s;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcp_seckeyblob(void *blob, pcp_key_t *k) {
|
void pcp_seckeyblob(void *blob, pcp_key_t *k) {
|
||||||
memcpy(blob, k, PCP_RAW_KEYSIZE);
|
memcpy(blob, k, PCP_RAW_KEYSIZE);
|
||||||
}
|
}
|
||||||
@@ -441,25 +419,3 @@ int pcp_sanitycheck_key(pcp_key_t *key) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcp_keysig_t *pcp_keysig_new(Buffer *blob) {
|
|
||||||
/* FIXME: sanity check before actually loading it */
|
|
||||||
|
|
||||||
pcp_keysig_t *sk = ucmalloc(sizeof(pcp_keysig_t));
|
|
||||||
|
|
||||||
uint8_t type = buffer_get8(blob);
|
|
||||||
uint32_t size = buffer_get32na(blob);
|
|
||||||
|
|
||||||
byte *checksum = ucmalloc(32);
|
|
||||||
buffer_get_chunk(blob, checksum, 32);
|
|
||||||
|
|
||||||
sk->blob = ucmalloc(size);
|
|
||||||
buffer_get_chunk(blob, sk->blob, size);
|
|
||||||
|
|
||||||
sk->size = size;
|
|
||||||
sk->type = type;
|
|
||||||
memcpy(sk->checksum, checksum, 32);
|
|
||||||
|
|
||||||
ucfree(checksum, 32);
|
|
||||||
|
|
||||||
return sk;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -54,7 +54,10 @@ void *urmalloc(size_t s) {
|
|||||||
|
|
||||||
void *ucrealloc(void *d, size_t oldlen, size_t newlen) {
|
void *ucrealloc(void *d, size_t oldlen, size_t newlen) {
|
||||||
newlen = newlen * sizeof(unsigned char);
|
newlen = newlen * sizeof(unsigned char);
|
||||||
void *value = realloc (d, newlen);
|
|
||||||
|
/* we're using a 1 byte sized pointer, so that we can
|
||||||
|
memset(zero) it after resizing */
|
||||||
|
unsigned char *value = realloc (d, newlen);
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
err(errno, "Cannot reallocate %ld bytes of memory", newlen);
|
err(errno, "Cannot reallocate %ld bytes of memory", newlen);
|
||||||
@@ -63,7 +66,7 @@ void *ucrealloc(void *d, size_t oldlen, size_t newlen) {
|
|||||||
|
|
||||||
memset (&value[oldlen], 0, newlen-oldlen);
|
memset (&value[oldlen], 0, newlen-oldlen);
|
||||||
|
|
||||||
return value;
|
return (void *)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ucfree(void *d, size_t len) {
|
void ucfree(void *d, size_t len) {
|
||||||
|
|||||||
143
libpcp/mgmt.c
143
libpcp/mgmt.c
@@ -93,6 +93,11 @@ int _check_sigsubs(Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader) {
|
|||||||
else if(strncmp(notation, "mail", 4) == 0) {
|
else if(strncmp(notation, "mail", 4) == 0) {
|
||||||
memcpy(p->mail, value, vsize);
|
memcpy(p->mail, value, vsize);
|
||||||
}
|
}
|
||||||
|
else if(strncmp(notation, "serial", 6) == 0) {
|
||||||
|
uint32_t serial;
|
||||||
|
memcpy(&serial, value, 4);
|
||||||
|
p->serial = htobe32(serial);
|
||||||
|
}
|
||||||
|
|
||||||
ucfree(notation, nsize);
|
ucfree(notation, nsize);
|
||||||
ucfree(value, vsize);
|
ucfree(value, vsize);
|
||||||
@@ -194,9 +199,7 @@ pcp_ks_bundle_t *pcp_import_pub(unsigned char *raw, size_t rawsize) {
|
|||||||
|
|
||||||
if(version == PCP_KEY_VERSION) {
|
if(version == PCP_KEY_VERSION) {
|
||||||
/* ah, homerun */
|
/* ah, homerun */
|
||||||
pcp_ks_bundle_t *b = pcp_import_pub_rfc(blob);
|
return pcp_import_pub_rfc(blob);
|
||||||
pcp_keysig_t *sk = b->s;
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* nope, it's probably pbp */
|
/* nope, it's probably pbp */
|
||||||
@@ -332,8 +335,8 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk) {
|
|||||||
|
|
||||||
|
|
||||||
Buffer *pcp_export_rfc_pub (pcp_key_t *sk) {
|
Buffer *pcp_export_rfc_pub (pcp_key_t *sk) {
|
||||||
Buffer *out = buffer_new(320, "bo1");
|
Buffer *out = buffer_new(320, "exportbuf");
|
||||||
Buffer *raw = buffer_new(256, "bs1");
|
Buffer *raw = buffer_new(256, "keysigbuf");
|
||||||
|
|
||||||
/* add the header */
|
/* add the header */
|
||||||
buffer_add8(out, PCP_KEY_VERSION);
|
buffer_add8(out, PCP_KEY_VERSION);
|
||||||
@@ -390,6 +393,15 @@ Buffer *pcp_export_rfc_pub (pcp_key_t *sk) {
|
|||||||
buffer_add(raw, sk->mail, strlen(sk->mail));
|
buffer_add(raw, sk->mail, strlen(sk->mail));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add serial number notation sub */
|
||||||
|
notation_size = 6 + 4 + 4;
|
||||||
|
buffer_add32be(raw, notation_size);
|
||||||
|
buffer_add8(raw, EXP_SIG_SUB_NOTATION);
|
||||||
|
buffer_add16be(raw, 6);
|
||||||
|
buffer_add16be(raw, 4);
|
||||||
|
buffer_add(raw, "serial", 6);
|
||||||
|
buffer_add32be(raw, sk->serial);
|
||||||
|
|
||||||
/* add key flags */
|
/* add key flags */
|
||||||
buffer_add32be(raw, 1);
|
buffer_add32be(raw, 1);
|
||||||
buffer_add8(raw, 27);
|
buffer_add8(raw, 27);
|
||||||
@@ -423,3 +435,124 @@ Buffer *pcp_export_rfc_pub (pcp_key_t *sk) {
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Buffer *pcp_export_secret(pcp_key_t *sk, char *passphrase) {
|
||||||
|
unsigned char *nonce = NULL;
|
||||||
|
unsigned char *symkey = NULL;
|
||||||
|
unsigned char *cipher = NULL;
|
||||||
|
size_t es;
|
||||||
|
|
||||||
|
Buffer *raw = buffer_new(512, "secretbuf");
|
||||||
|
Buffer *out = buffer_new(512, "secretciperblob");
|
||||||
|
|
||||||
|
buffer_add(raw, sk->mastersecret, 64);
|
||||||
|
buffer_add(raw, sk->secret, 32);
|
||||||
|
buffer_add(raw, sk->edsecret, 64);
|
||||||
|
|
||||||
|
buffer_add(raw, sk->masterpub, 32);
|
||||||
|
buffer_add(raw, sk->pub, 32);
|
||||||
|
buffer_add(raw, sk->edpub, 32);
|
||||||
|
|
||||||
|
if(strlen(sk->owner) > 0) {
|
||||||
|
buffer_add16be(raw, strlen(sk->owner));
|
||||||
|
buffer_add(raw, sk->owner, strlen(sk->owner));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buffer_add16be(raw, 0);
|
||||||
|
|
||||||
|
if(strlen(sk->mail) > 0) {
|
||||||
|
buffer_add16be(raw, strlen(sk->mail));
|
||||||
|
buffer_add(raw, sk->mail, strlen(sk->mail));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buffer_add16be(raw, 0);
|
||||||
|
|
||||||
|
buffer_add64be(raw, sk->ctime);
|
||||||
|
buffer_add32be(raw, sk->version);
|
||||||
|
buffer_add32be(raw, sk->serial);
|
||||||
|
|
||||||
|
nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
|
||||||
|
arc4random_buf(nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
symkey = pcp_scrypt(passphrase, strlen(passphrase), nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
|
||||||
|
es = pcp_sodium_mac(&cipher, buffer_get(raw), buffer_size(raw), nonce, symkey);
|
||||||
|
|
||||||
|
buffer_add(out, nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
buffer_add(out, cipher, es);
|
||||||
|
|
||||||
|
buffer_free(raw);
|
||||||
|
ucfree(nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
ucfree(symkey, 64);
|
||||||
|
ucfree(cipher, es);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcp_key_t *pcp_import_secret(Buffer *cipher, char *passphrase) {
|
||||||
|
pcp_key_t *sk = ucmalloc(sizeof(pcp_key_t));
|
||||||
|
unsigned char *nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
|
||||||
|
unsigned char *symkey = NULL;
|
||||||
|
unsigned char *clear = NULL;
|
||||||
|
size_t cipherlen = 0;
|
||||||
|
size_t minlen = (64 * 2) * (32 * 4) + 8 + 4 + 4;
|
||||||
|
uint16_t notationlen = 0;
|
||||||
|
|
||||||
|
Buffer *blob = buffer_new(512, "secretdecryptbuf");
|
||||||
|
|
||||||
|
if(buffer_get_chunk(cipher, nonce, crypto_secretbox_NONCEBYTES) == 0)
|
||||||
|
goto impserr1;
|
||||||
|
|
||||||
|
symkey = pcp_scrypt(passphrase, strlen(passphrase), nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
|
||||||
|
cipherlen = buffer_left(cipher);
|
||||||
|
if(cipherlen < minlen) {
|
||||||
|
fatal("expected decrypted secret key size %ld is less than minimum len %ld\n", cipherlen, minlen);
|
||||||
|
goto impserr1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pcp_sodium_verify_mac(&clear, buffer_get_remainder(cipher),
|
||||||
|
cipherlen, nonce, symkey) != 0)
|
||||||
|
goto impserr1;
|
||||||
|
|
||||||
|
buffer_add(blob, clear, cipherlen - PCP_CRYPTO_ADD);
|
||||||
|
|
||||||
|
buffer_get_chunk(blob, sk->mastersecret, 64);
|
||||||
|
buffer_get_chunk(blob, sk->secret, 32);
|
||||||
|
buffer_get_chunk(blob, sk->edsecret, 64);
|
||||||
|
|
||||||
|
buffer_get_chunk(blob, sk->masterpub, 32);
|
||||||
|
buffer_get_chunk(blob, sk->pub, 32);
|
||||||
|
buffer_get_chunk(blob, sk->edpub, 32);
|
||||||
|
|
||||||
|
notationlen = buffer_get16na(blob);
|
||||||
|
if(notationlen > 0)
|
||||||
|
buffer_get_chunk(blob, sk->owner, notationlen);
|
||||||
|
|
||||||
|
notationlen = buffer_get16na(blob);
|
||||||
|
if(notationlen > 0)
|
||||||
|
buffer_get_chunk(blob, sk->mail, notationlen);
|
||||||
|
|
||||||
|
if(buffer_done(blob) == 1)
|
||||||
|
goto impserr2;
|
||||||
|
|
||||||
|
sk->ctime = buffer_get64na(blob);
|
||||||
|
sk->version = buffer_get32na(blob);
|
||||||
|
sk->serial = buffer_get32na(blob);
|
||||||
|
|
||||||
|
/* ready */
|
||||||
|
ucfree(clear, cipherlen - PCP_CRYPTO_ADD);
|
||||||
|
ucfree(nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
ucfree(sk, sizeof(pcp_key_t));
|
||||||
|
buffer_free(blob);
|
||||||
|
|
||||||
|
return sk;
|
||||||
|
|
||||||
|
impserr2:
|
||||||
|
ucfree(clear, cipherlen - PCP_CRYPTO_ADD);
|
||||||
|
|
||||||
|
impserr1:
|
||||||
|
ucfree(nonce, crypto_secretbox_NONCEBYTES);
|
||||||
|
ucfree(sk, sizeof(pcp_key_t));
|
||||||
|
buffer_free(blob);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
@@ -168,22 +168,13 @@ int pcpvault_addkey(vault_t *vault, void *item, uint8_t type) {
|
|||||||
else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_NATIVE) {
|
else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_NATIVE) {
|
||||||
pcp_keysig_t *sk = (pcp_keysig_t *)item;
|
pcp_keysig_t *sk = (pcp_keysig_t *)item;
|
||||||
|
|
||||||
itemsize = PCP_RAW_KEYSIGSIZE + sk->size;
|
Buffer *b = pcp_keysig2blob(sk);
|
||||||
size_t blobsize = sk->size;
|
itemsize = buffer_size(b);
|
||||||
|
|
||||||
blob = ucmalloc(itemsize);
|
blob = ucmalloc(itemsize);
|
||||||
sk = keysig2be(sk);
|
|
||||||
|
|
||||||
/* FIXME: use Buffer or function */
|
memcpy(blob, buffer_get(b), buffer_size(b));
|
||||||
uint8_t t = sk->type;
|
buffer_free(b);
|
||||||
uint32_t s = sk->size;
|
|
||||||
memcpy(blob, &t, 1);
|
|
||||||
memcpy(blob+1, &s, 4);
|
|
||||||
memcpy(blob+5, sk->belongs, 17);
|
|
||||||
memcpy(blob+5+17, sk->checksum, 32);
|
|
||||||
memcpy(blob+5+17+32, sk->blob, blobsize);
|
|
||||||
|
|
||||||
sk = keysig2native(sk);
|
|
||||||
saveitem = (void *)sk;
|
saveitem = (void *)sk;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ int pcp_storekey (pcp_key_t *key) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcp_keygen(char *passwd, char *outfile) {
|
void pcp_keygen(char *passwd) {
|
||||||
pcp_key_t *k = pcpkey_new ();
|
pcp_key_t *k = pcpkey_new ();
|
||||||
pcp_key_t *key = NULL;
|
pcp_key_t *key = NULL;
|
||||||
|
|
||||||
@@ -101,21 +101,12 @@ void pcp_keygen(char *passwd, char *outfile) {
|
|||||||
|
|
||||||
if(key != NULL) {
|
if(key != NULL) {
|
||||||
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) {
|
if(pcp_storekey(key) == 0) {
|
||||||
pcpkey_printshortinfo(key);
|
pcpkey_printshortinfo(key);
|
||||||
memset(key, 0, sizeof(pcp_key_t));
|
memset(key, 0, sizeof(pcp_key_t));
|
||||||
free(key);
|
free(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
errkg1:
|
errkg1:
|
||||||
free(mail);
|
free(mail);
|
||||||
@@ -205,7 +196,7 @@ pcp_key_t *pcp_find_primary_secret() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcp_exportsecret(char *keyid, int useid, char *outfile) {
|
void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor) {
|
||||||
pcp_key_t *key = NULL;
|
pcp_key_t *key = NULL;
|
||||||
|
|
||||||
if(useid == 1) {
|
if(useid == 1) {
|
||||||
@@ -213,7 +204,7 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile) {
|
|||||||
HASH_FIND_STR(pcpkey_hash, keyid, key);
|
HASH_FIND_STR(pcpkey_hash, keyid, key);
|
||||||
if(key == NULL) {
|
if(key == NULL) {
|
||||||
fatal("Could not find a secret key with id 0x%s in vault %s!\n", keyid, vault->filename);
|
fatal("Could not find a secret key with id 0x%s in vault %s!\n", keyid, vault->filename);
|
||||||
free(key);
|
goto errexpse1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -221,15 +212,10 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile) {
|
|||||||
key = pcp_find_primary_secret();
|
key = pcp_find_primary_secret();
|
||||||
if(key == NULL) {
|
if(key == NULL) {
|
||||||
fatal("There's no primary secret key in the vault %s!\n", vault->filename);
|
fatal("There's no primary secret key in the vault %s!\n", vault->filename);
|
||||||
|
goto errexpse1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(key != NULL) {
|
|
||||||
pcp_exportsecretkey(key, outfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pcp_exportsecretkey(pcp_key_t *key, char *outfile) {
|
|
||||||
FILE *out;
|
FILE *out;
|
||||||
if(outfile == NULL) {
|
if(outfile == NULL) {
|
||||||
out = stdout;
|
out = stdout;
|
||||||
@@ -237,19 +223,57 @@ void pcp_exportsecretkey(pcp_key_t *key, char *outfile) {
|
|||||||
else {
|
else {
|
||||||
if((out = fopen(outfile, "wb+")) == NULL) {
|
if((out = fopen(outfile, "wb+")) == NULL) {
|
||||||
fatal("Could not create output file %s", outfile);
|
fatal("Could not create output file %s", outfile);
|
||||||
out = NULL;
|
goto errexpse1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(out != NULL) {
|
if(out != NULL) {
|
||||||
if(debug)
|
if(debug)
|
||||||
pcp_dumpkey(key);
|
pcp_dumpkey(key);
|
||||||
else
|
|
||||||
pcpkey_print(key, out);
|
if(key->secret[0] == 0) {
|
||||||
/* scip */
|
/* decrypt the secret key */
|
||||||
/* printf("EXPORT:\n"); */
|
char *passphrase;
|
||||||
/* pcpprint_bin(stdout, key, PCP_RAW_KEYSIZE); printf("\n"); */
|
pcp_readpass(&passphrase,
|
||||||
|
"Enter passphrase to decrypt your secret key", NULL, 1);
|
||||||
|
key = pcpkey_decrypt(key, passphrase);
|
||||||
|
|
||||||
|
if(key == NULL) {
|
||||||
|
memset(passphrase, 0, strlen(passphrase));
|
||||||
|
free(passphrase);
|
||||||
|
goto errexpse1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(passphrase, 0, strlen(passphrase));
|
||||||
|
free(passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *passphrase;
|
||||||
|
pcp_readpass(&passphrase,
|
||||||
|
"Enter passphrase to encrypt the exported secret key", "Repeat passphrase", 1);
|
||||||
|
|
||||||
|
Buffer *exported_sk = pcp_export_secret(key, passphrase);
|
||||||
|
|
||||||
|
if(exported_sk != NULL) {
|
||||||
|
if(armor == 1) {
|
||||||
|
size_t zlen;
|
||||||
|
char *z85 = pcp_z85_encode(buffer_get(exported_sk), buffer_size(exported_sk), &zlen);
|
||||||
|
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_SK_HEADER, z85, EXP_SK_FOOTER);
|
||||||
|
free(z85);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fwrite(buffer_get(exported_sk), 1, buffer_size(exported_sk), out);
|
||||||
|
}
|
||||||
|
buffer_free(exported_sk);
|
||||||
|
fprintf(stderr, "secret key exported.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(passphrase, 0, strlen(passphrase));
|
||||||
|
free(passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
errexpse1:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -264,7 +288,7 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
|
|||||||
int is_foreign = 0;
|
int is_foreign = 0;
|
||||||
pcp_pubkey_t *pk = NULL;
|
pcp_pubkey_t *pk = NULL;
|
||||||
pcp_key_t *sk = NULL;
|
pcp_key_t *sk = NULL;
|
||||||
Buffer *exported_pk;
|
Buffer *exported_pk = NULL;
|
||||||
|
|
||||||
if(outfile == NULL) {
|
if(outfile == NULL) {
|
||||||
out = stdout;
|
out = stdout;
|
||||||
@@ -316,9 +340,9 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
|
|||||||
"Enter passphrase to decrypt your secret key", NULL, 1);
|
"Enter passphrase to decrypt your secret key", NULL, 1);
|
||||||
sk = pcpkey_decrypt(sk, passphrase);
|
sk = pcpkey_decrypt(sk, passphrase);
|
||||||
if(sk == NULL) {
|
if(sk == NULL) {
|
||||||
goto errpcpexpu1;
|
|
||||||
memset(passphrase, 0, strlen(passphrase));
|
memset(passphrase, 0, strlen(passphrase));
|
||||||
free(passphrase);
|
free(passphrase);
|
||||||
|
goto errpcpexpu1;
|
||||||
}
|
}
|
||||||
memset(passphrase, 0, strlen(passphrase));
|
memset(passphrase, 0, strlen(passphrase));
|
||||||
free(passphrase);
|
free(passphrase);
|
||||||
@@ -333,9 +357,6 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
|
|||||||
size_t zlen;
|
size_t zlen;
|
||||||
char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen);
|
char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen);
|
||||||
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_PK_HEADER, z85, EXP_PK_FOOTER);
|
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_PK_HEADER, z85, EXP_PK_FOOTER);
|
||||||
FILE *t = fopen("binexp", "wb+");
|
|
||||||
fwrite(buffer_get(exported_pk), 1, buffer_size(exported_pk), t);
|
|
||||||
fclose(t);
|
|
||||||
free(z85);
|
free(z85);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -376,6 +397,7 @@ errpcpexpu1:
|
|||||||
|
|
||||||
|
|
||||||
int pcp_importsecret (vault_t *vault, FILE *in) {
|
int pcp_importsecret (vault_t *vault, FILE *in) {
|
||||||
|
fprintf(stderr, " pcp_importsecret line 400, port to new format\n");exit(1);
|
||||||
size_t clen;
|
size_t clen;
|
||||||
char *z85 = pcp_readz85file(in);
|
char *z85 = pcp_readz85file(in);
|
||||||
|
|
||||||
|
|||||||
@@ -47,11 +47,10 @@
|
|||||||
|
|
||||||
char *pcp_getstdin(const char *prompt);
|
char *pcp_getstdin(const char *prompt);
|
||||||
int pcp_storekey (pcp_key_t *key);
|
int pcp_storekey (pcp_key_t *key);
|
||||||
void pcp_keygen();
|
void pcp_keygen(char *passwd);
|
||||||
void pcp_listkeys();
|
void pcp_listkeys();
|
||||||
|
|
||||||
void pcp_exportsecret(char *keyid, int useid, char *outfile);
|
void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor);
|
||||||
void pcp_exportsecretkey(pcp_key_t *key, char *outfile);
|
|
||||||
void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int armor);
|
void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int armor);
|
||||||
|
|
||||||
pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd);
|
pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd);
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ int main (int argc, char **argv) {
|
|||||||
if(vault != NULL) {
|
if(vault != NULL) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PCP_MODE_KEYGEN:
|
case PCP_MODE_KEYGEN:
|
||||||
pcp_keygen(xpass, outfile);
|
pcp_keygen(xpass);
|
||||||
if(xpass != NULL)
|
if(xpass != NULL)
|
||||||
free(xpass);
|
free(xpass);
|
||||||
break;
|
break;
|
||||||
@@ -379,12 +379,12 @@ int main (int argc, char **argv) {
|
|||||||
if(useid) {
|
if(useid) {
|
||||||
id = pcp_normalize_id(keyid);
|
id = pcp_normalize_id(keyid);
|
||||||
if(id != NULL) {
|
if(id != NULL) {
|
||||||
pcp_exportsecret(id, useid, outfile);
|
pcp_exportsecret(id, useid, outfile, armor);
|
||||||
free(id);
|
free(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pcp_exportsecret(NULL, useid, outfile);
|
pcp_exportsecret(NULL, useid, outfile, armor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user