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_local.h" 12 #include <string.h> 13 14 /* 15 * The input and output encrypted as though 128bit cfb mode is being used. 16 * The extra state information to record how much of the 128bit block we have 17 * used is contained in *num; 18 */ 19 void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, 20 size_t len, const void *key, 21 unsigned char ivec[16], int *num, 22 int enc, block128_f block) 23 { 24 unsigned int n; 25 size_t l = 0; 26 27 n = *num; 28 29 if (enc) { 30 #if !defined(OPENSSL_SMALL_FOOTPRINT) 31 if (16 % sizeof(size_t) == 0) { /* always true actually */ 32 do { 33 while (n && len) { 34 *(out++) = ivec[n] ^= *(in++); 35 --len; 36 n = (n + 1) % 16; 37 } 38 # if defined(STRICT_ALIGNMENT) 39 if (((size_t)in | (size_t)out | (size_t)ivec) % 40 sizeof(size_t) != 0) 41 break; 42 # endif 43 while (len >= 16) { 44 (*block) (ivec, ivec, key); 45 for (; n < 16; n += sizeof(size_t)) { 46 *(size_t *)(out + n) = 47 *(size_t *)(ivec + n) ^= *(size_t *)(in + n); 48 } 49 len -= 16; 50 out += 16; 51 in += 16; 52 n = 0; 53 } 54 if (len) { 55 (*block) (ivec, ivec, key); 56 while (len--) { 57 out[n] = ivec[n] ^= in[n]; 58 ++n; 59 } 60 } 61 *num = n; 62 return; 63 } while (0); 64 } 65 /* the rest would be commonly eliminated by x86* compiler */ 66 #endif 67 while (l < len) { 68 if (n == 0) { 69 (*block) (ivec, ivec, key); 70 } 71 out[l] = ivec[n] ^= in[l]; 72 ++l; 73 n = (n + 1) % 16; 74 } 75 *num = n; 76 } else { 77 #if !defined(OPENSSL_SMALL_FOOTPRINT) 78 if (16 % sizeof(size_t) == 0) { /* always true actually */ 79 do { 80 while (n && len) { 81 unsigned char c; 82 *(out++) = ivec[n] ^ (c = *(in++)); 83 ivec[n] = c; 84 --len; 85 n = (n + 1) % 16; 86 } 87 # if defined(STRICT_ALIGNMENT) 88 if (((size_t)in | (size_t)out | (size_t)ivec) % 89 sizeof(size_t) != 0) 90 break; 91 # endif 92 while (len >= 16) { 93 (*block) (ivec, ivec, key); 94 for (; n < 16; n += sizeof(size_t)) { 95 size_t t = *(size_t *)(in + n); 96 *(size_t *)(out + n) = *(size_t *)(ivec + n) ^ t; 97 *(size_t *)(ivec + n) = t; 98 } 99 len -= 16; 100 out += 16; 101 in += 16; 102 n = 0; 103 } 104 if (len) { 105 (*block) (ivec, ivec, key); 106 while (len--) { 107 unsigned char c; 108 out[n] = ivec[n] ^ (c = in[n]); 109 ivec[n] = c; 110 ++n; 111 } 112 } 113 *num = n; 114 return; 115 } while (0); 116 } 117 /* the rest would be commonly eliminated by x86* compiler */ 118 #endif 119 while (l < len) { 120 unsigned char c; 121 if (n == 0) { 122 (*block) (ivec, ivec, key); 123 } 124 out[l] = ivec[n] ^ (c = in[l]); 125 ivec[n] = c; 126 ++l; 127 n = (n + 1) % 16; 128 } 129 *num = n; 130 } 131 } 132 133 /* 134 * This expects a single block of size nbits for both in and out. Note that 135 * it corrupts any extra bits in the last byte of out 136 */ 137 static void cfbr_encrypt_block(const unsigned char *in, unsigned char *out, 138 int nbits, const void *key, 139 unsigned char ivec[16], int enc, 140 block128_f block) 141 { 142 int n, rem, num; 143 unsigned char ovec[16 * 2 + 1]; /* +1 because we dereference (but don't 144 * use) one byte off the end */ 145 146 if (nbits <= 0 || nbits > 128) 147 return; 148 149 /* fill in the first half of the new IV with the current IV */ 150 memcpy(ovec, ivec, 16); 151 /* construct the new IV */ 152 (*block) (ivec, ivec, key); 153 num = (nbits + 7) / 8; 154 if (enc) /* encrypt the input */ 155 for (n = 0; n < num; ++n) 156 out[n] = (ovec[16 + n] = in[n] ^ ivec[n]); 157 else /* decrypt the input */ 158 for (n = 0; n < num; ++n) 159 out[n] = (ovec[16 + n] = in[n]) ^ ivec[n]; 160 /* shift ovec left... */ 161 rem = nbits % 8; 162 num = nbits / 8; 163 if (rem == 0) 164 memcpy(ivec, ovec + num, 16); 165 else 166 for (n = 0; n < 16; ++n) 167 ivec[n] = ovec[n + num] << rem | ovec[n + num + 1] >> (8 - rem); 168 169 /* it is not necessary to cleanse ovec, since the IV is not secret */ 170 } 171 172 /* N.B. This expects the input to be packed, MS bit first */ 173 void CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, 174 size_t bits, const void *key, 175 unsigned char ivec[16], int *num, 176 int enc, block128_f block) 177 { 178 size_t n; 179 unsigned char c[1], d[1]; 180 181 for (n = 0; n < bits; ++n) { 182 c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; 183 cfbr_encrypt_block(c, d, 1, key, ivec, enc, block); 184 out[n / 8] = (out[n / 8] & ~(1 << (unsigned int)(7 - n % 8))) | 185 ((d[0] & 0x80) >> (unsigned int)(n % 8)); 186 } 187 } 188 189 void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, 190 size_t length, const void *key, 191 unsigned char ivec[16], int *num, 192 int enc, block128_f block) 193 { 194 size_t n; 195 196 for (n = 0; n < length; ++n) 197 cfbr_encrypt_block(&in[n], &out[n], 8, key, ivec, enc, block); 198 } 199