From 1e64efb4c0d659ce9a436366040cf866df462f94 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Wed, 22 Jun 2016 04:39:58 +0300 Subject: [PATCH] sxt: added ciphers stubs, wrappers and API impl.; --- include/sxt/ciphers.h | 5 +- include/sxt/lcrypt.h | 4 + sxt/Makefile.am | 2 +- sxt/bcrypt.c | 1 + sxt/ciphers.c | 180 ++++++++++++++++++++++++++++++++++++++++++ sxt/core.c | 1 + sxt/ed25519.c | 1 + sxt/lcrypt.c | 173 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 364 insertions(+), 3 deletions(-) create mode 100644 sxt/ciphers.c create mode 100644 sxt/lcrypt.c diff --git a/include/sxt/ciphers.h b/include/sxt/ciphers.h index 9759404..818d295 100644 --- a/include/sxt/ciphers.h +++ b/include/sxt/ciphers.h @@ -27,7 +27,7 @@ #ifndef __SXT_CIPHERS_H__ #define __SXT_CIPHERS_H__ -#include +struct _lcrypt_cipher_priv; struct __cipher_stype; @@ -59,9 +59,10 @@ typedef struct __cipher_stype { /* API for workout with table */ sxt_cipher_t *sxt_cipher_get(const char *); +void sxt_cipher_free(sxt_cipher_t *); /* a little bit of internals TODO: move it out there */ int sxt_cipher_add(const char *name, unsigned int blksize, unsigned int keylen, - struct _cipher_ops *f); + unsigned int keysz, struct _cipher_ops *f); /* API to deal with cipher */ const char *sxt_cipher_getname(sxt_cipher_t *); diff --git a/include/sxt/lcrypt.h b/include/sxt/lcrypt.h index 2b66b39..5f40267 100644 --- a/include/sxt/lcrypt.h +++ b/include/sxt/lcrypt.h @@ -39,6 +39,10 @@ struct _lcrypt_cipher_priv void *ivec; }; +int lcrypt_init_ciphers(void); +void lcrypt_cleanup_keystub(sxt_cipher_t *); +int lcrypt_alloc_keystub(sxt_cipher_t *); + /* sxt wrapper around random numbers */ int sxt_get_random(void *data, int len, int pseudo); diff --git a/sxt/Makefile.am b/sxt/Makefile.am index 76440c3..6debbc9 100644 --- a/sxt/Makefile.am +++ b/sxt/Makefile.am @@ -15,7 +15,7 @@ lib_LTLIBRARIES = libsxt.la libsxt_la_SOURCES = \ core.c base64.c misc.c safebuffer.c rdb.c ppkp_ops.c \ - bcrypt.c blowfish.c \ + bcrypt.c blowfish.c ciphers.c lcrypt.c \ fe25519.c ge25519.c sc25519.c ed25519.c libsxt_la_LDFLAGS = diff --git a/sxt/bcrypt.c b/sxt/bcrypt.c index 70cc005..3d92ff0 100644 --- a/sxt/bcrypt.c +++ b/sxt/bcrypt.c @@ -27,6 +27,7 @@ #endif #include +#include #include #ifndef SHA512_DIGEST_LENGTH diff --git a/sxt/ciphers.c b/sxt/ciphers.c new file mode 100644 index 0000000..40d217d --- /dev/null +++ b/sxt/ciphers.c @@ -0,0 +1,180 @@ +/* + * Secure eXtended Message Passing framework + * Secure eXtended Transport layer implementation: (libsxt) + * - very similar to SSH2/TLS + * - using already proven and tested crypto algos + * - better than TLS for message passing + * + * Ciphers API + * + * (c) Alexander Vdolainen 2016 + * + * libsxmp is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libsxmp 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 program. If not, see ."; + * + */ + +#include +#include + +#include +#include +#include + +#include + +static list_head_t cipher_listhead; +static int __list_initied = 0; + +struct cipher_tbl { + sxt_cipher_t *cipher; + list_node_t node; +}; + +static sxt_cipher_t *__alloc_cipher(const char *name, unsigned int blksize, + unsigned int keylen, struct _cipher_ops *f) +{ + sxt_cipher_t *n = NULL; + + if(!name || !f) return NULL; + + if(!(n = malloc(sizeof(sxt_cipher_t)))) return NULL; + if(!(n->name = strdup(name))) { + free(n); + return NULL; + } + + n->blksize = blksize; + n->keylen = keylen; + n->f = f; + + return n; +} + +/* API for workout with table */ +sxt_cipher_t *sxt_cipher_get(const char *name) +{ + sxt_cipher_t *sc = NULL, *nn = NULL; + struct cipher_tbl *entry = NULL; + list_node_t *iter, *siter; + + if(!__list_initied || !name) return NULL; + + list_for_each_safe(&cipher_listhead, iter, siter) { + entry = list_entry(iter, struct cipher_tbl, node); + sc = entry->cipher; + if(!strcmp(sxt_cipher_getname(sc), name)) return sc; + else sc = NULL; + } + + if(sc) { + nn = malloc(sizeof(sxt_cipher_t)); + if(!nn) return NULL; + else memset(nn, 0, sizeof(sxt_cipher_t)); + nn->name = sc->name; + nn->f = sc->f; + nn->blksize = sc->blksize; + nn->keylen = sc->keylen; + nn->keysize = sc->keysize; + if(lcrypt_alloc_keystub(nn)) { + free(nn); + nn = NULL; + } + } + + return nn; +} + +void sxt_cipher_free(sxt_cipher_t *c) +{ + if(!c) return; + + lcrypt_cleanup_keystub(c); + memset(c, 0, sizeof(sxt_cipher_t)); + free(c); + + return; +} + +int sxt_cipher_add(const char *name, unsigned int blksize, unsigned int keylen, + unsigned int keysz, struct _cipher_ops *f) +{ + struct cipher_tbl *ne = NULL; + sxt_cipher_t *nec = NULL; + + /* take a check for head first */ + if(!__list_initied) { + list_init_head(&cipher_listhead); + __list_initied = 1; + } + + if(!f) return SXT_EINVAL; + if(!(ne = malloc(sizeof(struct cipher_tbl)))) return SXT_ENOMEM; + else { + nec = __alloc_cipher(name, blksize, keylen, f); + if(!nec) { + free(ne); + return SXT_ENOMEM; + } else nec->keysize = keysz; + + ne->cipher = nec; + list_init_node(&ne->node); + list_add2tail(&cipher_listhead, &ne->node); + } + + return SXT_SUCCESS; +} + +/* API to deal with cipher */ +const char *sxt_cipher_getname(sxt_cipher_t *c) +{ + if(!c || !c->name) return "none"; + else return c->name; +} + +int sxt_cipher_set_encrypt_key(sxt_cipher_t *c, void *key, void *ivec) +{ + if(!c || !key) return SXT_EINVAL; + if(!ivec) return SXT_EINVAL; + + return c->f->set_encrypt_key(c, key, ivec); +} + +int sxt_cipher_set_decrypt_key(sxt_cipher_t *c, void *key, void *ivec) +{ + if(!c || !key) return SXT_EINVAL; + if(!ivec) return SXT_EINVAL; + + return c->f->set_decrypt_key(c, key, ivec); +} + +void sxt_cipher_encrypt(sxt_cipher_t *c, void *in, void *out, unsigned long size) +{ + if(!c || !size) return; + if(!in || !out) return; + + c->f->encrypt(c, in, out, size); + + return; +} + +void sxt_cipher_decrypt(sxt_cipher_t *c, void *in, void *out, unsigned long size) +{ + if(!c || !size) return; + if(!in || !out) return; + + c->f->decrypt(c, in, out, size); + + return; +} + diff --git a/sxt/core.c b/sxt/core.c index 3b7ad3e..2cf948b 100644 --- a/sxt/core.c +++ b/sxt/core.c @@ -53,6 +53,7 @@ #include +#include #include int sxt_init(void) diff --git a/sxt/ed25519.c b/sxt/ed25519.c index fb82b34..9faea8e 100644 --- a/sxt/ed25519.c +++ b/sxt/ed25519.c @@ -9,6 +9,7 @@ #include #include #include +#include #include /* diff --git a/sxt/lcrypt.c b/sxt/lcrypt.c new file mode 100644 index 0000000..84c3902 --- /dev/null +++ b/sxt/lcrypt.c @@ -0,0 +1,173 @@ +/* + * Secure eXtended Message Passing framework + * Secure eXtended Transport layer implementation: (libsxt) + * - very similar to SSH2/TLS + * - using already proven and tested crypto algos + * - better than TLS for message passing + * + * libressl/openssl wrappers + * + * (c) Alexander Vdolainen 2016 + * + * libsxmp is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libsxmp 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 program. If not, see ."; + * + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* internals */ +static int __alloc_keybuf(sxt_cipher_t *c) +{ + if(!c->lcp) return -1; + if(!(c->lcp->key = malloc(c->keylen))) return -1; + + return 0; +} + +void lcrypt_cleanup_keystub(sxt_cipher_t *c) +{ + if(!c || !c->lcp) return; + + memset(c->lcp->key, 0, sizeof(c->keylen)); + free(c->lcp->key); + + memset(c->lcp, 0, sizeof(struct _lcrypt_cipher_priv)); + free(c->lcp); + + return; +} + +int lcrypt_alloc_keystub(sxt_cipher_t *c) +{ + if(!c) return -1; + + if(!(c->lcp = malloc(sizeof(struct _lcrypt_cipher_priv)))) return -1; + else memset(c->lcp, 0, sizeof(struct _lcrypt_cipher_priv)); + + return 0; +} + +/* AES */ +static int aes_set_encrypt_key(sxt_cipher_t *cipher, void *key, void *ivec) +{ + if (cipher->lcp->key == NULL) { + if (__alloc_keybuf(cipher) < 0) return -1; + + if(AES_set_encrypt_key(key, cipher->keysize, cipher->lcp->key) < 0) { + if(cipher->lcp->key) { + memset(cipher->lcp->key, 0, cipher->keylen); + free(cipher->lcp->key); + cipher->lcp->key = NULL; + } + return -1; + } + } + + cipher->lcp->ivec = ivec; + + return 0; +} + +static int aes_set_decrypt_key(sxt_cipher_t *cipher, void *key, void *ivec) +{ + if (cipher->lcp->key == NULL) { + if (__alloc_keybuf(cipher) < 0) return -1; + + if (AES_set_decrypt_key(key, cipher->keysize, cipher->lcp->key) < 0) { + if(cipher->lcp->key) { + memset(cipher->lcp->key, 0, cipher->keylen); + free(cipher->lcp->key); + cipher->lcp->key = NULL; + } + return -1; + } + } + + cipher->lcp->ivec = ivec; + + return 0; +} + +static void aes_encrypt(sxt_cipher_t *cipher, void *in, void *out, + unsigned long len) +{ + AES_cbc_encrypt(in, out, len, cipher->lcp->key, cipher->lcp->ivec, AES_ENCRYPT); +} + +static void aes_decrypt(sxt_cipher_t *cipher, void *in, void *out, + unsigned long len) +{ + AES_cbc_encrypt(in, out, len, cipher->lcp->key, cipher->lcp->ivec, AES_DECRYPT); +} + +static struct _cipher_ops aes_ops = { + .set_encrypt_key = aes_set_encrypt_key, + .set_decrypt_key = aes_set_decrypt_key, + .encrypt = aes_encrypt, + .decrypt = aes_decrypt, +}; + +/* blow fish */ +static int blowfish_set_key(sxt_cipher_t *cipher, void *key, void *ivec) +{ + if (cipher->lcp->key == NULL) { + if (__alloc_keybuf(cipher) < 0) return -1; + + BF_set_key(cipher->lcp->key, 16, key); + } + cipher->lcp->ivec = ivec; + + return 0; +} + +static void blowfish_encrypt(sxt_cipher_t *cipher, void *in, + void *out, unsigned long len) +{ + BF_cbc_encrypt(in, out, len, cipher->lcp->key, cipher->lcp->ivec, BF_ENCRYPT); +} + +static void blowfish_decrypt(sxt_cipher_t *cipher, void *in, + void *out, unsigned long len) +{ + BF_cbc_encrypt(in, out, len, cipher->lcp->key, cipher->lcp->ivec, BF_DECRYPT); +} + +static struct _cipher_ops bf_ops = { + .set_encrypt_key = blowfish_set_key, + .set_decrypt_key = blowfish_set_key, + .encrypt = blowfish_encrypt, + .decrypt = blowfish_decrypt, +}; + +int lcrypt_init_ciphers(void) +{ + int r = 0; + + r = sxt_cipher_add("blowfish-cbc", 8, sizeof(BF_KEY), 128, &bf_ops); + r = sxt_cipher_add("aes128-cbc", 16, sizeof(AES_KEY), 128, &aes_ops); + r = sxt_cipher_add("aes192-cbc", 16, sizeof(AES_KEY), 192, &aes_ops); + r = sxt_cipher_add("aes256-cbc", 16, sizeof(AES_KEY), 256, &aes_ops); + + return r; +} +