Home | History | Annotate | Download | only in modes
      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  */
     50 
     51 #include "modes.h"
     52 #include <string.h>
     53 
     54 #ifndef MODES_DEBUG
     55 # ifndef NDEBUG
     56 #  define NDEBUG
     57 # endif
     58 #endif
     59 #include <assert.h>
     60 
     61 #define STRICT_ALIGNMENT 1
     62 #if defined(__i386) || defined(__i386__) || \
     63     defined(__x86_64) || defined(__x86_64__) || \
     64     defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
     65     defined(__s390__) || defined(__s390x__)
     66 #  undef STRICT_ALIGNMENT
     67 #  define STRICT_ALIGNMENT 0
     68 #endif
     69 
     70 void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
     71 			size_t len, const void *key,
     72 			unsigned char ivec[16], block128_f block)
     73 {
     74 	size_t n;
     75 	const unsigned char *iv = ivec;
     76 
     77 	assert(in && out && key && ivec);
     78 
     79 #if !defined(OPENSSL_SMALL_FOOTPRINT)
     80 	if (STRICT_ALIGNMENT &&
     81 	    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
     82 		while (len>=16) {
     83 			for(n=0; n<16; ++n)
     84 				out[n] = in[n] ^ iv[n];
     85 			(*block)(out, out, key);
     86 			iv = out;
     87 			len -= 16;
     88 			in  += 16;
     89 			out += 16;
     90 		}
     91 	} else {
     92 		while (len>=16) {
     93 			for(n=0; n<16; n+=sizeof(size_t))
     94 				*(size_t*)(out+n) =
     95 				*(size_t*)(in+n) ^ *(size_t*)(iv+n);
     96 			(*block)(out, out, key);
     97 			iv = out;
     98 			len -= 16;
     99 			in  += 16;
    100 			out += 16;
    101 		}
    102 	}
    103 #endif
    104 	while (len) {
    105 		for(n=0; n<16 && n<len; ++n)
    106 			out[n] = in[n] ^ iv[n];
    107 		for(; n<16; ++n)
    108 			out[n] = iv[n];
    109 		(*block)(out, out, key);
    110 		iv = out;
    111 		if (len<=16) break;
    112 		len -= 16;
    113 		in  += 16;
    114 		out += 16;
    115 	}
    116 	memcpy(ivec,iv,16);
    117 }
    118 
    119 void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
    120 			size_t len, const void *key,
    121 			unsigned char ivec[16], block128_f block)
    122 {
    123 	size_t n;
    124 	union { size_t align; unsigned char c[16]; } tmp;
    125 
    126 	assert(in && out && key && ivec);
    127 
    128 #if !defined(OPENSSL_SMALL_FOOTPRINT)
    129 	if (in != out) {
    130 		const unsigned char *iv = ivec;
    131 
    132 		if (STRICT_ALIGNMENT &&
    133 		    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
    134 			while (len>=16) {
    135 				(*block)(in, out, key);
    136 				for(n=0; n<16; ++n)
    137 					out[n] ^= iv[n];
    138 				iv = in;
    139 				len -= 16;
    140 				in  += 16;
    141 				out += 16;
    142 			}
    143 		}
    144 		else {
    145 			while (len>=16) {
    146 				(*block)(in, out, key);
    147 				for(n=0; n<16; n+=sizeof(size_t))
    148 					*(size_t *)(out+n) ^= *(size_t *)(iv+n);
    149 				iv = in;
    150 				len -= 16;
    151 				in  += 16;
    152 				out += 16;
    153 			}
    154 		}
    155 		memcpy(ivec,iv,16);
    156 	} else {
    157 		if (STRICT_ALIGNMENT &&
    158 		    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
    159 			unsigned char c;
    160 			while (len>=16) {
    161 				(*block)(in, tmp.c, key);
    162 				for(n=0; n<16; ++n) {
    163 					c = in[n];
    164 					out[n] = tmp.c[n] ^ ivec[n];
    165 					ivec[n] = c;
    166 				}
    167 				len -= 16;
    168 				in  += 16;
    169 				out += 16;
    170 			}
    171 		}
    172 		else {
    173 			size_t c;
    174 			while (len>=16) {
    175 				(*block)(in, tmp.c, key);
    176 				for(n=0; n<16; n+=sizeof(size_t)) {
    177 					c = *(size_t *)(in+n);
    178 					*(size_t *)(out+n) =
    179 					*(size_t *)(tmp.c+n) ^ *(size_t *)(ivec+n);
    180 					*(size_t *)(ivec+n) = c;
    181 				}
    182 				len -= 16;
    183 				in  += 16;
    184 				out += 16;
    185 			}
    186 		}
    187 	}
    188 #endif
    189 	while (len) {
    190 		unsigned char c;
    191 		(*block)(in, tmp.c, key);
    192 		for(n=0; n<16 && n<len; ++n) {
    193 			c = in[n];
    194 			out[n] = tmp.c[n] ^ ivec[n];
    195 			ivec[n] = c;
    196 		}
    197 		if (len<=16) {
    198 			for (; n<16; ++n)
    199 				ivec[n] = in[n];
    200 			break;
    201 		}
    202 		len -= 16;
    203 		in  += 16;
    204 		out += 16;
    205 	}
    206 }
    207