/* * 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 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 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; }