/* * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * - Neither the name of the copyright holders nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * @author Johny Mattsson */ #include "mech.h" #include "sdk-aes.h" #include #include /* ----- AES ---------------------------------------------------------- */ static const struct aes_funcs { void *(*init) (const char *key, size_t keylen); void (*crypt) (void *ctx, const char *in, char *out); void (*deinit) (void *ctx); } aes_funcs[] = { { aes_encrypt_init, aes_encrypt, aes_encrypt_deinit }, { aes_decrypt_init, aes_decrypt, aes_decrypt_deinit } }; static bool do_aes (crypto_op_t *co, bool with_cbc) { const struct aes_funcs *funcs = &aes_funcs[co->op]; void *ctx = funcs->init (co->key, co->keylen); if (!ctx) return false; char iv[AES_BLOCKSIZE] = { 0 }; if (with_cbc && co->ivlen) memcpy (iv, co->iv, co->ivlen < AES_BLOCKSIZE ? co->ivlen : AES_BLOCKSIZE); const char *src = co->data; char *dst = co->out; size_t left = co->datalen; while (left) { char block[AES_BLOCKSIZE] = { 0 }; size_t n = left > AES_BLOCKSIZE ? AES_BLOCKSIZE : left; memcpy (block, src, n); if (with_cbc && co->op == OP_ENCRYPT) { const char *xor = (src == co->data) ? iv : dst - AES_BLOCKSIZE; int i; for (i = 0; i < AES_BLOCKSIZE; ++i) block[i] ^= xor[i]; } funcs->crypt (ctx, block, dst); if (with_cbc && co->op == OP_DECRYPT) { const char *xor = (src == co->data) ? iv : src - AES_BLOCKSIZE; int i; for (i = 0; i < AES_BLOCKSIZE; ++i) dst[i] ^= xor[i]; } left -= n; src += n; dst += n; } funcs->deinit (ctx); return true; } static bool do_aes_ecb (crypto_op_t *co) { return do_aes (co, false); } static bool do_aes_cbc (crypto_op_t *co) { return do_aes (co, true); } /* ----- mechs -------------------------------------------------------- */ static const crypto_mech_t mechs[] = { { "AES-ECB", do_aes_ecb, AES_BLOCKSIZE }, { "AES-CBC", do_aes_cbc, AES_BLOCKSIZE } }; const crypto_mech_t *crypto_encryption_mech (const char *name) { size_t i; for (i = 0; i < sizeof (mechs) / sizeof (mechs[0]); ++i) { const crypto_mech_t *mech = mechs + i; if (strcasecmp (name, mech->name) == 0) return mech; } return 0; }