2 * Copyright (C) 2005-2011 Andre Noll <maan@systemlinux.org>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file crypt_common.c Crypto functions independent of openssl/libgcrypt. */
15 #include "crypt_backend.h"
18 /** If the key begins with this text, we treat it as an ssh key. */
19 #define KEY_TYPE_TXT "ssh-rsa"
22 * Check if given buffer starts with a ssh rsa key signature.
24 * \param data The buffer.
25 * \param size Number of data bytes.
27 * \return Number of header bytes to be skipped on success, zero if
28 * ssh rsa signature was not found.
30 size_t is_ssh_rsa_key(char *data, size_t size)
34 if (size < strlen(KEY_TYPE_TXT) + 2)
36 cp = memchr(data, ' ', size);
39 if (strncmp(KEY_TYPE_TXT, data, strlen(KEY_TYPE_TXT)))
42 if (cp >= data + size)
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.
55 static const char Base64[] =
56 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57 static const char Pad64 = '=';
60 * base64-decode a buffer.
62 * \param src The buffer to decode.
63 * \param target Result is stored here.
64 * \param targsize Number of bytes of \a target.
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
70 * \return The number of data bytes stored at the target, -E_BASE64 on errors.
72 int base64_decode(char const *src, unsigned char *target, size_t targsize)
74 unsigned int tarindex, state;
81 while ((ch = *src++) != '\0') {
82 if (para_isspace(ch)) /* Skip whitespace anywhere. */
88 pos = strchr(Base64, ch);
89 if (pos == NULL) /* A non-base64 character. */
95 if (tarindex >= targsize)
97 target[tarindex] = (pos - Base64) << 2;
103 if (tarindex + 1 >= targsize)
105 target[tarindex] |= (pos - Base64) >> 4;
106 target[tarindex+1] = ((pos - Base64) & 0x0f)
114 if (tarindex + 1 >= targsize)
116 target[tarindex] |= (pos - Base64) >> 2;
117 target[tarindex+1] = ((pos - Base64) & 0x03)
125 if (tarindex >= targsize)
127 target[tarindex] |= (pos - Base64);
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.
140 if (ch == Pad64) { /* We got a pad char. */
141 ch = *src++; /* Skip it, get next. */
143 case 0: /* Invalid = in first position */
144 case 1: /* Invalid = in second position */
147 case 2: /* Valid, means one byte of info */
148 /* Skip any number of spaces. */
149 for (; ch != '\0'; ch = *src++)
152 /* Make sure there is another trailing = sign. */
155 ch = *src++; /* Skip the = */
156 /* Fall through to "single trailing =" case. */
159 case 3: /* Valid, means two bytes of info */
161 * We know this char is an =. Is there anything but
162 * whitespace after it?
164 for (; ch != '\0'; ch = *src++)
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.
174 if (target && target[tarindex] != 0)
179 * We ended by seeing the end of the string. Make sure we
180 * have no partial bytes lying around.
192 * \param src The buffer to decode.
193 * \param target Result buffer.
194 * \param targsize The length of \a target in bytes.
196 * This is just a simple wrapper for base64_decode() which strips whitespace.
198 * \return The return value of the underlying call to base64_decode().
200 int uudecode(const char *src, unsigned char *target, size_t targsize)
205 /* copy the 'readonly' source */
206 encoded = para_strdup(src);
207 /* skip whitespace and data */
208 for (p = encoded; *p == ' ' || *p == '\t'; p++)
210 for (; *p != '\0' && *p != ' ' && *p != '\t'; p++)
212 /* and remove trailing whitespace because base64_decode needs this */
214 len = base64_decode(encoded, target, targsize);
220 * Read a 4-byte number from a buffer in big-endian format.
222 * \param vp The buffer.
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.
227 * \return The 32 bit number given by \a vp.
229 uint32_t read_ssh_u32(const void *vp)
231 const unsigned char *p = (const unsigned char *)vp;
234 v = (uint32_t)p[0] << 24;
235 v |= (uint32_t)p[1] << 16;
236 v |= (uint32_t)p[2] << 8;
243 * Sanity checks for the header of an ssh key.
245 * \param blob The buffer.
246 * \param blen The number of bytes of \a blob.
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,
252 * \return The number of bytes to skip until the start of the first encoded
253 * number (usually 11).
255 int check_ssh_key_header(const unsigned char *blob, int blen)
257 const unsigned char *p = blob, *end = blob + blen;
261 return -E_SSH_KEY_HEADER;
262 rlen = read_ssh_u32(p);
265 return -E_SSH_KEY_HEADER;
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;
277 * Check existence and permissions of a key file.
279 * \param file The path of the key file.
280 * \param private_key Whether this is a private key.
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.
288 int check_key_file(const char *file, bool private_key)
292 if (stat(file, &st) != 0)
293 return -ERRNO_TO_PARA_ERROR(errno);
296 if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0)
301 void hash_to_asc(unsigned char *hash, char *asc)
304 const char hexchar[] = "0123456789abcdef";
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];
310 asc[2 * HASH_SIZE] = '\0';
313 int hash_compare(unsigned char *h1, unsigned char *h2)
317 for (i = 0; i < HASH_SIZE; i++) {
326 int sc_recv_buffer(struct stream_cipher_context *scc, char *buf, size_t size)
331 n = sc_recv_bin_buffer(scc, buf, size - 1);
339 int sc_send_buffer(struct stream_cipher_context *scc, char *buf)
341 return sc_send_bin_buffer(scc, buf, strlen(buf));
344 __printf_2_3 int sc_send_va_buffer(struct stream_cipher_context *scc,
345 const char *fmt, ...)
350 PARA_VSPRINTF(fmt, msg);
351 ret = sc_send_buffer(scc, msg);