crypt_common.c: Add missing doxygen documentation.
[paraslash.git] / crypt_common.c
1 /*
2 * Copyright (C) 2005-2011 Andre Noll <maan@systemlinux.org>
3 *
4 * Licensed under the GPL v2. For licencing details see COPYING.
5 */
6
7 /** \file crypt_common.c Crypto functions independent of openssl/libgcrypt. */
8
9 #include <regex.h>
10 #include <stdbool.h>
11
12 #include "para.h"
13 #include "error.h"
14 #include "string.h"
15 #include "crypt_backend.h"
16 #include "crypt.h"
17
18 /** If the key begins with this text, we treat it as an ssh key. */
19 #define KEY_TYPE_TXT "ssh-rsa"
20
21 /**
22 * Check if given buffer starts with a ssh rsa key signature.
23 *
24 * \param data The buffer.
25 * \param size Number of data bytes.
26 *
27 * \return Number of header bytes to be skipped on success, zero if
28 * ssh rsa signature was not found.
29 */
30 size_t is_ssh_rsa_key(char *data, size_t size)
31 {
32 char *cp;
33
34 if (size < strlen(KEY_TYPE_TXT) + 2)
35 return 0;
36 cp = memchr(data, ' ', size);
37 if (cp == NULL)
38 return 0;
39 if (strncmp(KEY_TYPE_TXT, data, strlen(KEY_TYPE_TXT)))
40 return 0;
41 cp++;
42 if (cp >= data + size)
43 return 0;
44 if (*cp == '\0')
45 return 0;
46 return cp - data;
47 }
48
49 /*
50 * This base64/uudecode stuff below is taken from openssh-5.2p1, Copyright (c)
51 * 1996 by Internet Software Consortium. Portions Copyright (c) 1995 by
52 * International Business Machines, Inc.
53 */
54
55 static const char Base64[] =
56 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57 static const char Pad64 = '=';
58
59 /**
60 * base64-decode a buffer.
61 *
62 * \param src The buffer to decode.
63 * \param target Result is stored here.
64 * \param targsize Number of bytes of \a target.
65 *
66 * Skips all whitespace anywhere. Converts characters, four at a time, starting
67 * at (or after) src from base - 64 numbers into three 8 bit bytes in the
68 * target area.
69 *
70 * \return The number of data bytes stored at the target, -E_BASE64 on errors.
71 */
72 int base64_decode(char const *src, unsigned char *target, size_t targsize)
73 {
74 unsigned int tarindex, state;
75 int ch;
76 char *pos;
77
78 state = 0;
79 tarindex = 0;
80
81 while ((ch = *src++) != '\0') {
82 if (para_isspace(ch)) /* Skip whitespace anywhere. */
83 continue;
84
85 if (ch == Pad64)
86 break;
87
88 pos = strchr(Base64, ch);
89 if (pos == 0) /* A non-base64 character. */
90 return -E_BASE64;
91
92 switch (state) {
93 case 0:
94 if (target) {
95 if (tarindex >= targsize)
96 return -E_BASE64;
97 target[tarindex] = (pos - Base64) << 2;
98 }
99 state = 1;
100 break;
101 case 1:
102 if (target) {
103 if (tarindex + 1 >= targsize)
104 return -E_BASE64;
105 target[tarindex] |= (pos - Base64) >> 4;
106 target[tarindex+1] = ((pos - Base64) & 0x0f)
107 << 4 ;
108 }
109 tarindex++;
110 state = 2;
111 break;
112 case 2:
113 if (target) {
114 if (tarindex + 1 >= targsize)
115 return -E_BASE64;
116 target[tarindex] |= (pos - Base64) >> 2;
117 target[tarindex+1] = ((pos - Base64) & 0x03)
118 << 6;
119 }
120 tarindex++;
121 state = 3;
122 break;
123 case 3:
124 if (target) {
125 if (tarindex >= targsize)
126 return -E_BASE64;
127 target[tarindex] |= (pos - Base64);
128 }
129 tarindex++;
130 state = 0;
131 break;
132 }
133 }
134
135 /*
136 * We are done decoding Base-64 chars. Let's see if we ended
137 * on a byte boundary, and/or with erroneous trailing characters.
138 */
139
140 if (ch == Pad64) { /* We got a pad char. */
141 ch = *src++; /* Skip it, get next. */
142 switch (state) {
143 case 0: /* Invalid = in first position */
144 case 1: /* Invalid = in second position */
145 return -E_BASE64;
146
147 case 2: /* Valid, means one byte of info */
148 /* Skip any number of spaces. */
149 for (; ch != '\0'; ch = *src++)
150 if (!isspace(ch))
151 break;
152 /* Make sure there is another trailing = sign. */
153 if (ch != Pad64)
154 return -E_BASE64;
155 ch = *src++; /* Skip the = */
156 /* Fall through to "single trailing =" case. */
157 /* FALLTHROUGH */
158
159 case 3: /* Valid, means two bytes of info */
160 /*
161 * We know this char is an =. Is there anything but
162 * whitespace after it?
163 */
164 for (; ch != '\0'; ch = *src++)
165 if (!isspace(ch))
166 return -E_BASE64;
167
168 /*
169 * Now make sure for cases 2 and 3 that the "extra"
170 * bits that slopped past the last full byte were
171 * zeros. If we don't check them, they become a
172 * subliminal channel.
173 */
174 if (target && target[tarindex] != 0)
175 return -E_BASE64;
176 }
177 } else {
178 /*
179 * We ended by seeing the end of the string. Make sure we
180 * have no partial bytes lying around.
181 */
182 if (state != 0)
183 return -E_BASE64;
184 }
185
186 return tarindex;
187 }
188
189 /**
190 * uudecode a buffer.
191 *
192 * \param src The buffer to decode.
193 * \param target Result buffer.
194 * \param targsize The length of \a target in bytes.
195 *
196 * This is just a simple wrapper for base64_decode() which strips whitespace.
197 *
198 * \return The return value of the underlying call to base64_decode().
199 */
200 int uudecode(const char *src, unsigned char *target, size_t targsize)
201 {
202 int len;
203 char *encoded, *p;
204
205 /* copy the 'readonly' source */
206 encoded = para_strdup(src);
207 /* skip whitespace and data */
208 for (p = encoded; *p == ' ' || *p == '\t'; p++)
209 ;
210 for (; *p != '\0' && *p != ' ' && *p != '\t'; p++)
211 ;
212 /* and remove trailing whitespace because base64_decode needs this */
213 *p = '\0';
214 len = base64_decode(encoded, target, targsize);
215 free(encoded);
216 return len;
217 }
218
219 /**
220 * Read a 4-byte number from a buffer in big-endian format.
221 *
222 * \param vp The buffer.
223 *
224 * The byte-order of the buffer is expected to be big-endian, unlike read_u32()
225 * of portable_io.h which expects little endian.
226 *
227 * \return The 32 bit number given by \a vp.
228 */
229 uint32_t read_ssh_u32(const void *vp)
230 {
231 const unsigned char *p = (const unsigned char *)vp;
232 uint32_t v;
233
234 v = (uint32_t)p[0] << 24;
235 v |= (uint32_t)p[1] << 16;
236 v |= (uint32_t)p[2] << 8;
237 v |= (uint32_t)p[3];
238
239 return v;
240 }
241
242 /**
243 * Sanity checks for the header of an ssh key.
244 *
245 * \param blob The buffer.
246 * \param blen The number of bytes of \a blob.
247 *
248 * This performs some checks to make sure we really have an ssh key. It also
249 * computes the offset in bytes of the start of the key values (modulus,
250 * exponent..).
251 *
252 * \return The number of bytes to skip until the start of the first encoded
253 * number (usually 11).
254 */
255 int check_ssh_key_header(const unsigned char *blob, int blen)
256 {
257 const unsigned char *p = blob, *end = blob + blen;
258 uint32_t rlen;
259
260 if (p + 4 > end)
261 return -E_SSH_KEY_HEADER;
262 rlen = read_ssh_u32(p);
263 p += 4;
264 if (p + rlen < p)
265 return -E_SSH_KEY_HEADER;
266 if (p + rlen > end)
267 return -E_SSH_KEY_HEADER;
268 if (rlen < strlen(KEY_TYPE_TXT))
269 return -E_SSH_KEY_HEADER;
270 PARA_DEBUG_LOG("type: %s, rlen: %d\n", p, rlen);
271 if (strncmp((char *)p, KEY_TYPE_TXT, strlen(KEY_TYPE_TXT)))
272 return -E_SSH_KEY_HEADER;
273 return 4 + rlen;
274 }
275
276 /**
277 * Check existence and permissions of a key file.
278 *
279 * \param file The path of the key file.
280 * \param private_key Whether this is a private key.
281 *
282 * This checks whether the file exists. If it is a private key, we additionally
283 * check that the permissions are restrictive enough. It is considered an error
284 * if we own the file and it is readable for others.
285 *
286 * \return Standard.
287 */
288 int check_key_file(const char *file, bool private_key)
289 {
290 struct stat st;
291
292 if (stat(file, &st) != 0)
293 return -ERRNO_TO_PARA_ERROR(errno);
294 if (!private_key)
295 return 0;
296 if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0)
297 return -E_KEY_PERM;
298 return 1;
299 }
300
301 void hash_to_asc(unsigned char *hash, char *asc)
302 {
303 int i;
304 const char hexchar[] = "0123456789abcdef";
305
306 for (i = 0; i < HASH_SIZE; i++) {
307 asc[2 * i] = hexchar[hash[i] >> 4];
308 asc[2 * i + 1] = hexchar[hash[i] & 0xf];
309 }
310 asc[2 * HASH_SIZE] = '\0';
311 }
312
313 int hash_compare(unsigned char *h1, unsigned char *h2)
314 {
315 int i;
316
317 for (i = 0; i < HASH_SIZE; i++) {
318 if (h1[i] < h2[i])
319 return -1;
320 if (h1[i] > h2[i])
321 return 1;
322 }
323 return 0;
324 }
325
326 int sc_recv_buffer(struct stream_cipher_context *scc, char *buf, size_t size)
327 {
328 int n;
329
330 assert(size);
331 n = sc_recv_bin_buffer(scc, buf, size - 1);
332 if (n >= 0)
333 buf[n] = '\0';
334 else
335 *buf = '\0';
336 return n;
337 }
338
339 int sc_send_buffer(struct stream_cipher_context *scc, char *buf)
340 {
341 return sc_send_bin_buffer(scc, buf, strlen(buf));
342 }
343
344 __printf_2_3 int sc_send_va_buffer(struct stream_cipher_context *scc,
345 const char *fmt, ...)
346 {
347 char *msg;
348 int ret;
349
350 PARA_VSPRINTF(fmt, msg);
351 ret = sc_send_buffer(scc, msg);
352 free(msg);
353 return ret;
354 }