2019-09-23 12:35:16 +08:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2019-10-04 20:44:42 +08:00
|
|
|
#include "prov/ciphercommon.h"
|
2019-09-23 12:35:16 +08:00
|
|
|
#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)
|