summaryrefslogtreecommitdiffstats
path: root/providers/default/ciphers
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2019-09-23 14:35:16 +1000
committerShane Lontis <shane.lontis@oracle.com>2019-09-23 14:35:16 +1000
commite3f3ee448f6c9d6765efc8739a09def8a04f0dc0 (patch)
treea9fd41b14a0bdb9af70260f3e03e9ae0324df080 /providers/default/ciphers
parenta941054ad7f5af9445896a37754ae451fad7ed98 (diff)
Add des ciphers to default provider
Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/9954)
Diffstat (limited to 'providers/default/ciphers')
-rw-r--r--providers/default/ciphers/build.info3
-rw-r--r--providers/default/ciphers/cipher_des.c163
-rw-r--r--providers/default/ciphers/cipher_des.h33
-rw-r--r--providers/default/ciphers/cipher_des_hw.c173
4 files changed, 371 insertions, 1 deletions
diff --git a/providers/default/ciphers/build.info b/providers/default/ciphers/build.info
index 02e0f7fa51..f942ccc030 100644
--- a/providers/default/ciphers/build.info
+++ b/providers/default/ciphers/build.info
@@ -4,7 +4,8 @@ IF[{- !$disabled{des} -}]
SOURCE[../../../libcrypto]=\
cipher_tdes_default.c cipher_tdes_default_hw.c \
cipher_tdes_wrap.c cipher_tdes_wrap_hw.c \
- cipher_desx.c cipher_desx_hw.c
+ cipher_desx.c cipher_desx_hw.c \
+ cipher_des.c cipher_des_hw.c
ENDIF
IF[{- !$disabled{aria} -}]
diff --git a/providers/default/ciphers/cipher_des.c b/providers/default/ciphers/cipher_des.c
new file mode 100644
index 0000000000..a1976fb737
--- /dev/null
+++ b/providers/default/ciphers/cipher_des.c
@@ -0,0 +1,163 @@
+/*
+ * 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"
+#include "cipher_des.h"
+#include "internal/rand_int.h"
+#include "internal/provider_algs.h"
+#include "internal/providercommonerr.h"
+
+/* TODO(3.0) Figure out what flags need to be here */
+#define DES_FLAGS (EVP_CIPH_RAND_KEY)
+
+static OSSL_OP_cipher_freectx_fn des_freectx;
+static OSSL_OP_cipher_encrypt_init_fn des_einit;
+static OSSL_OP_cipher_decrypt_init_fn des_dinit;
+static OSSL_OP_cipher_get_ctx_params_fn des_get_ctx_params;
+static OSSL_OP_cipher_gettable_ctx_params_fn des_gettable_ctx_params;
+
+static void *des_newctx(void *provctx, size_t kbits, size_t blkbits,
+ size_t ivbits, unsigned int mode, uint64_t flags,
+ const PROV_CIPHER_HW *hw)
+{
+ PROV_DES_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx != NULL)
+ cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags, hw,
+ provctx);
+ return ctx;
+}
+
+static void des_freectx(void *vctx)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static int des_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen, int enc)
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+ ctx->enc = enc;
+
+ if (iv != NULL) {
+ if (ivlen != ctx->ivlen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
+ return 0;
+ }
+ memcpy(ctx->iv, iv, ivlen);
+ }
+
+ if (key != NULL) {
+ if (keylen != ctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
+ return 0;
+ }
+ return ctx->hw->init(ctx, key, keylen);
+ }
+ return 1;
+}
+
+static int des_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen)
+{
+ return des_init(vctx, key, keylen, iv, ivlen, 1);
+}
+
+static int des_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen)
+{
+ return des_init(vctx, key, keylen, iv, ivlen, 0);
+}
+
+static int des_generatekey(PROV_CIPHER_CTX *ctx, void *ptr)
+{
+
+ DES_cblock *deskey = ptr;
+ size_t kl = ctx->keylen;
+
+ if (kl == 0 || rand_priv_bytes_ex(ctx->libctx, ptr, kl) <= 0)
+ return 0;
+ DES_set_odd_parity(deskey);
+ return 1;
+}
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(des)
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0),
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(des)
+
+static int des_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ if (!cipher_generic_get_ctx_params(vctx, params))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY);
+ if (p != NULL && !des_generatekey(ctx, p->data)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
+ return 0;
+ }
+ return 1;
+}
+
+#define IMPLEMENT_des_cipher(type, lcmode, UCMODE, flags, \
+ kbits, blkbits, ivbits, block) \
+static OSSL_OP_cipher_newctx_fn type##_##lcmode##_newctx; \
+static void *des_##lcmode##_newctx(void *provctx) \
+{ \
+ return des_newctx(provctx, kbits, blkbits, ivbits, \
+ EVP_CIPH_##UCMODE##_MODE, flags, \
+ PROV_CIPHER_HW_des_##lcmode()); \
+} \
+static OSSL_OP_cipher_get_params_fn des_##lcmode##_get_params; \
+static int des_##lcmode##_get_params(OSSL_PARAM params[]) \
+{ \
+ return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \
+ kbits, blkbits, ivbits); \
+} \
+const OSSL_DISPATCH des_##lcmode##_functions[] = { \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))des_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))des_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, \
+ (void (*)(void))cipher_generic_##block##_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##block##_final },\
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \
+ { OSSL_FUNC_CIPHER_NEWCTX, \
+ (void (*)(void))des_##lcmode##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))des_freectx }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void))des_##lcmode##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))des_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))des_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))cipher_generic_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))cipher_generic_settable_ctx_params }, \
+ { 0, NULL } \
+}
+
+/* des_ecb_functions */
+IMPLEMENT_des_cipher(des, ecb, ECB, DES_FLAGS, 64, 64, 0, block);
+/* des_cbc_functions */
+IMPLEMENT_des_cipher(des, cbc, CBC, DES_FLAGS, 64, 64, 64, block);
+/* des_ofb64_functions */
+IMPLEMENT_des_cipher(des, ofb64, OFB, DES_FLAGS, 64, 8, 64, stream);
+/* des_cfb64_functions */
+IMPLEMENT_des_cipher(des, cfb64, CFB, DES_FLAGS, 64, 8, 64, stream);
+/* des_cfb1_functions */
+IMPLEMENT_des_cipher(des, cfb1, CFB, DES_FLAGS, 64, 8, 64, stream);
+/* des_cfb8_functions */
+IMPLEMENT_des_cipher(des, cfb8, CFB, DES_FLAGS, 64, 8, 64, stream);
diff --git a/providers/default/ciphers/cipher_des.h b/providers/default/ciphers/cipher_des.h
new file mode 100644
index 0000000000..92dcfa11e9
--- /dev/null
+++ b/providers/default/ciphers/cipher_des.h
@@ -0,0 +1,33 @@
+/*
+ * 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 <openssl/des.h>
+
+/* TODO(3.0) Figure out what flags need to be here */
+#define TDES_FLAGS (EVP_CIPH_RAND_KEY)
+
+typedef struct prov_des_ctx_st {
+ PROV_CIPHER_CTX base; /* Must be first */
+ union {
+ OSSL_UNION_ALIGN;
+ DES_key_schedule ks;
+ } dks;
+ union {
+ void (*cbc) (const void *, void *, size_t,
+ const DES_key_schedule *, unsigned char *);
+ } dstream;
+
+} PROV_DES_CTX;
+
+const PROV_CIPHER_HW *PROV_CIPHER_HW_des_cbc(void);
+const PROV_CIPHER_HW *PROV_CIPHER_HW_des_ecb(void);
+const PROV_CIPHER_HW *PROV_CIPHER_HW_des_ofb64(void);
+const PROV_CIPHER_HW *PROV_CIPHER_HW_des_cfb64(void);
+const PROV_CIPHER_HW *PROV_CIPHER_HW_des_cfb1(void);
+const PROV_CIPHER_HW *PROV_CIPHER_HW_des_cfb8(void);
diff --git a/providers/default/ciphers/cipher_des_hw.c b/providers/default/ciphers/cipher_des_hw.c
new file mode 100644
index 0000000000..78107062a5
--- /dev/null
+++ b/providers/default/ciphers/cipher_des_hw.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright 1995-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 "internal/ciphers/ciphercommon.h"
+#include "cipher_des.h"
+
+static int cipher_hw_des_initkey(PROV_CIPHER_CTX *ctx,
+ const unsigned char *key, size_t keylen)
+{
+ PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx;
+ DES_cblock *deskey = (DES_cblock *)key;
+ DES_key_schedule *ks = &dctx->dks.ks;
+
+ dctx->dstream.cbc = NULL;
+#if defined(SPARC_DES_CAPABLE)
+ if (SPARC_DES_CAPABLE) {
+ if (ctx->mode == EVP_CIPH_CBC_MODE) {
+ des_t4_key_expand(&deskey[0], ks);
+ dctx->dstream.cbc = ctx->enc ? des_t4_cbc_encrypt :
+ des_t4_cbc_decrypt;
+ return 1;
+ }
+ }
+#endif
+ DES_set_key_unchecked(deskey, ks);
+ return 1;
+}
+
+static int cipher_hw_des_ecb_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ size_t i, bl = ctx->blocksize;
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+
+ if (len < bl)
+ return 1;
+ for (i = 0, len -= bl; i <= len; i += bl)
+ DES_ecb_encrypt((const_DES_cblock *)(in + i),
+ (const_DES_cblock *)(out + i), key, ctx->enc);
+ return 1;
+}
+
+static int cipher_hw_des_cbc_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+
+ while (len >= MAXCHUNK) {
+ DES_ncbc_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv,
+ ctx->enc);
+ len -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (len > 0)
+ DES_ncbc_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv,
+ ctx->enc);
+ return 1;
+}
+
+static int cipher_hw_des_ofb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int num = ctx->num;
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+
+ while (len >= MAXCHUNK) {
+ DES_ofb64_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, &num);
+ len -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (len > 0) {
+ DES_ofb64_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, &num);
+ }
+ ctx->num = num;
+ return 1;
+}
+
+static int cipher_hw_des_cfb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ size_t chunk = MAXCHUNK;
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+ int num = ctx->num;
+
+ if (len < chunk)
+ chunk = len;
+ while (len > 0 && len >= chunk) {
+ DES_cfb64_encrypt(in, out, (long)chunk, key, (DES_cblock *)ctx->iv,
+ &num, ctx->enc);
+ len -= chunk;
+ in += chunk;
+ out += chunk;
+ if (len < chunk)
+ chunk = len;
+ }
+ ctx->num = num;
+ return 1;
+}
+
+/*
+ * Although we have a CFB-r implementation for DES, it doesn't pack the right
+ * way, so wrap it here
+ */
+static int cipher_hw_des_cfb1_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ size_t n, chunk = MAXCHUNK / 8;
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+ unsigned char c[1], d[1];
+
+ if (inl < chunk)
+ chunk = inl;
+
+ while (inl && inl >= chunk) {
+ for (n = 0; n < chunk * 8; ++n) {
+ c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
+ DES_cfb_encrypt(c, d, 1, 1, key, (DES_cblock *)ctx->iv, ctx->enc);
+ out[n / 8] =
+ (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) |
+ ((d[0] & 0x80) >> (unsigned int)(n % 8));
+ }
+ inl -= chunk;
+ in += chunk;
+ out += chunk;
+ if (inl < chunk)
+ chunk = inl;
+ }
+
+ return 1;
+}
+
+static int cipher_hw_des_cfb8_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
+
+ while (inl >= MAXCHUNK) {
+ DES_cfb_encrypt(in, out, 8, (long)MAXCHUNK, key,
+ (DES_cblock *)ctx->iv, ctx->enc);
+ inl -= MAXCHUNK;
+ in += MAXCHUNK;
+ out += MAXCHUNK;
+ }
+ if (inl > 0)
+ DES_cfb_encrypt(in, out, 8, (long)inl, key,
+ (DES_cblock *)ctx->iv, ctx->enc);
+ return 1;
+}
+
+#define PROV_CIPHER_HW_des_mode(mode) \
+static const PROV_CIPHER_HW des_##mode = { \
+ cipher_hw_des_initkey, \
+ cipher_hw_des_##mode##_cipher \
+}; \
+const PROV_CIPHER_HW *PROV_CIPHER_HW_des_##mode(void) \
+{ \
+ return &des_##mode; \
+}
+
+PROV_CIPHER_HW_des_mode(ecb)
+PROV_CIPHER_HW_des_mode(cbc)
+PROV_CIPHER_HW_des_mode(ofb64)
+PROV_CIPHER_HW_des_mode(cfb64)
+PROV_CIPHER_HW_des_mode(cfb1)
+PROV_CIPHER_HW_des_mode(cfb8)