Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30066ce6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull crypto updates from Herbert Xu:
 "Here is the crypto update for 4.9:

  API:
   - The crypto engine code now supports hashes.

  Algorithms:
   - Allow keys >= 2048 bits in FIPS mode for RSA.

  Drivers:
   - Memory overwrite fix for vmx ghash.
   - Add support for building ARM sha1-neon in Thumb2 mode.
   - Reenable ARM ghash-ce code by adding import/export.
   - Reenable img-hash by adding import/export.
   - Add support for multiple cores in omap-aes.
   - Add little-endian support for sha1-powerpc.
   - Add Cavium HWRNG driver for ThunderX SoC"

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (137 commits)
  crypto: caam - treat SGT address pointer as u64
  crypto: ccp - Make syslog errors human-readable
  crypto: ccp - clean up data structure
  crypto: vmx - Ensure ghash-generic is enabled
  crypto: testmgr - add guard to dst buffer for ahash_export
  crypto: caam - Unmap region obtained by of_iomap
  crypto: sha1-powerpc - little-endian support
  crypto: gcm - Fix IV buffer size in crypto_gcm_setkey
  crypto: vmx - Fix memory corruption caused by p8_ghash
  crypto: ghash-generic - move common definitions to a new header file
  crypto: caam - fix sg dump
  hwrng: omap - Only fail if pm_runtime_get_sync returns < 0
  crypto: omap-sham - shrink the internal buffer size
  crypto: omap-sham - add support for export/import
  crypto: omap-sham - convert driver logic to use sgs for data xmit
  crypto: omap-sham - change the DMA threshold value to a define
  crypto: omap-sham - add support functions for sg based data handling
  crypto: omap-sham - rename sgl to sgl_tmp for deprecation
  crypto: omap-sham - align algorithms on word offset
  crypto: omap-sham - add context export/import stubs
  ...
parents 6763afe4 c3afafa4
Loading
Loading
Loading
Loading
+26 −12
Original line number Diff line number Diff line
@@ -797,7 +797,8 @@ kernel crypto API | Caller
     include/linux/crypto.h and their definition can be seen below.
     The former function registers a single transformation, while
     the latter works on an array of transformation descriptions.
     The latter is useful when registering transformations in bulk.
     The latter is useful when registering transformations in bulk,
     for example when a driver implements multiple transformations.
    </para>

    <programlisting>
@@ -822,18 +823,31 @@ kernel crypto API | Caller
    </para>

    <para>
     The bulk registration / unregistration functions require
     that struct crypto_alg is an array of count size. These
     functions simply loop over that array and register /
     unregister each individual algorithm. If an error occurs,
     the loop is terminated at the offending algorithm definition.
     That means, the algorithms prior to the offending algorithm
     are successfully registered. Note, the caller has no way of
     knowing which cipher implementations have successfully
     registered. If this is important to know, the caller should
     loop through the different implementations using the single
     instance *_alg functions for each individual implementation.
     The bulk registration/unregistration functions
     register/unregister each transformation in the given array of
     length count.  They handle errors as follows:
    </para>
    <itemizedlist>
     <listitem>
      <para>
       crypto_register_algs() succeeds if and only if it
       successfully registers all the given transformations. If an
       error occurs partway through, then it rolls back successful
       registrations before returning the error code. Note that if
       a driver needs to handle registration errors for individual
       transformations, then it will need to use the non-bulk
       function crypto_register_alg() instead.
      </para>
     </listitem>
     <listitem>
      <para>
       crypto_unregister_algs() tries to unregister all the given
       transformations, continuing on error. It logs errors and
       always returns zero.
      </para>
     </listitem>
    </itemizedlist>

   </sect1>

   <sect1><title>Single-Block Symmetric Ciphers [CIPHER]</title>
+25 −1
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ static struct shash_alg ghash_alg = {
	.setkey			= ghash_setkey,
	.descsize		= sizeof(struct ghash_desc_ctx),
	.base			= {
		.cra_name	= "ghash",
		.cra_name	= "__ghash",
		.cra_driver_name = "__driver-ghash-ce",
		.cra_priority	= 0,
		.cra_flags	= CRYPTO_ALG_TYPE_SHASH | CRYPTO_ALG_INTERNAL,
@@ -220,6 +220,27 @@ static int ghash_async_digest(struct ahash_request *req)
	}
}

static int ghash_async_import(struct ahash_request *req, const void *in)
{
	struct ahash_request *cryptd_req = ahash_request_ctx(req);
	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
	struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm);
	struct shash_desc *desc = cryptd_shash_desc(cryptd_req);

	desc->tfm = cryptd_ahash_child(ctx->cryptd_tfm);
	desc->flags = req->base.flags;

	return crypto_shash_import(desc, in);
}

static int ghash_async_export(struct ahash_request *req, void *out)
{
	struct ahash_request *cryptd_req = ahash_request_ctx(req);
	struct shash_desc *desc = cryptd_shash_desc(cryptd_req);

	return crypto_shash_export(desc, out);
}

static int ghash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
			      unsigned int keylen)
{
@@ -268,7 +289,10 @@ static struct ahash_alg ghash_async_alg = {
	.final			= ghash_async_final,
	.setkey			= ghash_async_setkey,
	.digest			= ghash_async_digest,
	.import			= ghash_async_import,
	.export			= ghash_async_export,
	.halg.digestsize	= GHASH_DIGEST_SIZE,
	.halg.statesize		= sizeof(struct ghash_desc_ctx),
	.halg.base		= {
		.cra_name	= "ghash",
		.cra_driver_name = "ghash-ce",
+0 −1
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@
#include <asm/assembler.h>

.syntax unified
.code   32
.fpu neon

.text
+11 −2
Original line number Diff line number Diff line
@@ -7,6 +7,15 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>

#ifdef __BIG_ENDIAN__
#define LWZ(rt, d, ra)	\
	lwz	rt,d(ra)
#else
#define LWZ(rt, d, ra)	\
	li	rt,d;	\
	lwbrx	rt,rt,ra
#endif

/*
 * We roll the registers for T, A, B, C, D, E around on each
 * iteration; T on iteration t is A on iteration t+1, and so on.
@@ -23,7 +32,7 @@
#define W(t)	(((t)%16)+16)

#define LOADW(t)				\
	lwz	W(t),(t)*4(r4)
	LWZ(W(t),(t)*4,r4)

#define STEPD0_LOAD(t)				\
	andc	r0,RD(t),RB(t);		\
@@ -33,7 +42,7 @@
	add	r0,RE(t),r15;			\
	add	RT(t),RT(t),r6;		\
	add	r14,r0,W(t);			\
	lwz	W((t)+4),((t)+4)*4(r4);	\
	LWZ(W((t)+4),((t)+4)*4,r4);	\
	rotlwi	RB(t),RB(t),30;			\
	add	RT(t),RT(t),r14

+61 −12
Original line number Diff line number Diff line
@@ -39,6 +39,37 @@ struct algif_hash_tfm {
	bool has_key;
};

static int hash_alloc_result(struct sock *sk, struct hash_ctx *ctx)
{
	unsigned ds;

	if (ctx->result)
		return 0;

	ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));

	ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
	if (!ctx->result)
		return -ENOMEM;

	memset(ctx->result, 0, ds);

	return 0;
}

static void hash_free_result(struct sock *sk, struct hash_ctx *ctx)
{
	unsigned ds;

	if (!ctx->result)
		return;

	ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));

	sock_kzfree_s(sk, ctx->result, ds);
	ctx->result = NULL;
}

static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
			size_t ignored)
{
@@ -54,6 +85,9 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,

	lock_sock(sk);
	if (!ctx->more) {
		if ((msg->msg_flags & MSG_MORE))
			hash_free_result(sk, ctx);

		err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
						&ctx->completion);
		if (err)
@@ -90,6 +124,10 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,

	ctx->more = msg->msg_flags & MSG_MORE;
	if (!ctx->more) {
		err = hash_alloc_result(sk, ctx);
		if (err)
			goto unlock;

		ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
		err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
						 &ctx->completion);
@@ -116,6 +154,13 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
	sg_init_table(ctx->sgl.sg, 1);
	sg_set_page(ctx->sgl.sg, page, size, offset);

	if (!(flags & MSG_MORE)) {
		err = hash_alloc_result(sk, ctx);
		if (err)
			goto unlock;
	} else if (!ctx->more)
		hash_free_result(sk, ctx);

	ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size);

	if (!(flags & MSG_MORE)) {
@@ -153,6 +198,7 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
	struct alg_sock *ask = alg_sk(sk);
	struct hash_ctx *ctx = ask->private;
	unsigned ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
	bool result;
	int err;

	if (len > ds)
@@ -161,17 +207,29 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
		msg->msg_flags |= MSG_TRUNC;

	lock_sock(sk);
	result = ctx->result;
	err = hash_alloc_result(sk, ctx);
	if (err)
		goto unlock;

	ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);

	if (ctx->more) {
		ctx->more = 0;
		ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
		err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
						 &ctx->completion);
		if (err)
			goto unlock;
	} else if (!result) {
		err = af_alg_wait_for_completion(
				crypto_ahash_digest(&ctx->req),
				&ctx->completion);
	}

	err = memcpy_to_msg(msg, ctx->result, len);

	hash_free_result(sk, ctx);

unlock:
	release_sock(sk);

@@ -394,8 +452,7 @@ static void hash_sock_destruct(struct sock *sk)
	struct alg_sock *ask = alg_sk(sk);
	struct hash_ctx *ctx = ask->private;

	sock_kzfree_s(sk, ctx->result,
		      crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
	hash_free_result(sk, ctx);
	sock_kfree_s(sk, ctx, ctx->len);
	af_alg_release_parent(sk);
}
@@ -407,20 +464,12 @@ static int hash_accept_parent_nokey(void *private, struct sock *sk)
	struct algif_hash_tfm *tfm = private;
	struct crypto_ahash *hash = tfm->hash;
	unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
	unsigned ds = crypto_ahash_digestsize(hash);

	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

	ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
	if (!ctx->result) {
		sock_kfree_s(sk, ctx, len);
		return -ENOMEM;
	}

	memset(ctx->result, 0, ds);

	ctx->result = NULL;
	ctx->len = len;
	ctx->more = 0;
	af_alg_init_completion(&ctx->completion);
Loading