Add "keyring dump" command

This commit is contained in:
Andrew Bettison 2013-04-30 17:29:06 +09:30
parent 74c82648f2
commit 1f10f05302
5 changed files with 205 additions and 93 deletions

5
cli.c
View File

@ -322,6 +322,11 @@ int cli_lookup_did(const char *text)
return text[0] == '\0' || strcmp(text, "*") == 0 || str_is_did(text);
}
int cli_path_regular(const char *arg)
{
return arg[0] != '\0' && arg[strlen(arg) - 1] != '/';
}
int cli_absolute_path(const char *arg)
{
return arg[0] == '/' && arg[1] != '\0';

1
cli.h
View File

@ -63,6 +63,7 @@ int _cli_arg(struct __sourceloc __whence, const struct cli_parsed *parsed, char
#define cli_arg(parsed, label, dst, validator, defaultvalue) _cli_arg(__WHENCE__, parsed, label, dst, validator, defaultvalue)
int cli_lookup_did(const char *text);
int cli_path_regular(const char *arg);
int cli_absolute_path(const char *arg);
int cli_optional_sid(const char *arg);
int cli_optional_bundle_key(const char *arg);

View File

@ -1767,6 +1767,26 @@ int app_keyring_create(const struct cli_parsed *parsed, void *context)
return 0;
}
int app_keyring_dump(const struct cli_parsed *parsed, void *context)
{
if (config.debug.verbose)
DEBUG_cli_parsed(parsed);
const char *path;
if (cli_arg(parsed, "file", &path, cli_path_regular, NULL) == -1)
return -1;
int include_secret = 0 == cli_arg(parsed, "--secret", NULL, NULL, NULL);
keyring_file *k = keyring_open_instance_cli(parsed);
if (!k)
return -1;
FILE *fp = path ? fopen(path, "w") : stdout;
if (fp == NULL)
return WHYF_perror("fopen(%s, \"w\")", alloca_str_toprint(path));
int ret = keyring_dump(k, XPRINTF_STDIO(fp), include_secret);
if (fp != stdout && fclose(fp) == EOF)
return WHYF_perror("fclose(%s)", alloca_str_toprint(path));
return ret;
}
int app_keyring_list(const struct cli_parsed *parsed, void *context)
{
if (config.debug.verbose)
@ -2419,12 +2439,14 @@ struct cli_schema command_line_options[]={
"Remove stale and orphaned content from the Rhizome store"},
{app_keyring_create,{"keyring","create",NULL}, 0,
"Create a new keyring file."},
{app_keyring_dump,{"keyring","dump" KEYRING_PIN_OPTIONS,"[--secret]","[<file>]",NULL}, 0,
"Dump all keyring identities that can be accessed using the specified PINs"},
{app_keyring_list,{"keyring","list" KEYRING_PIN_OPTIONS,NULL}, 0,
"List identites in specified key ring that can be accessed using the specified PINs"},
"List identities that can be accessed using the supplied PINs"},
{app_keyring_add,{"keyring","add" KEYRING_PIN_OPTIONS,"[<pin>]",NULL}, 0,
"Create a new identity in the keyring protected by the provided PIN"},
"Create a new identity in the keyring protected by the supplied PIN (empty PIN if not given)"},
{app_keyring_set_did,{"keyring", "set","did" KEYRING_PIN_OPTIONS,"<sid>","<did>","<name>",NULL}, 0,
"Set the DID for the specified SID. Optionally supply PIN to unlock the SID record in the keyring."},
"Set the DID for the specified SID (must supply PIN to unlock the SID record in the keyring)"},
{app_id_self,{"id","self|peers|allpeers",NULL}, 0,
"Return identity(s) as URIs of own node, or of known routable peers, or all known peers"},
{app_route_print, {"route","print",NULL}, 0,

261
keyring.c
View File

@ -31,28 +31,28 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
/*
Open keyring file, read BAM and create initial context using the
stored salt. */
keyring_file *keyring_open(char *file)
keyring_file *keyring_open(const char *path)
{
/* Allocate structure */
keyring_file *k = emalloc_zero(sizeof(keyring_file));
if (!k)
return NULL;
/* Open keyring file read-write if we can, else use it read-only */
k->file = fopen(file, "r+");
k->file = fopen(path, "r+");
if (!k->file) {
if (errno != EPERM && errno != ENOENT)
WHYF_perror("fopen(%s, \"r+\")", alloca_str_toprint(file));
WHYF_perror("fopen(%s, \"r+\")", alloca_str_toprint(path));
if (config.debug.keyring)
DEBUGF("cannot open %s in \"r+\" mode, falling back to \"r\"", alloca_str_toprint(file));
k->file = fopen(file, "r");
DEBUGF("cannot open %s in \"r+\" mode, falling back to \"r\"", alloca_str_toprint(path));
k->file = fopen(path, "r");
if (!k->file) {
if (errno != EPERM && errno != ENOENT)
WHYF_perror("fopen(%s, \"r\")", alloca_str_toprint(file));
WHYF_perror("fopen(%s, \"r\")", alloca_str_toprint(path));
if (config.debug.keyring)
DEBUGF("cannot open %s in \"r\" mode, falling back to \"w+\"", alloca_str_toprint(file));
k->file = fopen(file, "w+");
DEBUGF("cannot open %s in \"r\" mode, falling back to \"w+\"", alloca_str_toprint(path));
k->file = fopen(path, "w+");
if (!k->file) {
WHYF_perror("fopen(%s, \"w+\")", alloca_str_toprint(file));
WHYF_perror("fopen(%s, \"w+\")", alloca_str_toprint(path));
keyring_free(k);
return NULL;
}
@ -60,7 +60,7 @@ keyring_file *keyring_open(char *file)
}
assert(k->file != NULL);
if (fseeko(k->file, 0, SEEK_END)) {
WHYF_perror("fseeko(%s, 0, SEEK_END)", alloca_str_toprint(file));
WHYF_perror("fseeko(%s, 0, SEEK_END)", alloca_str_toprint(path));
keyring_free(k);
return NULL;
}
@ -69,25 +69,25 @@ keyring_file *keyring_open(char *file)
/* Uninitialised, so write 2KB of zeroes,
followed by 2KB of random bytes as salt. */
if (fseeko(k->file, 0, SEEK_SET)) {
WHYF_perror("fseeko(%s, 0, SEEK_END)", alloca_str_toprint(file));
WHYF_perror("fseeko(%s, 0, SEEK_END)", alloca_str_toprint(path));
keyring_free(k);
return NULL;
}
unsigned char buffer[KEYRING_PAGE_SIZE];
bzero(&buffer[0],KEYRING_BAM_BYTES);
if (fwrite(buffer, 2048, 1, k->file)!=1) {
WHYF_perror("fwrite(%p, 2048, 1, %s)", buffer, alloca_str_toprint(file));
WHYF_perror("fwrite(%p, 2048, 1, %s)", buffer, alloca_str_toprint(path));
WHY("Could not write empty bitmap in fresh keyring file");
keyring_free(k);
return NULL;
}
if (urandombytes(&buffer[0],KEYRING_PAGE_SIZE-KEYRING_BAM_BYTES)) {
WHYF("Could not get random keyring salt to put in fresh keyring file %s", file);
WHYF("Could not get random keyring salt to put in fresh keyring file %s", path);
keyring_free(k);
return NULL;
}
if (fwrite(buffer, KEYRING_PAGE_SIZE - KEYRING_BAM_BYTES, 1, k->file) != 1) {
WHYF_perror("fwrite(%p, %lu, 1, %s)", buffer, (long)(KEYRING_PAGE_SIZE - KEYRING_BAM_BYTES), alloca_str_toprint(file));
WHYF_perror("fwrite(%p, %lu, 1, %s)", buffer, (long)(KEYRING_PAGE_SIZE - KEYRING_BAM_BYTES), alloca_str_toprint(path));
WHYF("Could not write keyring salt in fresh keyring file");
keyring_free(k);
return NULL;
@ -102,14 +102,14 @@ keyring_file *keyring_open(char *file)
/* Read bitmap from slab.
Also, if offset is zero, read the salt */
if (fseeko(k->file,offset,SEEK_SET)) {
WHYF_perror("fseeko(%s, %ld, SEEK_SET)", alloca_str_toprint(file), (long)offset);
WHYF_perror("fseeko(%s, %ld, SEEK_SET)", alloca_str_toprint(path), (long)offset);
WHY("Could not seek to BAM in keyring file");
keyring_free(k);
return NULL;
}
*b = emalloc_zero(sizeof(keyring_bam));
if (!(*b)) {
WHYF("Could not allocate keyring_bam structure for key ring file %s", file);
WHYF("Could not allocate keyring_bam structure for key ring file %s", path);
keyring_free(k);
return NULL;
}
@ -117,7 +117,7 @@ keyring_file *keyring_open(char *file)
/* Read bitmap */
int r=fread((*b)->bitmap, KEYRING_BAM_BYTES, 1, k->file);
if (r!=1) {
WHYF_perror("fread(%p, %ld, 1, %s)", (*b)->bitmap, (long)KEYRING_BAM_BYTES, alloca_str_toprint(file));
WHYF_perror("fread(%p, %ld, 1, %s)", (*b)->bitmap, (long)KEYRING_BAM_BYTES, alloca_str_toprint(path));
WHYF("Could not read BAM from keyring file");
keyring_free(k);
return NULL;
@ -130,7 +130,7 @@ keyring_file *keyring_open(char *file)
if (!offset) {
k->contexts[0] = emalloc_zero(sizeof(keyring_context));
if (!k->contexts[0]) {
WHYF("Could not allocate keyring_context for keyring file %s", file);
WHYF("Could not allocate keyring_context for keyring file %s", path);
keyring_free(k);
return NULL;
}
@ -139,14 +139,14 @@ keyring_file *keyring_open(char *file)
k->contexts[0]->KeyRingSaltLen=KEYRING_PAGE_SIZE-KEYRING_BAM_BYTES;
k->contexts[0]->KeyRingSalt = emalloc(k->contexts[0]->KeyRingSaltLen);
if (!k->contexts[0]->KeyRingSalt) {
WHYF("Could not allocate keyring_context->salt for keyring file %s", file);
WHYF("Could not allocate keyring_context->salt for keyring file %s", path);
keyring_free(k);
return NULL;
}
r = fread(k->contexts[0]->KeyRingSalt, k->contexts[0]->KeyRingSaltLen, 1, k->file);
if (r!=1) {
WHYF_perror("fread(%p, %ld, 1, %s)", k->contexts[0]->KeyRingSalt, k->contexts[0]->KeyRingSaltLen, alloca_str_toprint(file));
WHYF("Could not read salt from keyring file %s", file);
WHYF_perror("fread(%p, %ld, 1, %s)", k->contexts[0]->KeyRingSalt, k->contexts[0]->KeyRingSaltLen, alloca_str_toprint(path));
WHYF("Could not read salt from keyring file %s", path);
keyring_free(k);
return NULL;
}
@ -395,12 +395,24 @@ int keyring_munge_block(unsigned char *block,int len /* includes the first 96 by
#undef APPEND
}
static const char *keytype_str(unsigned ktype)
{
switch (ktype) {
case KEYTYPE_CRYPTOBOX: return "CRYPTOBOX";
case KEYTYPE_CRYPTOSIGN: return "CRYPTOSIGN";
case KEYTYPE_RHIZOME: return "RHIZOME";
case KEYTYPE_DID: return "DID";
default: return "";
}
}
struct keytype {
size_t public_key_size;
size_t private_key_size;
size_t packed_size;
int (*packer)(const struct keytype *, const keypair *, struct rotbuf *);
int (*unpacker)(const struct keytype *, keypair *, struct rotbuf *);
void (*dumper)(const keypair *, XPRINTF, int);
};
static int pack_private_only(const struct keytype *kt, const keypair *kp, struct rotbuf *rb)
@ -416,6 +428,14 @@ static int pack_private_public(const struct keytype *kt, const keypair *kp, stru
return 0;
}
static void dump_raw_hex(const keypair *kp, XPRINTF xpf, int include_secret)
{
if (kp->public_key_len)
xprintf(xpf, " pub=%s", alloca_tohex(kp->public_key, kp->public_key_len));
if (include_secret && kp->private_key_len)
xprintf(xpf, " sec=%s", alloca_tohex(kp->private_key, kp->private_key_len));
}
static int unpack_private_public(const struct keytype *kt, keypair *kp, struct rotbuf *rb)
{
rotbuf_getbuf(rb, kp->private_key, kt->private_key_size);
@ -465,6 +485,12 @@ static int unpack_did_name(const struct keytype *kt, keypair *kp, struct rotbuf
return strnchr((const char *)kp->public_key, kt->public_key_size, '\0') == NULL ? -1 : 0;
}
static void dump_did_name(const keypair *kp, XPRINTF xpf, int include_secret)
{
xprintf(xpf, " DID=%s", alloca_str_toprint_quoted((const char *)kp->private_key, "\"\""));
xprintf(xpf, " Name=%s", alloca_str_toprint_quoted((const char *)kp->public_key, "\"\""));
}
/* This is where all the supported key types are declared. In order to preserve backward
* compatibility (reading keyring files from older versions of Serval DNA), DO NOT ERASE OR RE-USE
* ANY KEY TYPE ENTRIES FROM THIS ARRAY. If a key type is no longer used, it must be permanently
@ -480,7 +506,8 @@ const struct keytype keytypes[] = {
.public_key_size = crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES,
.packed_size = crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES,
.packer = pack_private_only,
.unpacker = unpack_private_derive_scalarmult_public
.unpacker = unpack_private_derive_scalarmult_public,
.dumper = dump_raw_hex
},
[KEYTYPE_CRYPTOSIGN] = {
/* The NaCl API does not expose any method to derive a cryptosign public key from its private
@ -492,7 +519,8 @@ const struct keytype keytypes[] = {
.public_key_size = crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES,
.packed_size = crypto_sign_edwards25519sha512batch_SECRETKEYBYTES + crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES,
.packer = pack_private_public,
.unpacker = unpack_private_public
.unpacker = unpack_private_public,
.dumper = dump_raw_hex
},
[KEYTYPE_RHIZOME] = {
/* Only the private key (Rhizome Secret) is stored, because the public key is never used.
@ -501,7 +529,8 @@ const struct keytype keytypes[] = {
.public_key_size = 0,
.packed_size = 32,
.packer = pack_private_only,
.unpacker = unpack_private_only
.unpacker = unpack_private_only,
.dumper = dump_raw_hex
},
[KEYTYPE_DID] = {
/* The DID is stored in unpacked form in the private key field, and the name in nul-terminated
@ -511,7 +540,8 @@ const struct keytype keytypes[] = {
.public_key_size = 64,
.packed_size = 32 + 64,
.packer = pack_did_name,
.unpacker = unpack_did_name
.unpacker = unpack_did_name,
.dumper = dump_did_name
}
// ADD MORE KEY TYPES HERE
};
@ -617,6 +647,24 @@ scram:
return -1;
}
static int cmp_keypair(const keypair *a, const keypair *b)
{
int c = a->type < b->type ? -1 : a->type > b->type ? 1 : 0;
if (c == 0 && a->public_key_len) {
assert(a->public_key_len == b->public_key_len);
assert(a->public_key != NULL);
assert(b->public_key != NULL);
c = memcmp(a->public_key, b->public_key, a->public_key_len);
}
if (c == 0 && a->private_key_len) {
assert(a->private_key_len == b->private_key_len);
assert(a->private_key != NULL);
assert(b->private_key != NULL);
c = memcmp(a->private_key, b->private_key, a->private_key_len);
}
return c;
}
static keyring_identity *keyring_unpack_identity(unsigned char *slot, const char *pin)
{
/* Skip salt and MAC */
@ -632,23 +680,14 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot, const char
slot + PKR_SALT_BYTES + PKR_MAC_BYTES + 2,
KEYRING_PAGE_SIZE - (PKR_SALT_BYTES + PKR_MAC_BYTES + 2),
rotation);
struct rotbuf rbo = rbuf;
while (!rbuf.wrap) {
if (config.debug.keyring) {
rotbuf_log(__HERE__, LOG_LEVEL_DEBUG, "rbo: ", &rbo);
rotbuf_log(__HERE__, LOG_LEVEL_DEBUG, "rbuf: ", &rbuf);
DEBUGF("offset %u", rotbuf_delta(&rbo, &rbuf));
}
if (id->keypair_count >= PKR_MAX_KEYPAIRS) {
WHY("too many key pairs");
keyring_free_identity(id);
return NULL;
}
struct rotbuf rbo = rbuf;
unsigned char ktype = rotbuf_getc(&rbuf);
if (config.debug.keyring) {
rotbuf_log(__HERE__, LOG_LEVEL_DEBUG, "rbuf: ", &rbuf);
DEBUGF("offset %u", rotbuf_delta(&rbo, &rbuf));
}
if (rbuf.wrap || ktype == 0x00)
break; // End of data, stop looking
const struct keytype *kt = &keytypes[ktype];
@ -671,7 +710,7 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot, const char
break;
if (ktype < NELS(keytypes) && kt->unpacker) {
if (config.debug.keyring)
DEBUGF("unpack key type = 0x%02x at offset %u", ktype, rotbuf_delta(&rbo, &rbuf));
DEBUGF("unpack key type = 0x%02x at offset %u", ktype, rotbuf_position(&rbo));
struct rotbuf rbstart = rbuf;
// Create keyring entries to hold the key pair.
keypair *kp = NULL;
@ -686,42 +725,54 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot, const char
kp->private_key_len = kt->private_key_size;
kp->public_key_len = kt->public_key_size;
if (kt->unpacker(kt, kp, &rbuf) != 0) {
// If there is an error, it could simply be an empty slot that passed the MAC validation.
// TODO emit a warning?
WARNF("key type 0x%02x does not unpack", ktype);
// If there is an error, it is probably an empty slot.
if (config.debug.keyring)
DEBUGF("key type 0x%02x does not unpack", ktype);
keyring_free_identity(id);
return NULL;
}
if (config.debug.keyring) {
rotbuf_log(__HERE__, LOG_LEVEL_DEBUG, "rbuf: ", &rbuf);
DEBUGF("offset %u", rotbuf_delta(&rbo, &rbuf));
}
// Ensure that the correct number of bytes was consumed.
size_t unpacked = rotbuf_delta(&rbstart, &rbuf);
if (unpacked != keypair_len) {
// If the number of bytes unpacked does not match the keypair length, it could be an empty
// slot that passed the MAC validation.
// TODO emit a warning?
WARNF("key type 0x%02x unpacked wrong length (unpacked %u, expecting %u)", ktype, unpacked, keypair_len);
// If the number of bytes unpacked does not match the keypair length, it is probably an
// empty slot.
if (config.debug.keyring)
DEBUGF("key type 0x%02x unpacked wrong length (unpacked %u, expecting %u)", ktype, unpacked, keypair_len);
keyring_free_identity(id);
return NULL;
}
// Got a valid key pair!
++id->keypair_count;
// Got a valid key pair! Sort the key pairs by (key type, public key, private key) and weed
// out duplicates.
{
int c = 1;
unsigned i = 0;
for (i = 0; i < id->keypair_count && (c = cmp_keypair(id->keypairs[i], id->keypairs[id->keypair_count])) < 0; ++i)
;
if (c > 0) {
keypair *tmp = id->keypairs[id->keypair_count];
unsigned j;
for (j = id->keypair_count; j > i; --j)
id->keypairs[j] = id->keypairs[j - 1];
id->keypairs[i] = tmp;
}
if (c)
++id->keypair_count;
}
} else {
WARNF("unsupported key type 0x%02x, skipping", ktype);
if (config.debug.keyring)
DEBUGF("unsupported key type 0x%02x at offset %u, skipping %u bytes", ktype, rotbuf_position(&rbo), keypair_len);
rotbuf_advance(&rbuf, keypair_len); // skip
}
if (config.debug.keyring) {
rotbuf_log(__HERE__, LOG_LEVEL_DEBUG, "rbuf: ", &rbuf);
DEBUGF("offset %u", rotbuf_delta(&rbo, &rbuf));
}
}
// If the buffer offset overshot, we got an invalid keypair code and length combination.
if (rbuf.wrap > 1) {
if (config.debug.keyring)
DEBUGF("slot overrun by %u bytes", rbuf.wrap - 1);
keyring_free_identity(id);
return NULL;
}
if (config.debug.keyring)
DEBUGF("unpacked %d key pairs", id->keypair_count);
return id;
}
@ -775,14 +826,14 @@ int keyring_decrypt_pkr(keyring_file *k,keyring_context *c,
k->contexts[0]->KeyRingSalt,
k->contexts[0]->KeyRingSaltLen,
c->KeyRingPin,pin)) {
WHY("keyring_munge_block() failed");
WHYF("keyring_munge_block() failed, slot=%u", slot_number);
goto kdp_safeexit;
}
/* 3. Unpack contents of slot into a new identity in the provided context. */
if ((id = keyring_unpack_identity(slot, pin)) == NULL)
goto kdp_safeexit; // Not a valid slot
if (id->keypair_count < 1)
if (config.debug.keyring)
DEBUGF("unpack slot %u", slot_number);
if (((id = keyring_unpack_identity(slot, pin)) == NULL) || id->keypair_count < 1)
goto kdp_safeexit; // Not a valid slot
id->slot = slot_number;
@ -1153,28 +1204,18 @@ int keyring_set_did(keyring_identity *id, const char *did, const char *name)
int keyring_find_did(const keyring_file *k,int *cn,int *in,int *kp,char *did)
{
if (keyring_sanitise_position(k,cn,in,kp)) return 0;
while (1) {
/* we know we have a sane position, so see if it is interesting */
if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_DID)
{
/* Compare DIDs */
if ((!did[0])
||(did[0]=='*'&&did[1]==0)
||(!strcasecmp(did,(char *)k->contexts[*cn]->identities[*in]
->keypairs[*kp]->private_key)))
{
/* match */
return 1;
}
for (; keyring_sanitise_position(k,cn,in,kp) == 0; ++*kp) {
if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_DID) {
/* Compare DIDs */
if ((!did[0])
||(did[0]=='*'&&did[1]==0)
||(!strcasecmp(did,(char *)k->contexts[*cn]->identities[*in]
->keypairs[*kp]->private_key))
) {
return 1; // match
}
(*kp)++;
if (keyring_sanitise_position(k,cn,in,kp)) return 0;
}
}
return 0;
}
@ -1189,11 +1230,9 @@ int keyring_identity_find_keytype(const keyring_file *k, int cn, int in, int key
int keyring_next_keytype(const keyring_file *k, int *cn, int *in, int *kp, int keytype)
{
while (!keyring_sanitise_position(k, cn, in, kp)) {
for (; keyring_sanitise_position(k, cn, in, kp) == 0; ++*kp)
if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type == keytype)
return 1;
++*kp;
}
return 0;
}
@ -1206,19 +1245,19 @@ int keyring_sanitise_position(const keyring_file *k,int *cn,int *in,int *kp)
{
if (!k) return 1;
/* Sanity check passed in position */
if ((*cn)>=keyring->context_count) return 1;
if ((*in)>=keyring->contexts[*cn]->identity_count)
if ((*cn)>=k->context_count) return 1;
if ((*in)>=k->contexts[*cn]->identity_count)
{
(*in)=0; (*cn)++;
if ((*cn)>=keyring->context_count) return 1;
if ((*cn)>=k->context_count) return 1;
}
if ((*kp)>=keyring->contexts[*cn]->identities[*in]->keypair_count)
if ((*kp)>=k->contexts[*cn]->identities[*in]->keypair_count)
{
*kp=0; (*in)++;
if ((*in)>=keyring->contexts[*cn]->identity_count)
if ((*in)>=k->contexts[*cn]->identity_count)
{
(*in)=0; (*cn)++;
if ((*cn)>=keyring->context_count) return 1;
if ((*cn)>=k->context_count) return 1;
}
}
return 0;
@ -1410,7 +1449,7 @@ int keyring_send_sas_request(struct subscriber *subscriber){
int keyring_find_sid(const keyring_file *k, int *cn, int *in, int *kp, const unsigned char *sid)
{
for (; !keyring_sanitise_position(k, cn, in, kp); ++*kp)
for (; keyring_sanitise_position(k, cn, in, kp) == 0; ++*kp)
if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type == KEYTYPE_CRYPTOBOX
&& memcmp(sid, k->contexts[*cn]->identities[*in]->keypairs[*kp]->public_key, SID_SIZE) == 0)
return 1;
@ -1576,7 +1615,51 @@ unsigned char *keyring_get_nm_bytes(unsigned char *known_sid, unsigned char *unk
->contexts[cn]
->identities[in]
->keypairs[kp]->private_key);
RETURN(nm_cache[i].nm_bytes);
OUT();
}
static int cmp_identity_ptrs(const keyring_identity *const *a, const keyring_identity *const *b)
{
int c;
unsigned i;
for (i = 0; i < (*a)->keypair_count && i < (*b)->keypair_count; ++i)
if ((c = cmp_keypair((*a)->keypairs[i], (*b)->keypairs[i])))
return c;
return i == (*a)->keypair_count ? -1 : 1;
}
int keyring_dump(keyring_file *k, XPRINTF xpf, int include_secret)
{
int cn, in, kp;
unsigned nids = 0;
for (cn = in = kp = 0; keyring_sanitise_position(k, &cn, &in, &kp) == 0; ++in)
++nids;
const keyring_identity *idx[nids];
unsigned i = 0;
for (cn = in = kp = 0; keyring_sanitise_position(k, &cn, &in, &kp) == 0; ++in) {
assert(i < nids);
idx[i++] = k->contexts[cn]->identities[in];
}
assert(i == nids);
qsort(idx, nids, sizeof(idx[0]), (int(*)(const void *, const void *)) cmp_identity_ptrs);
for (i = 0; i != nids; ++i) {
const keyring_identity *id = idx[i];
for (kp = 0; kp < id->keypair_count; ++kp) {
keypair *keyp = id->keypairs[kp];
xprintf(xpf, "%u: type=%u", i, keyp->type);
const char *kts = keytype_str(keyp->type);
if (kts && kts[0])
xprintf(xpf, "(%s)", kts);
assert(keyp->type != 0);
assert(keyp->type < NELS(keytypes));
xprintf(xpf, " ");
if (keytypes[keyp->type].dumper)
keytypes[keyp->type].dumper(keyp, xpf, include_secret);
else
dump_raw_hex(keyp, xpf, include_secret);
xprintf(xpf, "\n");
}
}
return 0;
}

View File

@ -265,7 +265,7 @@ int keyring_identity_mac(keyring_context *c,keyring_identity *id,
extern keyring_file *keyring;
/* Public calls to keyring management */
keyring_file *keyring_open(char *file);
keyring_file *keyring_open(const char *path);
keyring_file *keyring_open_instance();
keyring_file *keyring_open_instance_cli(const struct cli_parsed *parsed);
int keyring_enter_pin(keyring_file *k, const char *pin);
@ -284,6 +284,7 @@ int keyring_commit(keyring_file *k);
keyring_identity *keyring_create_identity(keyring_file *k,keyring_context *c, const char *pin);
int keyring_seed(keyring_file *k);
void keyring_identity_extract(const keyring_identity *id, const unsigned char **sidp, const char **didp, const char **namep);
int keyring_dump(keyring_file *k, XPRINTF xpf, int include_secret);
/* Make sure we have space to put bytes of the packet as we go along */
#define CHECK_PACKET_LEN(B) {if (((*packet_len)+(B))>=packet_maxlen) { return WHY("Packet composition ran out of space."); } }