summaryrefslogtreecommitdiff
path: root/src/libzrtpcpp/crypto/twofish_cfb.c
blob: 75407387d08c9a1cad093b7b2936fd3d5437693c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <stdint.h>
#include <stdlib.h>

#include "twofish.h"

void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in, 
			    Twofish_Byte* out, size_t len,
			    Twofish_Byte* ivec, int32_t *num)
{
  uint32_t n;

  n = *num;

  do {
    while (n && len) {
      *(out++) = ivec[n] ^= *(in++);
      --len;
      n = (n+1) % 16;
    }
    while (len>=16) {
      Twofish_encrypt(keyCtx, ivec, ivec);
      for (n=0; n<16; n+=sizeof(size_t)) {
	*(size_t*)(out+n) =
	  *(size_t*)(ivec+n) ^= *(size_t*)(in+n);
      }
      len -= 16;
      out += 16;
      in  += 16;
    }
    n = 0;
    if (len) {
      Twofish_encrypt(keyCtx, ivec, ivec);
      while (len--) {
	out[n] = ivec[n] ^= in[n];
	++n;
      }
    }
    *num = n;
    return;
  } while (0);
}


void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in, 
			    Twofish_Byte* out, size_t len,
			    Twofish_Byte* ivec, int32_t *num)
{
  uint32_t n;

  n = *num;

  do {
    while (n && len) {
      unsigned char c;
      *(out++) = ivec[n] ^ (c = *(in++)); ivec[n] = c;
      --len;
      n = (n+1) % 16;
    }
    while (len>=16) {
      Twofish_encrypt(keyCtx, ivec, ivec);
      for (n=0; n<16; n+=sizeof(size_t)) {
	size_t t = *(size_t*)(in+n);
	*(size_t*)(out+n) = *(size_t*)(ivec+n) ^ t;
	*(size_t*)(ivec+n) = t;
      }
      len -= 16;
      out += 16;
      in  += 16;
    }
    n = 0;
    if (len) {
      Twofish_encrypt(keyCtx, ivec, ivec);
      while (len--) {
	unsigned char c;
	out[n] = ivec[n] ^ (c = in[n]); ivec[n] = c;
	++n;
      }
    }
    *num = n;
    return;
  } while (0);
}