1 /* Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
3 /** \file crypt_common.c Crypto functions independent of openssl/libgcrypt. */
11 #include "crypt_backend.h"
12 #include "portable_io.h"
16 /** If the key begins with this text, we treat it as an ssh key. */
17 #define KEY_TYPE_TXT "ssh-rsa"
20 * Check if the given buffer starts with an ssh rsa key signature.
22 * Returns number of header bytes to be skipped on success, zero if no ssh rsa
23 * signature was found.
25 static size_t is_ssh_rsa_key(char *data, size_t size)
29 if (size < strlen(KEY_TYPE_TXT) + 2)
31 cp = memchr(data, ' ', size);
34 if (strncmp(KEY_TYPE_TXT, data, strlen(KEY_TYPE_TXT)))
37 if (cp >= data + size)
45 * Perform some sanity checks on the decoded ssh key.
47 * This function returns the size of the header. Usually, the header is 11
48 * bytes long: four bytes for the length field, and the string "ssh-rsa".
50 static int check_ssh_key_header(const unsigned char *blob, int blen)
52 const unsigned char *p = blob, *end = blob + blen;
56 return -E_SSH_KEY_HEADER;
57 rlen = read_u32_be(p);
60 return -E_SSH_KEY_HEADER;
62 return -E_SSH_KEY_HEADER;
63 if (rlen < strlen(KEY_TYPE_TXT))
64 return -E_SSH_KEY_HEADER;
65 PARA_DEBUG_LOG("type: %s, rlen: %u\n", p, rlen);
66 if (strncmp((char *)p, KEY_TYPE_TXT, strlen(KEY_TYPE_TXT)))
67 return -E_SSH_KEY_HEADER;
72 * Perform sanity checks and base64-decode an ssh-rsa key.
74 * \param filename The public key file (usually id_rsa.pub).
75 * \param blob Pointer to base64-decoded blob is returned here.
76 * \param decoded_size The size of the decoded blob.
78 * The memory pointed at by the returned blob pointer has to be freed by the
81 * \return On success, the offset in bytes of the start of the key values
82 * (modulus, exponent..). This is the number of bytes to skip from the blob
83 * until the start of the first encoded number. On failure, a negative error
86 * \sa \ref uudecode().
88 int decode_ssh_key(const char *filename, unsigned char **blob,
95 ret = mmap_full_file(filename, O_RDONLY, &map, &map_size, NULL);
98 ret = is_ssh_rsa_key(map, map_size);
103 ret = uudecode(map + ret, map_size - ret, (char **)blob, decoded_size);
106 ret = check_ssh_key_header(*blob, *decoded_size);
110 ret2 = para_munmap(map, map_size);
111 if (ret >= 0 && ret2 < 0)
117 * Check existence and permissions of a private key file.
119 * \param file The path of the key file.
121 * This checks whether the file exists and its permissions are restrictive
122 * enough. It is considered an error if we own the file and it is readable for
127 int check_private_key_file(const char *file)
131 if (stat(file, &st) != 0)
132 return -ERRNO_TO_PARA_ERROR(errno);
133 if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0)
138 void hash_to_asc(unsigned char *hash, char *asc)
141 const char hexchar[] = "0123456789abcdef";
143 for (i = 0; i < HASH_SIZE; i++) {
144 asc[2 * i] = hexchar[hash[i] >> 4];
145 asc[2 * i + 1] = hexchar[hash[i] & 0xf];
147 asc[2 * HASH_SIZE] = '\0';
150 int hash_compare(unsigned char *h1, unsigned char *h2)
154 for (i = 0; i < HASH_SIZE; i++) {