X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=crypt_common.c;h=a05572df85b1de5fb5e1043abfc34c66e26c65e7;hp=3bd603c0ec698ab6be9c3e48d99e7a76e52c53f0;hb=74592ed100009a2d73e03861ae9626363f06aca9;hpb=5957ec3c6deb0a5585f979ff470e9a346154ca62;ds=sidebyside diff --git a/crypt_common.c b/crypt_common.c index 3bd603c0..a05572df 100644 --- a/crypt_common.c +++ b/crypt_common.c @@ -1,20 +1,20 @@ /* - * Copyright (C) 2005-2011 Andre Noll + * Copyright (C) 2005 Andre Noll * * 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 #include "para.h" #include "error.h" #include "string.h" -#include "crypt_backend.h" #include "crypt.h" +#include "crypt_backend.h" +/** If the key begins with this text, we treat it as an ssh key. */ #define KEY_TYPE_TXT "ssh-rsa" /** @@ -45,160 +45,15 @@ size_t is_ssh_rsa_key(char *data, size_t size) return cp - data; } -/* - * This base64/uudecode stuff below is taken from openssh-5.2p1, Copyright (c) - * 1996 by Internet Software Consortium. Portions Copyright (c) 1995 by - * International Business Machines, Inc. - */ - -static const char Base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char Pad64 = '='; -/* - * 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 -E_BASE64 - * on error. - */ -int base64_decode(char const *src, unsigned char *target, size_t targsize) -{ - unsigned int tarindex, state; - int ch; - char *pos; - - state = 0; - tarindex = 0; - - while ((ch = *src++) != '\0') { - if (para_isspace(ch)) /* Skip whitespace anywhere. */ - continue; - - if (ch == Pad64) - break; - - pos = strchr(Base64, ch); - if (pos == 0) /* A non-base64 character. */ - return -E_BASE64; - - switch (state) { - case 0: - if (target) { - if (tarindex >= targsize) - return -E_BASE64; - target[tarindex] = (pos - Base64) << 2; - } - state = 1; - break; - case 1: - if (target) { - if (tarindex + 1 >= targsize) - return -E_BASE64; - target[tarindex] |= (pos - Base64) >> 4; - target[tarindex+1] = ((pos - Base64) & 0x0f) - << 4 ; - } - tarindex++; - state = 2; - break; - case 2: - if (target) { - if (tarindex + 1 >= targsize) - return -E_BASE64; - target[tarindex] |= (pos - Base64) >> 2; - target[tarindex+1] = ((pos - Base64) & 0x03) - << 6; - } - tarindex++; - state = 3; - break; - case 3: - if (target) { - if (tarindex >= targsize) - return -E_BASE64; - target[tarindex] |= (pos - Base64); - } - tarindex++; - state = 0; - break; - } - } - - /* - * We are done decoding Base-64 chars. Let's see if we ended - * on a byte boundary, and/or with erroneous trailing characters. - */ - - if (ch == Pad64) { /* We got a pad char. */ - ch = *src++; /* Skip it, get next. */ - switch (state) { - case 0: /* Invalid = in first position */ - case 1: /* Invalid = in second position */ - return -E_BASE64; - - case 2: /* Valid, means one byte of info */ - /* Skip any number of spaces. */ - for (; ch != '\0'; ch = *src++) - if (!isspace(ch)) - break; - /* Make sure there is another trailing = sign. */ - if (ch != Pad64) - return -E_BASE64; - ch = *src++; /* Skip the = */ - /* Fall through to "single trailing =" case. */ - /* FALLTHROUGH */ - - case 3: /* Valid, means two bytes of info */ - /* - * We know this char is an =. Is there anything but - * whitespace after it? - */ - for (; ch != '\0'; ch = *src++) - if (!isspace(ch)) - return -E_BASE64; - - /* - * Now make sure for cases 2 and 3 that the "extra" - * bits that slopped past the last full byte were - * zeros. If we don't check them, they become a - * subliminal channel. - */ - if (target && target[tarindex] != 0) - return -E_BASE64; - } - } else { - /* - * We ended by seeing the end of the string. Make sure we - * have no partial bytes lying around. - */ - if (state != 0) - return -E_BASE64; - } - - return tarindex; -} - -int uudecode(const char *src, unsigned char *target, size_t targsize) -{ - int len; - char *encoded, *p; - - /* copy the 'readonly' source */ - encoded = para_strdup(src); - /* skip whitespace and data */ - for (p = encoded; *p == ' ' || *p == '\t'; p++) - ; - for (; *p != '\0' && *p != ' ' && *p != '\t'; p++) - ; - /* and remove trailing whitespace because base64_decode needs this */ - *p = '\0'; - len = base64_decode(encoded, target, targsize); - free(encoded); - 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 +68,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; @@ -228,12 +96,24 @@ int check_ssh_key_header(const unsigned char *blob, int blen) return -E_SSH_KEY_HEADER; if (rlen < strlen(KEY_TYPE_TXT)) return -E_SSH_KEY_HEADER; - PARA_DEBUG_LOG("type: %s, rlen: %d\n", p, rlen); + PARA_DEBUG_LOG("type: %s, rlen: %u\n", p, rlen); if (strncmp((char *)p, KEY_TYPE_TXT, strlen(KEY_TYPE_TXT))) return -E_SSH_KEY_HEADER; 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 +127,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 +139,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; @@ -290,62 +151,3 @@ 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; - - assert(size); - n = sc_recv_bin_buffer(scc, buf, size - 1); - if (n >= 0) - buf[n] = '\0'; - else - *buf = '\0'; - 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) -{ - 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, ...) -{ - char *msg; - int ret; - - PARA_VSPRINTF(fmt, msg); - ret = sc_send_buffer(scc, msg); - free(msg); - return ret; -}