From ca24513599badd1b76a3fbabae22a65399c94667 Mon Sep 17 00:00:00 2001 From: gardners Date: Sat, 14 Apr 2012 02:14:41 +0930 Subject: [PATCH] Work towards actually authcrypting MDP payloads. Not complete. --- keyring.c | 18 ++++++++++++++++ overlay_buffer.c | 9 ++++++++ overlay_mdp.c | 54 ++++++++++++++++++++++++++++++++++++++++++++---- serval.h | 6 +++++- 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/keyring.c b/keyring.c index d1202f5c..0397434e 100644 --- a/keyring.c +++ b/keyring.c @@ -1142,3 +1142,21 @@ int keyring_seed(keyring_file *k) return 0; } +/* + The CryptoBox function of NaCl involves a scalar mult operation between the + public key of the recipient and the private key of the sender (or vice versa). + This can take about 1 cpu second on a phone, which is rather bad. + Fortunately, NaCl allows the caching of the result of this computation, which can + then be fed into the process to make it much, much faster. + Thus we need a mechanism for caching the various scalarmult results so that they + can indeed be reused. +*/ + +unsigned char *keyring_get_nm_bytes(sockaddr_mdp *priv,sockaddr_mdp *pub) +{ + if (!priv) WHYRETNULL("priv is null"); + if (!pub) WHYRETNULL("pub is null"); + if (!keyring) WHYRETNULL("keyring is null"); + + WHYRETNULL("Not implemented"); +} diff --git a/overlay_buffer.c b/overlay_buffer.c index 98035626..571c23e5 100644 --- a/overlay_buffer.c +++ b/overlay_buffer.c @@ -166,6 +166,15 @@ int ob_append_byte(overlay_buffer *b,unsigned char byte) return 0; } +unsigned char *ob_append_space(overlay_buffer *b,int count) +{ + if (ob_makespace(b,count)) { WHY("ob_makespace() failed"); return NULL; } + + unsigned char *r=&b->bytes[b->length]; + b->length+=count; + return r; +} + int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count) { if (ob_makespace(b,count)) return WHY("ob_makespace() failed"); diff --git a/overlay_mdp.c b/overlay_mdp.c index a43290bd..13973608 100644 --- a/overlay_mdp.c +++ b/overlay_mdp.c @@ -479,15 +479,61 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp, frame->prev=NULL; frame->next=NULL; + int fe=0; + /* Work out the disposition of the frame. For now we are only worried about the crypto matters, and not compression that may be applied before encryption (since applying it after is useless as ciphered text should have maximum entropy). */ switch(mdp->packetTypeAndFlags&(MDP_NOCRYPT|MDP_NOSIGN)) { - case 0: /* crypted and signed (using CryptBox authcryption primitive) */ - frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED; - op_free(frame); - return WHY("ciphered+signed MDP frames not implemented"); + case 0: /* crypted and signed (using CryptoBox authcryption primitive) */ + frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED; + /* Prepare payload */ + frame->payload=ob_new(1 /* frame type (MDP) */ + +1 /* MDP version */ + +4 /* dst port */ + +4 /* src port */ + +crypto_box_curve25519xsalsa20poly1305_NONCEBYTES + +crypto_box_curve25519xsalsa20poly1305_ZEROBYTES + +mdp->out.payload_length); + /* MDP version 1 */ + fe|=ob_append_byte(frame->payload,0x01); + fe|=ob_append_byte(frame->payload,0x01); + /* Destination port */ + fe|=ob_append_int(frame->payload,mdp->out.dst.port); + /* XXX we should probably pull the source port from the bindings + On that note, when a binding is granted, we should probably + provide a token that can be used to lookup the binding and + indicate which binding the packet is for? */ + fe|=ob_append_int(frame->payload,0); + { + /* write cryptobox nonce */ + unsigned char nonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES]; + if (urandombytes(nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES)) + { op_free(frame); WHY("urandombytes() failed to generate nonce"); } + fe|= + ob_append_bytes(frame->payload,nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES); + /* generate plain message with zero bytes and get ready to cipher it */ + unsigned char plain[crypto_box_curve25519xsalsa20poly1305_ZEROBYTES + +mdp->out.payload_length]; + bzero(&plain[0],crypto_box_curve25519xsalsa20poly1305_ZEROBYTES); + bcopy(&mdp->out.payload,&plain[crypto_box_curve25519xsalsa20poly1305_ZEROBYTES], + mdp->out.payload_length); + + /* get pre-computed PKxSK bytes (the slow part of auth-cryption that can be + retained and reused, and use that to do the encryption quickly. */ + unsigned char *k=keyring_get_nm_bytes(&mdp->out.src,&mdp->out.dst); + if (!k) { op_free(frame); return WHY("could not compute Curve25519(NxM)"); } + /* Get pointer to place in frame where the ciphered text needs to go */ + unsigned char *cipher_text=ob_append_space(frame->payload,sizeof(plain)); + if (fe||(!cipher_text)) + { op_free(frame); return WHY("could not make space for ciphered text"); } + /* Actually authcrypt the payload */ + if (crypto_box_afternm(cipher_text,plain, + crypto_box_curve25519xsalsa20poly1305_ZEROBYTES + +mdp->out.payload_length,nonce,k)) + { op_free(frame); return WHY("crypto_box_afternm() failed"); } + } break; case MDP_NOSIGN: /* ciphered, but not signed. diff --git a/serval.h b/serval.h index 5dd734ae..2ba23119 100644 --- a/serval.h +++ b/serval.h @@ -247,7 +247,6 @@ int keyring_find_sid(keyring_file *k,int *cn,int *in,int *kp,unsigned char *sid) int keyring_commit(keyring_file *k); keyring_identity *keyring_create_identity(keyring_file *k,keyring_context *c, char *pin); - int keyring_seed(keyring_file *k); /* Packet format: @@ -717,6 +716,7 @@ extern overlay_txqueue overlay_tx[OQ_MAX]; int setReason(char *fmt, ...); #define WHY(X) setReason("%s:%d:%s() %s",__FILE__,__LINE__,__FUNCTION__,X) +#define WHYRETNULL(X) { setReason("%s:%d:%s() %s",__FILE__,__LINE__,__FUNCTION__,X); return NULL; } #define WHYF(F, ...) setReason("%s:%d:%s() " F, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) overlay_buffer *ob_new(int size); @@ -728,6 +728,7 @@ int ob_unlimitsize(overlay_buffer *b); int ob_makespace(overlay_buffer *b,int bytes); int ob_append_byte(overlay_buffer *b,unsigned char byte); int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count); +unsigned char *ob_append_space(overlay_buffer *b,int count); int ob_append_short(overlay_buffer *b,unsigned short v); int ob_append_int(overlay_buffer *b,unsigned int v); int ob_patch_rfs(overlay_buffer *b,int l); @@ -1068,6 +1069,7 @@ typedef struct sockaddr_mdp { unsigned char sid[SID_SIZE]; unsigned int port; } sockaddr_mdp; +unsigned char *keyring_get_nm_bytes(sockaddr_mdp *priv,sockaddr_mdp *pub); #define MDP_TYPE_MASK 0xff #define MDP_FLAG_MASK 0xff00 @@ -1146,6 +1148,8 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp, int ob_bcopy(overlay_buffer *b,int from, int to, int len); int ob_setbyte(overlay_buffer *b,int ofs,unsigned char value); +int urandombytes(unsigned char *x,unsigned long long xlen); + #ifdef MALLOC_PARANOIA #define malloc(X) _serval_debug_malloc(X,__FILE__,__FUNCTION__,__LINE__) #define calloc(X,Y) _serval_debug_calloc(X,Y,__FILE__,__FUNCTION__,__LINE__)