1 /* 2 * Copyright 2008-2020 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 memcpy(ivec, iv, 16); 73 } 74 75 void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, 76 size_t len, const void *key, 77 unsigned char ivec[16], block128_f block) 78 { 79 size_t n; 80 union { 81 size_t t[16 / sizeof(size_t)]; 82 unsigned char c[16]; 83 } tmp; 84 85 if (len == 0) 86 return; 87 88 #if !defined(OPENSSL_SMALL_FOOTPRINT) 89 if (in != out) { 90 const unsigned char *iv = ivec; 91 92 if (STRICT_ALIGNMENT && 93 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 94 while (len >= 16) { 95 (*block) (in, out, key); 96 for (n = 0; n < 16; ++n) 97 out[n] ^= iv[n]; 98 iv = in; 99 len -= 16; 100 in += 16; 101 out += 16; 102 } 103 } else if (16 % sizeof(size_t) == 0) { /* always true */ 104 while (len >= 16) { 105 size_t_aX *out_t = (size_t_aX *)out; 106 size_t_aX *iv_t = (size_t_aX *)iv; 107 108 (*block) (in, out, key); 109 for (n = 0; n < 16 / sizeof(size_t); n++) 110 out_t[n] ^= iv_t[n]; 111 iv = in; 112 len -= 16; 113 in += 16; 114 out += 16; 115 } 116 } 117 memcpy(ivec, iv, 16); 118 } else { 119 if (STRICT_ALIGNMENT && 120 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 121 unsigned char c; 122 while (len >= 16) { 123 (*block) (in, tmp.c, key); 124 for (n = 0; n < 16; ++n) { 125 c = in[n]; 126 out[n] = tmp.c[n] ^ ivec[n]; 127 ivec[n] = c; 128 } 129 len -= 16; 130 in += 16; 131 out += 16; 132 } 133 } else if (16 % sizeof(size_t) == 0) { /* always true */ 134 while (len >= 16) { 135 size_t c; 136 size_t_aX *out_t = (size_t_aX *)out; 137 size_t_aX *ivec_t = (size_t_aX *)ivec; 138 const size_t_aX *in_t = (const size_t_aX *)in; 139 140 (*block) (in, tmp.c, key); 141 for (n = 0; n < 16 / sizeof(size_t); n++) { 142 c = in_t[n]; 143 out_t[n] = tmp.t[n] ^ ivec_t[n]; 144 ivec_t[n] = c; 145 } 146 len -= 16; 147 in += 16; 148 out += 16; 149 } 150 } 151 } 152 #endif 153 while (len) { 154 unsigned char c; 155 (*block) (in, tmp.c, key); 156 for (n = 0; n < 16 && n < len; ++n) { 157 c = in[n]; 158 out[n] = tmp.c[n] ^ ivec[n]; 159 ivec[n] = c; 160 } 161 if (len <= 16) { 162 for (; n < 16; ++n) 163 ivec[n] = in[n]; 164 break; 165 } 166 len -= 16; 167 in += 16; 168 out += 16; 169 } 170 } 171