aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/lustre/include/linux/libcfs/libcfs_crypto.h
blob: 64ca62f0cc930f65c3454e78c5982893fcdbb237 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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,
				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
 *			      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