/* ctr_mode.c - TinyCrypt CTR mode implementation */ /* * Copyright (C) 2017 by Intel Corporation, 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 Intel Corporation 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 OWNER 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. */ #include #include #include int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, uint8_t *ctr, uint32_t *blk_off, const TCAesKeySched_t sched) { uint8_t buffer[TC_AES_BLOCK_SIZE]; uint8_t nonce[TC_AES_BLOCK_SIZE]; unsigned int block_num; unsigned int i; uint32_t n; /* input sanity check: */ if (out == (uint8_t *) 0 || in == (uint8_t *) 0 || ctr == (uint8_t *) 0 || blk_off == (uint32_t *) 0 || sched == (TCAesKeySched_t) 0 || inlen == 0 || outlen == 0 || outlen != inlen) { return TC_CRYPTO_FAIL; } /* copy the ctr to the nonce */ (void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); /* select the last 4 bytes of the nonce to be incremented */ block_num = (nonce[12] << 24) | (nonce[13] << 16) | (nonce[14] << 8) | (nonce[15]); n = *blk_off; for (i = 0; i < inlen; ++i) { if (n == 0) { /* encrypt data using the current nonce */ if (tc_aes_encrypt(buffer, nonce, sched)) { block_num++; nonce[12] = (uint8_t)(block_num >> 24); nonce[13] = (uint8_t)(block_num >> 16); nonce[14] = (uint8_t)(block_num >> 8); nonce[15] = (uint8_t)(block_num); } else { return TC_CRYPTO_FAIL; } } /* update the output */ *out++ = buffer[n] ^ *in++; n = (n + 1) % TC_AES_BLOCK_SIZE; } *blk_off = n; /* update the counter */ ctr[12] = nonce[12]; ctr[13] = nonce[13]; ctr[14] = nonce[14]; ctr[15] = nonce[15]; return TC_CRYPTO_SUCCESS; }