1 /* 2 * Copyright 2008-2016 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_lcl.h" 12 #include <string.h> 13 14 #if !defined(STRICT_ALIGNMENT) && !defined(PEDANTIC) 15 # define STRICT_ALIGNMENT 0 16 #endif 17 18 void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, 19 size_t len, const void *key, 20 unsigned char ivec[16], block128_f block) 21 { 22 size_t n; 23 const unsigned char *iv = ivec; 24 25 if (len == 0) 26 return; 27 28 #if !defined(OPENSSL_SMALL_FOOTPRINT) 29 if (STRICT_ALIGNMENT && 30 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 31 while (len >= 16) { 32 for (n = 0; n < 16; ++n) 33 out[n] = in[n] ^ iv[n]; 34 (*block) (out, out, key); 35 iv = out; 36 len -= 16; 37 in += 16; 38 out += 16; 39 } 40 } else { 41 while (len >= 16) { 42 for (n = 0; n < 16; n += sizeof(size_t)) 43 *(size_t *)(out + n) = 44 *(size_t *)(in + n) ^ *(size_t *)(iv + n); 45 (*block) (out, out, key); 46 iv = out; 47 len -= 16; 48 in += 16; 49 out += 16; 50 } 51 } 52 #endif 53 while (len) { 54 for (n = 0; n < 16 && n < len; ++n) 55 out[n] = in[n] ^ iv[n]; 56 for (; n < 16; ++n) 57 out[n] = iv[n]; 58 (*block) (out, out, key); 59 iv = out; 60 if (len <= 16) 61 break; 62 len -= 16; 63 in += 16; 64 out += 16; 65 } 66 memcpy(ivec, iv, 16); 67 } 68 69 void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, 70 size_t len, const void *key, 71 unsigned char ivec[16], block128_f block) 72 { 73 size_t n; 74 union { 75 size_t t[16 / sizeof(size_t)]; 76 unsigned char c[16]; 77 } tmp; 78 79 if (len == 0) 80 return; 81 82 #if !defined(OPENSSL_SMALL_FOOTPRINT) 83 if (in != out) { 84 const unsigned char *iv = ivec; 85 86 if (STRICT_ALIGNMENT && 87 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 88 while (len >= 16) { 89 (*block) (in, out, key); 90 for (n = 0; n < 16; ++n) 91 out[n] ^= iv[n]; 92 iv = in; 93 len -= 16; 94 in += 16; 95 out += 16; 96 } 97 } else if (16 % sizeof(size_t) == 0) { /* always true */ 98 while (len >= 16) { 99 size_t *out_t = (size_t *)out, *iv_t = (size_t *)iv; 100 101 (*block) (in, out, key); 102 for (n = 0; n < 16 / sizeof(size_t); n++) 103 out_t[n] ^= iv_t[n]; 104 iv = in; 105 len -= 16; 106 in += 16; 107 out += 16; 108 } 109 } 110 memcpy(ivec, iv, 16); 111 } else { 112 if (STRICT_ALIGNMENT && 113 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { 114 unsigned char c; 115 while (len >= 16) { 116 (*block) (in, tmp.c, key); 117 for (n = 0; n < 16; ++n) { 118 c = in[n]; 119 out[n] = tmp.c[n] ^ ivec[n]; 120 ivec[n] = c; 121 } 122 len -= 16; 123 in += 16; 124 out += 16; 125 } 126 } else if (16 % sizeof(size_t) == 0) { /* always true */ 127 while (len >= 16) { 128 size_t c, *out_t = (size_t *)out, *ivec_t = (size_t *)ivec; 129 const size_t *in_t = (const size_t *)in; 130 131 (*block) (in, tmp.c, key); 132 for (n = 0; n < 16 / sizeof(size_t); n++) { 133 c = in_t[n]; 134 out_t[n] = tmp.t[n] ^ ivec_t[n]; 135 ivec_t[n] = c; 136 } 137 len -= 16; 138 in += 16; 139 out += 16; 140 } 141 } 142 } 143 #endif 144 while (len) { 145 unsigned char c; 146 (*block) (in, tmp.c, key); 147 for (n = 0; n < 16 && n < len; ++n) { 148 c = in[n]; 149 out[n] = tmp.c[n] ^ ivec[n]; 150 ivec[n] = c; 151 } 152 if (len <= 16) { 153 for (; n < 16; ++n) 154 ivec[n] = in[n]; 155 break; 156 } 157 len -= 16; 158 in += 16; 159 out += 16; 160 } 161 } 162