aboutsummaryrefslogtreecommitdiff
path: root/src/op/buffers.c
blob: 39a4e442d2d32780ed8d1c8de9f47c7e3f89968a (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
144
145
146
/**
 * buffers.c
 * Buffers.
 *
 * Matej Pfajfar <mp292@cam.ac.uk>
 */

/*
 * Changes :
 * $Log$
 * Revision 1.1  2002/06/26 22:45:50  arma
 * Initial revision
 *
 * Revision 1.1  2002/04/02 14:28:01  badbytes
 * Final finishes.
 *
 */


#include <unistd.h>
#include <openssl/evp.h>

#include "../common/cell.h"
#include "../common/log.h"

#include "buffers.h"
#include "crypto.h"
#include "op.h"

int buffer_data(uint16_t aci, unsigned char *buf, size_t buflen, unsigned char **outbuf, size_t *outbuflen, size_t *outbuf_dataoffset, size_t *outbuf_datalen, crypt_path_t **cpath, size_t cpathlen)
{
  int retval;
  int i;
  cell_t *cellbuf;
  cell_t *c;
  size_t cellbuflen;
  size_t cells;
  unsigned char *tmpbuf; /* temporary buffer for realloc() operations */
  
  if (!buf || !outbuf || !outbuflen) /* invalid parameters */
    return -1;
  
  /* split the plaintext into DATA cells */
  retval = pack_data(aci,buf, buflen, (unsigned char **)&cellbuf, &cellbuflen);
  if (retval == -1)
  {
    log(LOG_DEBUG,"buffer_data() : Could not pack data into cells.");
    return -1;
  }
  log(LOG_DEBUG,"buffer_data() : DATA cells created.");
  
  cells = cellbuflen/(sizeof(cell_t));
  /* encrypt the cells */
  for (i=0; i<cells; i++)
  {
    c = cellbuf+i;
    /* encrypt the payload length */
    retval = crypt_f((unsigned char *)&c->length, 1, cpath, cpathlen);
    if (retval == -1)
    {
      log(LOG_ERR,"Could not encrypt the payload length of a DATA cell.");
      free((void *)cellbuf);
      return -1;
    }
    /* encrypt the payload */
    retval = crypt_f((unsigned char *)c->payload, CELL_PAYLOAD_SIZE, cpath, cpathlen);
    if (retval == -1)
    {
      log(LOG_ERR,"Could not encrypt the payload of a DATA cell.");
      free((void *)cellbuf);
      return -1;
    }
  }

  /* now copy the cells into the output buffer */
  if (*outbuflen-*outbuf_dataoffset-*outbuf_datalen < cellbuflen) /* increase the buffer size if necessary */
  {
    /* allocate a new buffer (in OP_DEFAULT_BUFSIZE chunks)*/
    tmpbuf = (unsigned char *)malloc(((cellbuflen+*outbuf_datalen)/OP_DEFAULT_BUFSIZE+1)*OP_DEFAULT_BUFSIZE);
    if (!tmpbuf)
    {
      log(LOG_ERR,"Error allocating memory.");
      free((void *)cellbuf);
      return -1;
    }
    /* copy old data to the new buffer */
    memcpy((void *)tmpbuf,(void *)(*outbuf+*outbuf_dataoffset),*outbuf_datalen);
    /* replace the old buffer with the new one */
    if (*outbuf)
      free((void *)*outbuf);
    *outbuf = tmpbuf;
    *outbuflen = ((cellbuflen+*outbuf_datalen)/OP_DEFAULT_BUFSIZE+1) * OP_DEFAULT_BUFSIZE;
    *outbuf_dataoffset = 0;
  }
  memcpy((void *)(*outbuf + *outbuf_dataoffset + *outbuf_datalen), (void *)cellbuf, cellbuflen);
  *outbuf_datalen += cellbuflen;
  
  return 0;
}

int buffer_create(uint16_t aci, unsigned char *onion, size_t onionlen, unsigned char **outbuf, size_t *outbuflen, size_t *outbuf_dataoffset, size_t *outbuf_datalen, crypt_path_t **cpath, size_t cpathlen)
{
  int retval;
  cell_t *cellbuf;
  size_t cells;
  size_t cellbuflen;
  unsigned char *tmpbuf; /* temporary buffer for realloc() operations */
  
  if (!onion || !outbuf || !outbuflen || !outbuf_dataoffset || !outbuf_datalen) /* invalid parameters */
    return -1;
  
  retval = pack_create(aci,onion, onionlen, (unsigned char **)&cellbuf, &cellbuflen);
  if (retval == -1)
  {
    log(LOG_DEBUG,"buffer_create() : Could not pack the onion into cells.");
    return -1;
  }
  log(LOG_DEBUG,"buffer_create() : CREATE cells created.");

  cells = cellbuflen/(sizeof(cell_t));

  /* now copy the cells into the output buffer */
  if (*outbuflen-*outbuf_dataoffset-*outbuf_datalen < cellbuflen) /* increase the buffer size if necessary */
  {
    /* allocate a new buffer (in OP_DEFAULT_BUFSIZE chunks)*/
    tmpbuf = (unsigned char *)malloc(((cellbuflen+*outbuf_datalen)/OP_DEFAULT_BUFSIZE+1)*OP_DEFAULT_BUFSIZE);
    if (!tmpbuf)
    {
      log(LOG_ERR,"Error allocating memory.");
      free((void *)cellbuf);
      return -1;
    }
    /* copy old data to the new buffer */
    memcpy((void *)tmpbuf,(void *)(*outbuf+*outbuf_dataoffset),*outbuf_datalen);
    /* replace the old buffer with the new one */
    if (*outbuf)
      free((void *)*outbuf);
    *outbuf = tmpbuf;
    *outbuflen = ((cellbuflen+*outbuf_datalen)/OP_DEFAULT_BUFSIZE+1) * OP_DEFAULT_BUFSIZE;
    *outbuf_dataoffset = 0;
  }
  memcpy((void *)(*outbuf + *outbuf_dataoffset + *outbuf_datalen), (void *)cellbuf, cellbuflen);
  *outbuf_datalen += cellbuflen;
  
  return 0;
}