/* * 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 2.1 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 #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; } /* misc */ int lcrypt_reseed(void) { randombytes_stir(); return SXT_SUCCESS; }