💾 Archived View for gmi.noulin.net › gitRepositories › sodiumTest › file › client3.c.gmi captured on 2023-07-10 at 18:14:38. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

sodiumTest

Log

Files

Refs

README

client3.c (6245B)

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