decrypt.c 4.51 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1
2
3
4
/* decrypt.c
 *
 */

Niels Möller's avatar
Niels Möller committed
5
6
7
#include "decrypt.h"
#include "werror.h"
#include "xalloc.h"
Niels Möller's avatar
Niels Möller committed
8
9
10
11
12

#define WAIT_HEADER 0
#define WAIT_CONTENTS 1
#define WAIT_MAC 2

Niels Möller's avatar
Niels Möller committed
13
14
15
16
#define MIN(a, b) ( ((a)<(b)) ? (a) : (b) )
#define MAX(a, b) ( ((a)>(b)) ? (a) : (b) )

static int do_decrypt(struct decrypt_processor *closure,
Niels Möller's avatar
Niels Möller committed
17
		      struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
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
{
  /* Number of octets n the input packet that have been processed */
  UINT32 pos = 0;

  while(pos < packet->length)
    switch(closure->state)
      {
      case WAIT_HEADER:
	{
	  UINT32 left = closure->block_size - closure->pos;
	  UINT32 copy = MIN(left, (packet->length - pos));

	  memcpy(closure->block_buffer + closure->pos,
		 packet->data + pos,
		 copy);

	  pos += copy;
	  closure->pos += copy;
	  
	  if (left == copy)
	    {
	      /* Read a full header */
	      UINT32 length;

	      /* Decrypt the first block */
	      closure->decrypt_function(closure->decrypt_state,
Niels Möller's avatar
Niels Möller committed
44
					closure->block_size, closure->block_buffer,
Niels Möller's avatar
Niels Möller committed
45
46
					closure->block_buffer);

Niels Möller's avatar
Niels Möller committed
47
	      length = READ_UINT32(closure->block_buffer);
Niels Möller's avatar
Niels Möller committed
48
49
50
51
52
53
54
55
56
57
58
59
60

	      if (length > closure->max_packet)
		return 0;

	      if ( (length < 12)
		   || (length < (closure->block_size - 4))
		   || ( (length + 4) % closure->block_size))
		return 0;
	      
	      /* The length of remaining data. Note that the first,
	       * already decrypted, block contains some of the
	       * decypted payload. */
	      closure->recieved
Niels Möller's avatar
Niels Möller committed
61
		= lsh_string_alloc(length
Niels Möller's avatar
Niels Möller committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
				      - (closure->block_size - 4));
	      
	      closure->pos = 0;
	      closure->state = WAIT_CONTENTS;
	      /* Fall through to WAIT_CONTNTS */
	    }
	  else
	    /* Processed all octets of this packet. Still no complete
	     * header. */
	    break;
	}
      case WAIT_CONTENTS:
	{
	  UINT32 left = closure->recieved->length - closure->pos;
	  UINT32 copy = MIN(left, packet->length - pos);

	  memcpy(closure->recieved->data + closure->pos,
		 packet->data + pos,
		 copy);

	  pos += copy;
	  closure->pos += copy;

	  if (left == copy)
	    {
	      /* Read a complete packet (but no MAC yet) */

	      UINT32 left_overs = closure->block_size - 4;
	      /* Full packet (including left-overs from the first block) */
Niels Möller's avatar
Niels Möller committed
91
92
	      struct lsh_string *new
		= lsh_string_alloc(closure->recieved->length
Niels Möller's avatar
Niels Möller committed
93
94
95
96
97
98
99
				      + left_overs);

	      memcpy(new->data, closure->block_buffer + 4,
		     left_overs);

	      closure->decrypt_function(closure->decrypt_state,
					closure->recieved->length,
Niels Möller's avatar
Niels Möller committed
100
					closure->recieved->data,
Niels Möller's avatar
Niels Möller committed
101
102
					new->data + left_overs);

Niels Möller's avatar
Niels Möller committed
103
	      lsh_string_free(closure->recieved);
Niels Möller's avatar
Niels Möller committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
	      closure->recieved = new;

	      if (closure->mac_size)
		closure->mac_function(closure->mac_state,
				      new->length,
				      new->data,
				      closure->block_buffer);

	      closure->pos = 0;
	      closure->state = WAIT_MAC;

	      /* Fall through */
	    }
	  else
	    /* Processe all octets, but still haven't got a complete packet */
	    break;
	}
      case WAIT_MAC:
	if (closure->mac_size)
	  {
	    UINT32 left = closure->mac_size - closure->pos;
	    UINT32 cmp = MIN(left, packet->length - pos);

	    if (!memcpy(closure->block_buffer + closure->pos,
			packet->data + pos,
			cmp))
	      return 0;

	    pos += cmp;
	    closure->pos += cmp;

	    if (left > cmp)
	      {
		/* Processed all octets, but still haven't received a
                   complete MAC */
		break;
	      }
	  }
	/* MAC was ok, pass packet on */
	
Niels Möller's avatar
Niels Möller committed
144
	if (!apply_processor(closure->c.next, closure->recieved))
Niels Möller's avatar
Niels Möller committed
145
146
147
148
149
150
151
152
153
154
155
156
157
158
	  return 0;
	
	closure->recieved = NULL;
	closure->pos = 0;
	closure->state = WAIT_HEADER;
	break;

      default:
	fatal("Internal error");
      }
  /* Processed all octets of this packet. */
  return 1;
}
  
Niels Möller's avatar
Niels Möller committed
159
160
struct abstract_write *
make_decrypt_processor(struct abstract_write *continuation,
Niels Möller's avatar
Niels Möller committed
161
162
163
164
165
		       UINT32 max_packet,
		       unsigned mac_size,
		       transform_function mac_function,
		       void *mac_state,
		       unsigned block_size,
Niels Möller's avatar
Niels Möller committed
166
167
		       transform_function decrypt_function,
		       void *decrypt_state)
Niels Möller's avatar
Niels Möller committed
168
{
Niels Möller's avatar
Niels Möller committed
169
  struct decrypt_processor *closure = xalloc(sizeof(struct decrypt_processor)
Niels Möller's avatar
Niels Möller committed
170
171
					 + MAX(block_size, mac_size) - 1);
  
Niels Möller's avatar
Niels Möller committed
172
  closure->c.p.f = (abstract_write_f) do_decrypt;
Niels Möller's avatar
Niels Möller committed
173
  closure->c.next = continuation;
Niels Möller's avatar
Niels Möller committed
174
175
176
177
178
179
180
181
182
183
184
185

  /* state */
  closure->state = WAIT_HEADER;
  closure->pos = 0;
  closure->recieved = NULL;
  
  closure->max_packet = max_packet;
  
  closure->mac_size = mac_size;
  closure->mac_function = mac_function;
  closure->mac_state = mac_state;
  closure->block_size = block_size;
Niels Möller's avatar
Niels Möller committed
186
187
  closure->decrypt_function = decrypt_function;
  closure->decrypt_state = decrypt_state;
Niels Möller's avatar
Niels Möller committed
188

Niels Möller's avatar
Niels Möller committed
189
  return (struct abstract_write *) closure;
Niels Möller's avatar
Niels Möller committed
190
}