forked from Qortal/Brooklyn
* NVME, SATA NAND Security added * Qortal Core exception fetcher is now redone. * Update DT overlays for firmware * Fix for bvb clockj settings * Fix for no audio for sissy desktop porn watchers -_- ( thanks crowetic for watching gay porn and reporting me that bug asshat ) * Normalize the fetch() stream while doing a peer to peer handshake for nodes * Fix for RNG token editing error while performing a SHA256 encryption * Now under voltage errors will blink red led constantly for 5 minutes then go solid. * Improve kernel thread scaling for Qortal 2.0 core * HDMI circuit is now enabled at power up instead. * Added KMS * Added line replication instead of interpolation for VC4 GPU resulting in slightly better frame rates * Fix for long and doubles * Backplane clock is now set at standard rate * Capped HVEC clocks * Add support for Creative Cinema webcam for donkers who like sharing dick pics. *looks at crowetic* * More scanline XGA modes for people who have weird ass monitors of all sorts. * TX/RX flow control support is now 100% stable. No lags over 1Gbps ethernet. ( Hello Qortal 3.0 ) * Using flush cache instead of fetch for QC 2.0 resulting in performance gains * VC4 clock is now enforced for desktop oriented images. * Ondemand governor now waits for 2 seconds instead of 0.5ms to scale down to the lowest safest clock freq preventing lags to the core. * Timeout of OC set at 35ms from 90ms resulting in way better clocks and sync for Qortal 2.0 core
267 lines
5.4 KiB
C
267 lines
5.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (C) 2019 Samsung Electronics Co., Ltd.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/string.h>
|
|
#include <linux/err.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/wait.h>
|
|
#include <linux/sched.h>
|
|
|
|
#include "glob.h"
|
|
#include "crypto_ctx.h"
|
|
|
|
struct crypto_ctx_list {
|
|
spinlock_t ctx_lock;
|
|
int avail_ctx;
|
|
struct list_head idle_ctx;
|
|
wait_queue_head_t ctx_wait;
|
|
};
|
|
|
|
static struct crypto_ctx_list ctx_list;
|
|
|
|
static inline void free_aead(struct crypto_aead *aead)
|
|
{
|
|
if (aead)
|
|
crypto_free_aead(aead);
|
|
}
|
|
|
|
static void free_shash(struct shash_desc *shash)
|
|
{
|
|
if (shash) {
|
|
crypto_free_shash(shash->tfm);
|
|
kfree(shash);
|
|
}
|
|
}
|
|
|
|
static struct crypto_aead *alloc_aead(int id)
|
|
{
|
|
struct crypto_aead *tfm = NULL;
|
|
|
|
switch (id) {
|
|
case CRYPTO_AEAD_AES_GCM:
|
|
tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
|
|
break;
|
|
case CRYPTO_AEAD_AES_CCM:
|
|
tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
|
|
break;
|
|
default:
|
|
pr_err("Does not support encrypt ahead(id : %d)\n", id);
|
|
return NULL;
|
|
}
|
|
|
|
if (IS_ERR(tfm)) {
|
|
pr_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
|
|
return NULL;
|
|
}
|
|
|
|
return tfm;
|
|
}
|
|
|
|
static struct shash_desc *alloc_shash_desc(int id)
|
|
{
|
|
struct crypto_shash *tfm = NULL;
|
|
struct shash_desc *shash;
|
|
|
|
switch (id) {
|
|
case CRYPTO_SHASH_HMACMD5:
|
|
tfm = crypto_alloc_shash("hmac(md5)", 0, 0);
|
|
break;
|
|
case CRYPTO_SHASH_HMACSHA256:
|
|
tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
|
|
break;
|
|
case CRYPTO_SHASH_CMACAES:
|
|
tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
|
|
break;
|
|
case CRYPTO_SHASH_SHA256:
|
|
tfm = crypto_alloc_shash("sha256", 0, 0);
|
|
break;
|
|
case CRYPTO_SHASH_SHA512:
|
|
tfm = crypto_alloc_shash("sha512", 0, 0);
|
|
break;
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
if (IS_ERR(tfm))
|
|
return NULL;
|
|
|
|
shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
|
|
GFP_KERNEL);
|
|
if (!shash)
|
|
crypto_free_shash(tfm);
|
|
else
|
|
shash->tfm = tfm;
|
|
return shash;
|
|
}
|
|
|
|
static void ctx_free(struct ksmbd_crypto_ctx *ctx)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < CRYPTO_SHASH_MAX; i++)
|
|
free_shash(ctx->desc[i]);
|
|
for (i = 0; i < CRYPTO_AEAD_MAX; i++)
|
|
free_aead(ctx->ccmaes[i]);
|
|
kfree(ctx);
|
|
}
|
|
|
|
static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
|
|
{
|
|
struct ksmbd_crypto_ctx *ctx;
|
|
|
|
while (1) {
|
|
spin_lock(&ctx_list.ctx_lock);
|
|
if (!list_empty(&ctx_list.idle_ctx)) {
|
|
ctx = list_entry(ctx_list.idle_ctx.next,
|
|
struct ksmbd_crypto_ctx,
|
|
list);
|
|
list_del(&ctx->list);
|
|
spin_unlock(&ctx_list.ctx_lock);
|
|
return ctx;
|
|
}
|
|
|
|
if (ctx_list.avail_ctx > num_online_cpus()) {
|
|
spin_unlock(&ctx_list.ctx_lock);
|
|
wait_event(ctx_list.ctx_wait,
|
|
!list_empty(&ctx_list.idle_ctx));
|
|
continue;
|
|
}
|
|
|
|
ctx_list.avail_ctx++;
|
|
spin_unlock(&ctx_list.ctx_lock);
|
|
|
|
ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
|
|
if (!ctx) {
|
|
spin_lock(&ctx_list.ctx_lock);
|
|
ctx_list.avail_ctx--;
|
|
spin_unlock(&ctx_list.ctx_lock);
|
|
wait_event(ctx_list.ctx_wait,
|
|
!list_empty(&ctx_list.idle_ctx));
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
return ctx;
|
|
}
|
|
|
|
void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx)
|
|
{
|
|
if (!ctx)
|
|
return;
|
|
|
|
spin_lock(&ctx_list.ctx_lock);
|
|
if (ctx_list.avail_ctx <= num_online_cpus()) {
|
|
list_add(&ctx->list, &ctx_list.idle_ctx);
|
|
spin_unlock(&ctx_list.ctx_lock);
|
|
wake_up(&ctx_list.ctx_wait);
|
|
return;
|
|
}
|
|
|
|
ctx_list.avail_ctx--;
|
|
spin_unlock(&ctx_list.ctx_lock);
|
|
ctx_free(ctx);
|
|
}
|
|
|
|
static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
|
|
{
|
|
struct ksmbd_crypto_ctx *ctx;
|
|
|
|
if (id >= CRYPTO_SHASH_MAX)
|
|
return NULL;
|
|
|
|
ctx = ksmbd_find_crypto_ctx();
|
|
if (ctx->desc[id])
|
|
return ctx;
|
|
|
|
ctx->desc[id] = alloc_shash_desc(id);
|
|
if (ctx->desc[id])
|
|
return ctx;
|
|
ksmbd_release_crypto_ctx(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void)
|
|
{
|
|
return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACMD5);
|
|
}
|
|
|
|
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void)
|
|
{
|
|
return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACSHA256);
|
|
}
|
|
|
|
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
|
|
{
|
|
return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
|
|
}
|
|
|
|
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void)
|
|
{
|
|
return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA256);
|
|
}
|
|
|
|
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void)
|
|
{
|
|
return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512);
|
|
}
|
|
|
|
static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
|
|
{
|
|
struct ksmbd_crypto_ctx *ctx;
|
|
|
|
if (id >= CRYPTO_AEAD_MAX)
|
|
return NULL;
|
|
|
|
ctx = ksmbd_find_crypto_ctx();
|
|
if (ctx->ccmaes[id])
|
|
return ctx;
|
|
|
|
ctx->ccmaes[id] = alloc_aead(id);
|
|
if (ctx->ccmaes[id])
|
|
return ctx;
|
|
ksmbd_release_crypto_ctx(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void)
|
|
{
|
|
return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_GCM);
|
|
}
|
|
|
|
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void)
|
|
{
|
|
return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_CCM);
|
|
}
|
|
|
|
void ksmbd_crypto_destroy(void)
|
|
{
|
|
struct ksmbd_crypto_ctx *ctx;
|
|
|
|
while (!list_empty(&ctx_list.idle_ctx)) {
|
|
ctx = list_entry(ctx_list.idle_ctx.next,
|
|
struct ksmbd_crypto_ctx,
|
|
list);
|
|
list_del(&ctx->list);
|
|
ctx_free(ctx);
|
|
}
|
|
}
|
|
|
|
int ksmbd_crypto_create(void)
|
|
{
|
|
struct ksmbd_crypto_ctx *ctx;
|
|
|
|
spin_lock_init(&ctx_list.ctx_lock);
|
|
INIT_LIST_HEAD(&ctx_list.idle_ctx);
|
|
init_waitqueue_head(&ctx_list.ctx_wait);
|
|
ctx_list.avail_ctx = 1;
|
|
|
|
ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
|
|
if (!ctx)
|
|
return -ENOMEM;
|
|
list_add(&ctx->list, &ctx_list.idle_ctx);
|
|
return 0;
|
|
}
|