20160517 20:51:04 +02:00



/*

20200604 15:33:57 +02:00



* Copyright 20082020 The OpenSSL Project Authors. All Rights Reserved.

20081216 09:39:21 +01:00



*

20181206 13:46:12 +01:00



* Licensed under the Apache License 2.0 (the "License"). You may not use

20160517 20:51:04 +02:00



* this file except in compliance with the License. You can obtain a copy




* in the file LICENSE in the source distribution or at




* https://www.openssl.org/source/license.html

20081216 09:39:21 +01:00



*/








#include <string.h>

20190716 01:46:14 +02:00



#include <openssl/crypto.h>

20190928 00:45:33 +02:00



#include "crypto/modes.h"

20081216 09:39:21 +01:00




20140708 22:24:44 +02:00



#if !defined(STRICT_ALIGNMENT) && !defined(PEDANTIC)

20150122 04:40:55 +01:00



# define STRICT_ALIGNMENT 0

20081216 09:39:21 +01:00



#endif





20180424 21:10:13 +02:00



#if defined(__GNUC__) && !STRICT_ALIGNMENT




typedef size_t size_t_aX __attribute((__aligned__(1)));




#else




typedef size_t size_t_aX;




#endif





20081216 09:39:21 +01:00



void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,

20150122 04:40:55 +01:00



size_t len, const void *key,




unsigned char ivec[16], block128_f block)

20081216 09:39:21 +01:00



{

20150122 04:40:55 +01:00



size_t n;




const unsigned char *iv = ivec;

20081216 09:39:21 +01:00




20170221 01:17:53 +01:00



if (len == 0)




return;





20081216 09:39:21 +01:00



#if !defined(OPENSSL_SMALL_FOOTPRINT)

20150122 04:40:55 +01:00



if (STRICT_ALIGNMENT &&




((size_t)in  (size_t)out  (size_t)ivec) % sizeof(size_t) != 0) {




while (len >= 16) {




for (n = 0; n < 16; ++n)




out[n] = in[n] ^ iv[n];




(*block) (out, out, key);




iv = out;




len = 16;




in += 16;




out += 16;




}




} else {




while (len >= 16) {




for (n = 0; n < 16; n += sizeof(size_t))

20180424 21:10:13 +02:00



*(size_t_aX *)(out + n) =




*(size_t_aX *)(in + n) ^ *(size_t_aX *)(iv + n);

20150122 04:40:55 +01:00



(*block) (out, out, key);




iv = out;




len = 16;




in += 16;




out += 16;




}




}

20081216 09:39:21 +01:00



#endif

20150122 04:40:55 +01:00



while (len) {




for (n = 0; n < 16 && n < len; ++n)




out[n] = in[n] ^ iv[n];




for (; n < 16; ++n)




out[n] = iv[n];




(*block) (out, out, key);




iv = out;




if (len <= 16)




break;




len = 16;




in += 16;




out += 16;




}




memcpy(ivec, iv, 16);

20081216 09:39:21 +01:00



}








void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,

20150122 04:40:55 +01:00



size_t len, const void *key,




unsigned char ivec[16], block128_f block)

20081216 09:39:21 +01:00



{

20150122 04:40:55 +01:00



size_t n;




union {




size_t t[16 / sizeof(size_t)];




unsigned char c[16];




} tmp;

20081216 09:39:21 +01:00




20170221 01:17:53 +01:00



if (len == 0)




return;





20081216 09:39:21 +01:00



#if !defined(OPENSSL_SMALL_FOOTPRINT)

20150122 04:40:55 +01:00



if (in != out) {




const unsigned char *iv = ivec;

20081216 09:39:21 +01:00




20150122 04:40:55 +01:00



if (STRICT_ALIGNMENT &&




((size_t)in  (size_t)out  (size_t)ivec) % sizeof(size_t) != 0) {




while (len >= 16) {




(*block) (in, out, key);




for (n = 0; n < 16; ++n)




out[n] ^= iv[n];




iv = in;




len = 16;




in += 16;




out += 16;




}




} else if (16 % sizeof(size_t) == 0) { /* always true */




while (len >= 16) {

20180424 21:10:13 +02:00



size_t_aX *out_t = (size_t_aX *)out;




size_t_aX *iv_t = (size_t_aX *)iv;

20121105 18:03:39 +01:00




20150122 04:40:55 +01:00



(*block) (in, out, key);




for (n = 0; n < 16 / sizeof(size_t); n++)




out_t[n] ^= iv_t[n];




iv = in;




len = 16;




in += 16;




out += 16;




}




}




memcpy(ivec, iv, 16);




} else {




if (STRICT_ALIGNMENT &&




((size_t)in  (size_t)out  (size_t)ivec) % sizeof(size_t) != 0) {




unsigned char c;




while (len >= 16) {




(*block) (in, tmp.c, key);




for (n = 0; n < 16; ++n) {




c = in[n];




out[n] = tmp.c[n] ^ ivec[n];




ivec[n] = c;




}




len = 16;




in += 16;




out += 16;




}




} else if (16 % sizeof(size_t) == 0) { /* always true */




while (len >= 16) {

20180424 21:10:13 +02:00



size_t c;




size_t_aX *out_t = (size_t_aX *)out;




size_t_aX *ivec_t = (size_t_aX *)ivec;




const size_t_aX *in_t = (const size_t_aX *)in;

20121105 18:03:39 +01:00




20150122 04:40:55 +01:00



(*block) (in, tmp.c, key);




for (n = 0; n < 16 / sizeof(size_t); n++) {




c = in_t[n];




out_t[n] = tmp.t[n] ^ ivec_t[n];




ivec_t[n] = c;




}




len = 16;




in += 16;




out += 16;




}




}




}

20081216 09:39:21 +01:00



#endif

20150122 04:40:55 +01:00



while (len) {




unsigned char c;




(*block) (in, tmp.c, key);




for (n = 0; n < 16 && n < len; ++n) {




c = in[n];




out[n] = tmp.c[n] ^ ivec[n];




ivec[n] = c;




}




if (len <= 16) {




for (; n < 16; ++n)




ivec[n] = in[n];




break;




}




len = 16;




in += 16;




out += 16;




}

20081216 09:39:21 +01:00



}
