1 /* GPL HEADER START
2 *
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 only,
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License version 2 for more details (a copy is included
13 * in the LICENSE file that accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License
16 * version 2 along with this program; If not, see http://www.gnu.org/licenses
17 *
18 * Please visit http://www.xyratex.com/contact if you need additional
19 * information or have any questions.
20 *
21 * GPL HEADER END
22 */
23
24 /*
25 * Copyright 2012 Xyratex Technology Limited
26 */
27
28 #ifndef _LIBCFS_CRYPTO_H
29 #define _LIBCFS_CRYPTO_H
30
31 struct cfs_crypto_hash_type {
32 char *cht_name; /**< hash algorithm name, equal to
33 * format name for crypto api */
34 unsigned int cht_key; /**< init key by default (valid for
35 * 4 bytes context like crc32, adler */
36 unsigned int cht_size; /**< hash digest size */
37 };
38
39 enum cfs_crypto_hash_alg {
40 CFS_HASH_ALG_NULL = 0,
41 CFS_HASH_ALG_ADLER32,
42 CFS_HASH_ALG_CRC32,
43 CFS_HASH_ALG_MD5,
44 CFS_HASH_ALG_SHA1,
45 CFS_HASH_ALG_SHA256,
46 CFS_HASH_ALG_SHA384,
47 CFS_HASH_ALG_SHA512,
48 CFS_HASH_ALG_CRC32C,
49 CFS_HASH_ALG_MAX
50 };
51
52 static struct cfs_crypto_hash_type hash_types[] = {
53 [CFS_HASH_ALG_NULL] = { "null", 0, 0 },
54 [CFS_HASH_ALG_ADLER32] = { "adler32", 1, 4 },
55 [CFS_HASH_ALG_CRC32] = { "crc32", ~0, 4 },
56 [CFS_HASH_ALG_CRC32C] = { "crc32c", ~0, 4 },
57 [CFS_HASH_ALG_MD5] = { "md5", 0, 16 },
58 [CFS_HASH_ALG_SHA1] = { "sha1", 0, 20 },
59 [CFS_HASH_ALG_SHA256] = { "sha256", 0, 32 },
60 [CFS_HASH_ALG_SHA384] = { "sha384", 0, 48 },
61 [CFS_HASH_ALG_SHA512] = { "sha512", 0, 64 },
62 };
63
64 /** Return pointer to type of hash for valid hash algorithm identifier */
65 static inline const struct cfs_crypto_hash_type *
cfs_crypto_hash_type(unsigned char hash_alg)66 cfs_crypto_hash_type(unsigned char hash_alg)
67 {
68 struct cfs_crypto_hash_type *ht;
69
70 if (hash_alg < CFS_HASH_ALG_MAX) {
71 ht = &hash_types[hash_alg];
72 if (ht->cht_name)
73 return ht;
74 }
75 return NULL;
76 }
77
78 /** Return hash name for valid hash algorithm identifier or "unknown" */
cfs_crypto_hash_name(unsigned char hash_alg)79 static inline const char *cfs_crypto_hash_name(unsigned char hash_alg)
80 {
81 const struct cfs_crypto_hash_type *ht;
82
83 ht = cfs_crypto_hash_type(hash_alg);
84 if (ht)
85 return ht->cht_name;
86 return "unknown";
87 }
88
89 /** Return digest size for valid algorithm identifier or 0 */
cfs_crypto_hash_digestsize(unsigned char hash_alg)90 static inline int cfs_crypto_hash_digestsize(unsigned char hash_alg)
91 {
92 const struct cfs_crypto_hash_type *ht;
93
94 ht = cfs_crypto_hash_type(hash_alg);
95 if (ht)
96 return ht->cht_size;
97 return 0;
98 }
99
100 /** Return hash identifier for valid hash algorithm name or 0xFF */
cfs_crypto_hash_alg(const char * algname)101 static inline unsigned char cfs_crypto_hash_alg(const char *algname)
102 {
103 unsigned char i;
104
105 for (i = 0; i < CFS_HASH_ALG_MAX; i++)
106 if (!strcmp(hash_types[i].cht_name, algname))
107 break;
108 return (i == CFS_HASH_ALG_MAX ? 0xFF : i);
109 }
110
111 /** Calculate hash digest for buffer.
112 * @param alg id of hash algorithm
113 * @param buf buffer of data
114 * @param buf_len buffer len
115 * @param key initial value for algorithm, if it is NULL,
116 * default initial value should be used.
117 * @param key_len len of initial value
118 * @param hash [out] pointer to hash, if it is NULL, hash_len is
119 * set to valid digest size in bytes, retval -ENOSPC.
120 * @param hash_len [in,out] size of hash buffer
121 * @returns status of operation
122 * @retval -EINVAL if buf, buf_len, hash_len or alg_id is invalid
123 * @retval -ENODEV if this algorithm is unsupported
124 * @retval -ENOSPC if pointer to hash is NULL, or hash_len less than
125 * digest size
126 * @retval 0 for success
127 * @retval < 0 other errors from lower layers.
128 */
129 int cfs_crypto_hash_digest(unsigned char alg,
130 const void *buf, unsigned int buf_len,
131 unsigned char *key, unsigned int key_len,
132 unsigned char *hash, unsigned int *hash_len);
133
134 /* cfs crypto hash descriptor */
135 struct cfs_crypto_hash_desc;
136
137 /** Allocate and initialize descriptor for hash algorithm.
138 * @param alg algorithm id
139 * @param key initial value for algorithm, if it is NULL,
140 * default initial value should be used.
141 * @param key_len len of initial value
142 * @returns pointer to descriptor of hash instance
143 * @retval ERR_PTR(error) when errors occurred.
144 */
145 struct cfs_crypto_hash_desc*
146 cfs_crypto_hash_init(unsigned char alg,
147 unsigned char *key, unsigned int key_len);
148
149 /** Update digest by part of data.
150 * @param desc hash descriptor
151 * @param page data page
152 * @param offset data offset
153 * @param len data len
154 * @returns status of operation
155 * @retval 0 for success.
156 */
157 int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *desc,
158 struct page *page, unsigned int offset,
159 unsigned int len);
160
161 /** Update digest by part of data.
162 * @param desc hash descriptor
163 * @param buf pointer to data buffer
164 * @param buf_len size of data at buffer
165 * @returns status of operation
166 * @retval 0 for success.
167 */
168 int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *desc, const void *buf,
169 unsigned int buf_len);
170
171 /** Finalize hash calculation, copy hash digest to buffer, destroy hash
172 * descriptor.
173 * @param desc hash descriptor
174 * @param hash buffer pointer to store hash digest
175 * @param hash_len pointer to hash buffer size, if NULL
176 * destroy hash descriptor
177 * @returns status of operation
178 * @retval -ENOSPC if hash is NULL, or *hash_len less than
179 * digest size
180 * @retval 0 for success
181 * @retval < 0 other errors from lower layers.
182 */
183 int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *desc,
184 unsigned char *hash, unsigned int *hash_len);
185 /**
186 * Register crypto hash algorithms
187 */
188 int cfs_crypto_register(void);
189
190 /**
191 * Unregister
192 */
193 void cfs_crypto_unregister(void);
194
195 /** Return hash speed in Mbytes per second for valid hash algorithm
196 * identifier. If test was unsuccessful -1 would be returned.
197 */
198 int cfs_crypto_hash_speed(unsigned char hash_alg);
199 #endif
200