1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ==================================================================== 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met: 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer. 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer in 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the documentation and/or other materials provided with the 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * distribution. 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * software must display the following acknowledgment: 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * endorse or promote products derived from this software without 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * prior written permission. For written permission, please contact 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * openssl-core@openssl.org. 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL" 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * nor may "OpenSSL" appear in their names without prior written 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * permission of the OpenSSL Project. 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * acknowledgment: 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ==================================================================== */ 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <assert.h> 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h" 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len, 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const void *key, uint8_t ivec[16], 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley block128_f block) { 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t n; 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *iv = ivec; 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 61f4e427204234da139fd0585def4b4e22502e33f0Adam Langley assert(key != NULL && ivec != NULL); 62f4e427204234da139fd0585def4b4e22502e33f0Adam Langley assert(len == 0 || (in != NULL && out != NULL)); 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (STRICT_ALIGNMENT && 65d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan ((uintptr_t)in | (uintptr_t)out | (uintptr_t)ivec) % sizeof(size_t) != 66d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan 0) { 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len >= 16) { 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (n = 0; n < 16; ++n) { 69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out[n] = in[n] ^ iv[n]; 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*block)(out, out, key); 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iv = out; 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len -= 16; 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in += 16; 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out += 16; 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len >= 16) { 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (n = 0; n < 16; n += sizeof(size_t)) { 80d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan store_word_le(out + n, load_word_le(in + n) ^ load_word_le(iv + n)); 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*block)(out, out, key); 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iv = out; 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len -= 16; 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in += 16; 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out += 16; 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len) { 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (n = 0; n < 16 && n < len; ++n) { 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out[n] = in[n] ^ iv[n]; 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (; n < 16; ++n) { 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out[n] = iv[n]; 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*block)(out, out, key); 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iv = out; 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (len <= 16) { 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley break; 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len -= 16; 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in += 16; 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out += 16; 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 10769939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan OPENSSL_memcpy(ivec, iv, 16); 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len, 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const void *key, uint8_t ivec[16], 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley block128_f block) { 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t n; 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley union { 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t t[16 / sizeof(size_t)]; 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t c[16]; 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } tmp; 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 119f4e427204234da139fd0585def4b4e22502e33f0Adam Langley assert(key != NULL && ivec != NULL); 120f4e427204234da139fd0585def4b4e22502e33f0Adam Langley assert(len == 0 || (in != NULL && out != NULL)); 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 122f4e427204234da139fd0585def4b4e22502e33f0Adam Langley const uintptr_t inptr = (uintptr_t) in; 123f4e427204234da139fd0585def4b4e22502e33f0Adam Langley const uintptr_t outptr = (uintptr_t) out; 1248f860b133896bf655e4342ecefe692d52df81d48Robert Sloan // If |in| and |out| alias, |in| must be ahead. 125f4e427204234da139fd0585def4b4e22502e33f0Adam Langley assert(inptr >= outptr || inptr + len <= outptr); 126f4e427204234da139fd0585def4b4e22502e33f0Adam Langley 127f4e427204234da139fd0585def4b4e22502e33f0Adam Langley if ((inptr >= 32 && outptr <= inptr - 32) || inptr < outptr) { 1288f860b133896bf655e4342ecefe692d52df81d48Robert Sloan // If |out| is at least two blocks behind |in| or completely disjoint, there 1298f860b133896bf655e4342ecefe692d52df81d48Robert Sloan // is no need to decrypt to a temporary block. 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *iv = ivec; 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (STRICT_ALIGNMENT && 133d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan ((uintptr_t)in | (uintptr_t)out | (uintptr_t)ivec) % sizeof(size_t) != 134d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan 0) { 135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len >= 16) { 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*block)(in, out, key); 137e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (n = 0; n < 16; ++n) { 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out[n] ^= iv[n]; 139e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iv = in; 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len -= 16; 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in += 16; 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out += 16; 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1458f860b133896bf655e4342ecefe692d52df81d48Robert Sloan } else if (16 % sizeof(size_t) == 0) { // always true 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len >= 16) { 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*block)(in, out, key); 148d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan for (n = 0; n < 16; n += sizeof(size_t)) { 149d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan store_word_le(out + n, load_word_le(out + n) ^ load_word_le(iv + n)); 150e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley iv = in; 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len -= 16; 153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in += 16; 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out += 16; 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 15769939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan OPENSSL_memcpy(ivec, iv, 16); 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 1598f860b133896bf655e4342ecefe692d52df81d48Robert Sloan // |out| is less than two blocks behind |in|. Decrypting an input block 1608f860b133896bf655e4342ecefe692d52df81d48Robert Sloan // directly to |out| would overwrite a ciphertext block before it is used as 1618f860b133896bf655e4342ecefe692d52df81d48Robert Sloan // the next block's IV. Decrypt to a temporary block instead. 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (STRICT_ALIGNMENT && 163d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan ((uintptr_t)in | (uintptr_t)out | (uintptr_t)ivec) % sizeof(size_t) != 164d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan 0) { 165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t c; 166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len >= 16) { 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*block)(in, tmp.c, key); 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (n = 0; n < 16; ++n) { 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley c = in[n]; 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out[n] = tmp.c[n] ^ ivec[n]; 171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ivec[n] = c; 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len -= 16; 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in += 16; 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out += 16; 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 1778f860b133896bf655e4342ecefe692d52df81d48Robert Sloan } else if (16 % sizeof(size_t) == 0) { // always true 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len >= 16) { 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*block)(in, tmp.c, key); 180d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan for (n = 0; n < 16; n += sizeof(size_t)) { 181d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan size_t c = load_word_le(in + n); 182d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan store_word_le(out + n, 183d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan tmp.t[n / sizeof(size_t)] ^ load_word_le(ivec + n)); 184d5c2215355e1ae960be386b0d69aed228102cdaeRobert Sloan store_word_le(ivec + n, c); 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len -= 16; 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in += 16; 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out += 16; 189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len) { 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t c; 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*block)(in, tmp.c, key); 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (n = 0; n < 16 && n < len; ++n) { 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley c = in[n]; 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out[n] = tmp.c[n] ^ ivec[n]; 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ivec[n] = c; 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (len <= 16) { 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (; n < 16; ++n) { 203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ivec[n] = in[n]; 204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley break; 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len -= 16; 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in += 16; 209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley out += 16; 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 212