1 /* 2 * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <openssl/crypto.h> 11 #include "modes_local.h" 12 #include <string.h> 13 14 #if !defined(STRICT_ALIGNMENT) && !defined(PEDANTIC) 15 # define STRICT_ALIGNMENT 0 16 #endif 17 18 #if defined(__GNUC__) && !STRICT_ALIGNMENT 19 typedef size_t size_t_aX __attribute((__aligned__(1))); 20 #else 21 typedef size_t size_t_aX; 22 #endif 23 24 void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, 25 size_t len, const void *key, 26 unsigned char ivec[16], block128_f block) 27 { 28 size_t n; 29 const unsigned char *iv = ivec; 30 31 if (len == 0) 32 return; 33 34 #if !defined(OPENSSL_SMALL_FOOTPRINT) 35 if (STRICT_ALIGNMENT && 36 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 37 while (len >= 16) { 38 for (n = 0; n < 16; ++n) 39 out[n] = in[n] ^ iv[n]; 40 (*block) (out, out, key); 41 iv = out; 42 len -= 16; 43 in += 16; 44 out += 16; 45 } 46 } else { 47 while (len >= 16) { 48 for (n = 0; n < 16; n += sizeof(size_t)) 49 *(size_t_aX *)(out + n) = 50 *(size_t_aX *)(in + n) ^ *(size_t_aX *)(iv + n); 51 (*block) (out, out, key); 52 iv = out; 53 len -= 16; 54 in += 16; 55 out += 16; 56 } 57 } 58 #endif 59 while (len) { 60 for (n = 0; n < 16 && n < len; ++n) 61 out[n] = in[n] ^ iv[n]; 62 for (; n < 16; ++n) 63 out[n] = iv[n]; 64 (*block) (out, out, key); 65 iv = out; 66 if (len <= 16) 67 break; 68 len -= 16; 69 in += 16; 70 out += 16; 71 } 72 if (ivec != iv) 73 memcpy(ivec, iv, 16); 74 } 75 76 void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, 77 size_t len, const void *key, 78 unsigned char ivec[16], block128_f block) 79 { 80 size_t n; 81 union { 82 size_t t[16 / sizeof(size_t)]; 83 unsigned char c[16]; 84 } tmp; 85 86 if (len == 0) 87 return; 88 89 #if !defined(OPENSSL_SMALL_FOOTPRINT) 90 if (in != out) { 91 const unsigned char *iv = ivec; 92 93 if (STRICT_ALIGNMENT && 94 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 95 while (len >= 16) { 96 (*block) (in, out, key); 97 for (n = 0; n < 16; ++n) 98 out[n] ^= iv[n]; 99 iv = in; 100 len -= 16; 101 in += 16; 102 out += 16; 103 } 104 } else if (16 % sizeof(size_t) == 0) { /* always true */ 105 while (len >= 16) { 106 size_t_aX *out_t = (size_t_aX *)out; 107 size_t_aX *iv_t = (size_t_aX *)iv; 108 109 (*block) (in, out, key); 110 for (n = 0; n < 16 / sizeof(size_t); n++) 111 out_t[n] ^= iv_t[n]; 112 iv = in; 113 len -= 16; 114 in += 16; 115 out += 16; 116 } 117 } 118 if (ivec != iv) 119 memcpy(ivec, iv, 16); 120 } else { 121 if (STRICT_ALIGNMENT && 122 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 123 unsigned char c; 124 while (len >= 16) { 125 (*block) (in, tmp.c, key); 126 for (n = 0; n < 16; ++n) { 127 c = in[n]; 128 out[n] = tmp.c[n] ^ ivec[n]; 129 ivec[n] = c; 130 } 131 len -= 16; 132 in += 16; 133 out += 16; 134 } 135 } else if (16 % sizeof(size_t) == 0) { /* always true */ 136 while (len >= 16) { 137 size_t c; 138 size_t_aX *out_t = (size_t_aX *)out; 139 size_t_aX *ivec_t = (size_t_aX *)ivec; 140 const size_t_aX *in_t = (const size_t_aX *)in; 141 142 (*block) (in, tmp.c, key); 143 for (n = 0; n < 16 / sizeof(size_t); n++) { 144 c = in_t[n]; 145 out_t[n] = tmp.t[n] ^ ivec_t[n]; 146 ivec_t[n] = c; 147 } 148 len -= 16; 149 in += 16; 150 out += 16; 151 } 152 } 153 } 154 #endif 155 while (len) { 156 unsigned char c; 157 (*block) (in, tmp.c, key); 158 for (n = 0; n < 16 && n < len; ++n) { 159 c = in[n]; 160 out[n] = tmp.c[n] ^ ivec[n]; 161 ivec[n] = c; 162 } 163 if (len <= 16) { 164 for (; n < 16; ++n) 165 ivec[n] = in[n]; 166 break; 167 } 168 len -= 16; 169 in += 16; 170 out += 16; 171 } 172 } 173