You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libsxmp/sxt/ciphers.c

181 lines
4.1 KiB
C

/*
* 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 <avdolainen@zoho.com>
*
* 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 <http://www.gnu.org/licenses/>.";
*
*/
#include <stdlib.h>
#include <string.h>
#include <sxt/errno.h>
#include <sxt/ciphers.h>
#include <sxt/lcrypt.h>
#include <tdata/list.h>
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)) break;
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;
}