Whamcloud - gitweb
LU-1201 checksum: add libcfs crypto hash
[fs/lustre-release.git] / libcfs / include / libcfs / libcfs_crypto.h
diff --git a/libcfs/include/libcfs/libcfs_crypto.h b/libcfs/include/libcfs/libcfs_crypto.h
new file mode 100644 (file)
index 0000000..291191a
--- /dev/null
@@ -0,0 +1,201 @@
+/* GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see http://www.gnu.org/licenses
+ *
+ * Please  visit http://www.xyratex.com/contact if you need additional
+ * information or have any questions.
+ *
+ * GPL HEADER END
+ */
+
+/*
+ * Copyright 2012 Xyratex Technology Limited
+ */
+
+#ifndef _LIBCFS_CRYPTO_H
+#define _LIBCFS_CRYPTO_H
+
+struct cfs_crypto_hash_type {
+       char            *cht_name;      /**< hash algorithm name, equal to
+                                        * format name for crypto api */
+       unsigned int    cht_key;        /**< init key by default (vaild for
+                                        * 4 bytes context like crc32, adler */
+       unsigned int    cht_size;       /**< hash digest size */
+};
+
+enum cfs_crypto_hash_alg {
+       CFS_HASH_ALG_NULL       = 0,
+       CFS_HASH_ALG_ADLER32,
+       CFS_HASH_ALG_CRC32,
+       CFS_HASH_ALG_MD5,
+       CFS_HASH_ALG_SHA1,
+       CFS_HASH_ALG_SHA256,
+       CFS_HASH_ALG_SHA384,
+       CFS_HASH_ALG_SHA512,
+       CFS_HASH_ALG_CRC32C,
+       CFS_HASH_ALG_MAX
+};
+
+static struct cfs_crypto_hash_type hash_types[] = {
+       [CFS_HASH_ALG_NULL]    = { "null",     0,      0 },
+       [CFS_HASH_ALG_ADLER32] = { "adler32",  1,      4 },
+       [CFS_HASH_ALG_CRC32]   = { "crc32",   ~0,      4 },
+       [CFS_HASH_ALG_CRC32C]  = { "crc32c",  ~0,      4 },
+       [CFS_HASH_ALG_MD5]     = { "md5",      0,     16 },
+       [CFS_HASH_ALG_SHA1]    = { "sha1",     0,     20 },
+       [CFS_HASH_ALG_SHA256]  = { "sha256",   0,     32 },
+       [CFS_HASH_ALG_SHA384]  = { "sha384",   0,     48 },
+       [CFS_HASH_ALG_SHA512]  = { "sha512",   0,     64 },
+};
+
+/**    Return pointer to type of hash for valid hash algorithm identifier */
+static inline const struct cfs_crypto_hash_type *
+                   cfs_crypto_hash_type(unsigned char hash_alg)
+{
+       struct cfs_crypto_hash_type *ht;
+
+       if (hash_alg < CFS_HASH_ALG_MAX) {
+               ht = &hash_types[hash_alg];
+               if (ht->cht_name)
+                       return ht;
+       }
+       return NULL;
+}
+
+/**     Return hash name for valid hash algorithm identifier or "unknown" */
+static inline const char *cfs_crypto_hash_name(unsigned char hash_alg)
+{
+       const struct cfs_crypto_hash_type *ht;
+
+       ht = cfs_crypto_hash_type(hash_alg);
+       if (ht)
+               return ht->cht_name;
+       else
+               return "unknown";
+}
+
+/**     Return digest size for valid algorithm identifier or 0 */
+static inline int cfs_crypto_hash_digestsize(unsigned char hash_alg)
+{
+       const struct cfs_crypto_hash_type *ht;
+
+       ht = cfs_crypto_hash_type(hash_alg);
+       if (ht)
+               return ht->cht_size;
+       else
+               return 0;
+}
+
+/**     Return hash identifier for valid hash algorithm name or 0xFF */
+static inline unsigned char cfs_crypto_hash_alg(const char *algname)
+{
+       unsigned char   i;
+
+       for (i = 0; i < CFS_HASH_ALG_MAX; i++)
+               if (!strcmp(hash_types[i].cht_name, algname))
+                       break;
+       return (i == CFS_HASH_ALG_MAX ? 0xFF : i);
+}
+
+/**     Calculate hash digest for buffer.
+ *      @param alg         id of hash algorithm
+ *      @param buf         buffer of data
+ *      @param buf_len buffer len
+ *      @param key         initial value for algorithm, if it is NULL,
+ *                         default initial value should be used.
+ *      @param key_len len of initial value
+ *      @param hash       [out] pointer to hash, if it is NULL, hash_len is
+ *                         set to valid digest size in bytes, retval -ENOSPC.
+ *      @param hash_len       [in,out] size of hash buffer
+ *      @returns             status of operation
+ *      @retval -EINVAL       if buf, buf_len, hash_len or alg_id is invalid
+ *      @retval -ENODEV       if this algorithm is unsupported
+ *      @retval -ENOSPC       if pointer to hash is NULL, or hash_len less than
+ *                         digest size
+ *      @retval 0           for success
+ *      @retval < 0       other errors from lower layers.
+ */
+int cfs_crypto_hash_digest(unsigned char alg,
+                          const void *buf, unsigned int buf_len,
+                          unsigned char *key, unsigned int key_len,
+                          unsigned char *hash, unsigned int *hash_len);
+
+/* cfs crypto hash descriptor */
+struct cfs_crypto_hash_desc;
+
+/**     Allocate and initialize desriptor for hash algorithm.
+ *      @param alg         algorithm id
+ *      @param key         initial value for algorithm, if it is NULL,
+ *                         default initial value should be used.
+ *      @param key_len len of initial value
+ *      @returns             pointer to descriptor of hash instance
+ *      @retval ERR_PTR(error) when errors occured.
+ */
+struct cfs_crypto_hash_desc*
+       cfs_crypto_hash_init(unsigned char alg,
+                            unsigned char *key, unsigned int key_len);
+
+/**    Update digest by part of data.
+ *     @param desc           hash descriptor
+ *     @param page           data page
+ *     @param offset       data offset
+ *     @param len             data len
+ *     @returns                 status of operation
+ *     @retval 0               for success.
+ */
+int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *desc,
+                               cfs_page_t *page, unsigned int offset,
+                               unsigned int len);
+
+/**    Update digest by part of data.
+ *     @param desc           hash descriptor
+ *     @param buf             pointer to data buffer
+ *     @param buf_len     size of data at buffer
+ *     @returns                 status of operation
+ *     @retval 0               for success.
+ */
+int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *desc, const void *buf,
+                          unsigned int buf_len);
+
+/**    Finalize hash calculation, copy hash digest to buffer, destroy hash
+ *     descriptor.
+ *     @param desc           hash descriptor
+ *     @param hash           buffer pointer to store hash digest
+ *     @param hash_len   pointer to hash buffer size, if NULL
+ *                           destory hash descriptor
+ *     @returns                 status of operation
+ *     @retval -ENOSPC   if hash is NULL, or *hash_len less than
+ *                           digest size
+ *     @retval 0               for success
+ *     @retval < 0           other errors from lower layers.
+ */
+int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *desc,
+                         unsigned char *hash, unsigned int *hash_len);
+/**
+ *      Register crypto hash algorithms
+ */
+int cfs_crypto_register(void);
+
+/**
+ *      Unregister
+ */
+void cfs_crypto_unregister(void);
+
+/**     Return hash speed in Mbytes per second for valid hash algorithm
+ *      identifier. If test was unsuccessfull -1 would be return.
+ */
+int cfs_crypto_hash_speed(unsigned char hash_alg);
+#endif