From 2b260402b5cf2c181e80e85091ecf5ff3cb208ea Mon Sep 17 00:00:00 2001 From: gardners Date: Tue, 10 Apr 2012 12:55:46 +0930 Subject: [PATCH] Added keyring.c and begun work on routines to manipulate keyrings. --- Makefile.in | 4 +- keyring.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++ serval.h | 65 ++++++++++++++++- 3 files changed, 270 insertions(+), 6 deletions(-) create mode 100644 keyring.c diff --git a/Makefile.in b/Makefile.in index 3ee929a5..39619b72 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/keyring.c b/keyring.c new file mode 100644 index 00000000..d97656f2 --- /dev/null +++ b/keyring.c @@ -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(offsetfile_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;icontexts[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;iidentities[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;ikeypairs[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; +} diff --git a/serval.h b/serval.h index 146add1c..56af72fc 100644 --- a/serval.h +++ b/serval.h @@ -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);