/* ------------------------------------------------------------------------ libcperm - A library for creating random cpermutations. Copyright (c) 2014, Lance Alt This file is part of libcperm. This library 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. 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, see . ------------------------------------------------------------------------ */ #include #include #include #include #include #include "cperm.h" #include "cperm-internal.h" #include "prefix.h" #include "cycle.h" #include "ciphers/rc5.h" #include "ciphers/speck.h" int cperm_errno = 0; /* List of available cpermutation modes. Each mode has an identifier, and four functions. See ModeFuncs struct for description of the fields. */ static struct ModeFuncs available_modes[] = { { PERM_MODE_PREFIX, perm_prefix_create, perm_prefix_next, perm_prefix_get, perm_prefix_destroy }, { PERM_MODE_CYCLE, perm_cycle_create, perm_cycle_next, perm_cycle_get, perm_cycle_destroy }, { PERM_MODE_ERROR, NULL, NULL } }; /* List of available ciphers. Each cipher has an identifier, and four functions. See CipherFuncs struct for description of the fields. */ static struct CipherFuncs available_ciphers[] = { { PERM_CIPHER_RC5, perm_rc5_create, perm_rc5_enc, perm_rc5_dec, perm_rc5_destroy }, { PERM_CIPHER_SPECK, perm_speck_create, perm_speck_enc, perm_speck_dec, perm_speck_destroy }, { PERM_CIPHER_ERROR, NULL, NULL }, }; struct cperm_t* cperm_create(uint32_t range, PermMode m, PermCipher a, uint8_t* key, int key_len) { struct cperm_t* perm = calloc(sizeof(*perm), 1); if(!perm) { cperm_errno = PERM_ERROR_NOMEM; return NULL; } perm->range = range; /* Locate the selected mode and initialize function pointers */ struct ModeFuncs* mf = available_modes; while(mf->mode != PERM_MODE_ERROR) { if(mf->mode == m) { perm->mode = mf; break; } mf++; } if(perm->mode == NULL) { free(perm); cperm_errno = PERM_ERROR_MODE_NOT_SUPP; return NULL; } /* Locate the selected cipher and initialize function pointers */ struct CipherFuncs* cf = available_ciphers; while(cf->algo != PERM_CIPHER_ERROR) { if(cf->algo == a) { perm->cipher = cf; break; } cf++; } /* Set the cipher key */ cperm_set_key(perm, key, key_len); /* Initialize the cipher */ if(0 != perm->cipher->create(perm)) { free(perm); return NULL; } /* Initialize the cpermutation mode */ if(0 != perm->mode->create(perm)) { perm->cipher->destroy(perm); free(perm); return NULL; } return perm; } int cperm_set_key(struct cperm_t* perm, const unsigned char* key, uint16_t length) { if(!perm) { return PERM_ERROR_BAD_HANDLE; } if(perm->cipher) { perm->cipher->destroy(perm); } perm->key = malloc(length); memcpy(perm->key, key, length); perm->key_len = length; return 0; } void cperm_destroy(struct cperm_t* perm) { if(perm) { perm->mode->destroy(perm); perm->cipher->destroy(perm); if(perm->key) { free(perm->key); } free(perm); } } int cperm_next(struct cperm_t* perm, uint32_t* ct) { if(!perm) { return PERM_ERROR_BAD_HANDLE; } perm->position++; return perm->mode->next(perm, ct); } int cperm_enc(struct cperm_t* perm, uint32_t pt, uint32_t* ct) { if(!perm) { return PERM_ERROR_BAD_HANDLE; } return perm->mode->get(perm, pt, ct); } uint32_t cperm_dec(struct cperm_t* cperm, uint32_t pt) { return 0; } int cperm_get_last_error() { return cperm_errno; } int cperm_reset(struct cperm_t* perm) { if(!perm) { return PERM_ERROR_BAD_HANDLE; } perm->mode->destroy(perm); perm->mode->create(perm); return 1; } uint32_t cperm_get_range(const struct cperm_t* perm) { if(!perm) { return 0; } return perm->range; } uint32_t cperm_get_position(const struct cperm_t* perm) { if(!perm) { return 0; } return perm->position; }