/* * Copyright 1995-2021 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 */ /* * DES low level APIs are deprecated for public use, but still ok for internal * use. */ #include "internal/deprecated.h" #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 void cipher_hw_des_copyctx(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src) { PROV_DES_CTX *sctx = (PROV_DES_CTX *)src; PROV_DES_CTX *dctx = (PROV_DES_CTX *)dst; *dctx = *sctx; dst->ks = &dctx->dks.ks; } 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) { PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx; DES_key_schedule *key = &(dctx->dks.ks); if (dctx->dstream.cbc != NULL) { (*dctx->dstream.cbc) (in, out, len, key, ctx->iv); return 1; } 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, \ cipher_hw_des_copyctx \ }; \ const PROV_CIPHER_HW *ossl_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)