From 8efb6fd49726af759a88b44947bba5e23a285d2a Mon Sep 17 00:00:00 2001 From: gardners Date: Thu, 12 Apr 2012 07:51:53 +0930 Subject: [PATCH] Work towards being able to create a new identity. Still need to pack, crypt and store the resulting identity. --- keyring.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ serval.h | 11 ++-- 2 files changed, 153 insertions(+), 4 deletions(-) diff --git a/keyring.c b/keyring.c index 418a7a6f..1fa180e7 100644 --- a/keyring.c +++ b/keyring.c @@ -555,3 +555,149 @@ int keyring_decrypt_pkr(keyring_file *k,keyring_context *c, return exit_code; } +/* Try all valid slots with the PIN and see if we find any identities with that PIN. + We might find more than one. */ +int keyring_enter_pin(keyring_file *k,char *pin) +{ + if (!k) return -1; + if (!pin) pin=""; + + int slot; + int identitiesFound=0; + + for(slot=0;slotfile_size/KEYRING_PAGE_SIZE;slot++) + { + 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; + + /* 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<context_count;c++) + { + int result=keyring_decrypt_pkr(k,k->contexts[c],pin,slot); + if (!result) identitiesFound++; + } + } + } + } + + /* Tell the caller how many identities we found */ + return identitiesFound; + +} + +/* Create a new identity in the specified context (which supplies the keyring pin) + with the specified PKR pin. + The crypto_box and crypto_sign key pairs are automatically created, and the PKR + is packed and written to a hithero unallocated slot which is then marked full. +*/ +int keyring_create_identity(keyring_file *k,keyring_context *c,char *pin) +{ + int exit_code=1; + if (!k) return WHY("keyring is NULL"); + if (!k->bam) return WHY("keyring lacks BAM (not to be confused with KAPOW)"); + if (!c) return WHY("keyring context is NULL"); + if (!pin) pin=""; + + keyring_identity *id=calloc(sizeof(keyring_identity),1); + + /* Store pin */ + id->PKRPin=strdup(pin); + if (!id->PKRPin) { + WHY("Could not store pin"); + goto kci_safeexit; + } + + /* Find free slot in keyring */ + /* XXX Only stores to first slab! */ + keyring_bam *b=k->bam; + for(id->slot=0;id->slotslot++) + { + int position=id->slot&(KEYRING_BAM_BITS-1); + int byte=position>>3; + int bit=position&7; + if (!(b->bitmap[byte]&(1<slot>=KEYRING_BAM_BITS) { + WHY("no free slots in first slab (and I don't know how to store in subsequent slabs yet"); + goto kci_safeexit; + } + + /* Allocate key pairs */ + + /* crypto_box key pair */ + id->keypairs[0]=calloc(sizeof(keypair),1); + if (!id->keypairs[0]) { + WHY("calloc() failed preparing first key pair storage"); + goto kci_safeexit; + } + id->keypair_count=1; + id->keypairs[0]->type=KEYTYPE_CRYPTOBOX; + id->keypairs[0]->private_key_len=crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES; + id->keypairs[0]->private_key=malloc(id->keypairs[0]->private_key_len); + if (!id->keypairs[0]->private_key) { + WHY("malloc() failed preparing first private key storage"); + goto kci_safeexit; + } + id->keypairs[0]->public_key_len=crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES; + id->keypairs[0]->public_key=malloc(id->keypairs[0]->public_key_len); + if (!id->keypairs[0]->public_key) { + WHY("malloc() failed preparing first public key storage"); + goto kci_safeexit; + } + crypto_box_curve25519xsalsa20poly1305_keypair(id->keypairs[0]->public_key, + id->keypairs[0]->private_key); + + /* crypto_box key pair */ + id->keypairs[1]=calloc(sizeof(keypair),1); + if (!id->keypairs[1]) { + WHY("calloc() failed preparing second key pair storage"); + goto kci_safeexit; + } + id->keypair_count=2; + id->keypairs[1]->type=KEYTYPE_CRYPTOSIGN; + id->keypairs[1]->private_key_len=crypto_sign_edwards25519sha512batch_SECRETKEYBYTES; + id->keypairs[1]->private_key=malloc(id->keypairs[1]->private_key_len); + if (!id->keypairs[1]->private_key) { + WHY("malloc() failed preparing second private key storage"); + goto kci_safeexit; + } + id->keypairs[1]->public_key_len=crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES; + id->keypairs[1]->public_key=malloc(id->keypairs[1]->public_key_len); + if (!id->keypairs[1]->public_key) { + WHY("malloc() failed preparing second public key storage"); + goto kci_safeexit; + } + crypto_sign_edwards25519sha512batch_keypair(id->keypairs[1]->public_key, + id->keypairs[1]->private_key); + + + + + /* XXX + - Create packed and encrypted PKR. + - Mark slot in-use. + - Clean up sensitive data + */ + WHY("Not implemented"); + + kci_safeexit: + if (id) keyring_free_identity(id); + return exit_code; +} diff --git a/serval.h b/serval.h index 98e9ae9d..c7ac6f61 100644 --- a/serval.h +++ b/serval.h @@ -1122,9 +1122,10 @@ typedef struct keyring_context { keyring_identity *identities[KEYRING_MAX_IDENTITIES]; } keyring_context; -#define KEYRING_PAGE_SIZE 4096 -#define KEYRING_BAM_BYTES 2048 -#define KEYRING_SLAB_SIZE (KEYRING_PAGE_SIZE*(KEYRING_BAM_BYTES<<3)) +#define KEYRING_PAGE_SIZE 4096LL +#define KEYRING_BAM_BYTES 2048LL +#define KEYRING_BAM_BITS (KEYRING_BAM_BYTES<<3) +#define KEYRING_SLAB_SIZE (KEYRING_PAGE_SIZE*KEYRING_BAM_BITS) typedef struct keyring_bam { unsigned long file_offset; unsigned char bitmap[KEYRING_BAM_BYTES]; @@ -1140,7 +1141,6 @@ typedef struct keyring_file { off_t file_size; } keyring_file; -keyring_file *keyring_open(char *file); void keyring_free(keyring_file *k); void keyring_free_context(keyring_context *c); void keyring_free_identity(keyring_identity *id); @@ -1148,3 +1148,6 @@ void keyring_free_keypair(keypair *kp); #define KEYTYPE_CRYPTOBOX 0x01 #define KEYTYPE_CRYPTOSIGN 0x02 +/* Public calls to keyring management */ +keyring_file *keyring_open(char *file); +int keyring_enter_pin(keyring_file *k,char *pin);