Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/* 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,
	CFS_HASH_ALG_UNKNOWN	= 0xff
};

static struct cfs_crypto_hash_type hash_types[] = {
	[CFS_HASH_ALG_NULL] = {
		.cht_name	= "null",
		.cht_key	= 0,
		.cht_size	= 0
	},
	[CFS_HASH_ALG_ADLER32] = {
		.cht_name	= "adler32",
		.cht_key	= 1,
		.cht_size	= 4
	},
	[CFS_HASH_ALG_CRC32] = {
		.cht_name	= "crc32",
		.cht_key	= ~0,
		.cht_size	= 4
	},
	[CFS_HASH_ALG_CRC32C] = {
		.cht_name	= "crc32c",
		.cht_key	= ~0,
		.cht_size	= 4
	},
	[CFS_HASH_ALG_MD5] = {
		.cht_name	= "md5",
		.cht_key	= 0,
		.cht_size	= 16
	},
	[CFS_HASH_ALG_SHA1] = {
		.cht_name	= "sha1",
		.cht_key	= 0,
		.cht_size	= 20
	},
	[CFS_HASH_ALG_SHA256] = {
		.cht_name	= "sha256",
		.cht_key	= 0,
		.cht_size	= 32
	},
	[CFS_HASH_ALG_SHA384] = {
		.cht_name	= "sha384",
		.cht_key	= 0,
		.cht_size	= 48
	},
	[CFS_HASH_ALG_SHA512] = {
		.cht_name	= "sha512",
		.cht_key	= 0,
		.cht_size	= 64
	},
	[CFS_HASH_ALG_MAX] = {
		.cht_name	= NULL,
		.cht_key	= 0,
		.cht_size	= 64
	},
};

/* Maximum size of hash_types[].cht_size */
#define CFS_CRYPTO_HASH_DIGESTSIZE_MAX	64

/**
 * Return hash algorithm information for the specified algorithm identifier
 *
 * Hash information includes algorithm name, initial seed, hash size.
 *
 * \retval	cfs_crypto_hash_type for valid ID (CFS_HASH_ALG_*)
 * \retval	NULL for unknown algorithm identifier
 */
static inline const struct cfs_crypto_hash_type *
cfs_crypto_hash_type(enum cfs_crypto_hash_alg 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 hash algorithm identifier
 *
 * \param[in]	hash_alg hash alrgorithm id (CFS_HASH_ALG_*)
 *
 * \retval	string name of known hash algorithm
 * \retval	"unknown" if hash algorithm is unknown
 */
static inline const char *
cfs_crypto_hash_name(enum cfs_crypto_hash_alg 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 hash algorithm type
 *
 * \param[in]	hash_alg hash alrgorithm id (CFS_HASH_ALG_*)
 *
 * \retval	hash algorithm digest size in bytes
 * \retval	0 if hash algorithm type is unknown
 */
static inline int cfs_crypto_hash_digestsize(enum cfs_crypto_hash_alg hash_alg)
{
	const struct cfs_crypto_hash_type *ht;

	ht = cfs_crypto_hash_type(hash_alg);
	if (ht)
		return ht->cht_size;
	return 0;
}

/**
 * Find hash algorithm ID for the specified algorithm name
 *
 * \retval	hash algorithm ID for valid ID (CFS_HASH_ALG_*)
 * \retval	CFS_HASH_ALG_UNKNOWN for unknown algorithm name
 */
static inline unsigned char cfs_crypto_hash_alg(const char *algname)
{
	enum cfs_crypto_hash_alg hash_alg;

	for (hash_alg = 0; hash_alg < CFS_HASH_ALG_MAX; hash_alg++)
		if (!strcmp(hash_types[hash_alg].cht_name, algname))
			return hash_alg;

	return CFS_HASH_ALG_UNKNOWN;
}

int cfs_crypto_hash_digest(enum cfs_crypto_hash_alg hash_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;

struct cfs_crypto_hash_desc *
cfs_crypto_hash_init(enum cfs_crypto_hash_alg hash_alg,
		     unsigned char *key, unsigned int key_len);
int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *desc,
				struct page *page, unsigned int offset,
				unsigned int len);
int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *desc, const void *buf,
			   unsigned int buf_len);
int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *desc,
			  unsigned char *hash, unsigned int *hash_len);
int cfs_crypto_register(void);
void cfs_crypto_unregister(void);
int cfs_crypto_hash_speed(enum cfs_crypto_hash_alg hash_alg);
#endif