cfb128.c 6.8 KB

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