summaryrefslogtreecommitdiffstats
path: root/providers/common/ciphers/cipher_common_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'providers/common/ciphers/cipher_common_hw.c')
-rw-r--r--providers/common/ciphers/cipher_common_hw.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/providers/common/ciphers/cipher_common_hw.c b/providers/common/ciphers/cipher_common_hw.c
new file mode 100644
index 0000000000..47e14afbbb
--- /dev/null
+++ b/providers/common/ciphers/cipher_common_hw.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "cipher_locl.h"
+
+#define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2))
+#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4))
+
+/*-
+ * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
+ * Used if there is no special hardware implementations.
+ */
+int cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ if (dat->stream.cbc)
+ (*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc);
+ else if (dat->enc)
+ CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block);
+ else
+ CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block);
+
+ return 1;
+}
+
+int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ size_t i, bl = dat->blocksize;
+
+ if (len < bl)
+ return 1;
+
+ for (i = 0, len -= bl; i <= len; i += bl)
+ (*dat->block) (in + i, out + i, dat->ks);
+
+ return 1;
+}
+
+int cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = dat->num;
+
+ CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block);
+ dat->num = num;
+
+ return 1;
+}
+
+int cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = dat->num;
+
+ CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
+ dat->block);
+ dat->num = num;
+
+ return 1;
+}
+
+int cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = dat->num;
+
+ CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
+ dat->block);
+ dat->num = num;
+
+ return 1;
+}
+
+int cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = dat->num;
+
+ if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
+ CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num,
+ dat->enc, dat->block);
+ dat->num = num;
+ return 1;
+ }
+
+ while (len >= MAXBITCHUNK) {
+ CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks,
+ dat->iv, &num, dat->enc, dat->block);
+ len -= MAXBITCHUNK;
+ out += MAXBITCHUNK;
+ in += MAXBITCHUNK;
+ }
+ if (len)
+ CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num,
+ dat->enc, dat->block);
+
+ dat->num = num;
+
+ return 1;
+}
+
+int cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ unsigned int num = dat->num;
+
+ if (dat->stream.ctr)
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf,
+ &num, dat->stream.ctr);
+ else
+ CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf,
+ &num, dat->block);
+ dat->num = num;
+
+ return 1;
+}
+
+/*-
+ * The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
+ * Used if there is no special hardware implementations.
+ */
+
+int cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ while (inl >= MAXCHUNK) {
+ cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ cipher_hw_generic_cbc(ctx, out, in, inl);
+ return 1;
+}
+
+int cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ size_t chunk = MAXCHUNK;
+
+ if (inl < chunk)
+ chunk = inl;
+ while (inl > 0 && inl >= chunk) {
+ cipher_hw_generic_cfb8(ctx, out, in, inl);
+ inl -= chunk;
+ in += chunk;
+ out += chunk;
+ if (inl < chunk)
+ chunk = inl;
+ }
+ return 1;
+}
+
+int cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ size_t chunk = MAXCHUNK;
+
+ if (inl < chunk)
+ chunk = inl;
+ while (inl > 0 && inl >= chunk) {
+ cipher_hw_generic_cfb128(ctx, out, in, inl);
+ inl -= chunk;
+ in += chunk;
+ out += chunk;
+ if (inl < chunk)
+ chunk = inl;
+ }
+ return 1;
+}
+
+int cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ while (inl >= MAXCHUNK) {
+ cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ cipher_hw_generic_ofb128(ctx, out, in, inl);
+ return 1;
+}