cfb128.c 6.9 KB

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