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 #ifndef STRICT_ALIGNMENT 56 # define STRICT_ALIGNMENT 0 57 #endif 58 59 void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len, 60 const void *key, uint8_t ivec[16], 61 block128_f block) { 62 size_t n; 63 const uint8_t *iv = ivec; 64 65 assert(key != NULL && ivec != NULL); 66 assert(len == 0 || (in != NULL && out != NULL)); 67 68 if (STRICT_ALIGNMENT && 69 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 70 while (len >= 16) { 71 for (n = 0; n < 16; ++n) { 72 out[n] = in[n] ^ iv[n]; 73 } 74 (*block)(out, out, key); 75 iv = out; 76 len -= 16; 77 in += 16; 78 out += 16; 79 } 80 } else { 81 while (len >= 16) { 82 for (n = 0; n < 16; n += sizeof(size_t)) { 83 *(size_t *)(out + n) = *(size_t *)(in + n) ^ *(size_t *)(iv + n); 84 } 85 (*block)(out, out, key); 86 iv = out; 87 len -= 16; 88 in += 16; 89 out += 16; 90 } 91 } 92 93 while (len) { 94 for (n = 0; n < 16 && n < len; ++n) { 95 out[n] = in[n] ^ iv[n]; 96 } 97 for (; n < 16; ++n) { 98 out[n] = iv[n]; 99 } 100 (*block)(out, out, key); 101 iv = out; 102 if (len <= 16) { 103 break; 104 } 105 len -= 16; 106 in += 16; 107 out += 16; 108 } 109 110 memcpy(ivec, iv, 16); 111 } 112 113 void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len, 114 const void *key, uint8_t ivec[16], 115 block128_f block) { 116 size_t n; 117 union { 118 size_t t[16 / sizeof(size_t)]; 119 uint8_t c[16]; 120 } tmp; 121 122 assert(key != NULL && ivec != NULL); 123 assert(len == 0 || (in != NULL && out != NULL)); 124 125 const uintptr_t inptr = (uintptr_t) in; 126 const uintptr_t outptr = (uintptr_t) out; 127 /* If |in| and |out| alias, |in| must be ahead. */ 128 assert(inptr >= outptr || inptr + len <= outptr); 129 130 if ((inptr >= 32 && outptr <= inptr - 32) || inptr < outptr) { 131 /* If |out| is at least two blocks behind |in| or completely disjoint, there 132 * is no need to decrypt to a temporary block. */ 133 const uint8_t *iv = ivec; 134 135 if (STRICT_ALIGNMENT && 136 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 137 while (len >= 16) { 138 (*block)(in, out, key); 139 for (n = 0; n < 16; ++n) { 140 out[n] ^= iv[n]; 141 } 142 iv = in; 143 len -= 16; 144 in += 16; 145 out += 16; 146 } 147 } else if (16 % sizeof(size_t) == 0) { /* always true */ 148 while (len >= 16) { 149 size_t *out_t = (size_t *)out, *iv_t = (size_t *)iv; 150 151 (*block)(in, out, key); 152 for (n = 0; n < 16 / sizeof(size_t); n++) { 153 out_t[n] ^= iv_t[n]; 154 } 155 iv = in; 156 len -= 16; 157 in += 16; 158 out += 16; 159 } 160 } 161 memcpy(ivec, iv, 16); 162 } else { 163 /* |out| is less than two blocks behind |in|. Decrypting an input block 164 * directly to |out| would overwrite a ciphertext block before it is used as 165 * the next block's IV. Decrypt to a temporary block instead. */ 166 if (STRICT_ALIGNMENT && 167 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 168 uint8_t c; 169 while (len >= 16) { 170 (*block)(in, tmp.c, key); 171 for (n = 0; n < 16; ++n) { 172 c = in[n]; 173 out[n] = tmp.c[n] ^ ivec[n]; 174 ivec[n] = c; 175 } 176 len -= 16; 177 in += 16; 178 out += 16; 179 } 180 } else if (16 % sizeof(size_t) == 0) { /* always true */ 181 while (len >= 16) { 182 size_t c, *out_t = (size_t *)out, *ivec_t = (size_t *)ivec; 183 const size_t *in_t = (const size_t *)in; 184 185 (*block)(in, tmp.c, key); 186 for (n = 0; n < 16 / sizeof(size_t); n++) { 187 c = in_t[n]; 188 out_t[n] = tmp.t[n] ^ ivec_t[n]; 189 ivec_t[n] = c; 190 } 191 len -= 16; 192 in += 16; 193 out += 16; 194 } 195 } 196 } 197 198 while (len) { 199 uint8_t c; 200 (*block)(in, tmp.c, key); 201 for (n = 0; n < 16 && n < len; ++n) { 202 c = in[n]; 203 out[n] = tmp.c[n] ^ ivec[n]; 204 ivec[n] = c; 205 } 206 if (len <= 16) { 207 for (; n < 16; ++n) { 208 ivec[n] = in[n]; 209 } 210 break; 211 } 212 len -= 16; 213 in += 16; 214 out += 16; 215 } 216 } 217