crypt: Don't use plain integer as NULL pointer.
[paraslash.git] / crypt_common.c
index 1308af4..8de346c 100644 (file)
@@ -4,7 +4,7 @@
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
  * 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 <regex.h>
 #include <stdbool.h>
 
 #include <regex.h>
 #include <stdbool.h>
@@ -15,6 +15,7 @@
 #include "crypt_backend.h"
 #include "crypt.h"
 
 #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"
 
 /**
 #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 = '=';
 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
  * 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;
 {
        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);
                        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)
 
                switch (state) {
                case 0:
                        if (target) {
                                if (tarindex >= targsize)
-                                       return (-1);
+                                       return -E_BASE64;
                                target[tarindex] = (pos - Base64) << 2;
                        }
                        state = 1;
                                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)
                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 ;
                                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)
                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;
                                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)
                case 3:
                        if (target) {
                                if (tarindex >= targsize)
-                                       return (-1);
+                                       return -E_BASE64;
                                target[tarindex] |= (pos - Base64);
                        }
                        tarindex++;
                                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 */
                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. */
 
                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)
                                        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 */
                        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))
                         */
                        for (; ch != '\0'; ch = *src++)
                                if (!isspace(ch))
-                                       return (-1);
+                                       return -E_BASE64;
 
                        /*
                         * Now make sure for cases 2 and 3 that the "extra"
 
                        /*
                         * 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)
                         * subliminal channel.
                         */
                        if (target && target[tarindex] != 0)
-                               return (-1);
+                               return -E_BASE64;
                }
        } else {
                /*
                }
        } 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)
                 * 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;
 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);
        *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)
 {
  */
 uint32_t read_ssh_u32(const void *vp)
 {
@@ -213,6 +239,19 @@ uint32_t read_ssh_u32(const void *vp)
        return v;
 }
 
        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;
 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;
 }
 
        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;
 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;
 }
 
        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;
 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';
 }
 
        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;
 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;
 }
 
        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;
 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;
 }
 
        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));
 }
 
 {
        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, ...)
 {
 __printf_2_3 int sc_send_va_buffer(struct stream_cipher_context *scc,
                const char *fmt, ...)
 {