sodiumTest

Log

Files

Refs

README

client2.c (5872B)

     1 #! /usr/bin/env sheepy
     2 
     3 /*
     4 client2 and server2 are following request/response model.
     5 
     6 Steps in client
     7 - generate keys
     8 - connect to server
     9 - send signature, identity public key, session public key, write 0 for id key and signature if
    10   the client doesn't have an id
    11 - check server identity with signature, store nonce
    12 - store remote public key
    13 - send encrypted message
    14 - get encrypted response
    15 
    16 Steps in server
    17 - generate keys
    18 - start event loop
    19 - store remote session public key
    20 - check identity with signature
    21 - send signature, identity public key, session public key, nonce
    22 - get encrypted message
    23 - send encrypted response
    24 
    25 This version uses secret/symetric key encryption after the key exchange.
    26 
    27 For more nonce randomness, the server can provide the first nonce with the public keys when the session opens
    28 
    29 >> when sending large amount of data, use stream functions
    30 >> use aead functions only if there are metadata
    31 >> privelege separation: have a seperate process with the secrets
    32 >> to change id: sign id public key, sign id public key and signature and the new id public key with the new id key
    33 
    34 */
    35 
    36 #include "libsheepyObject.h"
    37 
    38 #include <sys/types.h>
    39 #include <sys/socket.h>
    40 #include <netdb.h>
    41 #include <netinet/in.h>
    42 
    43 #include "sel.h"
    44 
    45 int main(int ac, char **av) {
    46 
    47   setLogMode(LOG_FUNC);
    48 
    49   if (not selInit()) ret 1;
    50 
    51   // generate keys
    52   bool isKnownServer                      = no;
    53   const char* remoteIdFilename            = "remoteId.bin";
    54   bool sendClientIdToServer               = yes;
    55 
    56   newKeys();
    57   newSignKeys();
    58 
    59   // load server id if possible
    60   if (isPath(remoteIdFilename)) {
    61     logI("Server is known");
    62     pError0(bLReadFile(remoteIdFilename, remoteId, sizeof(remoteId)));
    63     isKnownServer = yes;
    64   }
    65 
    66         char *msg = "Hello";
    67 
    68         logI("message: %s\n", msg);
    69 
    70 
    71   // connect to server
    72   int sock;
    73   struct sockaddr_in server;
    74   struct hostent *hp;
    75   int mysock;
    76   char buf[128*1024];
    77   int rval;
    78 
    79   sock = socket(AF_INET, SOCK_STREAM, 0);
    80   if (sock < 0){
    81     perror("Failed to create socket");
    82   }
    83 
    84   server.sin_family = AF_INET;
    85 
    86   hp = gethostbyname(av[1]);
    87   if (hp==0) {
    88     perror("gethostbyname failed");
    89     close(sock);
    90     exit(1);
    91   }
    92 
    93   memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
    94   server.sin_port = htons(5000);
    95 
    96   if (connect(sock,(struct sockaddr *) &server, sizeof(server))){
    97     perror("connect failed");
    98     close(sock);
    99     exit(1);
   100   }
   101 
   102   void snd(void *buf, size_t sz) {
   103     logVarG(sz);
   104     if(send(sock, buf, sz, 0) < 0){
   105       perror("send failed");
   106       close(sock);
   107       exit(1);
   108     }
   109   }
   110 
   111   void rcv(void *buf, size_t sz) {
   112     while (sz > 0) {
   113       rval = recv(sock, buf, sz, MSG_WAITALL);
   114       if (rval < 0) {
   115         perror("reading message");
   116         exit(1);
   117       }
   118       else if (rval == 0) {
   119         logI("Ending connection");
   120         close(sock);
   121         exit(0);
   122       }
   123       sz -= rval;
   124     }
   125     logVarG(rval);
   126   }
   127 
   128   // send public key
   129   // store remote public key
   130   void getServerPublicKey(void) {
   131     u8 exchange[crypto_sign_BYTES + crypto_sign_PUBLICKEYBYTES + sizeof(keys.publicKey)] = init0Var;
   132     memcpy(exchange+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES, &keys.publicKey, sizeof(keys.publicKey));
   133     if (not sendClientIdToServer) {
   134       snd(exchange, sizeof(exchange));
   135     }
   136     else {
   137       // send client id
   138       // sign keys with id key
   139       memcpy(exchange+crypto_sign_BYTES, &identityKeys.publicKey, sizeof(identityKeys.publicKey));
   140       u8 signed_message[sizeof(exchange)] = init0Var;
   141       unsigned long long signed_message_len = 0;
   142       crypto_sign(signed_message, &signed_message_len, exchange+crypto_sign_BYTES, sizeof(exchange)-crypto_sign_BYTES, identityKeys.secretKey);
   143       snd(signed_message, sizeof(signed_message));
   144     }
   145 
   146     u8 serverInfo[crypto_sign_BYTES + crypto_sign_PUBLICKEYBYTES + sizeof(keys.remotePublicKey) + crypto_box_NONCEBYTES] = init0Var;
   147     rcv(serverInfo, sizeof(serverInfo));
   148 
   149     // check remote server
   150     u8 unsigned_message[crypto_sign_PUBLICKEYBYTES + sizeof(keys.remotePublicKey) + crypto_box_NONCEBYTES] = init0Var;
   151     unsigned long long unsigned_message_len;
   152     const u8 *idPublicKey = remoteId;
   153     if (not isKnownServer) {
   154       // TOFU - trust on first use
   155       idPublicKey = serverInfo + crypto_sign_BYTES;
   156     }
   157 
   158     if (crypto_sign_open(unsigned_message, &unsigned_message_len, serverInfo, sizeof(serverInfo), idPublicKey) != 0) {
   159       logE("Incorrect signature!");
   160     }
   161     else {
   162       logP("Correct signature");
   163     }
   164 
   165     memcpy(keys.remotePublicKey, unsigned_message + crypto_sign_PUBLICKEYBYTES, sizeof(keys.remotePublicKey));
   166     memcpy(sessionKeys.nonce, unsigned_message + crypto_sign_PUBLICKEYBYTES + sizeof(keys.remotePublicKey), crypto_box_NONCEBYTES);
   167 
   168     if (not isKnownServer) {
   169       // store server id key
   170       pError0(writeFile(remoteIdFilename, (u8*)idPublicKey, crypto_sign_PUBLICKEYBYTES));
   171       logI("Saved server id");
   172     }
   173 
   174     logD("Remote public key");
   175     loghex(keys.remotePublicKey, sizeof(keys.remotePublicKey));
   176     put;
   177 
   178     // key exchange
   179     if (not computeSharedKeys(CLIENT_SESSION_KEYS)) {
   180       logE("Invalid server key");
   181       exit(1);
   182     }
   183   }
   184 
   185   getServerPublicKey();
   186 
   187   // send encrypted message
   188   // *nonce is incremented by after sending or receiving a message
   189   // *nonce is allowed to wrap from the max value
   190   u64 *nonce = (u64*)sessionKeys.nonce;
   191   logVarG(*nonce);
   192   int len = selEncrypt(buf, sizeof(buf), msg, strlen(msg));
   193   inc *nonce;
   194 
   195   logVarG(len);
   196 
   197   snd(&len, sizeof(len));
   198   snd(buf, len);
   199 
   200   // get encrypted response
   201   rcv(&len, sizeof(len));
   202   rcv(buf, len);
   203 
   204         u8 decrypted[1000];
   205   logVarG(*nonce);
   206   len = selDecrypt(decrypted, sizeof(decrypted), buf, len);
   207   inc *nonce;
   208 
   209   if (!len) {
   210     logE("failed to decrypt");
   211     ret 1;
   212   }
   213 
   214   decrypted[len] = 0;
   215 
   216   logI("decrypted: %s", decrypted);
   217 
   218   close(sock);
   219 }
   220 // vim: set expandtab ts=2 sw=2: