allow reading/writing the camouflage
[xonotic/d0_blind_id.git] / d0_iobuf.c
1 /*
2 Blind-ID library for user identification using RSA blind signatures
3 Copyright (C) 2010  Rudolf Polzer
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20 #include "d0_iobuf.h"
21
22 #include <string.h>
23
24 struct d0_iobuf_s
25 {
26         const unsigned char *inbuf;
27         unsigned char *outbuf;
28         size_t inpos, outpos, inbuflen, outbuflen;
29         BOOL ok;
30 };
31
32 d0_iobuf_t *d0_iobuf_open_read(const void *buf, size_t len)
33 {
34         d0_iobuf_t *b = d0_malloc(sizeof(d0_iobuf_t));
35         b->inbuf = (const unsigned char *) buf;
36         b->outbuf = NULL;
37         b->inpos = b->outpos = 0;
38         b->inbuflen = len;
39         b->outbuflen = 0;
40         b->ok = 1;
41         return b;
42 }
43
44 d0_iobuf_t *d0_iobuf_open_write(void *buf, size_t len)
45 {
46         d0_iobuf_t *b = d0_malloc(sizeof(d0_iobuf_t));
47         b->inbuf = (const unsigned char *) buf;
48         b->outbuf = (unsigned char *) buf;
49         b->inpos = b->outpos = 0;
50         b->inbuflen = len;
51         b->outbuflen = len;
52         b->ok = 1;
53         return b;
54 }
55
56 BOOL d0_iobuf_close(d0_iobuf_t *buf, size_t *len)
57 {
58         BOOL r = buf->ok;
59         if(len)
60                 *len = buf->outpos;
61         d0_free(buf);
62         return r;
63 }
64
65 size_t d0_iobuf_write_raw(d0_iobuf_t *buf, const void *s, size_t n)
66 {
67         size_t nreal = n;
68         if(nreal > buf->outbuflen - buf->outpos)
69         {
70                 buf->ok = 0;
71                 nreal = buf->outbuflen - buf->outpos;
72         }
73         memcpy(buf->outbuf + buf->outpos, s, nreal);
74         buf->outpos += nreal;
75         return nreal;
76 }
77
78 size_t d0_iobuf_read_raw(d0_iobuf_t *buf, void *s, size_t n)
79 {
80         size_t nreal = n;
81         if(nreal > buf->inbuflen - buf->inpos)
82         {
83                 buf->ok = 0;
84                 nreal = buf->inbuflen - buf->inpos;
85         }
86         memcpy(s, buf->inbuf + buf->inpos, nreal);
87         buf->inpos += nreal;
88         return nreal;
89 }
90
91 BOOL d0_iobuf_write_packet(d0_iobuf_t *buf, const void *s, size_t n)
92 {
93         unsigned char c;
94         size_t nn = n;
95         while(nn)
96         {
97                 c = nn & 255;
98                 nn >>= 8;
99                 if(d0_iobuf_write_raw(buf, &c, 1) != 1)
100                         return 0;
101         }
102         c = 0;
103         if(d0_iobuf_write_raw(buf, &c, 1) != 1)
104                 return 0;
105         if(d0_iobuf_write_raw(buf, s, n) != n)
106                 return 0;
107         return 1;
108 }
109
110 BOOL d0_iobuf_read_packet(d0_iobuf_t *buf, void *s, size_t *np)
111 {
112         unsigned char c;
113         size_t n = 0;
114         size_t nn = 1;
115         do
116         {
117                 if(d0_iobuf_read_raw(buf, &c, 1) != 1)
118                         return 0;
119                 n |= nn * c;
120                 nn <<= 8;
121         }
122         while(c);
123         if(n > *np)
124                 return 0;
125         if(d0_iobuf_read_raw(buf, s, n) != n)
126                 return 0;
127         *np = n;
128         return 1;
129 }
130
131 BOOL d0_iobuf_conv_base64_in(d0_iobuf_t *buf)
132 {
133         // compand the in-buffer
134         return 0;
135 }
136
137 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
138 static void base64_3to4(const unsigned char *in, unsigned char *out, int bytes)
139 {
140         unsigned char i0 = (bytes > 0) ? in[0] : 0;
141         unsigned char i1 = (bytes > 1) ? in[1] : 0;
142         unsigned char i2 = (bytes > 2) ? in[2] : 0;
143         unsigned char o0 = base64[i0 >> 2];
144         unsigned char o1 = base64[((i0 << 4) | (i1 >> 4)) & 077];
145         unsigned char o2 = base64[((i1 << 2) | (i2 >> 6)) & 077];
146         unsigned char o3 = base64[i2 & 077];
147         out[0] = (bytes > 0) ? o0 : '?';
148         out[1] = (bytes > 0) ? o1 : '?';
149         out[2] = (bytes > 1) ? o2 : '=';
150         out[3] = (bytes > 2) ? o3 : '=';
151 }
152
153 BOOL d0_iobuf_conv_base64_out(d0_iobuf_t *buf)
154 {
155         size_t blocks, i;
156         // expand the out-buffer
157         blocks = ((buf->outpos + 2) / 3);
158         if(blocks*4 > buf->outbuflen)
159                 return 0;
160         for(i = blocks; i > 0; )
161         {
162                 --i;
163                 base64_3to4(buf->outbuf + 3*i, buf->outbuf + 4*i, buf->outpos - 3*i);
164         }
165         buf->outpos = blocks * 4;
166         return 1;
167 }