1238384Sjkim/* ==================================================================== 2238384Sjkim * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 3238384Sjkim * 4238384Sjkim * Redistribution and use in source and binary forms, with or without 5238384Sjkim * modification, are permitted provided that the following conditions 6238384Sjkim * are met: 7238384Sjkim * 8238384Sjkim * 1. Redistributions of source code must retain the above copyright 9280297Sjkim * notice, this list of conditions and the following disclaimer. 10238384Sjkim * 11238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 12238384Sjkim * notice, this list of conditions and the following disclaimer in 13238384Sjkim * the documentation and/or other materials provided with the 14238384Sjkim * distribution. 15238384Sjkim * 16238384Sjkim * 3. All advertising materials mentioning features or use of this 17238384Sjkim * software must display the following acknowledgment: 18238384Sjkim * "This product includes software developed by the OpenSSL Project 19238384Sjkim * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 20238384Sjkim * 21238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22238384Sjkim * endorse or promote products derived from this software without 23238384Sjkim * prior written permission. For written permission, please contact 24238384Sjkim * openssl-core@openssl.org. 25238384Sjkim * 26238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 27238384Sjkim * nor may "OpenSSL" appear in their names without prior written 28238384Sjkim * permission of the OpenSSL Project. 29238384Sjkim * 30238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 31238384Sjkim * acknowledgment: 32238384Sjkim * "This product includes software developed by the OpenSSL Project 33238384Sjkim * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 34238384Sjkim * 35238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 47238384Sjkim * ==================================================================== 48238384Sjkim * 49238384Sjkim */ 50238384Sjkim 51238384Sjkim#include <openssl/crypto.h> 52238384Sjkim#include "modes_lcl.h" 53238384Sjkim#include <string.h> 54238384Sjkim 55238384Sjkim#ifndef MODES_DEBUG 56238384Sjkim# ifndef NDEBUG 57238384Sjkim# define NDEBUG 58238384Sjkim# endif 59238384Sjkim#endif 60238384Sjkim#include <assert.h> 61238384Sjkim 62280297Sjkim/* 63280297Sjkim * The input and output encrypted as though 128bit cfb mode is being used. 64280297Sjkim * The extra state information to record how much of the 128bit block we have 65280297Sjkim * used is contained in *num; 66238384Sjkim */ 67238384Sjkimvoid CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, 68280297Sjkim size_t len, const void *key, 69280297Sjkim unsigned char ivec[16], int *num, 70280297Sjkim int enc, block128_f block) 71238384Sjkim{ 72238384Sjkim unsigned int n; 73238384Sjkim size_t l = 0; 74238384Sjkim 75238384Sjkim assert(in && out && key && ivec && num); 76238384Sjkim 77238384Sjkim n = *num; 78238384Sjkim 79238384Sjkim if (enc) { 80238384Sjkim#if !defined(OPENSSL_SMALL_FOOTPRINT) 81280297Sjkim if (16 % sizeof(size_t) == 0) { /* always true actually */ 82280297Sjkim do { 83280297Sjkim while (n && len) { 84280297Sjkim *(out++) = ivec[n] ^= *(in++); 85280297Sjkim --len; 86280297Sjkim n = (n + 1) % 16; 87280297Sjkim } 88280297Sjkim# if defined(STRICT_ALIGNMENT) 89280297Sjkim if (((size_t)in | (size_t)out | (size_t)ivec) % 90280297Sjkim sizeof(size_t) != 0) 91280297Sjkim break; 92280297Sjkim# endif 93280297Sjkim while (len >= 16) { 94280297Sjkim (*block) (ivec, ivec, key); 95280297Sjkim for (; n < 16; n += sizeof(size_t)) { 96280297Sjkim *(size_t *)(out + n) = 97280297Sjkim *(size_t *)(ivec + n) ^= *(size_t *)(in + n); 98280297Sjkim } 99280297Sjkim len -= 16; 100280297Sjkim out += 16; 101280297Sjkim in += 16; 102280297Sjkim n = 0; 103280297Sjkim } 104280297Sjkim if (len) { 105280297Sjkim (*block) (ivec, ivec, key); 106280297Sjkim while (len--) { 107280297Sjkim out[n] = ivec[n] ^= in[n]; 108280297Sjkim ++n; 109280297Sjkim } 110280297Sjkim } 111280297Sjkim *num = n; 112280297Sjkim return; 113280297Sjkim } while (0); 114280297Sjkim } 115280297Sjkim /* the rest would be commonly eliminated by x86* compiler */ 116238384Sjkim#endif 117280297Sjkim while (l < len) { 118280297Sjkim if (n == 0) { 119280297Sjkim (*block) (ivec, ivec, key); 120280297Sjkim } 121280297Sjkim out[l] = ivec[n] ^= in[l]; 122280297Sjkim ++l; 123280297Sjkim n = (n + 1) % 16; 124280297Sjkim } 125280297Sjkim *num = n; 126238384Sjkim } else { 127238384Sjkim#if !defined(OPENSSL_SMALL_FOOTPRINT) 128280297Sjkim if (16 % sizeof(size_t) == 0) { /* always true actually */ 129280297Sjkim do { 130280297Sjkim while (n && len) { 131280297Sjkim unsigned char c; 132280297Sjkim *(out++) = ivec[n] ^ (c = *(in++)); 133280297Sjkim ivec[n] = c; 134280297Sjkim --len; 135280297Sjkim n = (n + 1) % 16; 136280297Sjkim } 137280297Sjkim# if defined(STRICT_ALIGNMENT) 138280297Sjkim if (((size_t)in | (size_t)out | (size_t)ivec) % 139280297Sjkim sizeof(size_t) != 0) 140280297Sjkim break; 141280297Sjkim# endif 142280297Sjkim while (len >= 16) { 143280297Sjkim (*block) (ivec, ivec, key); 144280297Sjkim for (; n < 16; n += sizeof(size_t)) { 145280297Sjkim size_t t = *(size_t *)(in + n); 146280297Sjkim *(size_t *)(out + n) = *(size_t *)(ivec + n) ^ t; 147280297Sjkim *(size_t *)(ivec + n) = t; 148280297Sjkim } 149280297Sjkim len -= 16; 150280297Sjkim out += 16; 151280297Sjkim in += 16; 152280297Sjkim n = 0; 153280297Sjkim } 154280297Sjkim if (len) { 155280297Sjkim (*block) (ivec, ivec, key); 156280297Sjkim while (len--) { 157280297Sjkim unsigned char c; 158280297Sjkim out[n] = ivec[n] ^ (c = in[n]); 159280297Sjkim ivec[n] = c; 160280297Sjkim ++n; 161280297Sjkim } 162280297Sjkim } 163280297Sjkim *num = n; 164280297Sjkim return; 165280297Sjkim } while (0); 166280297Sjkim } 167280297Sjkim /* the rest would be commonly eliminated by x86* compiler */ 168238384Sjkim#endif 169280297Sjkim while (l < len) { 170280297Sjkim unsigned char c; 171280297Sjkim if (n == 0) { 172280297Sjkim (*block) (ivec, ivec, key); 173280297Sjkim } 174280297Sjkim out[l] = ivec[n] ^ (c = in[l]); 175280297Sjkim ivec[n] = c; 176280297Sjkim ++l; 177280297Sjkim n = (n + 1) % 16; 178280297Sjkim } 179280297Sjkim *num = n; 180238384Sjkim } 181238384Sjkim} 182238384Sjkim 183280297Sjkim/* 184280297Sjkim * This expects a single block of size nbits for both in and out. Note that 185280297Sjkim * it corrupts any extra bits in the last byte of out 186280297Sjkim */ 187280297Sjkimstatic void cfbr_encrypt_block(const unsigned char *in, unsigned char *out, 188280297Sjkim int nbits, const void *key, 189280297Sjkim unsigned char ivec[16], int enc, 190280297Sjkim block128_f block) 191238384Sjkim{ 192280297Sjkim int n, rem, num; 193280297Sjkim unsigned char ovec[16 * 2 + 1]; /* +1 because we dererefence (but don't 194280297Sjkim * use) one byte off the end */ 195238384Sjkim 196280297Sjkim if (nbits <= 0 || nbits > 128) 197280297Sjkim return; 198238384Sjkim 199280297Sjkim /* fill in the first half of the new IV with the current IV */ 200280297Sjkim memcpy(ovec, ivec, 16); 201280297Sjkim /* construct the new IV */ 202280297Sjkim (*block) (ivec, ivec, key); 203280297Sjkim num = (nbits + 7) / 8; 204280297Sjkim if (enc) /* encrypt the input */ 205280297Sjkim for (n = 0; n < num; ++n) 206280297Sjkim out[n] = (ovec[16 + n] = in[n] ^ ivec[n]); 207280297Sjkim else /* decrypt the input */ 208280297Sjkim for (n = 0; n < num; ++n) 209280297Sjkim out[n] = (ovec[16 + n] = in[n]) ^ ivec[n]; 210280297Sjkim /* shift ovec left... */ 211280297Sjkim rem = nbits % 8; 212280297Sjkim num = nbits / 8; 213280297Sjkim if (rem == 0) 214280297Sjkim memcpy(ivec, ovec + num, 16); 215280297Sjkim else 216280297Sjkim for (n = 0; n < 16; ++n) 217280297Sjkim ivec[n] = ovec[n + num] << rem | ovec[n + num + 1] >> (8 - rem); 218238384Sjkim 219238384Sjkim /* it is not necessary to cleanse ovec, since the IV is not secret */ 220238384Sjkim} 221238384Sjkim 222238384Sjkim/* N.B. This expects the input to be packed, MS bit first */ 223238384Sjkimvoid CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, 224280297Sjkim size_t bits, const void *key, 225280297Sjkim unsigned char ivec[16], int *num, 226280297Sjkim int enc, block128_f block) 227238384Sjkim{ 228238384Sjkim size_t n; 229280297Sjkim unsigned char c[1], d[1]; 230238384Sjkim 231238384Sjkim assert(in && out && key && ivec && num); 232238384Sjkim assert(*num == 0); 233238384Sjkim 234280297Sjkim for (n = 0; n < bits; ++n) { 235280297Sjkim c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; 236280297Sjkim cfbr_encrypt_block(c, d, 1, key, ivec, enc, block); 237280297Sjkim out[n / 8] = (out[n / 8] & ~(1 << (unsigned int)(7 - n % 8))) | 238280297Sjkim ((d[0] & 0x80) >> (unsigned int)(n % 8)); 239280297Sjkim } 240238384Sjkim} 241238384Sjkim 242238384Sjkimvoid CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, 243280297Sjkim size_t length, const void *key, 244280297Sjkim unsigned char ivec[16], int *num, 245280297Sjkim int enc, block128_f block) 246238384Sjkim{ 247238384Sjkim size_t n; 248238384Sjkim 249238384Sjkim assert(in && out && key && ivec && num); 250238384Sjkim assert(*num == 0); 251238384Sjkim 252280297Sjkim for (n = 0; n < length; ++n) 253280297Sjkim cfbr_encrypt_block(&in[n], &out[n], 8, key, ivec, enc, block); 254238384Sjkim} 255