"Fossies" - the Fresh Open Source Software Archive

Member "n2n-3.0/src/transform_cc20.c" (27 Oct 2021, 4938 Bytes) of package /linux/misc/n2n-3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "transform_cc20.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8_vs_3.0.

    1 /**
    2  * (C) 2007-21 - ntop.org and contributors
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 3 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not see see <http://www.gnu.org/licenses/>
   16  *
   17  */
   18 
   19 
   20 #include "n2n.h"
   21 
   22 
   23 // ChaCha20 plaintext preamble
   24 #define CC20_PREAMBLE_SIZE    (CC20_IV_SIZE)
   25 
   26 
   27 typedef struct transop_cc20 {
   28     cc20_context_t       *ctx;
   29 } transop_cc20_t;
   30 
   31 
   32 static int transop_deinit_cc20 (n2n_trans_op_t *arg) {
   33 
   34     transop_cc20_t *priv = (transop_cc20_t *)arg->priv;
   35 
   36     if(priv->ctx)
   37         cc20_deinit(priv->ctx);
   38 
   39     if(priv)
   40         free(priv);
   41 
   42     return 0;
   43 }
   44 
   45 
   46 // the ChaCha20 packet format consists of
   47 //
   48 //  - a 128-bit random iv
   49 //  - encrypted payload
   50 //
   51 //  [IIII|DDDDDDDDDDDDDDDDDDDDD]
   52 //       |<---- encrypted ---->|
   53 //
   54 static int transop_encode_cc20 (n2n_trans_op_t *arg,
   55                                 uint8_t *outbuf,
   56                                 size_t out_len,
   57                                 const uint8_t *inbuf,
   58                                 size_t in_len,
   59                                 const uint8_t *peer_mac) {
   60 
   61     int len = -1;
   62     transop_cc20_t *priv = (transop_cc20_t *)arg->priv;
   63 
   64     if(in_len <= N2N_PKT_BUF_SIZE) {
   65         if((in_len + CC20_PREAMBLE_SIZE) <= out_len) {
   66             size_t idx = 0;
   67 
   68             traceEvent(TRACE_DEBUG, "encode_cc20 %lu bytes", in_len);
   69 
   70             // full iv sized random value (128 bit)
   71             encode_uint64(outbuf, &idx, n2n_rand());
   72             encode_uint64(outbuf, &idx, n2n_rand());
   73 
   74             len = in_len;
   75             cc20_crypt(outbuf + CC20_PREAMBLE_SIZE,
   76                        inbuf,
   77                        in_len,
   78                        outbuf, /* iv */
   79                        priv->ctx);
   80 
   81             // size of datacarried in UDP
   82             len += CC20_PREAMBLE_SIZE;
   83         } else
   84             traceEvent(TRACE_ERROR, "encode_cc20 outbuf too small.");
   85     } else
   86         traceEvent(TRACE_ERROR, "encode_cc20 inbuf too big to encrypt.");
   87 
   88     return len;
   89 }
   90 
   91 
   92 // see transop_encode_cc20 for packet format
   93 static int transop_decode_cc20 (n2n_trans_op_t *arg,
   94                                 uint8_t *outbuf,
   95                                 size_t out_len,
   96                                 const uint8_t *inbuf,
   97                                 size_t in_len,
   98                                 const uint8_t *peer_mac) {
   99 
  100     int len = 0;
  101     transop_cc20_t *priv = (transop_cc20_t *)arg->priv;
  102 
  103     if(((in_len - CC20_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in assembly */
  104        && (in_len >= CC20_PREAMBLE_SIZE)) {                /* has at least iv */
  105 
  106         traceEvent(TRACE_DEBUG, "decode_cc20 %lu bytes", in_len);
  107 
  108         len = (in_len - CC20_PREAMBLE_SIZE);
  109 
  110         cc20_crypt(outbuf,
  111                    inbuf + CC20_PREAMBLE_SIZE,
  112                    in_len,
  113                    inbuf, /* iv */
  114                    priv->ctx);
  115     } else
  116         traceEvent(TRACE_ERROR, "decode_cc20 inbuf wrong size (%ul) to decrypt.", in_len);
  117 
  118     return len;
  119 }
  120 
  121 
  122 static int setup_cc20_key (transop_cc20_t *priv, const uint8_t *password, ssize_t password_len) {
  123 
  124     uint8_t key_mat[CC20_KEY_BYTES];
  125 
  126     // the input key always gets hashed to make a more unpredictable and more complete use of the key space
  127     pearson_hash_256(key_mat, password, password_len);
  128 
  129     if(cc20_init(key_mat, &(priv->ctx))) {
  130         traceEvent(TRACE_ERROR, "setup_cc20_key setup unsuccessful");
  131         return -1;
  132     }
  133 
  134     traceEvent(TRACE_DEBUG, "setup_cc20_key completed");
  135 
  136     return 0;
  137 }
  138 
  139 
  140 static void transop_tick_cc20 (n2n_trans_op_t *arg, time_t now) {
  141 
  142     // no tick action
  143 }
  144 
  145 
  146 // ChaCha20 initialization function
  147 int n2n_transop_cc20_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
  148 
  149     transop_cc20_t *priv;
  150     const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
  151     size_t encrypt_key_len = strlen(conf->encrypt_key);
  152 
  153     memset(ttt, 0, sizeof(*ttt));
  154     ttt->transform_id = N2N_TRANSFORM_ID_CHACHA20;
  155 
  156     ttt->tick         = transop_tick_cc20;
  157     ttt->deinit       = transop_deinit_cc20;
  158     ttt->fwd          = transop_encode_cc20;
  159     ttt->rev          = transop_decode_cc20;
  160 
  161     priv = (transop_cc20_t*)calloc(1, sizeof(transop_cc20_t));
  162     if(!priv) {
  163         traceEvent(TRACE_ERROR, "cannot allocate transop_cc20_t memory");
  164         return -1;
  165     }
  166     ttt->priv = priv;
  167 
  168     // setup the cipher and key
  169     return setup_cc20_key(priv, encrypt_key, encrypt_key_len);
  170 }