diff options
| author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2019-08-02 19:12:34 +0200 | 
|---|---|---|
| committer | Sander Vrijders <sander@ouroboros.rocks> | 2019-08-03 12:10:57 +0200 | 
| commit | 9e8d603d14561095fb8d08871319a315d3bf6763 (patch) | |
| tree | 7a87c212fcd642a8696145b4246a4fc4cf964e10 /src/lib | |
| parent | 8a37ffbf8c0776a38f2de18a63e885383960ee68 (diff) | |
| download | ouroboros-9e8d603d14561095fb8d08871319a315d3bf6763.tar.gz ouroboros-9e8d603d14561095fb8d08871319a315d3bf6763.zip | |
lib: Add per-message encryption with OpenSSL
This adds a per-message symmetric encryption using the OpenSSL
library. At flow allocation, an Elliptic Curve Diffie-Hellman exchange
is performed to derive a shared secret, which is then hashed using
SHA3-256 to be used as a key for symmetric AES-256 encryption. Each
message on an encrypted flow adds a small crypto header that includes
a random 128-bit Initialization Vector (IV). If the server does not
have OpenSSL enabled, the flow allocation will fail with an -ECRYPT
error.
Future optimizations are to piggyback the public keys on the flow
allocation message, and to enable per-flow encryption that maintains
the context of the encryption over multiple packets and doesn't
require sending IVs.
Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/config.h.in | 4 | ||||
| -rw-r--r-- | src/lib/crypt.c | 490 | ||||
| -rw-r--r-- | src/lib/dev.c | 121 | ||||
| -rw-r--r-- | src/lib/qosspec.proto | 1 | ||||
| -rw-r--r-- | src/lib/sockets.c | 6 | 
5 files changed, 605 insertions, 17 deletions
| diff --git a/src/lib/config.h.in b/src/lib/config.h.in index 3e5a7b1e..70261cab 100644 --- a/src/lib/config.h.in +++ b/src/lib/config.h.in @@ -24,6 +24,10 @@  #cmakedefine HAVE_LIBGCRYPT  #cmakedefine HAVE_OPENSSL +#ifdef HAVE_OPENSSL +#define HAVE_ENCRYPTION +#endif +  #define SYS_MAX_FLOWS       @SYS_MAX_FLOWS@  #cmakedefine                SHM_RBUFF_LOCKLESS diff --git a/src/lib/crypt.c b/src/lib/crypt.c new file mode 100644 index 00000000..94f1b50e --- /dev/null +++ b/src/lib/crypt.c @@ -0,0 +1,490 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2019 + * + * Elliptic curve Diffie-Hellman key exchange and + * AES encryption for flows using OpenSSL + * + *    Dimitri Staessens <dimitri@ouroboros.rocks> + *    Sander Vrijders   <sander@ouroboros.rocks> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#ifdef HAVE_OPENSSL + +#include <openssl/evp.h> +#include <openssl/ec.h> +#include <openssl/pem.h> + +#define MSGBUFSZ 2048 +#define IVSZ     16 +#define DH_TIMEO 2 /* seconds */ +/* SYMMKEYSZ defined in dev.c */ + +/* + * Derive the common secret from + *  your public key pair (kp) + *  the remote public key (pub). + * Store it in a preallocated buffer (s). + */ +static int __openssl_ecdh_derive_secret(EVP_PKEY * kp, +                                        EVP_PKEY * pub, +                                        uint8_t *  s) +{ +        EVP_PKEY_CTX * ctx; +        int            ret; +        uint8_t *      secret; +        size_t         secret_len; + +        ctx = EVP_PKEY_CTX_new(kp, NULL); +        if (ctx == NULL) +                goto fail_new; + +        ret = EVP_PKEY_derive_init(ctx); +        if (ret != 1) +                goto fail_ctx; + +        ret = EVP_PKEY_derive_set_peer(ctx, pub); +        if (ret != 1) +                goto fail_ctx; + +        ret = EVP_PKEY_derive(ctx, NULL, &secret_len); +        if (ret != 1) +                goto fail_ctx; + +        if (secret_len < SYMMKEYSZ) +                goto fail_ctx; + +        secret = OPENSSL_malloc(secret_len); +        if (secret == NULL) +                goto fail_ctx; + +        ret = EVP_PKEY_derive(ctx, secret, &secret_len); +        if (ret != 1) +                goto fail_derive; + +        /* Hash the secret for use as AES key. */ +        mem_hash(HASH_SHA3_256, s, secret, secret_len); + +        OPENSSL_free(secret); +        EVP_PKEY_CTX_free(ctx); + +        return 0; + + fail_derive: +        OPENSSL_free(s); + fail_ctx: +        EVP_PKEY_CTX_free(ctx); + fail_new: +        return -ECRYPT; +} + +static int __openssl_ecdh_gen_key(EVP_PKEY ** kp) +{ +        EVP_PKEY_CTX * ctx    = NULL; +        EVP_PKEY_CTX * kctx   = NULL; +        EVP_PKEY *     params = NULL; +        int            ret; + +        ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); +        if (ctx == NULL) +                goto fail_new_id; + +        ret = EVP_PKEY_paramgen_init(ctx); +        if (ret != 1) +                goto fail_paramgen; + +        ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_X9_62_prime256v1); +        if (ret != 1) +                goto fail_paramgen; + +        ret = EVP_PKEY_paramgen(ctx, ¶ms); +        if (ret != 1) +                goto fail_paramgen; + +        kctx = EVP_PKEY_CTX_new(params, NULL); +        if (kctx == NULL) +                goto fail_keygen_init; + +        ret = EVP_PKEY_keygen_init(kctx); +        if (ret != 1) +                goto fail_keygen; + +        ret = EVP_PKEY_keygen(kctx, kp); +        if (ret != 1) +                goto fail_keygen; + +        EVP_PKEY_free(params); +        EVP_PKEY_CTX_free(kctx); +        EVP_PKEY_CTX_free(ctx); + +        return 0; + + fail_keygen: +        EVP_PKEY_CTX_free(kctx); + fail_keygen_init: +        EVP_PKEY_free(params); + fail_paramgen: +        EVP_PKEY_CTX_free(ctx); + fail_new_id: +        return -ECRYPT; +} + +/* ECDH from the server side. */ +static int openssl_ecdh_srv(int       fd, +                            uint8_t * s) +{ +        EVP_PKEY *      kp    = NULL; +        EVP_PKEY *      pub   = NULL; +        uint8_t         buf[MSGBUFSZ]; +        ssize_t         len; +        int             buf_sz; +        uint8_t *       pos; +        struct timespec timeo = {DH_TIMEO,0}; + +        assert(s != NULL); + +        (void) fd; +        (void) s; + +        if (__openssl_ecdh_gen_key(&kp) < 0) +                goto fail_gen_key; + +        fccntl(fd, FLOWSRCVTIMEO, &timeo); + +        len = flow_read(fd, buf, MSGBUFSZ); +        if (len < 0) { +                fccntl(fd, FLOWSRCVTIMEO, NULL); +                goto fail_get_key; +        } + +        fccntl(fd, FLOWSRCVTIMEO, NULL); + +        pos = buf; /* i2d_PUBKEY increments the pointer, don't use buf! */ +        pub = d2i_PUBKEY(NULL, (const uint8_t **) &pos, (long) len); + +        pos = buf; /* i2d_PUBKEY increments the pointer, don't use buf! */ +        buf_sz = i2d_PUBKEY(kp, &pos); +        if (buf_sz < 0) +                goto fail_get_key; + +        if (flow_write(fd, buf, (size_t) buf_sz) < 0) +                goto fail_get_key; + +        if (__openssl_ecdh_derive_secret(kp, pub, s) < 0) +                goto fail_get_key; + +        EVP_PKEY_free(kp); +        EVP_PKEY_free(pub); + +        return 0; + + fail_get_key: +        EVP_PKEY_free(kp); + fail_gen_key: +        return -ECRYPT; +} + +/* ECDH from the client side. */ +static int openssl_ecdh_clt(int       fd, +                            uint8_t * s) +{ +        EVP_PKEY *      kp    = NULL; +        EVP_PKEY *      pub   = NULL; +        uint8_t         buf[MSGBUFSZ]; +        int             buf_sz; +        uint8_t *       pos; +        ssize_t         len; +        struct timespec timeo = {DH_TIMEO,0}; + +        assert(s != NULL); + +        (void) fd; +        (void) s; + +        if (__openssl_ecdh_gen_key(&kp) < 0) +                goto fail_gen_key; + +        pos = buf; /* i2d_PUBKEY increments the pointer, don't use buf! */ +        buf_sz = i2d_PUBKEY(kp, &pos); +        if (buf_sz < 0) +                goto fail_get_key; + +        if (flow_write(fd, buf, (size_t) buf_sz) < 0) +                goto fail_get_key; + +        fccntl(fd, FLOWSRCVTIMEO, &timeo); + +        len = flow_read(fd, buf, MSGBUFSZ); +        if (len < 0) { +                fccntl(fd, FLOWSRCVTIMEO, NULL); +                goto fail_get_key; +        } + +        fccntl(fd, FLOWSRCVTIMEO, NULL); + +        pos = buf; /* i2d_PUBKEY increments the pointer, don't use buf! */ +        pub = d2i_PUBKEY(NULL, (const uint8_t **) &pos, (long) len); + +        if (__openssl_ecdh_derive_secret(kp, pub, s) < 0) +                goto fail_get_key; + +        EVP_PKEY_free(kp); +        EVP_PKEY_free(pub); + +        return 0; + + fail_get_key: +        EVP_PKEY_free(kp); + fail_gen_key: +        return -ECRYPT; +} + +/* + * AES encryption calls. If FRCT is disabled, we should generate a + * 128-bit random IV and append it to the packet.  If the flow is + * reliable, we could initialize the context once, and consider the + * stream a single encrypted message to avoid initializing the + * encryption context for each packet. + */ + +static int openssl_encrypt(struct flow *        f, +                           struct shm_du_buff * sdb) +{ +        uint8_t * out; +        uint8_t * in; +        uint8_t * head; +        uint8_t   iv[IVSZ]; +        int       in_sz; +        int       out_sz; +        int       tmp_sz; +        int       ret; + +        in = shm_du_buff_head(sdb); +        in_sz = shm_du_buff_tail(sdb) - in; + +        if (random_buffer(iv, IVSZ) < 0) +                goto fail_iv; + +        out = malloc(in_sz + EVP_MAX_BLOCK_LENGTH); +        if (out == NULL) +                goto fail_iv; + +        EVP_CIPHER_CTX_reset(f->ctx); + +        ret = EVP_EncryptInit_ex(f->ctx, +                                 EVP_aes_256_cbc(), +                                 NULL, +                                 f->key, +                                 iv); +        if (ret != 1) +                goto fail_encrypt_init; + +        ret = EVP_EncryptUpdate(f->ctx, out, &tmp_sz, in, in_sz); +        if (ret != 1) +                goto fail_encrypt; + +        out_sz = tmp_sz; +        ret =  EVP_EncryptFinal_ex(f->ctx, out + tmp_sz, &tmp_sz); +        if (ret != 1) +                goto fail_encrypt; + +        out_sz += tmp_sz; + +        EVP_CIPHER_CTX_cleanup(f->ctx); + +        assert(out_sz >= in_sz); + +        head = shm_du_buff_head_alloc(sdb, IVSZ); +        if (head == NULL) +                goto fail_encrypt; + +        if (shm_du_buff_tail_alloc(sdb, out_sz - in_sz) == NULL) +                goto fail_tail_alloc; + +        memcpy(head, iv, IVSZ); +        memcpy(in, out, out_sz); + +        free(out); + +        return 0; + + fail_tail_alloc: +        shm_du_buff_head_release(sdb, IVSZ); + fail_encrypt: +        EVP_CIPHER_CTX_cleanup(f->ctx); + fail_encrypt_init: +        free(out); + fail_iv: +        return -ECRYPT; +} + +static int openssl_decrypt(struct flow *        f, +                           struct shm_du_buff * sdb) +{ +        uint8_t * in; +        uint8_t * out; +        uint8_t   iv[IVSZ]; +        int       ret; +        int       out_sz; +        int       in_sz; +        int       tmp_sz; + +        in = shm_du_buff_head_release(sdb, IVSZ); + +        memcpy(iv, in, IVSZ); + +        in = shm_du_buff_head(sdb); + +        in_sz = shm_du_buff_tail(sdb) - shm_du_buff_head(sdb); + +        out = malloc(in_sz); +        if (out == NULL) +                goto fail_malloc; + +        EVP_CIPHER_CTX_reset(f->ctx); + +        ret = EVP_DecryptInit_ex(f->ctx, +                                 EVP_aes_256_cbc(), +                                 NULL, +                                 f->key, +                                 iv); +        if (ret != 1) +                goto fail_decrypt_init; + +        ret = EVP_DecryptUpdate(f->ctx, out, &tmp_sz, in, in_sz); +        if (ret != 1) +                goto fail_decrypt; + +        out_sz = tmp_sz; + +        ret = EVP_DecryptFinal_ex(f->ctx, out + tmp_sz, &tmp_sz); +        if (ret != 1) +                goto fail_decrypt; + +        out_sz += tmp_sz; + +        assert(out_sz <= in_sz); + +        shm_du_buff_tail_release(sdb, in_sz - out_sz); + +        memcpy(in, out, out_sz); + +        free(out); + +        return 0; + + fail_decrypt: +        EVP_CIPHER_CTX_cleanup(f->ctx); + fail_decrypt_init: +        free(out); + fail_malloc: +        return -ECRYPT; + +} + +static int openssl_crypt_init(struct flow * f) +{ +        f->ctx = EVP_CIPHER_CTX_new(); +        if (f->ctx == NULL) +                goto fail_new; + +        return 0; + + fail_new: +        return -ECRYPT; +} + +static void openssl_crypt_fini(struct flow * f) +{ +        EVP_CIPHER_CTX_free(f->ctx); +        f->ctx = NULL; +} + +#endif /* HAVE_OPENSSL */ + +static int crypt_dh_srv(int       fd, +                        uint8_t * s) +{ +#ifdef HAVE_OPENSSL +        return openssl_ecdh_clt(fd, s); +#else +        (void) fd; + +        memset(s, 0, SYMMKEYSZ); + +        return -ECRYPT; +#endif +} + +static int crypt_dh_clt(int       fd, +                        uint8_t * s) +{ +#ifdef HAVE_OPENSSL +        return openssl_ecdh_srv(fd, s); +#else +        (void) fd; + +        memset(s, 0, SYMMKEYSZ); + +        return 0; +#endif +} + +static int crypt_encrypt(struct flow *        f, +                         struct shm_du_buff * sdb) +{ +#ifdef HAVE_OPENSSL +        return openssl_encrypt(f, sdb); +#else +        (void) f; +        (void) sdb; + +        return 0; +#endif +} + +static int crypt_decrypt(struct flow *        f, +                         struct shm_du_buff * sdb) +{ +#ifdef HAVE_OPENSSL +        return openssl_decrypt(f, sdb); +#else +        (void) f; +        (void) sdb; + +        return 0; +#endif +} + + +static int crypt_init(struct flow * f) +{ +#ifdef HAVE_OPENSSL +        return openssl_crypt_init(f); +#else +        (void) f; + +        return 0; +#endif +} + +static void crypt_fini(struct flow * f) +{ +#ifdef HAVE_OPENSSL +        openssl_crypt_fini(f); +#else +        (void) f; +#endif +} diff --git a/src/lib/dev.c b/src/lib/dev.c index 229a1470..1e0a177d 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -29,6 +29,7 @@  #include "config.h"  #include <ouroboros/hash.h> +#include <ouroboros/cacep.h>  #include <ouroboros/errno.h>  #include <ouroboros/dev.h>  #include <ouroboros/ipcp-dev.h> @@ -59,6 +60,8 @@  #define DONE_PART    -2  #define CRCLEN    (sizeof(uint32_t)) +#define SECMEMSZ  16384 +#define SYMMKEYSZ  32  struct flow_set {          size_t   idx; @@ -98,6 +101,9 @@ struct flow {          qosspec_t             spec;          ssize_t               part_idx; +        void *                ctx; +        uint8_t               key[SYMMKEYSZ]; +          pid_t                 pid;          bool                  snd_timesout; @@ -237,6 +243,8 @@ static void flow_clear(int fd)          ai.flows[fd].pid      = -1;  } +#include "crypt.c" +  static void flow_fini(int fd)  {          assert(fd >= 0 && fd < SYS_MAX_FLOWS); @@ -266,6 +274,9 @@ static void flow_fini(int fd)          if (ai.flows[fd].frcti != NULL)                  frcti_destroy(ai.flows[fd].frcti); +        if (ai.flows[fd].spec.cypher_s > 0) +                crypt_fini(&ai.flows[fd]); +          flow_clear(fd);  } @@ -286,15 +297,15 @@ static int flow_init(int       flow_id,          ai.flows[fd].rx_rb = shm_rbuff_open(ai.pid, flow_id);          if (ai.flows[fd].rx_rb == NULL) -                goto fail; +                goto fail_rx_rb;          ai.flows[fd].tx_rb = shm_rbuff_open(pid, flow_id);          if (ai.flows[fd].tx_rb == NULL) -                goto fail; +                goto fail_tx_rb;          ai.flows[fd].set = shm_flow_set_open(pid);          if (ai.flows[fd].set == NULL) -                goto fail; +                goto fail_set;          ai.flows[fd].flow_id  = flow_id;          ai.flows[fd].oflags   = FLOWFDEFAULT; @@ -302,6 +313,9 @@ static int flow_init(int       flow_id,          ai.flows[fd].part_idx = NO_PART;          ai.flows[fd].spec     = qs; +        if (qs.cypher_s > 0 && crypt_init(&ai.flows[fd]) < 0) +                goto fail_crypt; +          ai.ports[flow_id].fd = fd;          port_set_state(&ai.ports[flow_id], PORT_ID_ASSIGNED); @@ -310,8 +324,14 @@ static int flow_init(int       flow_id,          return fd; - fail: -        flow_fini(fd); + fail_crypt: +        shm_flow_set_close(ai.flows[fd].set); + fail_set: +        shm_rbuff_close(ai.flows[fd].tx_rb); + fail_tx_rb: +        shm_rbuff_close(ai.flows[fd].rx_rb); + fail_rx_rb: +        bmp_release(ai.fds, fd);   fail_fds:          pthread_rwlock_unlock(&ai.lock);          return err; @@ -344,12 +364,11 @@ static void init(int     argc,          ai.pid = getpid();  #ifdef HAVE_LIBGCRYPT -        if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) { +        if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) {                  if (!gcry_check_version(GCRYPT_VERSION))                          goto fail_fds; -                /* Needs to be enabled when we add encryption. */ -                gcry_control (GCRYCTL_DISABLE_SECMEM, 0); -                gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); +                gcry_control(GCRYCTL_DISABLE_SECMEM, 0); +                gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);          }  #endif          ai.fds = bmp_create(PROG_MAX_FLOWS - PROG_RES_FDS, PROG_RES_FDS); @@ -550,8 +569,8 @@ int flow_accept(qosspec_t *             qs,          if (ai.flows[fd].spec.in_order != 0) {                  ai.flows[fd].frcti = frcti_create(fd);                  if (ai.flows[fd].frcti == NULL) { -                        flow_fini(fd);                          pthread_rwlock_unlock(&ai.lock); +                        flow_dealloc(fd);                          return -ENOMEM;                  }          } @@ -561,6 +580,31 @@ int flow_accept(qosspec_t *             qs,          pthread_rwlock_unlock(&ai.lock); +        /* TODO: piggyback public keys at flow allocation. */ +        if (ai.flows[fd].spec.cypher_s > 0) { +                uint8_t  key[SYMMKEYSZ]; +                uint16_t tmp; + +                pthread_rwlock_wrlock(&ai.lock); + +                tmp = ai.flows[fd].spec.cypher_s; +                ai.flows[fd].spec.cypher_s = 0; + +                pthread_rwlock_unlock(&ai.lock); + +                if (crypt_dh_srv(fd, key) < 0) { +                        flow_dealloc(fd); +                        return -ECRYPT; +                } + +                pthread_rwlock_wrlock(&ai.lock); + +                ai.flows[fd].spec.cypher_s = tmp; +                memcpy(ai.flows[fd].key, key, SYMMKEYSZ); + +                pthread_rwlock_unlock(&ai.lock); +        } +          return fd;  } @@ -579,9 +623,9 @@ static int __flow_alloc(const char *            dst,                  qs->ber = 1;  #endif          if (join) -                msg.code    = IRM_MSG_CODE__IRM_FLOW_JOIN; +                msg.code = IRM_MSG_CODE__IRM_FLOW_JOIN;          else -                msg.code    = IRM_MSG_CODE__IRM_FLOW_ALLOC; +                msg.code = IRM_MSG_CODE__IRM_FLOW_ALLOC;          msg.dst     = (char *) dst;          msg.has_pid = true;          msg.pid     = ai.pid; @@ -605,7 +649,7 @@ static int __flow_alloc(const char *            dst,          }          if (recv_msg->result != 0) { -                int res =  recv_msg->result; +                int res = recv_msg->result;                  irm_msg__free_unpacked(recv_msg, NULL);                  return res;          } @@ -630,14 +674,39 @@ static int __flow_alloc(const char *            dst,          if (ai.flows[fd].spec.in_order != 0) {                  ai.flows[fd].frcti = frcti_create(fd);                  if (ai.flows[fd].frcti == NULL) { -                        flow_fini(fd);                          pthread_rwlock_unlock(&ai.lock); +                        flow_dealloc(fd);                          return -ENOMEM;                  }          }          pthread_rwlock_unlock(&ai.lock); +        /* TODO: piggyback public keys at flow allocation. */ +        if (!join && ai.flows[fd].spec.cypher_s > 0) { +                uint8_t  key[SYMMKEYSZ]; +                uint16_t tmp; + +                pthread_rwlock_wrlock(&ai.lock); + +                tmp = ai.flows[fd].spec.cypher_s; +                ai.flows[fd].spec.cypher_s = 0; + +                pthread_rwlock_unlock(&ai.lock); + +                if (crypt_dh_clt(fd, key) < 0) { +                        flow_dealloc(fd); +                        return -ECRYPT; +                } + +                pthread_rwlock_wrlock(&ai.lock); + +                ai.flows[fd].spec.cypher_s = tmp; +                memcpy(ai.flows[fd].key, key, SYMMKEYSZ); + +                pthread_rwlock_unlock(&ai.lock); +        } +          return fd;  } @@ -931,6 +1000,15 @@ ssize_t flow_write(int          fd,                  return -ENOMEM;          } +        pthread_rwlock_wrlock(&ai.lock); +        if (flow->spec.cypher_s > 0) +                if (crypt_encrypt(flow, sdb) < 0) { +                        pthread_rwlock_unlock(&ai.lock); +                        shm_rdrbuff_remove(ai.rdrb, idx); +                        return -ENOMEM; +                } +        pthread_rwlock_unlock(&ai.lock); +          if (flow->spec.ber == 0 && add_crc(sdb) != 0) {                  shm_rdrbuff_remove(ai.rdrb, idx);                  return -ENOMEM; @@ -1009,9 +1087,22 @@ ssize_t flow_read(int    fd,                                          shm_rbuff_read_b(rb, abstime);                                  if (idx < 0)                                          return idx; +                                  sdb = shm_rdrbuff_get(ai.rdrb, idx); -                                if (flow->spec.ber == 0  && chk_crc(sdb) != 0) +                                if (flow->spec.ber == 0 && chk_crc(sdb) != 0) { +                                        shm_rdrbuff_remove(ai.rdrb, idx);                                          continue; +                                } + +                                pthread_rwlock_wrlock(&ai.lock); +                                if (flow->spec.cypher_s > 0) +                                        if (crypt_decrypt(flow, sdb) < 0) { +                                                pthread_rwlock_unlock(&ai.lock); +                                                shm_rdrbuff_remove(ai.rdrb, +                                                                   idx); +                                                return -ENOMEM; +                                        } +                                pthread_rwlock_unlock(&ai.lock);                          } while (frcti_rcv(flow->frcti, sdb) != 0);                  }          } diff --git a/src/lib/qosspec.proto b/src/lib/qosspec.proto index c9e5a6e6..0cbcd41a 100644 --- a/src/lib/qosspec.proto +++ b/src/lib/qosspec.proto @@ -30,4 +30,5 @@ message qosspec_msg {          required uint32 ber          = 5; /* Bit error rate, ppb */          required uint32 in_order     = 6; /* In-order delivery */          required uint32 max_gap      = 7; /* In ms */ +        required uint32 cypher_s     = 8; /* Crypto strength in bits */  }; diff --git a/src/lib/sockets.c b/src/lib/sockets.c index b08bae8e..347e9244 100644 --- a/src/lib/sockets.c +++ b/src/lib/sockets.c @@ -166,7 +166,7 @@ char * ipcp_sock_path(pid_t pid)          return full_name;  } -qosspec_msg_t spec_to_msg(qosspec_t * qs) +qosspec_msg_t spec_to_msg(const qosspec_t * qs)  {          qosspec_t     spec;          qosspec_msg_t msg = QOSSPEC_MSG__INIT; @@ -180,11 +180,12 @@ qosspec_msg_t spec_to_msg(qosspec_t * qs)          msg.ber          = spec.ber;          msg.in_order     = spec.in_order;          msg.max_gap      = spec.max_gap; +        msg.cypher_s     = spec.cypher_s;          return msg;  } -qosspec_t msg_to_spec(qosspec_msg_t * msg) +qosspec_t msg_to_spec(const qosspec_msg_t * msg)  {          qosspec_t     spec; @@ -197,6 +198,7 @@ qosspec_t msg_to_spec(qosspec_msg_t * msg)          spec.ber          = msg->ber;          spec.in_order     = msg->in_order;          spec.max_gap      = msg->max_gap; +        spec.cypher_s     = msg->cypher_s;          return spec;  } | 
