1/*
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10/*
11 * DES low level APIs are deprecated for public use, but still ok for internal
12 * use.
13 */
14#include "internal/deprecated.h"
15
16#include "prov/ciphercommon.h"
17#include "cipher_des.h"
18
19static int cipher_hw_des_initkey(PROV_CIPHER_CTX *ctx,
20                                 const unsigned char *key, size_t keylen)
21{
22    PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx;
23    DES_cblock *deskey = (DES_cblock *)key;
24    DES_key_schedule *ks = &dctx->dks.ks;
25
26    dctx->dstream.cbc = NULL;
27#if defined(SPARC_DES_CAPABLE)
28    if (SPARC_DES_CAPABLE) {
29        if (ctx->mode == EVP_CIPH_CBC_MODE) {
30            des_t4_key_expand(&deskey[0], ks);
31            dctx->dstream.cbc = ctx->enc ? des_t4_cbc_encrypt :
32                                           des_t4_cbc_decrypt;
33            return 1;
34        }
35    }
36#endif
37    DES_set_key_unchecked(deskey, ks);
38    return 1;
39}
40
41static void cipher_hw_des_copyctx(PROV_CIPHER_CTX *dst,
42                                  const PROV_CIPHER_CTX *src)
43{
44    PROV_DES_CTX *sctx = (PROV_DES_CTX *)src;
45    PROV_DES_CTX *dctx = (PROV_DES_CTX *)dst;
46
47    *dctx = *sctx;
48    dst->ks = &dctx->dks.ks;
49}
50
51static int cipher_hw_des_ecb_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
52                                    const unsigned char *in, size_t len)
53{
54    size_t i, bl = ctx->blocksize;
55    DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
56
57    if (len < bl)
58        return 1;
59    for (i = 0, len -= bl; i <= len; i += bl)
60        DES_ecb_encrypt((const_DES_cblock *)(in + i),
61                        (const_DES_cblock *)(out + i), key, ctx->enc);
62    return 1;
63}
64
65static int cipher_hw_des_cbc_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
66                                    const unsigned char *in, size_t len)
67{
68    PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx;
69    DES_key_schedule *key = &(dctx->dks.ks);
70
71    if (dctx->dstream.cbc != NULL) {
72        (*dctx->dstream.cbc) (in, out, len, key, ctx->iv);
73        return 1;
74    }
75
76    while (len >= MAXCHUNK) {
77        DES_ncbc_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv,
78                         ctx->enc);
79        len -= MAXCHUNK;
80        in += MAXCHUNK;
81        out += MAXCHUNK;
82    }
83    if (len > 0)
84        DES_ncbc_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv,
85                         ctx->enc);
86    return 1;
87}
88
89static int cipher_hw_des_ofb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
90                                      const unsigned char *in, size_t len)
91{
92    int num = ctx->num;
93    DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
94
95    while (len >= MAXCHUNK) {
96        DES_ofb64_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, &num);
97        len -= MAXCHUNK;
98        in += MAXCHUNK;
99        out += MAXCHUNK;
100    }
101    if (len > 0) {
102        DES_ofb64_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, &num);
103    }
104    ctx->num = num;
105    return 1;
106}
107
108static int cipher_hw_des_cfb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
109                                      const unsigned char *in, size_t len)
110{
111    size_t chunk = MAXCHUNK;
112    DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
113    int num = ctx->num;
114
115    if (len < chunk)
116        chunk = len;
117    while (len > 0 && len >= chunk) {
118        DES_cfb64_encrypt(in, out, (long)chunk, key, (DES_cblock *)ctx->iv,
119                          &num, ctx->enc);
120        len -= chunk;
121        in += chunk;
122        out += chunk;
123        if (len < chunk)
124            chunk = len;
125    }
126    ctx->num = num;
127    return 1;
128}
129
130/*
131 * Although we have a CFB-r implementation for DES, it doesn't pack the right
132 * way, so wrap it here
133 */
134static int cipher_hw_des_cfb1_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
135                                     const unsigned char *in, size_t inl)
136{
137    size_t n, chunk = MAXCHUNK / 8;
138    DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
139    unsigned char c[1], d[1];
140
141    if (inl < chunk)
142        chunk = inl;
143
144    while (inl && inl >= chunk) {
145        for (n = 0; n < chunk * 8; ++n) {
146            c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
147            DES_cfb_encrypt(c, d, 1, 1, key, (DES_cblock *)ctx->iv, ctx->enc);
148            out[n / 8] =
149                (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) |
150                ((d[0] & 0x80) >> (unsigned int)(n % 8));
151        }
152        inl -= chunk;
153        in += chunk;
154        out += chunk;
155        if (inl < chunk)
156            chunk = inl;
157    }
158
159    return 1;
160}
161
162static int cipher_hw_des_cfb8_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
163                                     const unsigned char *in, size_t inl)
164{
165    DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
166
167    while (inl >= MAXCHUNK) {
168        DES_cfb_encrypt(in, out, 8, (long)MAXCHUNK, key,
169                        (DES_cblock *)ctx->iv, ctx->enc);
170        inl -= MAXCHUNK;
171        in += MAXCHUNK;
172        out += MAXCHUNK;
173    }
174    if (inl > 0)
175        DES_cfb_encrypt(in, out, 8, (long)inl, key,
176                        (DES_cblock *)ctx->iv, ctx->enc);
177    return 1;
178}
179
180#define PROV_CIPHER_HW_des_mode(mode)                                          \
181static const PROV_CIPHER_HW des_##mode = {                                     \
182    cipher_hw_des_initkey,                                                     \
183    cipher_hw_des_##mode##_cipher,                                             \
184    cipher_hw_des_copyctx                                                      \
185};                                                                             \
186const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_##mode(void)                     \
187{                                                                              \
188    return &des_##mode;                                                        \
189}
190
191PROV_CIPHER_HW_des_mode(ecb)
192PROV_CIPHER_HW_des_mode(cbc)
193PROV_CIPHER_HW_des_mode(ofb64)
194PROV_CIPHER_HW_des_mode(cfb64)
195PROV_CIPHER_HW_des_mode(cfb1)
196PROV_CIPHER_HW_des_mode(cfb8)
197