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