X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=crypt_common.c;h=8de346c74b47468a15c566cae29a4ff484b056c6;hp=1308af4148851246fbf328c2d4037a44dc43ac39;hb=72f53a08032153d2fd6b2b5811d797358ad86f96;hpb=6a7393e2abdcf30dd4201b84a417d08f6136e8d6 diff --git a/crypt_common.c b/crypt_common.c index 1308af41..8de346c7 100644 --- a/crypt_common.c +++ b/crypt_common.c @@ -4,7 +4,7 @@ * Licensed under the GPL v2. For licencing details see COPYING. */ -/** \file crypt_common.c Crypto functions independent of the implementation. */ +/** \file crypt_common.c Crypto functions independent of openssl/libgcrypt. */ #include #include @@ -15,6 +15,7 @@ #include "crypt_backend.h" #include "crypt.h" +/** If the key begins with this text, we treat it as an ssh key. */ #define KEY_TYPE_TXT "ssh-rsa" /** @@ -54,13 +55,21 @@ size_t is_ssh_rsa_key(char *data, size_t size) static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char Pad64 = '='; -/* + +/** + * base64-decode a buffer. + * + * \param src The buffer to decode. + * \param target Result is stored here. + * \param targsize Number of bytes of \a target. + * * Skips all whitespace anywhere. Converts characters, four at a time, starting * at (or after) src from base - 64 numbers into three 8 bit bytes in the - * target area. it returns the number of data bytes stored at the target, or -1 - * on error. + * target area. + * + * \return The number of data bytes stored at the target, -E_BASE64 on errors. */ -static int base64_decode(char const *src, unsigned char *target, size_t targsize) +int base64_decode(char const *src, unsigned char *target, size_t targsize) { unsigned int tarindex, state; int ch; @@ -77,14 +86,14 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize break; pos = strchr(Base64, ch); - if (pos == 0) /* A non-base64 character. */ - return -1; + if (pos == NULL) /* A non-base64 character. */ + return -E_BASE64; switch (state) { case 0: if (target) { if (tarindex >= targsize) - return (-1); + return -E_BASE64; target[tarindex] = (pos - Base64) << 2; } state = 1; @@ -92,7 +101,7 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize case 1: if (target) { if (tarindex + 1 >= targsize) - return (-1); + return -E_BASE64; target[tarindex] |= (pos - Base64) >> 4; target[tarindex+1] = ((pos - Base64) & 0x0f) << 4 ; @@ -103,7 +112,7 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize case 2: if (target) { if (tarindex + 1 >= targsize) - return (-1); + return -E_BASE64; target[tarindex] |= (pos - Base64) >> 2; target[tarindex+1] = ((pos - Base64) & 0x03) << 6; @@ -114,7 +123,7 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize case 3: if (target) { if (tarindex >= targsize) - return (-1); + return -E_BASE64; target[tarindex] |= (pos - Base64); } tarindex++; @@ -133,7 +142,7 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize switch (state) { case 0: /* Invalid = in first position */ case 1: /* Invalid = in second position */ - return (-1); + return -E_BASE64; case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ @@ -142,7 +151,7 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize break; /* Make sure there is another trailing = sign. */ if (ch != Pad64) - return (-1); + return -E_BASE64; ch = *src++; /* Skip the = */ /* Fall through to "single trailing =" case. */ /* FALLTHROUGH */ @@ -154,7 +163,7 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize */ for (; ch != '\0'; ch = *src++) if (!isspace(ch)) - return (-1); + return -E_BASE64; /* * Now make sure for cases 2 and 3 that the "extra" @@ -163,7 +172,7 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize * subliminal channel. */ if (target && target[tarindex] != 0) - return (-1); + return -E_BASE64; } } else { /* @@ -171,12 +180,23 @@ static int base64_decode(char const *src, unsigned char *target, size_t targsize * have no partial bytes lying around. */ if (state != 0) - return (-1); + return -E_BASE64; } - return (tarindex); + return tarindex; } +/** + * uudecode a buffer. + * + * \param src The buffer to decode. + * \param target Result buffer. + * \param targsize The length of \a target in bytes. + * + * This is just a simple wrapper for base64_decode() which strips whitespace. + * + * \return The return value of the underlying call to base64_decode(). + */ int uudecode(const char *src, unsigned char *target, size_t targsize) { int len; @@ -193,12 +213,18 @@ int uudecode(const char *src, unsigned char *target, size_t targsize) *p = '\0'; len = base64_decode(encoded, target, targsize); free(encoded); - return len >= 0? len : -E_BASE64; + return len; } -/* - * Can not use the inline functions of portable_io.h here because the byte - * order is different. +/** + * Read a 4-byte number from a buffer in big-endian format. + * + * \param vp The buffer. + * + * The byte-order of the buffer is expected to be big-endian, unlike read_u32() + * of portable_io.h which expects little endian. + * + * \return The 32 bit number given by \a vp. */ uint32_t read_ssh_u32(const void *vp) { @@ -213,6 +239,19 @@ uint32_t read_ssh_u32(const void *vp) return v; } +/** + * Sanity checks for the header of an ssh key. + * + * \param blob The buffer. + * \param blen The number of bytes of \a blob. + * + * This performs some checks to make sure we really have an ssh key. It also + * computes the offset in bytes of the start of the key values (modulus, + * exponent..). + * + * \return The number of bytes to skip until the start of the first encoded + * number (usually 11). + */ int check_ssh_key_header(const unsigned char *blob, int blen) { const unsigned char *p = blob, *end = blob + blen; @@ -234,6 +273,18 @@ int check_ssh_key_header(const unsigned char *blob, int blen) return 4 + rlen; } +/** + * Check existence and permissions of a key file. + * + * \param file The path of the key file. + * \param private_key Whether this is a private key. + * + * This checks whether the file exists. If it is a private key, we additionally + * check that the permissions are restrictive enough. It is considered an error + * if we own the file and it is readable for others. + * + * \return Standard. + */ int check_key_file(const char *file, bool private_key) { struct stat st; @@ -247,16 +298,6 @@ int check_key_file(const char *file, bool private_key) return 1; } -/** - * Convert a hash value to ascii format. - * - * \param hash the hash value. - * \param asc Result pointer. - * - * \a asc must point to an area of at least 2 * \p HASH_SIZE + 1 bytes which - * will be filled by the function with the ascii representation of the hash - * value given by \a hash, and a terminating \p NULL byte. - */ void hash_to_asc(unsigned char *hash, char *asc) { int i; @@ -269,15 +310,6 @@ void hash_to_asc(unsigned char *hash, char *asc) asc[2 * HASH_SIZE] = '\0'; } -/** - * Compare two hashes. - * - * \param h1 Pointer to the first hash value. - * \param h2 Pointer to the second hash value. - * - * \return 1, -1, or zero, depending on whether \a h1 is greater than, - * less than or equal to h2, respectively. - */ int hash_compare(unsigned char *h1, unsigned char *h2) { int i; @@ -291,19 +323,6 @@ int hash_compare(unsigned char *h1, unsigned char *h2) return 0; } -/** - * Receive a buffer, decrypt it and write terminating NULL byte. - * - * \param scc The context. - * \param buf The buffer to write the decrypted data to. - * \param size The size of \a buf. - * - * Read at most \a size - 1 bytes from file descriptor given by \a scc, decrypt - * the received data and write a NULL byte at the end of the decrypted data. - * - * \return The return value of the underlying call to \ref - * sc_recv_bin_buffer(). - */ int sc_recv_buffer(struct stream_cipher_context *scc, char *buf, size_t size) { int n; @@ -317,27 +336,11 @@ int sc_recv_buffer(struct stream_cipher_context *scc, char *buf, size_t size) return n; } -/** - * Encrypt and send a \p NULL-terminated buffer. - * - * \param scc The context. - * \param buf The buffer to send. - * - * \return The return value of the underyling call to sc_send_bin_buffer(). - */ -int sc_send_buffer(struct stream_cipher_context *scc, const char *buf) +int sc_send_buffer(struct stream_cipher_context *scc, char *buf) { return sc_send_bin_buffer(scc, buf, strlen(buf)); } -/** - * Format, encrypt and send a buffer. - * - * \param scc The context. - * \param fmt A format string. - * - * \return The return value of the underyling call to sc_send_buffer(). - */ __printf_2_3 int sc_send_va_buffer(struct stream_cipher_context *scc, const char *fmt, ...) {