mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 12:00:56 +01:00
changed internal key format again, now we've got a master-key-signing keypair as well, used for exports. also, fixed a security hole in pcp_keynew(): the actual key material, unencrypted, have been stored on heap and not zeroed after exit.
This commit is contained in:
@@ -49,7 +49,7 @@ typedef unsigned int qbyte; /* Quad byte = 32 bits */
|
|||||||
|
|
||||||
#define PCP_ME "Pretty Curved Privacy"
|
#define PCP_ME "Pretty Curved Privacy"
|
||||||
|
|
||||||
#define PCP_KEY_VERSION 5
|
#define PCP_KEY_VERSION 6
|
||||||
#define PCP_KEY_PRIMITIVE "CURVE25519-ED25519-SALSA20-POLY1305"
|
#define PCP_KEY_PRIMITIVE "CURVE25519-ED25519-SALSA20-POLY1305"
|
||||||
|
|
||||||
#define PCP_KEY_TYPE_MAINSECRET 1
|
#define PCP_KEY_TYPE_MAINSECRET 1
|
||||||
@@ -57,7 +57,7 @@ typedef unsigned int qbyte; /* Quad byte = 32 bits */
|
|||||||
#define PCP_KEY_TYPE_PUBLIC 3
|
#define PCP_KEY_TYPE_PUBLIC 3
|
||||||
|
|
||||||
/* save typing, dammit */
|
/* save typing, dammit */
|
||||||
#define PCP_ENCRYPT_PAD crypto_secretbox_ZEROBYTES + crypto_secretbox_NONCEBYTES
|
#define PCP_ENCRYPT_MAC crypto_secretbox_ZEROBYTES + crypto_secretbox_NONCEBYTES
|
||||||
|
|
||||||
/* vault id */
|
/* vault id */
|
||||||
#define PCP_VAULT_ID 14
|
#define PCP_VAULT_ID 14
|
||||||
|
|||||||
@@ -43,6 +43,9 @@
|
|||||||
returns NULL otherwise */
|
returns NULL otherwise */
|
||||||
unsigned char *pcp_ed_sign(unsigned char *message, size_t messagesize, pcp_key_t *s);
|
unsigned char *pcp_ed_sign(unsigned char *message, size_t messagesize, pcp_key_t *s);
|
||||||
|
|
||||||
|
/* the same, but use the mastersecret instead, usually for keysigning */
|
||||||
|
unsigned char *pcp_ed_sign_key(unsigned char *message, size_t messagesize, pcp_key_t *s);
|
||||||
|
|
||||||
/* verify a signature of siglen size using p->edpub, if the signature verifies
|
/* verify a signature of siglen size using p->edpub, if the signature verifies
|
||||||
return the raw message with the signature removed (size: siglen - crypto_sign_BYTES),
|
return the raw message with the signature removed (size: siglen - crypto_sign_BYTES),
|
||||||
returns NULL otherwise */
|
returns NULL otherwise */
|
||||||
|
|||||||
@@ -75,12 +75,14 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
struct _pcp_key_t {
|
struct _pcp_key_t {
|
||||||
|
byte masterpub[32];
|
||||||
|
byte mastersecret[64];
|
||||||
byte pub[32];
|
byte pub[32];
|
||||||
byte secret[32];
|
byte secret[32];
|
||||||
byte edpub[32];
|
byte edpub[32];
|
||||||
byte edsecret[64];
|
byte edsecret[64];
|
||||||
byte nonce[24];
|
byte nonce[24];
|
||||||
byte encrypted[112]; /* both ed+curve encrypted */
|
byte encrypted[176]; /* both sign+ed+curve encrypted */
|
||||||
char owner[255];
|
char owner[255];
|
||||||
char mail[255];
|
char mail[255];
|
||||||
char id[17];
|
char id[17];
|
||||||
@@ -92,6 +94,7 @@ struct _pcp_key_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct _pcp_pubkey_t {
|
struct _pcp_pubkey_t {
|
||||||
|
byte sigpub[32];
|
||||||
byte pub[32];
|
byte pub[32];
|
||||||
byte edpub[32];
|
byte edpub[32];
|
||||||
char owner[255];
|
char owner[255];
|
||||||
@@ -101,6 +104,8 @@ struct _pcp_pubkey_t {
|
|||||||
uint64_t ctime;
|
uint64_t ctime;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
|
uint8_t valid;
|
||||||
|
byte signature[crypto_generichash_BYTES_MAX + crypto_sign_BYTES];
|
||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -146,8 +151,7 @@ typedef struct _pcp_rec_t pcp_rec_t;
|
|||||||
void pcp_cleanhashes();
|
void pcp_cleanhashes();
|
||||||
pcp_key_t *pcpkey_new ();
|
pcp_key_t *pcpkey_new ();
|
||||||
|
|
||||||
void pcp_keypairs(byte *csk, byte *cpk, byte *esk, byte *epk);
|
void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *epk);
|
||||||
void pcp_ed_keypairs(byte *csk, byte *esk);
|
|
||||||
|
|
||||||
char *pcppubkey_get_art(pcp_pubkey_t *k);
|
char *pcppubkey_get_art(pcp_pubkey_t *k);
|
||||||
char *pcpkey_get_art(pcp_key_t *k);
|
char *pcpkey_get_art(pcp_key_t *k);
|
||||||
|
|||||||
@@ -37,6 +37,15 @@ unsigned char * pcp_ed_verify(unsigned char *signature, size_t siglen, pcp_pubke
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char *pcp_ed_sign_key(unsigned char *message, size_t messagesize, pcp_key_t *s) {
|
||||||
|
unsigned long long mlen = messagesize + crypto_sign_BYTES;
|
||||||
|
unsigned char *signature = ucmalloc(mlen);
|
||||||
|
|
||||||
|
crypto_sign(signature, &mlen, message, messagesize, s->mastersecret);
|
||||||
|
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char *pcp_ed_sign(unsigned char *message, size_t messagesize, pcp_key_t *s) {
|
unsigned char *pcp_ed_sign(unsigned char *message, size_t messagesize, pcp_key_t *s) {
|
||||||
unsigned long long mlen = messagesize + crypto_sign_BYTES;
|
unsigned long long mlen = messagesize + crypto_sign_BYTES;
|
||||||
unsigned char *signature = ucmalloc(mlen);
|
unsigned char *signature = ucmalloc(mlen);
|
||||||
|
|||||||
84
libpcp/key.c
84
libpcp/key.c
@@ -68,39 +68,51 @@ char *pcp_getpubkeyid(pcp_pubkey_t *k) {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcp_keypairs(byte *csk, byte *cpk, byte *esk, byte *epk) {
|
void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *epk) {
|
||||||
/* generate ed25519 + curve25519 keypair from random seed */
|
/* generate keypairs from random seed */
|
||||||
byte *seed = urmalloc(32);
|
byte *ms = urmalloc(32);
|
||||||
byte *tmp = urmalloc(32);
|
byte *ss = urmalloc(32);
|
||||||
|
byte *cs = urmalloc(32);
|
||||||
|
|
||||||
|
/* ed25519 master key */
|
||||||
|
crypto_sign_seed_keypair(mpk, msk, ms);
|
||||||
|
|
||||||
/* ed25519 signing key */
|
/* ed25519 signing key */
|
||||||
crypto_sign_seed_keypair(epk, esk, seed);
|
crypto_sign_seed_keypair(epk, esk, ss);
|
||||||
|
|
||||||
/* curve25519 secret key */
|
/* curve25519 secret key */
|
||||||
tmp[0] &= 248;
|
memcpy(csk, cs, 32);
|
||||||
tmp[31] &= 63;
|
csk[0] &= 248;
|
||||||
tmp[31] |= 64;
|
csk[31] &= 63;
|
||||||
memcpy(csk, tmp, 32);
|
csk[31] |= 64;
|
||||||
|
|
||||||
/* curve25519 public key */
|
/* curve25519 public key */
|
||||||
crypto_scalarmult_curve25519_base(cpk, csk);
|
crypto_scalarmult_curve25519_base(cpk, csk);
|
||||||
memset(tmp, 0, 32);
|
|
||||||
|
ucfree(ms, 32);
|
||||||
|
ucfree(ss, 32);
|
||||||
|
ucfree(cs, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pcp_key_t * pcpkey_new () {
|
pcp_key_t * pcpkey_new () {
|
||||||
byte pub[32] = { 0 };
|
byte *mp = ucmalloc(32);
|
||||||
byte secret[32] = { 0 };
|
byte *ms = ucmalloc(64);
|
||||||
byte edpub[32] = { 0 };
|
byte *sp = ucmalloc(32);
|
||||||
byte edsec[64] = { 0 };
|
byte *ss = ucmalloc(64);
|
||||||
|
byte *cp = ucmalloc(32);
|
||||||
|
byte *cs = ucmalloc(32);
|
||||||
|
|
||||||
pcp_keypairs(secret, pub, edsec, edpub);
|
/* generate key material */
|
||||||
|
pcp_keypairs(ms, mp, cs, cp, ss, sp);
|
||||||
|
|
||||||
/* fill in our struct */
|
/* fill in our struct */
|
||||||
pcp_key_t *key = urmalloc(sizeof(pcp_key_t));
|
pcp_key_t *key = urmalloc(sizeof(pcp_key_t));
|
||||||
memcpy (key->pub, pub, 32);
|
memcpy (key->masterpub, mp, 32);
|
||||||
memcpy (key->secret, secret, 32);
|
memcpy (key->mastersecret, ms, 64);
|
||||||
memcpy (key->edpub, edpub, 32);
|
memcpy (key->pub, cp, 32);
|
||||||
memcpy (key->edsecret, edsec, 64);
|
memcpy (key->secret, cs, 32);
|
||||||
|
memcpy (key->edpub, ss, 32);
|
||||||
|
memcpy (key->edsecret, sp, 64);
|
||||||
memcpy (key->id, pcp_getkeyid(key), 17);
|
memcpy (key->id, pcp_getkeyid(key), 17);
|
||||||
|
|
||||||
key->ctime = (long)time(0);
|
key->ctime = (long)time(0);
|
||||||
@@ -108,6 +120,15 @@ pcp_key_t * pcpkey_new () {
|
|||||||
key->version = PCP_KEY_VERSION;
|
key->version = PCP_KEY_VERSION;
|
||||||
key->serial = arc4random();
|
key->serial = arc4random();
|
||||||
key->type = PCP_KEY_TYPE_SECRET;
|
key->type = PCP_KEY_TYPE_SECRET;
|
||||||
|
|
||||||
|
/* clean up */
|
||||||
|
ucfree(ms, 64);
|
||||||
|
ucfree(ss, 64);
|
||||||
|
ucfree(mp, 32);
|
||||||
|
ucfree(sp, 32);
|
||||||
|
ucfree(cs, 32);
|
||||||
|
ucfree(cp, 32);
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,24 +149,26 @@ pcp_key_t *pcpkey_encrypt(pcp_key_t *key, char *passphrase) {
|
|||||||
unsigned char *encrypted;
|
unsigned char *encrypted;
|
||||||
size_t es;
|
size_t es;
|
||||||
|
|
||||||
unsigned char *both = ucmalloc(96);
|
Buffer *both = buffer_new(128, "keypack");
|
||||||
memcpy(both, key->edsecret, 64);
|
buffer_add(both, key->mastersecret, 64);
|
||||||
memcpy(&both[64], key->secret, 32);
|
buffer_add(both, key->edsecret, 64);
|
||||||
|
buffer_add(both, key->secret, 32);
|
||||||
|
|
||||||
es = pcp_sodium_mac(&encrypted, both, 96, key->nonce, encryptkey);
|
es = pcp_sodium_mac(&encrypted, buffer_get(both), buffer_size(both), key->nonce, encryptkey);
|
||||||
|
|
||||||
memset(encryptkey, 0, 32);
|
memset(encryptkey, 0, 32);
|
||||||
memset(both, 0, 96);
|
buffer_free(both);
|
||||||
free(encryptkey);
|
free(encryptkey);
|
||||||
free(both);
|
|
||||||
|
|
||||||
if(es == 112) {
|
if(es == 176) {
|
||||||
/* success */
|
/* success */
|
||||||
memcpy(key->encrypted, encrypted, 112);
|
memcpy(key->encrypted, encrypted, 176);
|
||||||
arc4random_buf(key->secret, 32);
|
arc4random_buf(key->secret, 32);
|
||||||
arc4random_buf(key->edsecret, 64);
|
arc4random_buf(key->edsecret, 64);
|
||||||
|
arc4random_buf(key->mastersecret, 64);
|
||||||
key->secret[0] = 0;
|
key->secret[0] = 0;
|
||||||
key->edsecret[0] = 0;
|
key->edsecret[0] = 0;
|
||||||
|
key->mastersecret[0] = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fatal("failed to encrypt the secret key!\n");
|
fatal("failed to encrypt the secret key!\n");
|
||||||
@@ -162,15 +185,16 @@ pcp_key_t *pcpkey_decrypt(pcp_key_t *key, char *passphrase) {
|
|||||||
unsigned char *decrypted;
|
unsigned char *decrypted;
|
||||||
size_t es;
|
size_t es;
|
||||||
|
|
||||||
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, 112, key->nonce, encryptkey);
|
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, 176, key->nonce, encryptkey);
|
||||||
|
|
||||||
memset(encryptkey, 0, 32);
|
memset(encryptkey, 0, 32);
|
||||||
free(encryptkey);
|
free(encryptkey);
|
||||||
|
|
||||||
if(es == 0) {
|
if(es == 0) {
|
||||||
/* success */
|
/* success */
|
||||||
memcpy(key->edsecret, decrypted, 64);
|
memcpy(key->mastersecret, decrypted, 64);
|
||||||
memcpy(key->secret, &decrypted[64], 32);
|
memcpy(key->edsecret, decrypted + 64, 64);
|
||||||
|
memcpy(key->secret, decrypted +128, 32);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fatal("failed to decrypt the secret key (got %d, expected 32)!\n", es);
|
fatal("failed to decrypt the secret key (got %d, expected 32)!\n", es);
|
||||||
|
|||||||
Reference in New Issue
Block a user