/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef _CRYPTO_SIG_H
#define _CRYPTO_SIG_H

#include <linux/crypto.h>


struct crypto_sig {
	struct crypto_tfm base;
};


struct sig_alg {
	int (*sign)(struct crypto_sig *tfm,
		    const void *src, unsigned int slen,
		    void *dst, unsigned int dlen);
	int (*verify)(struct crypto_sig *tfm,
		      const void *src, unsigned int slen,
		      const void *digest, unsigned int dlen);
	int (*set_pub_key)(struct crypto_sig *tfm,
			   const void *key, unsigned int keylen);
	int (*set_priv_key)(struct crypto_sig *tfm,
			    const void *key, unsigned int keylen);
	unsigned int (*key_size)(struct crypto_sig *tfm);
	unsigned int (*digest_size)(struct crypto_sig *tfm);
	unsigned int (*max_size)(struct crypto_sig *tfm);
	int (*init)(struct crypto_sig *tfm);
	void (*exit)(struct crypto_sig *tfm);

	struct crypto_alg base;
};




struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask);

static inline struct crypto_tfm *crypto_sig_tfm(struct crypto_sig *tfm)
{
	return &tfm->base;
}

static inline struct crypto_sig *__crypto_sig_tfm(struct crypto_tfm *tfm)
{
	return container_of(tfm, struct crypto_sig, base);
}

static inline struct sig_alg *__crypto_sig_alg(struct crypto_alg *alg)
{
	return container_of(alg, struct sig_alg, base);
}

static inline struct sig_alg *crypto_sig_alg(struct crypto_sig *tfm)
{
	return __crypto_sig_alg(crypto_sig_tfm(tfm)->__crt_alg);
}


static inline void crypto_free_sig(struct crypto_sig *tfm)
{
	crypto_destroy_tfm(tfm, crypto_sig_tfm(tfm));
}


static inline unsigned int crypto_sig_keysize(struct crypto_sig *tfm)
{
	struct sig_alg *alg = crypto_sig_alg(tfm);

	return alg->key_size(tfm);
}


static inline unsigned int crypto_sig_digestsize(struct crypto_sig *tfm)
{
	struct sig_alg *alg = crypto_sig_alg(tfm);

	return alg->digest_size(tfm);
}


static inline unsigned int crypto_sig_maxsize(struct crypto_sig *tfm)
{
	struct sig_alg *alg = crypto_sig_alg(tfm);

	return alg->max_size(tfm);
}


static inline int crypto_sig_sign(struct crypto_sig *tfm,
				  const void *src, unsigned int slen,
				  void *dst, unsigned int dlen)
{
	struct sig_alg *alg = crypto_sig_alg(tfm);

	return alg->sign(tfm, src, slen, dst, dlen);
}


static inline int crypto_sig_verify(struct crypto_sig *tfm,
				    const void *src, unsigned int slen,
				    const void *digest, unsigned int dlen)
{
	struct sig_alg *alg = crypto_sig_alg(tfm);

	return alg->verify(tfm, src, slen, digest, dlen);
}


static inline int crypto_sig_set_pubkey(struct crypto_sig *tfm,
					const void *key, unsigned int keylen)
{
	struct sig_alg *alg = crypto_sig_alg(tfm);

	return alg->set_pub_key(tfm, key, keylen);
}


static inline int crypto_sig_set_privkey(struct crypto_sig *tfm,
					 const void *key, unsigned int keylen)
{
	struct sig_alg *alg = crypto_sig_alg(tfm);

	return alg->set_priv_key(tfm, key, keylen);
}
#endif
