| /* 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 (valid 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; |
| 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; |
| 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 descriptor 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 occurred. |
| */ |
| 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, |
| struct page *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 |
| * destroy 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 unsuccessful -1 would be returned. |
| */ |
| int cfs_crypto_hash_speed(unsigned char hash_alg); |
| #endif |