diff options
Diffstat (limited to 'providers/implementations/ciphers/cipher_des_hw.c')
-rw-r--r-- | providers/implementations/ciphers/cipher_des_hw.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/providers/implementations/ciphers/cipher_des_hw.c b/providers/implementations/ciphers/cipher_des_hw.c new file mode 100644 index 0000000000..c3a67080fd --- /dev/null +++ b/providers/implementations/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 "prov/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) |