load_chunk_table(): Don't trust afhi->chunks_total.
[paraslash.git] / crypt_common.c
1 /*
2  * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /** \file crypt_common.c Crypto functions independent of openssl/libgcrypt. */
8
9 #include <regex.h>
10
11 #include "para.h"
12 #include "error.h"
13 #include "string.h"
14 #include "crypt.h"
15 #include "crypt_backend.h"
16
17 /** If the key begins with this text, we treat it as an ssh key. */
18 #define KEY_TYPE_TXT "ssh-rsa"
19
20 /**
21  * Check if given buffer starts with a ssh rsa key signature.
22  *
23  * \param data The buffer.
24  * \param size Number of data bytes.
25  *
26  * \return Number of header bytes to be skipped on success, zero if
27  * ssh rsa signature was not found.
28  */
29 size_t is_ssh_rsa_key(char *data, size_t size)
30 {
31         char *cp;
32
33         if (size < strlen(KEY_TYPE_TXT) + 2)
34                 return 0;
35         cp = memchr(data, ' ', size);
36         if (cp == NULL)
37                 return 0;
38         if (strncmp(KEY_TYPE_TXT, data, strlen(KEY_TYPE_TXT)))
39                 return 0;
40         cp++;
41         if (cp >= data + size)
42                 return 0;
43         if (*cp == '\0')
44                 return 0;
45         return cp - data;
46 }
47
48 /**
49  * Read a 4-byte number from a buffer in big-endian format.
50  *
51  * \param vp The buffer.
52  *
53  * The byte-order of the buffer is expected to be big-endian, unlike read_u32()
54  * of portable_io.h which expects little endian.
55  *
56  * \return The 32 bit number given by \a vp.
57  */
58 uint32_t read_ssh_u32(const void *vp)
59 {
60         const unsigned char *p = (const unsigned char *)vp;
61         uint32_t v;
62
63         v  = (uint32_t)p[0] << 24;
64         v |= (uint32_t)p[1] << 16;
65         v |= (uint32_t)p[2] << 8;
66         v |= (uint32_t)p[3];
67
68         return v;
69 }
70
71 /**
72  * Sanity checks for the header of an ssh key.
73  *
74  * \param blob The buffer.
75  * \param blen The number of bytes of \a blob.
76  *
77  * This performs some checks to make sure we really have an ssh key. It also
78  * computes the offset in bytes of the start of the key values (modulus,
79  * exponent..).
80  *
81  * \return The number of bytes to skip until the start of the first encoded
82  * number (usually 11).
83  */
84 int check_ssh_key_header(const unsigned char *blob, int blen)
85 {
86         const unsigned char *p = blob, *end = blob + blen;
87         uint32_t rlen;
88
89         if (p + 4 > end)
90                 return -E_SSH_KEY_HEADER;
91         rlen = read_ssh_u32(p);
92         p += 4;
93         if (p + rlen < p)
94                 return -E_SSH_KEY_HEADER;
95         if (p + rlen > end)
96                 return -E_SSH_KEY_HEADER;
97         if (rlen < strlen(KEY_TYPE_TXT))
98                 return -E_SSH_KEY_HEADER;
99         PARA_DEBUG_LOG("type: %s, rlen: %u\n", p, rlen);
100         if (strncmp((char *)p, KEY_TYPE_TXT, strlen(KEY_TYPE_TXT)))
101                 return -E_SSH_KEY_HEADER;
102         return 4 + rlen;
103 }
104
105 /**
106  * Check existence and permissions of a key file.
107  *
108  * \param file The path of the key file.
109  * \param private_key Whether this is a private key.
110  *
111  * This checks whether the file exists. If it is a private key, we additionally
112  * check that the permissions are restrictive enough. It is considered an error
113  * if we own the file and it is readable for others.
114  *
115  * \return Standard.
116  */
117 int check_key_file(const char *file, bool private_key)
118 {
119         struct stat st;
120
121         if (stat(file, &st) != 0)
122                 return -ERRNO_TO_PARA_ERROR(errno);
123         if (!private_key)
124                 return 0;
125         if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0)
126                 return -E_KEY_PERM;
127         return 1;
128 }
129
130 void hash_to_asc(unsigned char *hash, char *asc)
131 {
132         int i;
133         const char hexchar[] = "0123456789abcdef";
134
135         for (i = 0; i < HASH_SIZE; i++) {
136                 asc[2 * i] = hexchar[hash[i] >> 4];
137                 asc[2 * i + 1] = hexchar[hash[i] & 0xf];
138         }
139         asc[2 * HASH_SIZE] = '\0';
140 }
141
142 int hash_compare(unsigned char *h1, unsigned char *h2)
143 {
144         int i;
145
146         for (i = 0; i < HASH_SIZE; i++) {
147                 if (h1[i] < h2[i])
148                         return -1;
149                 if (h1[i] > h2[i])
150                         return 1;
151         }
152         return 0;
153 }