Added keyring.c and begun work on routines to manipulate keyrings.

This commit is contained in:
gardners 2012-04-10 12:55:46 +09:30
parent ce5dc011b8
commit 2b260402b5
3 changed files with 270 additions and 6 deletions

@ -5,7 +5,7 @@ SRCS= dna.c server.c client.c peers.c ciphers.c responses.c packetformats.c data
rhizome.c rhizome_http.c rhizome_bundle.c rhizome_database.c rhizome_crypto.c \
rhizome_packetformats.c rhizome_fetch.c sqlite3.c encode.c sha2.c randombytes.c \
overlay_broadcast.c dna_identity.c commandline.c serval_packetvisualise.c \
trans_cache.c
trans_cache.c keyring.c
OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o dataformats.o \
hlrdata.o srandomdev.o simulate.o batman.o export.o gateway.o \
@ -14,7 +14,7 @@ OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o data
rhizome.o rhizome_http.o rhizome_bundle.o rhizome_database.o rhizome_crypto.o \
rhizome_packetformats.o rhizome_fetch.o sqlite3.o encode.o sha2.o randombytes.o \
overlay_broadcast.o dna_identity.o commandline.o serval_packetvisualise.o \
trans_cache.o
trans_cache.o keyring.o
HDRS= Makefile serval.h sqlite-amalgamation-3070900/sqlite3.h sha2.h rhizome.h

207
keyring.c Normal file

@ -0,0 +1,207 @@
/*
Copyright (C) 2010-2012 Paul Gardner-Stephen, Serval Project.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "serval.h"
/*
Open keyring file, read BAM and create initial context using the
stored salt. */
keyring_file *keyring_open(char *file)
{
/* Allocate structure */
keyring_file *k=calloc(sizeof(keyring_file),1);
if (!k) { WHY("calloc() failed"); return NULL; }
/* Open keyring file read-write if we can, else use it read-only */
k->file=fopen(file,"r+");
if (!k->file) k->file=fopen(file,"r");
if (!k->file) {
WHY("Could not open keyring file");
keyring_free(k);
return NULL;
}
if (fseeko(k->file,0,SEEK_END))
{
WHY("Could not seek to end of keyring file");
keyring_free(k);
return NULL;
}
k->file_size=ftello(k->file);
/* Read BAMs for each slab in the file */
keyring_bam **b=&k->bam;
off_t offset=0;
while(offset<k->file_size) {
/* Read bitmap from slab.
Also, if offset is zero, read the salt */
if (fseeko(k->file,offset,SEEK_SET))
{
WHY("Could not seek to BAM in keyring file");
keyring_free(k);
return NULL;
}
*b=calloc(sizeof(keyring_bam),1);
if (!(*b))
{
WHY("Could not allocate keyring_bam structure for key ring file");
keyring_free(k);
return NULL;
}
(*b)->file_offset=offset;
/* Read bitmap */
int r=fread(&(*b)->bitmap[0],KEYRING_BAM_BYTES,1,k->file);
if (r!=1)
{
WHY("Could not read BAM from keyring file");
keyring_free(k);
return NULL;
}
/* Read salt if this is the first bitmap block.
We setup a context for this self-supplied key-ring salt.
(other keyring salts may be provided later on, resulting in
multiple contexts being loaded) */
if (!offset) {
k->contexts[0]=calloc(sizeof(keyring_context),1);
if (!k->contexts[0])
{
WHY("Could not allocate keyring_context for keyring file");
keyring_free(k);
return NULL;
}
k->contexts[0]->KeyRingSaltLen=KEYRING_PAGE_SIZE-KEYRING_BAM_BYTES;
k->contexts[0]->KeyRingSalt=malloc(k->contexts[0]->KeyRingSaltLen);
if (!k->contexts[0]->KeyRingSalt)
{
WHY("Could not allocate keyring_context->salt for keyring file");
keyring_free(k);
return NULL;
}
r=fread(&k->contexts[0]->KeyRingSalt[0],k->contexts[0]->KeyRingSaltLen,1,k->file);
if (r!=1)
{
WHY("Could not read salt from keyring file");
keyring_free(k);
return NULL;
}
k->context_count=1;
}
/* Skip to next slab, and find next bam pointer. */
offset+=KEYRING_PAGE_SIZE*(KEYRING_BAM_BYTES<<3);
b=&(*b)->next;
}
return k;
}
void keyring_free(keyring_file *k)
{
int i;
if (!k) return;
/* Close keyring file handle */
if (k->file) fclose(k->file);
k->file=NULL;
/* Free BAMs (no substructure, so easy) */
keyring_bam *b=k->bam;
while(b) {
keyring_bam *last_bam=b;
b=b->next;
/* Clear out any private data */
bzero(last_bam,sizeof(keyring_bam));
/* release structure */
free(last_bam);
}
/* Free contexts (including subordinate identities and dynamically allocated salt strings).
Don't forget to overwrite any private data. */
for(i=0;i<KEYRING_MAX_CONTEXTS;i++)
if (k->contexts[i]) {
keyring_free_context(k->contexts[i]);
k->contexts[i]=NULL;
}
/* Wipe everything, just to be sure. */
bzero(k,sizeof(keyring_file));
return;
}
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;
}
if (c->KeyRingSalt) {
bzero(c->KeyRingSalt,c->KeyRingSaltLen);
c->KeyRingSalt=NULL;
c->KeyRingSaltLen=0;
}
/* Wipe out any loaded identities */
for(i=0;i<KEYRING_MAX_IDENTITIES;i++)
if (c->identities[i]) keyring_free_identity(c->identities[i]);
/* Make sure any private data is wiped out */
bzero(c,sizeof(keyring_context));
return;
}
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++) id->PKRPin[i]=' '; i=0;
free(id->PKRPin); id->PKRPin=NULL;
}
for(i=0;i<PKR_MAX_KEYPAIRS;i++)
if (id->keypairs[i])
keyring_free_keypair(id->keypairs[i]);
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;
}

@ -1009,11 +1009,12 @@ typedef struct sockaddr_mdp {
#define MDP_NOSIGN 0x0400
#define MDP_TX 1
#define MDP_RX 2
typedef struct overlay_mdp_outgoing_frame {
typedef struct overlay_mdp_data_frame {
sockaddr_mdp src;
sockaddr_mdp dst;
unsigned short payload_length;
unsigned char payload[1900];
#define MDP_MTU 2000
unsigned char payload[MDP_MTU-100];
} overlay_mdp_data_frame;
#define MDP_BIND 3
@ -1036,7 +1037,7 @@ typedef struct overlay_mdp_addrlist {
unsigned int last_sid;
unsigned char frame_sid_count; /* how many of the following 59 slots are
populated */
/* 59*32 < 1900, so up to 59 SIDs in a single reply.
/* 59*32 < (MDP_MTU-100), so up to 59 SIDs in a single reply.
Multiple replies can be used to respond with more. */
#define MDP_MAX_SID_REQUEST 59
unsigned char sids[MDP_MAX_SID_REQUEST][SID_SIZE];
@ -1053,7 +1054,7 @@ typedef struct overlay_mdp_frame {
overlay_mdp_error error;
/* 2048 is too large (causes EMSGSIZE errors on OSX, but probably fine on
Linux) */
char raw[2000];
char raw[MDP_MTU];
};
} overlay_mdp_frame;
@ -1087,3 +1088,59 @@ void *_serval_debug_malloc(unsigned int bytes,char *file,const char *func,int li
void *_serval_debug_calloc(unsigned int bytes,unsigned int count,char *file,const char *func,int line);
void _serval_debug_free(void *p,char *file,const char *func,int line);
#endif
typedef struct keypair {
int type;
unsigned char *private_key;
int private_key_len;
unsigned char *public_key;
int public_key_len;
} keypair;
/* Contains just the list of private:public key pairs and types,
the pin used to extract them, and the slot in the keyring file
(so that it can be replaced/rewritten as required). */
#define PKR_MAX_KEYPAIRS 64
typedef struct keyring_identity {
char *PKRPin;
unsigned int slot;
keypair *keypairs[PKR_MAX_KEYPAIRS];
} keyring_identity;
/* 64K identities, can easily be increased should the need arise,
but keep it low-ish for now so that the 64K pointers don't eat too
much ram on a small device. Should probably think about having
small and large device settings for some of these things */
#define KEYRING_MAX_IDENTITIES 65536
typedef struct keyring_context {
char *KeyRingPin;
unsigned char *KeyRingSalt;
int KeyRingSaltLen;
int identity_count;
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))
typedef struct keyring_bam {
unsigned long file_offset;
unsigned char bitmap[KEYRING_BAM_BYTES];
struct keyring_bam *next;
} keyring_bam;
#define KEYRING_MAX_CONTEXTS 256
typedef struct keyring_file {
int context_count;
keyring_bam *bam;
keyring_context *contexts[KEYRING_MAX_CONTEXTS];
FILE *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);
void keyring_free_keypair(keypair *kp);