Start work on "keyring load" command

This commit is contained in:
Andrew Bettison 2013-09-02 17:33:52 +09:30
parent 080ccd957a
commit 425aa1005c
3 changed files with 312 additions and 190 deletions

View File

@ -1768,6 +1768,35 @@ int app_keyring_dump(const struct cli_parsed *parsed, struct cli_context *contex
return ret;
}
int app_keyring_load(const struct cli_parsed *parsed, struct cli_context *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;
unsigned pinc = 0;
unsigned i;
for (i = 0; i < parsed->labelc; ++i)
if (strn_str_cmp(parsed->labelv[i].label, parsed->labelv[i].len, "pin") == 0)
++pinc;
const char *pinv[pinc];
unsigned pc = 0;
for (i = 0; i < parsed->labelc; ++i)
if (strn_str_cmp(parsed->labelv[i].label, parsed->labelv[i].len, "pin") == 0) {
assert(pc < pinc);
pinv[pc++] = parsed->labelv[i].text;
}
keyring_file *k = keyring_open_instance_cli(parsed);
if (!k)
return -1;
FILE *fp = path && strcmp(path, "-") != 0 ? fopen(path, "r") : stdin;
if (fp == NULL)
return WHYF_perror("fopen(%s, \"r\")", alloca_str_toprint(path));
int ret = keyring_load(k, pinc, pinv, fp);
return ret;
}
int app_keyring_list(const struct cli_parsed *parsed, struct cli_context *context)
{
if (config.debug.verbose)
@ -2299,7 +2328,9 @@ int app_network_scan(const struct cli_parsed *parsed, struct cli_context *contex
/* See cli_parse() for details of command specification syntax.
*/
#define KEYRING_PIN_OPTIONS ,"[--keyring-pin=<pin>]","[--entry-pin=<pin>]..."
#define KEYRING_PIN_OPTION ,"[--keyring-pin=<pin>]"
#define KEYRING_ENTRY_PIN_OPTION ,"[--entry-pin=<pin>]"
#define KEYRING_PIN_OPTIONS KEYRING_PIN_OPTION KEYRING_ENTRY_PIN_OPTION "..."
struct cli_schema command_line_options[]={
{commandline_usage,{"help|-h|--help","...",NULL},CLIFLAG_PERMISSIVE_CONFIG,
"Display command usage."},
@ -2307,7 +2338,7 @@ struct cli_schema command_line_options[]={
"Output the supplied string."},
{app_log,{"log","error|warn|hint|info|debug","<message>",NULL},CLIFLAG_PERMISSIVE_CONFIG,
"Log the supplied message at given level."},
{app_server_start,{"start","[foreground|exec <path>]",NULL}, 0,
{app_server_start,{"start" KEYRING_PIN_OPTIONS, "[foreground|exec <path>]",NULL}, 0,
"Start daemon with instance path from SERVALINSTANCE_PATH environment variable."},
{app_server_stop,{"stop",NULL},CLIFLAG_PERMISSIVE_CONFIG,
"Stop a running daemon with instance path from SERVALINSTANCE_PATH environment variable."},
@ -2380,6 +2411,8 @@ struct cli_schema command_line_options[]={
"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_load,{"keyring","load" KEYRING_PIN_OPTIONS,"<file>","[<pin>]...",NULL}, 0,
"Load identities from the given dump text and insert them into the keyring using the specified entry PINs"},
{app_keyring_list,{"keyring","list" KEYRING_PIN_OPTIONS,NULL}, 0,
"List identities that can be accessed using the supplied PINs"},
{app_keyring_add,{"keyring","add" KEYRING_PIN_OPTIONS,"[<pin>]",NULL}, 0,

463
keyring.c
View File

@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "nacl.h"
#include "overlay_address.h"
static void keyring_free_keypair(keypair *kp);
static int _keyring_open(keyring_file *k, const char *path, const char *mode)
{
if (config.debug.keyring)
@ -205,20 +207,30 @@ void keyring_free(keyring_file *k)
return;
}
static void wipestr(char *str)
{
while (*str) {
if (config.debug.keyring)
DEBUGF("wiping PIN char '%c'", *str);
*str++ = ' ';
}
}
void keyring_free_context(keyring_context *c)
{
int i;
if (!c) return;
if (c->KeyRingPin) {
/* Wipe pin before freeing (slightly tricky since this is a variable length string */
for(i=0;c->KeyRingPin[i];i++) c->KeyRingPin[i]=' '; i=0;
free(c->KeyRingPin); c->KeyRingPin=NULL;
/* Wipe pin from local memory before freeing. */
wipestr(c->KeyRingPin);
free(c->KeyRingPin);
c->KeyRingPin = NULL;
}
if (c->KeyRingSalt) {
bzero(c->KeyRingSalt,c->KeyRingSaltLen);
c->KeyRingSalt=NULL;
c->KeyRingSaltLen=0;
c->KeyRingSalt = NULL;
c->KeyRingSaltLen = 0;
}
/* Wipe out any loaded identities */
@ -233,50 +245,25 @@ void keyring_free_context(keyring_context *c)
void keyring_free_identity(keyring_identity *id)
{
int i;
if (id->PKRPin) {
/* Wipe pin before freeing (slightly tricky since this is a variable length string */
for(i=0;id->PKRPin[i];i++) {
if (config.debug.keyring)
DEBUGF("clearing PIN char '%c'", id->PKRPin[i]);
id->PKRPin[i]=' ';
}
i=0;
free(id->PKRPin); id->PKRPin=NULL;
/* Wipe pin from local memory before freeing. */
wipestr(id->PKRPin);
free(id->PKRPin);
id->PKRPin = NULL;
}
int i;
for(i=0;i<PKR_MAX_KEYPAIRS;i++)
if (id->keypairs[i])
keyring_free_keypair(id->keypairs[i]);
if (id->subscriber){
if (id->subscriber) {
id->subscriber->identity=NULL;
if (id->subscriber->reachable == REACHABLE_SELF)
id->subscriber->reachable = REACHABLE_NONE;
}
bzero(id,sizeof(keyring_identity));
return;
}
void keyring_free_keypair(keypair *kp)
{
if (kp->private_key) {
bzero(kp->private_key,kp->private_key_len);
free(kp->private_key);
kp->private_key=NULL;
}
if (kp->public_key) {
bzero(kp->public_key,kp->public_key_len);
free(kp->public_key);
kp->public_key=NULL;
}
bzero(kp,sizeof(keypair));
return;
}
/* Create a new keyring context for the loaded keyring file.
We don't need to load any identities etc, as that happens when we enter
an identity pin.
@ -421,21 +408,22 @@ 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 (*packer)(const keypair *, struct rotbuf *);
int (*unpacker)(const struct keytype *, keypair *, struct rotbuf *);
void (*dumper)(const keypair *, XPRINTF, int);
int (*loader)(const keypair *, const char *);
};
static int pack_private_only(const struct keytype *kt, const keypair *kp, struct rotbuf *rb)
static int pack_private_only(const keypair *kp, struct rotbuf *rb)
{
rotbuf_putbuf(rb, kp->private_key, kt->private_key_size);
rotbuf_putbuf(rb, kp->private_key, kp->private_key_len);
return 0;
}
static int pack_private_public(const struct keytype *kt, const keypair *kp, struct rotbuf *rb)
static int pack_private_public(const keypair *kp, struct rotbuf *rb)
{
rotbuf_putbuf(rb, kp->private_key, kt->private_key_size);
rotbuf_putbuf(rb, kp->public_key, kt->public_key_size);
rotbuf_putbuf(rb, kp->private_key, kp->private_key_len);
rotbuf_putbuf(rb, kp->public_key, kp->public_key_len);
return 0;
}
@ -447,6 +435,11 @@ static void dump_raw_hex(const keypair *kp, XPRINTF xpf, int include_secret)
xprintf(xpf, " sec=%s", alloca_tohex(kp->private_key, kp->private_key_len));
}
static int load_raw_hex(const keypair *kp, const char *text)
{
return 0;
}
static int unpack_private_public(const struct keytype *kt, keypair *kp, struct rotbuf *rb)
{
rotbuf_getbuf(rb, kp->private_key, kt->private_key_size);
@ -480,12 +473,12 @@ static int unpack_private_derive_scalarmult_public(const struct keytype *kt, key
return 0;
}
static int pack_did_name(const struct keytype *kt, const keypair *kp, struct rotbuf *rb)
static int pack_did_name(const keypair *kp, struct rotbuf *rb)
{
// Ensure name is nul terminated.
if (strnchr((const char *)kp->public_key, kt->public_key_size, '\0') == NULL)
if (strnchr((const char *)kp->public_key, kp->public_key_len, '\0') == NULL)
return WHY("missing nul terminator");
return pack_private_public(kt, kp, rb);
return pack_private_public(kp, rb);
}
static int unpack_did_name(const struct keytype *kt, keypair *kp, struct rotbuf *rb)
@ -502,6 +495,25 @@ static void dump_did_name(const keypair *kp, XPRINTF xpf, int include_secret)
xprintf(xpf, " Name=%s", alloca_str_toprint_quoted((const char *)kp->public_key, "\"\""));
}
static int load_did_name(const keypair *kp, const char *text)
{
const char *s;
const char *t;
if ((s = strstr(text, " DID=\"")) == NULL)
return WHY("missing DID");
bzero(kp->private_key, kp->private_key_len);
strn_fromprint(kp->private_key, kp->private_key_len, s + 6, '"', &t);
if (*t != '"')
return WHY("malformed DID quoted string");
if ((s = strstr(text, " Name=\"")) == NULL)
return WHY("missing Name");
bzero(kp->public_key, kp->public_key_len);
strn_fromprint(kp->public_key, kp->public_key_len, s + 6, '"', &t);
if (*t != '"')
return WHY("malformed Name quoted string");
return 0;
}
/* 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
@ -518,7 +530,8 @@ const struct keytype keytypes[] = {
.packed_size = crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES,
.packer = pack_private_only,
.unpacker = unpack_private_derive_scalarmult_public,
.dumper = dump_raw_hex
.dumper = dump_raw_hex,
.loader = load_raw_hex
},
[KEYTYPE_CRYPTOSIGN] = {
/* The NaCl API does not expose any method to derive a cryptosign public key from its private
@ -531,7 +544,8 @@ const struct keytype keytypes[] = {
.packed_size = crypto_sign_edwards25519sha512batch_SECRETKEYBYTES + crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES,
.packer = pack_private_public,
.unpacker = unpack_private_public,
.dumper = dump_raw_hex
.dumper = dump_raw_hex,
.loader = load_raw_hex
},
[KEYTYPE_RHIZOME] = {
/* The Rhizome Secret (a large, unguessable number) is stored in the private key field, and
@ -542,7 +556,8 @@ const struct keytype keytypes[] = {
.packed_size = 32,
.packer = pack_private_only,
.unpacker = unpack_private_only,
.dumper = dump_raw_hex
.dumper = dump_raw_hex,
.loader = load_raw_hex
},
[KEYTYPE_DID] = {
/* The DID is stored in unpacked form in the private key field, and the name in nul-terminated
@ -553,11 +568,58 @@ const struct keytype keytypes[] = {
.packed_size = 32 + 64,
.packer = pack_did_name,
.unpacker = unpack_did_name,
.dumper = dump_did_name
.dumper = dump_did_name,
.loader = load_did_name
}
// ADD MORE KEY TYPES HERE
};
static void keyring_free_keypair(keypair *kp)
{
if (kp->private_key) {
bzero(kp->private_key, kp->private_key_len);
free(kp->private_key);
}
if (kp->public_key) {
bzero(kp->public_key, kp->public_key_len);
free(kp->public_key);
}
bzero(kp, sizeof(keypair));
}
static keypair *keyring_alloc_keypair(unsigned ktype, size_t len)
{
assert(ktype != 0);
keypair *kp = emalloc_zero(sizeof(keypair));
if (!kp)
return NULL;
kp->type = ktype;
if (ktype < NELS(keytypes)) {
kp->private_key_len = keytypes[ktype].private_key_size;
kp->public_key_len = keytypes[ktype].public_key_size;
if (kp->private_key_len + kp->public_key_len != len) {
WHYF("keytype=%u private_key_len(%u) + public_key_len(%u) != len(%u)",
ktype,
kp->private_key_len,
kp->public_key_len,
len
);
keyring_free_keypair(kp);
return NULL;
}
} else {
kp->private_key_len = len;
kp->public_key_len = 0;
}
if ( (kp->private_key_len && (kp->private_key = emalloc_zero(kp->private_key_len)) == NULL)
|| (kp->public_key_len && (kp->public_key = emalloc_zero(kp->public_key_len)) == NULL)
) {
keyring_free_keypair(kp);
return NULL;
}
return kp;
}
static int keyring_pack_identity(keyring_context *c, keyring_identity *id, unsigned char packed[KEYRING_PAGE_SIZE])
{
/* Convert an identity to a KEYRING_PAGE_SIZE bytes long block that consists of 32 bytes of random
@ -589,44 +651,68 @@ static int keyring_pack_identity(keyring_context *c, keyring_identity *id, unsig
unsigned kp;
for (kp = 0; kp < id->keypair_count && !rbuf.wrap; ++kp) {
unsigned ktype = id->keypairs[kp]->type;
if (ktype == 0x00 || ktype >= NELS(keytypes)) {
WHYF("illegal key type 0x%02x at kp=%u", ktype, kp);
goto scram;
}
const char *kts = keytype_str(ktype);
int (*packer)(const keypair *, struct rotbuf *) = NULL;
size_t keypair_len;
const struct keytype *kt = &keytypes[ktype];
if (kt->packer == NULL) {
WARNF("unsupported key type 0x%02x, omitted from keyring file", ktype);
continue;
if (ktype == 0x00)
FATALF("ktype=0 in keypair kp=%u", kp);
if (ktype < NELS(keytypes)) {
packer = kt->packer;
keypair_len = kt->packed_size;
} else {
kts = "unknown";
packer = pack_private_only;
keypair_len = id->keypairs[kp]->private_key_len;
}
if (config.debug.keyring)
DEBUGF("pack key type = 0x%02x", ktype);
// First byte is the key type code.
rotbuf_putc(&rbuf, ktype);
// The next two bytes are the key pair length, for forward compatibility: so older software can
// skip over key pairs with an unrecognised type. The original four first key types do not
// store the length, for the sake of backward compatibility with legacy keyring files. Their
// entry lengths are hard-coded.
size_t keypair_len = kt->packed_size;
switch (ktype) {
case KEYTYPE_CRYPTOBOX:
case KEYTYPE_CRYPTOSIGN:
case KEYTYPE_RHIZOME:
case KEYTYPE_DID:
break;
default:
rotbuf_putc(&rbuf, (keypair_len >> 8) & 0xff);
rotbuf_putc(&rbuf, keypair_len & 0xff);
break;
}
// The remaining bytes is the key pair in whatever format it uses.
struct rotbuf rbstart = rbuf;
if (kt->packer(kt, id->keypairs[kp], &rbuf) != 0)
break;
// Ensure the correct number of bytes were written.
unsigned packed = rotbuf_delta(&rbstart, &rbuf);
if (packed != keypair_len) {
WHYF("key type 0x%02x packed wrong length (packed %u, expecting %u)", ktype, packed, (int)keypair_len);
goto scram;
if (packer == NULL) {
WARNF("no packer function for key type 0x%02x%s%s%s, omitted from keyring file",
ktype,
kts && *kts ? " (" : "",
kts ? kts : "",
kts && *kts ? ")" : ""
);
} else {
if (config.debug.keyring)
DEBUGF("pack key type = 0x%02x%s%s%s",
ktype,
kts && *kts ? " (" : "",
kts ? kts : "",
kts && *kts ? ")" : ""
);
// First byte is the key type code.
rotbuf_putc(&rbuf, ktype);
// The next two bytes are the key pair length, for forward compatibility: so older software can
// skip over key pairs with an unrecognised type. The original four first key types do not
// store the length, for the sake of backward compatibility with legacy keyring files. Their
// entry lengths are hard-coded.
switch (ktype) {
case KEYTYPE_CRYPTOBOX:
case KEYTYPE_CRYPTOSIGN:
case KEYTYPE_RHIZOME:
case KEYTYPE_DID:
break;
default:
rotbuf_putc(&rbuf, (keypair_len >> 8) & 0xff);
rotbuf_putc(&rbuf, keypair_len & 0xff);
break;
}
// The remaining bytes is the key pair in whatever format it uses.
struct rotbuf rbstart = rbuf;
if (packer(id->keypairs[kp], &rbuf) != 0)
break;
// Ensure the correct number of bytes were written.
unsigned packed = rotbuf_delta(&rbstart, &rbuf);
if (packed != keypair_len) {
WHYF("key type 0x%02x%s%s%s packed wrong length (packed %u, expecting %u)",
ktype,
kts && *kts ? " (" : "",
kts ? kts : "",
kts && *kts ? ")" : "",
packed, (int)keypair_len
);
goto scram;
}
}
}
// Final byte is a zero key type code.
@ -681,8 +767,8 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot, const char
{
/* Skip salt and MAC */
keyring_identity *id = emalloc_zero(sizeof(keyring_identity));
if (!id) { WHY("malloc of identity failed"); return NULL; }
if (!slot) { WHY("slot is null"); return NULL; }
if (!id)
return NULL;
id->PKRPin = str_edup(pin);
// The two bytes immediately following the MAC describe the rotation offset.
uint16_t rotation = (slot[PKR_SALT_BYTES + PKR_MAC_BYTES] << 8) | slot[PKR_SALT_BYTES + PKR_MAC_BYTES + 1];
@ -720,14 +806,17 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot, const char
}
if (rbuf.wrap)
break;
// Create keyring entry to hold the key pair. Even entries of unknown type are stored,
// so they can be dumped.
keypair *kp = keyring_alloc_keypair(ktype, keypair_len);
if (kp == NULL)
return NULL;
struct rotbuf rbstart = rbuf;
if (ktype < NELS(keytypes) && kt->unpacker) {
if (config.debug.keyring)
DEBUGF("unpack key type = 0x%02x at offset %u", ktype, (int)rotbuf_position(&rbo));
struct rotbuf rbstart = rbuf;
// Create keyring entries to hold the key pair.
keypair *kp = NULL;
if ( (kp = id->keypairs[id->keypair_count] = emalloc_zero(sizeof(keypair))) == NULL
|| (kt->private_key_size && (kp->private_key = emalloc(kt->private_key_size)) == NULL)
if ( (kt->private_key_size && (kp->private_key = emalloc(kt->private_key_size)) == NULL)
|| (kt->public_key_size && (kp->public_key = emalloc(kt->public_key_size)) == NULL)
) {
keyring_free_identity(id);
@ -743,37 +832,37 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot, const char
keyring_free_identity(id);
return NULL;
}
// 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 is probably an
// empty slot.
if (config.debug.keyring)
DEBUGF("key type 0x%02x unpacked wrong length (unpacked %u, expecting %u)", ktype, (int)unpacked, (int)keypair_len);
keyring_free_identity(id);
return NULL;
}
// 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 {
if (config.debug.keyring)
DEBUGF("unsupported key type 0x%02x at offset %u, skipping %u bytes", ktype, (int)rotbuf_position(&rbo), (int)keypair_len);
rotbuf_advance(&rbuf, keypair_len); // skip
DEBUGF("unsupported key type 0x%02x at offset %u, reading %u bytes as private key", ktype, (int)rotbuf_position(&rbo), (int)keypair_len);
rotbuf_getbuf(&rbuf, kp->private_key, kp->private_key_len);
}
// 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 is probably an
// empty slot.
if (config.debug.keyring)
DEBUGF("key type 0x%02x unpacked wrong length (unpacked %u, expecting %u)", ktype, (int)unpacked, (int)keypair_len);
keyring_free_identity(id);
return NULL;
}
// 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;
}
}
// If the buffer offset overshot, we got an invalid keypair code and length combination.
@ -814,14 +903,12 @@ int keyring_identity_mac(keyring_context *c, keyring_identity *id,
}
/* Read the slot, and try to decrypt it.
Decryption is symmetric with encryption, so the same function is used
for munging the slot before making use of it, whichever way we are going.
Once munged, we then need to verify that the slot is valid, and if so
unpack the details of the identity.
*/
int keyring_decrypt_pkr(keyring_file *k,keyring_context *c,
const char *pin,int slot_number)
/* Read the slot, and try to decrypt it. Decryption is symmetric with encryption, so the same
* function is used for munging the slot before making use of it, whichever way we are going. Once
* munged, we then need to verify that the slot is valid, and if so unpack the details of the
* identity.
*/
int keyring_decrypt_pkr(keyring_file *k, keyring_context *c, const char *pin, int slot_number)
{
int exit_code=1;
unsigned char slot[KEYRING_PAGE_SIZE];
@ -909,39 +996,33 @@ int keyring_enter_pin(keyring_file *k, const char *pin)
int slot;
int identitiesFound=0;
for(slot=0;slot<k->file_size/KEYRING_PAGE_SIZE;slot++)
{
/* slot zero is the BAM and salt, so skip it */
if (slot&(KEYRING_BAM_BITS-1)) {
/* Not a BAM slot, so examine */
off_t file_offset=slot*KEYRING_PAGE_SIZE;
for(slot=0;slot<k->file_size/KEYRING_PAGE_SIZE;slot++) {
/* slot zero is the BAM and salt, so skip it */
if (slot&(KEYRING_BAM_BITS-1)) {
/* Not a BAM slot, so examine */
off_t file_offset=slot*KEYRING_PAGE_SIZE;
/* See if this part of the keyring file is organised */
keyring_bam *b=k->bam;
while (b&&(file_offset>=b->file_offset+KEYRING_SLAB_SIZE))
b=b->next;
if (!b) continue;
/* See if this part of the keyring file is organised */
keyring_bam *b=k->bam;
while (b&&(file_offset>=b->file_offset+KEYRING_SLAB_SIZE))
b=b->next;
if (!b) continue;
/* Now see if slot is marked in-use. No point checking unallocated slots,
especially since the cost can be upto a second of CPU time on a phone. */
int position=slot&(KEYRING_BAM_BITS-1);
int byte=position>>3;
int bit=position&7;
if (b->bitmap[byte]&(1<<bit)) {
/* Slot is occupied, so check it.
We have to check it for each keyring context (ie keyring pin) */
int c;
for(c=0;c<k->context_count;c++)
{
int result=keyring_decrypt_pkr(k,k->contexts[c],pin?pin:"",slot);
if (!result)
identitiesFound++;
}
}
/* Now see if slot is marked in-use. No point checking unallocated slots,
especially since the cost can be upto a second of CPU time on a phone. */
int position=slot&(KEYRING_BAM_BITS-1);
int byte=position>>3;
int bit=position&7;
if (b->bitmap[byte]&(1<<bit)) {
/* Slot is occupied, so check it.
We have to check it for each keyring context (ie keyring pin) */
int c;
for (c=0;c<k->context_count;c++)
if (keyring_decrypt_pkr(k,k->contexts[c],pin?pin:"",slot) == 0)
++identitiesFound;
}
}
}
/* Tell the caller how many identities we found */
RETURN(identitiesFound);
OUT();
@ -969,13 +1050,10 @@ keyring_identity *keyring_create_identity(keyring_file *k,keyring_context *c, co
keyring_identity *id = emalloc_zero(sizeof(keyring_identity));
if (!id)
return NULL;
/* Store pin */
id->PKRPin = str_edup(pin);
if (!id->PKRPin) {
WHY("Could not store pin");
/* Remember pin */
if (!(id->PKRPin = str_edup(pin)))
goto kci_safeexit;
}
/* Find free slot in keyring.
Slot 0 in any slab is the BAM and possible keyring salt, so only search for
@ -1174,29 +1252,16 @@ int keyring_set_did(keyring_identity *id, const char *did, const char *name)
for(i=0;i<id->keypair_count;i++)
if (id->keypairs[i]->type==KEYTYPE_DID) {
if (config.debug.keyring)
DEBUG("Identity contains DID");
DEBUG("Identity already contains DID");
break;
}
if (i>=PKR_MAX_KEYPAIRS) return WHY("Too many key pairs");
if (i >= PKR_MAX_KEYPAIRS)
return WHY("Too many key pairs");
/* allocate if needed */
if (i>=id->keypair_count) {
id->keypairs[i] = emalloc_zero(sizeof(keypair));
if (!id->keypairs[i])
if (i >= id->keypair_count) {
if ((id->keypairs[i] = keyring_alloc_keypair(KEYTYPE_DID, keytypes[KEYTYPE_DID].packed_size)) == NULL)
return -1;
id->keypairs[i]->type=KEYTYPE_DID;
unsigned char *packedDid = emalloc_zero(32);
if (!packedDid)
return -1;
unsigned char *packedName = emalloc_zero(64);
if (!packedName)
return -1;
id->keypairs[i]->private_key=packedDid;
id->keypairs[i]->private_key_len=32;
id->keypairs[i]->public_key=packedName;
id->keypairs[i]->public_key_len=64;
id->keypair_count++;
++id->keypair_count;
if (config.debug.keyring)
DEBUG("Created DID record for identity");
}
@ -1671,13 +1736,13 @@ int keyring_dump(keyring_file *k, XPRINTF xpf, int include_secret)
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, " ");
xprintf(xpf, "%u: type=%u", i, keyp->type);
const char *kts = keytype_str(keyp->type);
if (!kts || !kts[0])
kts = "unknown";
xprintf(xpf, "(%s) ", kts);
if (keytypes[keyp->type].dumper)
keytypes[keyp->type].dumper(keyp, xpf, include_secret);
else
@ -1687,3 +1752,27 @@ int keyring_dump(keyring_file *k, XPRINTF xpf, int include_secret)
}
return 0;
}
int keyring_load(keyring_file *k, unsigned pinc, const char **pinv, FILE *input)
{
clearerr(input);
while (1) {
unsigned id;
unsigned ktype;
int i = 0;
char content[1024];
content[0] = '\0';
int n = fscanf(input, "%u: type=%u(%*[^)]) %n", &id, &ktype, &i);
fgets(content, sizeof content - 1, input);
DEBUGF("n=%d i=%d content=%s", n, i, alloca_str_toprint(content));
if (n == EOF && (ferror(input) || feof(input)))
break;
if (n != 2)
return WHY("malformed input");
if (ktype == 0)
return WHY("invalid input: key type = 0");
}
if (ferror(input))
return WHYF_perror("fscanf");
return 0;
}

View File

@ -253,7 +253,6 @@ typedef struct keyring_file {
void keyring_free(keyring_file *k);
void keyring_free_context(keyring_context *c);
void keyring_free_identity(keyring_identity *id);
void keyring_free_keypair(keypair *kp);
int keyring_identity_mac(keyring_context *c,keyring_identity *id,
unsigned char *pkrsalt,unsigned char *mac);
#define KEYTYPE_CRYPTOBOX 0x01
@ -286,6 +285,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_load(keyring_file *k, unsigned pinc, const char **pinv, FILE *input);
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 */