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 the implementation. */
15 #include "crypt_backend.h"
18 #define KEY_TYPE_TXT "ssh-rsa"
21 * Check if given buffer starts with a ssh rsa key signature.
23 * \param data The buffer.
24 * \param size Number of data bytes.
26 * \return Number of header bytes to be skipped on success, zero if
27 * ssh rsa signature was not found.
29 size_t is_ssh_rsa_key(char *data
, size_t size
)
33 if (size
< strlen(KEY_TYPE_TXT
) + 2)
35 cp
= memchr(data
, ' ', size
);
38 if (strncmp(KEY_TYPE_TXT
, data
, strlen(KEY_TYPE_TXT
)))
41 if (cp
>= data
+ size
)
49 * This base64/uudecode stuff below is taken from openssh-5.2p1, Copyright (c)
50 * 1996 by Internet Software Consortium. Portions Copyright (c) 1995 by
51 * International Business Machines, Inc.
54 static const char Base64
[] =
55 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
56 static const char Pad64
= '=';
58 * Skips all whitespace anywhere. Converts characters, four at a time, starting
59 * at (or after) src from base - 64 numbers into three 8 bit bytes in the
60 * target area. it returns the number of data bytes stored at the target, or -E_BASE64
63 int base64_decode(char const *src
, unsigned char *target
, size_t targsize
)
65 unsigned int tarindex
, state
;
72 while ((ch
= *src
++) != '\0') {
73 if (para_isspace(ch
)) /* Skip whitespace anywhere. */
79 pos
= strchr(Base64
, ch
);
80 if (pos
== 0) /* A non-base64 character. */
86 if (tarindex
>= targsize
)
88 target
[tarindex
] = (pos
- Base64
) << 2;
94 if (tarindex
+ 1 >= targsize
)
96 target
[tarindex
] |= (pos
- Base64
) >> 4;
97 target
[tarindex
+1] = ((pos
- Base64
) & 0x0f)
105 if (tarindex
+ 1 >= targsize
)
107 target
[tarindex
] |= (pos
- Base64
) >> 2;
108 target
[tarindex
+1] = ((pos
- Base64
) & 0x03)
116 if (tarindex
>= targsize
)
118 target
[tarindex
] |= (pos
- Base64
);
127 * We are done decoding Base-64 chars. Let's see if we ended
128 * on a byte boundary, and/or with erroneous trailing characters.
131 if (ch
== Pad64
) { /* We got a pad char. */
132 ch
= *src
++; /* Skip it, get next. */
134 case 0: /* Invalid = in first position */
135 case 1: /* Invalid = in second position */
138 case 2: /* Valid, means one byte of info */
139 /* Skip any number of spaces. */
140 for (; ch
!= '\0'; ch
= *src
++)
143 /* Make sure there is another trailing = sign. */
146 ch
= *src
++; /* Skip the = */
147 /* Fall through to "single trailing =" case. */
150 case 3: /* Valid, means two bytes of info */
152 * We know this char is an =. Is there anything but
153 * whitespace after it?
155 for (; ch
!= '\0'; ch
= *src
++)
160 * Now make sure for cases 2 and 3 that the "extra"
161 * bits that slopped past the last full byte were
162 * zeros. If we don't check them, they become a
163 * subliminal channel.
165 if (target
&& target
[tarindex
] != 0)
170 * We ended by seeing the end of the string. Make sure we
171 * have no partial bytes lying around.
180 int uudecode(const char *src
, unsigned char *target
, size_t targsize
)
185 /* copy the 'readonly' source */
186 encoded
= para_strdup(src
);
187 /* skip whitespace and data */
188 for (p
= encoded
; *p
== ' ' || *p
== '\t'; p
++)
190 for (; *p
!= '\0' && *p
!= ' ' && *p
!= '\t'; p
++)
192 /* and remove trailing whitespace because base64_decode needs this */
194 len
= base64_decode(encoded
, target
, targsize
);
200 * Can not use the inline functions of portable_io.h here because the byte
201 * order is different.
203 uint32_t read_ssh_u32(const void *vp
)
205 const unsigned char *p
= (const unsigned char *)vp
;
208 v
= (uint32_t)p
[0] << 24;
209 v
|= (uint32_t)p
[1] << 16;
210 v
|= (uint32_t)p
[2] << 8;
216 int check_ssh_key_header(const unsigned char *blob
, int blen
)
218 const unsigned char *p
= blob
, *end
= blob
+ blen
;
222 return -E_SSH_KEY_HEADER
;
223 rlen
= read_ssh_u32(p
);
226 return -E_SSH_KEY_HEADER
;
228 return -E_SSH_KEY_HEADER
;
229 if (rlen
< strlen(KEY_TYPE_TXT
))
230 return -E_SSH_KEY_HEADER
;
231 PARA_DEBUG_LOG("type: %s, rlen: %d\n", p
, rlen
);
232 if (strncmp((char *)p
, KEY_TYPE_TXT
, strlen(KEY_TYPE_TXT
)))
233 return -E_SSH_KEY_HEADER
;
237 int check_key_file(const char *file
, bool private_key
)
241 if (stat(file
, &st
) != 0)
242 return -ERRNO_TO_PARA_ERROR(errno
);
245 if ((st
.st_uid
== getuid()) && (st
.st_mode
& 077) != 0)
250 void hash_to_asc(unsigned char *hash
, char *asc
)
253 const char hexchar
[] = "0123456789abcdef";
255 for (i
= 0; i
< HASH_SIZE
; i
++) {
256 asc
[2 * i
] = hexchar
[hash
[i
] >> 4];
257 asc
[2 * i
+ 1] = hexchar
[hash
[i
] & 0xf];
259 asc
[2 * HASH_SIZE
] = '\0';
262 int hash_compare(unsigned char *h1
, unsigned char *h2
)
266 for (i
= 0; i
< HASH_SIZE
; i
++) {
275 int sc_recv_buffer(struct stream_cipher_context
*scc
, char *buf
, size_t size
)
280 n
= sc_recv_bin_buffer(scc
, buf
, size
- 1);
288 int sc_send_buffer(struct stream_cipher_context
*scc
, char *buf
)
290 return sc_send_bin_buffer(scc
, buf
, strlen(buf
));
293 __printf_2_3
int sc_send_va_buffer(struct stream_cipher_context
*scc
,
294 const char *fmt
, ...)
299 PARA_VSPRINTF(fmt
, msg
);
300 ret
= sc_send_buffer(scc
, msg
);