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