Merge branch 'refs/heads/t/portable_io'
[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 #include "portable_io.h"
17
18 /** If the key begins with this text, we treat it as an ssh key. */
19 #define KEY_TYPE_TXT "ssh-rsa"
20
21 /**
22 * Check if given buffer starts with a ssh rsa key signature.
23 *
24 * \param data The buffer.
25 * \param size Number of data bytes.
26 *
27 * \return Number of header bytes to be skipped on success, zero if
28 * ssh rsa signature was not found.
29 */
30 size_t is_ssh_rsa_key(char *data, size_t size)
31 {
32 char *cp;
33
34 if (size < strlen(KEY_TYPE_TXT) + 2)
35 return 0;
36 cp = memchr(data, ' ', size);
37 if (cp == NULL)
38 return 0;
39 if (strncmp(KEY_TYPE_TXT, data, strlen(KEY_TYPE_TXT)))
40 return 0;
41 cp++;
42 if (cp >= data + size)
43 return 0;
44 if (*cp == '\0')
45 return 0;
46 return cp - data;
47 }
48
49 /**
50 * Sanity checks for the header of an ssh key.
51 *
52 * \param blob The buffer.
53 * \param blen The number of bytes of \a blob.
54 *
55 * This performs some checks to make sure we really have an ssh key. It also
56 * computes the offset in bytes of the start of the key values (modulus,
57 * exponent..).
58 *
59 * \return The number of bytes to skip until the start of the first encoded
60 * number (usually 11).
61 */
62 int check_ssh_key_header(const unsigned char *blob, int blen)
63 {
64 const unsigned char *p = blob, *end = blob + blen;
65 uint32_t rlen;
66
67 if (p + 4 > end)
68 return -E_SSH_KEY_HEADER;
69 rlen = read_u32_be(p);
70 p += 4;
71 if (p + rlen < p)
72 return -E_SSH_KEY_HEADER;
73 if (p + rlen > end)
74 return -E_SSH_KEY_HEADER;
75 if (rlen < strlen(KEY_TYPE_TXT))
76 return -E_SSH_KEY_HEADER;
77 PARA_DEBUG_LOG("type: %s, rlen: %u\n", p, rlen);
78 if (strncmp((char *)p, KEY_TYPE_TXT, strlen(KEY_TYPE_TXT)))
79 return -E_SSH_KEY_HEADER;
80 return 4 + rlen;
81 }
82
83 /**
84 * Check existence and permissions of a private key file.
85 *
86 * \param file The path of the key file.
87 *
88 * This checks whether the file exists and its permissions are restrictive
89 * enough. It is considered an error if we own the file and it is readable for
90 * others.
91 *
92 * \return Standard.
93 */
94 int check_private_key_file(const char *file)
95 {
96 struct stat st;
97
98 if (stat(file, &st) != 0)
99 return -ERRNO_TO_PARA_ERROR(errno);
100 if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0)
101 return -E_KEY_PERM;
102 return 1;
103 }
104
105 void hash_to_asc(unsigned char *hash, char *asc)
106 {
107 int i;
108 const char hexchar[] = "0123456789abcdef";
109
110 for (i = 0; i < HASH_SIZE; i++) {
111 asc[2 * i] = hexchar[hash[i] >> 4];
112 asc[2 * i + 1] = hexchar[hash[i] & 0xf];
113 }
114 asc[2 * HASH_SIZE] = '\0';
115 }
116
117 int hash_compare(unsigned char *h1, unsigned char *h2)
118 {
119 int i;
120
121 for (i = 0; i < HASH_SIZE; i++) {
122 if (h1[i] < h2[i])
123 return -1;
124 if (h1[i] > h2[i])
125 return 1;
126 }
127 return 0;
128 }