return 1;
}
-void hash_to_asc(unsigned char *hash, char *asc)
+void hash_to_asc(const unsigned char *hash, char *asc)
{
int i;
const char hexchar[] = "0123456789abcdef";
asc[2 * HASH_SIZE] = '\0';
}
-int hash_compare(unsigned char *h1, unsigned char *h2)
+int hash_compare(const unsigned char *h1, const unsigned char *h2)
{
int i;
return 0;
}
+void hash2_to_asc(const unsigned char *hash, char *asc)
+{
+ int i;
+ const char hexchar[] = "0123456789abcdef";
+
+ for (i = 0; i < HASH2_SIZE; i++) {
+ asc[2 * i] = hexchar[hash[i] >> 4];
+ asc[2 * i + 1] = hexchar[hash[i] & 0xf];
+ }
+ asc[2 * HASH2_SIZE] = '\0';
+}
+
+int hash2_compare(const unsigned char *h1, const unsigned char *h2)
+{
+ int i;
+
+ for (i = 0; i < HASH2_SIZE; i++) {
+ if (h1[i] < h2[i])
+ return -1;
+ if (h1[i] > h2[i])
+ return 1;
+ }
+ return 0;
+}
+
/**
* Check header of an openssh private key and compute bignum offset.
*
return p - data;
}
+/** Private PEM keys (legacy format) start with this header. */
+#define PRIVATE_PEM_KEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
+/** Private OPENSSH keys (RFC4716) start with this header. */
+#define PRIVATE_OPENSSH_KEY_HEADER "-----BEGIN OPENSSH PRIVATE KEY-----"
+/** Private PEM keys (legacy format) end with this footer. */
+#define PRIVATE_PEM_KEY_FOOTER "-----END RSA PRIVATE KEY-----"
+/** Private OPENSSH keys (RFC4716) end with this footer. */
+#define PRIVATE_OPENSSH_KEY_FOOTER "-----END OPENSSH PRIVATE KEY-----"
+
+/**
+ * Decode an openssh-v1 (aka RFC4716) or PEM (aka ASN.1) private key.
+ *
+ * \param key_file The private key file (usually id_rsa).
+ * \param result Pointer to base64-decoded blob is returned here.
+ * \param blob_size The size of the decoded blob.
+ *
+ * This only checks header and footer and base64-decodes the part in between.
+ * No attempt to read the decoded part is made.
+ *
+ * \return Negative on errors, PKT_PEM or PKT_OPENSSH on success, indicating
+ * the type of key.
+ */
+int decode_private_key(const char *key_file, unsigned char **result,
+ size_t *blob_size)
+{
+ int ret, ret2, i, j, key_type;
+ void *map;
+ size_t map_size, key_size;
+ unsigned char *blob = NULL;
+ char *begin, *footer, *key;
+
+ ret = mmap_full_file(key_file, O_RDONLY, &map, &map_size, NULL);
+ if (ret < 0)
+ goto out;
+ ret = -E_KEY_MARKER;
+ if (strncmp(map, PRIVATE_PEM_KEY_HEADER,
+ strlen(PRIVATE_PEM_KEY_HEADER)) == 0) {
+ key_type = PKT_PEM;
+ begin = map + strlen(PRIVATE_PEM_KEY_HEADER);
+ footer = strstr(map, PRIVATE_PEM_KEY_FOOTER);
+ PARA_WARNING_LOG("detected legacy PEM key %s\n", key_file);
+ } else if (strncmp(map, PRIVATE_OPENSSH_KEY_HEADER,
+ strlen(PRIVATE_OPENSSH_KEY_HEADER)) == 0) {
+ key_type = PKT_OPENSSH;
+ begin = map + strlen(PRIVATE_OPENSSH_KEY_HEADER);
+ footer = strstr(map, PRIVATE_OPENSSH_KEY_FOOTER);
+ PARA_INFO_LOG("detected openssh key %s\n", key_file);
+ } else
+ goto unmap;
+ if (!footer)
+ goto unmap;
+ /* skip whitespace at the beginning */
+ for (; begin < footer; begin++) {
+ if (para_isspace(*begin))
+ continue;
+ break;
+ }
+ ret = -E_KEY_MARKER;
+ if (begin >= footer)
+ goto unmap;
+
+ key_size = footer - begin;
+ key = alloc(key_size + 1);
+ for (i = 0, j = 0; begin + i < footer; i++) {
+ if (para_isspace(begin[i]))
+ continue;
+ key[j++] = begin[i];
+ }
+ key[j] = '\0';
+ ret = base64_decode(key, j, (char **)&blob, blob_size);
+ free(key);
+ if (ret < 0)
+ goto unmap;
+ ret = key_type;
+unmap:
+ ret2 = para_munmap(map, map_size);
+ if (ret >= 0 && ret2 < 0)
+ ret = ret2;
+ if (ret < 0) {
+ free(blob);
+ blob = NULL;
+ }
+out:
+ *result = blob;
+ return ret;
+}
+