Use enum for keyring key type codes

This commit is contained in:
Andrew Bettison 2018-03-26 11:24:21 +10:30
parent 3388170468
commit 288fae4f2b
3 changed files with 98 additions and 62 deletions

103
keyring.c
View File

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2016-2017 Flinders University Copyright (C) 2016-2018 Flinders University
Copyright (C) 2013-2015 Serval Project Inc. Copyright (C) 2013-2015 Serval Project Inc.
Copyright (C) 2010-2012 Paul Gardner-Stephen Copyright (C) 2010-2012 Paul Gardner-Stephen
@ -245,7 +245,7 @@ keypair * keyring_next_key(keyring_iterator *it)
return it->keypair; return it->keypair;
} }
keypair *keyring_next_keytype(keyring_iterator *it, unsigned keytype) keypair *keyring_next_keytype(keyring_iterator *it, enum keyring_keytype keytype)
{ {
keypair *kp; keypair *kp;
while((kp=keyring_next_key(it)) && kp->type!=keytype) while((kp=keyring_next_key(it)) && kp->type!=keytype)
@ -253,7 +253,7 @@ keypair *keyring_next_keytype(keyring_iterator *it, unsigned keytype)
return kp; return kp;
} }
keypair *keyring_identity_keytype(const keyring_identity *id, unsigned keytype) keypair *keyring_identity_keytype(const keyring_identity *id, enum keyring_keytype keytype)
{ {
keypair *kp=id->keypairs; keypair *kp=id->keypairs;
while(kp && kp->type!=keytype) while(kp && kp->type!=keytype)
@ -535,9 +535,10 @@ static int keyring_munge_block(
#undef APPEND #undef APPEND
} }
static const char *keytype_str(unsigned ktype, const char *unknown) const char *keytype_str(enum keyring_keytype ktype, const char *unknown)
{ {
switch (ktype) { switch (ktype) {
case KEYTYPE_INVALID: return "INVALID";
case KEYTYPE_CRYPTOBOX: return "CRYPTOBOX"; case KEYTYPE_CRYPTOBOX: return "CRYPTOBOX";
case KEYTYPE_CRYPTOSIGN: return "CRYPTOSIGN"; case KEYTYPE_CRYPTOSIGN: return "CRYPTOSIGN";
case KEYTYPE_RHIZOME: return "RHIZOME"; case KEYTYPE_RHIZOME: return "RHIZOME";
@ -548,7 +549,7 @@ static const char *keytype_str(unsigned ktype, const char *unknown)
} }
} }
struct keytype { struct key_type {
size_t public_key_size; size_t public_key_size;
size_t private_key_size; size_t private_key_size;
size_t packed_size; size_t packed_size;
@ -863,7 +864,7 @@ static int load_did_name(keypair *kp, const char *text)
* deprecated, ie, recognised and simply skipped. The packer and unpacker functions can be changed * deprecated, ie, recognised and simply skipped. The packer and unpacker functions can be changed
* to NULL. * to NULL.
*/ */
const struct keytype keytypes[] = { const struct key_type key_types[] = {
[KEYTYPE_CRYPTOBOX] = { [KEYTYPE_CRYPTOBOX] = {
/* Only the private key is stored, and the public key (SID) is derived from the private key /* Only the private key is stored, and the public key (SID) is derived from the private key
* when the keyring is read. * when the keyring is read.
@ -959,16 +960,16 @@ static void keyring_free_keypair(keypair *kp)
free(kp); free(kp);
} }
static keypair *keyring_alloc_keypair(unsigned ktype, size_t len) static keypair *keyring_alloc_keypair(enum keyring_keytype ktype, size_t len)
{ {
assert(ktype != 0); assert(ktype != KEYTYPE_INVALID);
keypair *kp = emalloc_zero(sizeof(keypair)); keypair *kp = emalloc_zero(sizeof(keypair));
if (!kp) if (!kp)
return NULL; return NULL;
kp->type = ktype; kp->type = ktype;
if (ktype < NELS(keytypes)) { if (ktype < NELS(key_types)) {
kp->private_key_len = keytypes[ktype].private_key_size; kp->private_key_len = key_types[ktype].private_key_size;
kp->public_key_len = keytypes[ktype].public_key_size; kp->public_key_len = key_types[ktype].public_key_size;
} else { } else {
kp->private_key_len = len; kp->private_key_len = len;
kp->public_key_len = 0; kp->public_key_len = 0;
@ -1009,14 +1010,14 @@ static int keyring_pack_identity(const keyring_identity *id, unsigned char packe
rotation); rotation);
keypair *kp=id->keypairs; keypair *kp=id->keypairs;
while(kp && !rbuf.wrap){ while(kp && !rbuf.wrap){
unsigned ktype = kp->type; enum keyring_keytype ktype = kp->type;
const char *kts = keytype_str(ktype, "unknown"); const char *kts = keytype_str(ktype, "unknown");
int (*packer)(const keypair *, struct rotbuf *) = NULL; int (*packer)(const keypair *, struct rotbuf *) = NULL;
size_t keypair_len=0; size_t keypair_len=0;
const struct keytype *kt = &keytypes[ktype]; const struct key_type *kt = &key_types[ktype];
if (ktype == 0x00) if (ktype == KEYTYPE_INVALID)
FATALF("ktype=0 in keypair kp=%u", kp); FATALF("ktype = 0x%02x(%s) in keypair kp=%u", ktype, keytype_str(ktype, "unknown"), kp);
if (ktype < NELS(keytypes)) { if (ktype < NELS(key_types)) {
packer = kt->packer; packer = kt->packer;
keypair_len = kt->packed_size; keypair_len = kt->packed_size;
if (keypair_len==0){ if (keypair_len==0){
@ -1166,8 +1167,8 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot_data, const
rotation); rotation);
while (!rbuf.wrap) { while (!rbuf.wrap) {
struct rotbuf rbo = rbuf; struct rotbuf rbo = rbuf;
unsigned char ktype = rotbuf_getc(&rbuf); enum keyring_keytype ktype = rotbuf_getc(&rbuf);
if (rbuf.wrap || ktype == 0x00) if (rbuf.wrap || ktype == KEYTYPE_INVALID)
break; // End of data, stop looking break; // End of data, stop looking
size_t keypair_len; size_t keypair_len;
// No length bytes after the original four key types, for backward compatibility. All other key // No length bytes after the original four key types, for backward compatibility. All other key
@ -1177,8 +1178,10 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot_data, const
case KEYTYPE_CRYPTOSIGN: case KEYTYPE_CRYPTOSIGN:
case KEYTYPE_RHIZOME: case KEYTYPE_RHIZOME:
case KEYTYPE_DID: case KEYTYPE_DID:
keypair_len = keytypes[ktype].packed_size; keypair_len = key_types[ktype].packed_size;
break; break;
case KEYTYPE_INVALID:
FATAL("invalid");
default: default:
keypair_len = rotbuf_getc(&rbuf) << 8; keypair_len = rotbuf_getc(&rbuf) << 8;
keypair_len |= rotbuf_getc(&rbuf); keypair_len |= rotbuf_getc(&rbuf);
@ -1198,8 +1201,8 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot_data, const
} }
struct rotbuf rbstart = rbuf; struct rotbuf rbstart = rbuf;
int (*unpacker)(keypair *, struct rotbuf *, size_t) = NULL; int (*unpacker)(keypair *, struct rotbuf *, size_t) = NULL;
if (ktype < NELS(keytypes)) if (ktype < NELS(key_types))
unpacker = keytypes[ktype].unpacker; unpacker = key_types[ktype].unpacker;
else else
unpacker = unpack_private_only; unpacker = unpack_private_only;
@ -1278,23 +1281,25 @@ static int keyring_finalise_identity(uint8_t *dirty, keyring_identity *id)
keypair *kp = id->keypairs; keypair *kp = id->keypairs;
while(kp){ while(kp){
switch(kp->type){ switch(kp->type){
case KEYTYPE_INVALID:
FATALF("ktype = 0x%02x(%s)", kp->type, keytype_str(kp->type, "unknown"));
case KEYTYPE_CRYPTOBOX: case KEYTYPE_CRYPTOBOX:
id->box_pk = (const sid_t *)kp->public_key; id->box_pk = (const sid_t *)kp->public_key;
id->box_sk = kp->private_key; id->box_sk = kp->private_key;
break; break;
case KEYTYPE_CRYPTOSIGN:{ case KEYTYPE_CRYPTOSIGN:{
const sign_keypair_t *keypair = (const sign_keypair_t *)kp->private_key; const sign_keypair_t *keypair = (const sign_keypair_t *)kp->private_key;
if (!crypto_isvalid_keypair(&keypair->private_key, &keypair->public_key)){ if (!crypto_isvalid_keypair(&keypair->private_key, &keypair->public_key)){
/* SAS key is invalid (perhaps because it was a pre 0.90 format one), /* SAS key is invalid (perhaps because it was a pre 0.90 format one),
so replace it */ so replace it */
WARN("SAS key is invalid -- regenerating."); WARN("SAS key is invalid -- regenerating.");
crypto_sign_keypair(kp->public_key, kp->private_key); crypto_sign_keypair(kp->public_key, kp->private_key);
if (dirty) if (dirty)
*dirty = 1; *dirty = 1;
}
id->sign_keypair = (const sign_keypair_t *)kp->private_key;
} }
id->sign_keypair = (const sign_keypair_t *)kp->private_key; break;
}
break;
case KEYTYPE_CRYPTOCOMBINED:{ case KEYTYPE_CRYPTOCOMBINED:{
struct combined_pk *pk = (struct combined_pk *)kp->public_key; struct combined_pk *pk = (struct combined_pk *)kp->public_key;
struct combined_sk *sk = (struct combined_sk *)kp->private_key; struct combined_sk *sk = (struct combined_sk *)kp->private_key;
@ -1302,6 +1307,10 @@ static int keyring_finalise_identity(uint8_t *dirty, keyring_identity *id)
id->box_sk = sk->box_key; id->box_sk = sk->box_key;
id->sign_keypair = &sk->sign_key; id->sign_keypair = &sk->sign_key;
break; break;
case KEYTYPE_RHIZOME:
case KEYTYPE_DID:
case KEYTYPE_PUBLIC_TAG:
break;
} }
} }
kp = kp->next; kp = kp->next;
@ -1476,14 +1485,14 @@ static keyring_identity *keyring_new_identity()
/* Allocate key pairs */ /* Allocate key pairs */
unsigned ktype; unsigned ktype;
for (ktype = 1; ktype < NELS(keytypes); ++ktype) { for (ktype = 1; ktype < NELS(key_types); ++ktype) {
if (keytypes[ktype].creator) { if (key_types[ktype].creator) {
keypair *kp = keyring_alloc_keypair(ktype, 0); keypair *kp = keyring_alloc_keypair(ktype, 0);
if (kp == NULL){ if (kp == NULL){
keyring_free_identity(id); keyring_free_identity(id);
return NULL; return NULL;
} }
keytypes[ktype].creator(kp); key_types[ktype].creator(kp);
keyring_identity_add_keypair(id, kp); keyring_identity_add_keypair(id, kp);
} }
} }
@ -1941,6 +1950,14 @@ void keyring_identity_extract(const keyring_identity *id, const char **didp, con
if (namep) if (namep)
*namep = (const char *) kp->public_key; *namep = (const char *) kp->public_key;
return; return;
case KEYTYPE_CRYPTOBOX:
case KEYTYPE_CRYPTOSIGN:
case KEYTYPE_RHIZOME:
case KEYTYPE_PUBLIC_TAG:
case KEYTYPE_CRYPTOCOMBINED:
break;
case KEYTYPE_INVALID:
FATALF("ktype = 0x%02x(%s)", kp->type, keytype_str(kp->type, "unknown"));
} }
kp=kp->next; kp=kp->next;
} }
@ -2086,10 +2103,10 @@ static int cmp_identity_ptrs(const keyring_identity *const *a, const keyring_ide
static void keyring_dump_keypair(const keypair *kp, XPRINTF xpf, int include_secret) static void keyring_dump_keypair(const keypair *kp, XPRINTF xpf, int include_secret)
{ {
assert(kp->type != 0); assert(kp->type != 0);
assert(kp->type < NELS(keytypes)); assert(kp->type < NELS(key_types));
xprintf(xpf, "type=%u(%s) ", kp->type, keytype_str(kp->type, "unknown")); xprintf(xpf, "type=0x%02x(%s) ", kp->type, keytype_str(kp->type, "unknown"));
if (keytypes[kp->type].dumper) if (key_types[kp->type].dumper)
keytypes[kp->type].dumper(kp, xpf, include_secret); key_types[kp->type].dumper(kp, xpf, include_secret);
else else
dump_private_public(kp, xpf, include_secret); dump_private_public(kp, xpf, include_secret);
} }
@ -2148,7 +2165,7 @@ int keyring_load_from_dump(keyring_file *k, unsigned entry_pinc, const char **en
unsigned idn; unsigned idn;
unsigned ktype; unsigned ktype;
int i, j; int i, j;
int n = sscanf(line, "%u: type=%u (%n%*[^)]%n)", &idn, &ktype, &i, &j); int n = sscanf(line, "%u: type=0x%x (%n%*[^)]%n)", &idn, &ktype, &i, &j);
if (n == EOF && (ferror(input) || feof(input))) if (n == EOF && (ferror(input) || feof(input)))
break; break;
if (n != 2){ if (n != 2){
@ -2156,7 +2173,7 @@ int keyring_load_from_dump(keyring_file *k, unsigned entry_pinc, const char **en
keyring_free_identity(id); keyring_free_identity(id);
return WHYF("malformed input n=%u", n); return WHYF("malformed input n=%u", n);
} }
if (ktype == 0){ if (ktype == KEYTYPE_INVALID){
if (id) if (id)
keyring_free_identity(id); keyring_free_identity(id);
return WHY("invalid input: ktype=0"); return WHY("invalid input: ktype=0");
@ -2172,8 +2189,8 @@ int keyring_load_from_dump(keyring_file *k, unsigned entry_pinc, const char **en
return -1; return -1;
} }
int (*loader)(keypair *, const char *) = load_unknown; int (*loader)(keypair *, const char *) = load_unknown;
if (strcmp(ktypestr, "unknown") != 0 && ktype < NELS(keytypes)) if (strcmp(ktypestr, "unknown") != 0 && ktype < NELS(key_types))
loader = keytypes[ktype].loader; loader = key_types[ktype].loader;
if (loader(kp, content) == -1) { if (loader(kp, content) == -1) {
if (id) if (id)
keyring_free_identity(id); keyring_free_identity(id);

View File

@ -28,8 +28,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
struct cli_parsed; struct cli_parsed;
#include "xprintf.h" #include "xprintf.h"
enum keyring_keytype {
KEYTYPE_INVALID = 0,
KEYTYPE_CRYPTOBOX = 0x01, // must be lowest valid
KEYTYPE_CRYPTOSIGN = 0x02,
KEYTYPE_RHIZOME = 0x03,
// DIDs aren't really keys, but the keyring is a real handy place to keep
// them, and keep them private if people so desire
KEYTYPE_DID = 0x04,
// Arbitrary name/value pairs
KEYTYPE_PUBLIC_TAG = 0x05,
// Combined signing / encryption key data
KEYTYPE_CRYPTOCOMBINED = 0x06,
};
const char *keytype_str(enum keyring_keytype ktype, const char *unknown);
typedef struct keypair { typedef struct keypair {
unsigned type; enum keyring_keytype type;
unsigned char *private_key; unsigned char *private_key;
size_t private_key_len; size_t private_key_len;
unsigned char *public_key; unsigned char *public_key;
@ -105,8 +121,8 @@ typedef struct keyring_iterator{
void keyring_iterator_start(keyring_file *k, keyring_iterator *it); void keyring_iterator_start(keyring_file *k, keyring_iterator *it);
keyring_identity * keyring_next_identity(keyring_iterator *it); keyring_identity * keyring_next_identity(keyring_iterator *it);
keypair * keyring_next_key(keyring_iterator *it); keypair * keyring_next_key(keyring_iterator *it);
keypair * keyring_next_keytype(keyring_iterator *it, unsigned keytype); keypair * keyring_next_keytype(keyring_iterator *it, enum keyring_keytype keytype);
keypair *keyring_identity_keytype(const keyring_identity *id, unsigned keytype); keypair *keyring_identity_keytype(const keyring_identity *id, enum keyring_keytype keytype);
keypair *keyring_find_did(keyring_iterator *it, const char *did); keypair *keyring_find_did(keyring_iterator *it, const char *did);
keyring_identity *keyring_find_identity_sid(keyring_file *k, const sid_t *sidp); keyring_identity *keyring_find_identity_sid(keyring_file *k, const sid_t *sidp);
keyring_identity *keyring_find_identity(keyring_file *k, const identity_t *sign); keyring_identity *keyring_find_identity(keyring_file *k, const identity_t *sign);
@ -116,19 +132,6 @@ void keyring_release_identities_by_pin(keyring_file *f, const char *pin);
void keyring_release_identity(keyring_file *k, keyring_identity *id); void keyring_release_identity(keyring_file *k, keyring_identity *id);
int keyring_release_subscriber(keyring_file *k, const sid_t *sid); int keyring_release_subscriber(keyring_file *k, const sid_t *sid);
#define KEYTYPE_CRYPTOBOX 0x01 // must be lowest
#define KEYTYPE_CRYPTOSIGN 0x02
#define KEYTYPE_RHIZOME 0x03
/* DIDs aren't really keys, but the keyring is a real handy place to keep them,
and keep them private if people so desire */
#define KEYTYPE_DID 0x04
/* Arbitrary name / value pairs */
#define KEYTYPE_PUBLIC_TAG 0x05
// Combined signing / encryption key data
#define KEYTYPE_CRYPTOCOMBINED 0x06
/* per-thread global handle to keyring file for use in running commands and server */ /* per-thread global handle to keyring file for use in running commands and server */
extern __thread keyring_file *keyring; extern __thread keyring_file *keyring;

View File

@ -172,6 +172,13 @@ static void cli_output_identity(struct cli_context *context, const keyring_ident
} }
} }
break; break;
case KEYTYPE_CRYPTOBOX:
case KEYTYPE_CRYPTOSIGN:
case KEYTYPE_CRYPTOCOMBINED:
case KEYTYPE_RHIZOME:
break;
case KEYTYPE_INVALID:
FATALF("ktype = 0x%02x(%s)", kp->type, keytype_str(kp->type, "unknown"));
} }
kp=kp->next; kp=kp->next;
} }
@ -184,7 +191,6 @@ static int app_keyring_list2(const struct cli_parsed *parsed, struct cli_context
assert(keyring == NULL); assert(keyring == NULL);
if (!(keyring = keyring_open_instance_cli(parsed))) if (!(keyring = keyring_open_instance_cli(parsed)))
return -1; return -1;
keyring_iterator it; keyring_iterator it;
keyring_iterator_start(keyring, &it); keyring_iterator_start(keyring, &it);
const keyring_identity *id; const keyring_identity *id;
@ -194,13 +200,23 @@ static int app_keyring_list2(const struct cli_parsed *parsed, struct cli_context
keypair *kp=id->keypairs; keypair *kp=id->keypairs;
fields+=2; fields+=2;
while(kp){ while(kp){
if (kp->type==KEYTYPE_PUBLIC_TAG) switch (kp->type) {
case KEYTYPE_PUBLIC_TAG:
fields++; fields++;
if (kp->type==KEYTYPE_DID){ break;
case KEYTYPE_DID:
if (strlen((char*)kp->private_key)) if (strlen((char*)kp->private_key))
fields++; fields++;
if (strlen((char*)kp->public_key)) if (strlen((char*)kp->public_key))
fields++; fields++;
break;
case KEYTYPE_CRYPTOBOX:
case KEYTYPE_CRYPTOSIGN:
case KEYTYPE_CRYPTOCOMBINED:
case KEYTYPE_RHIZOME:
break;
case KEYTYPE_INVALID:
FATALF("ktype = 0x%02x(%s)", kp->type, keytype_str(kp->type, "unknown"));
} }
kp=kp->next; kp=kp->next;
} }