c3a67080fd144a5f01b93d6cc067a33ac5a7de3b
[openssl.git] / providers / implementations / ciphers / cipher_des_hw.c
1 /*
2  * Copyright 1995-2019 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 #include "prov/ciphercommon.h"
11 #include "cipher_des.h"
12
13 static int cipher_hw_des_initkey(PROV_CIPHER_CTX *ctx,
14                                  const unsigned char *key, size_t keylen)
15 {
16     PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx;
17     DES_cblock *deskey = (DES_cblock *)key;
18     DES_key_schedule *ks = &dctx->dks.ks;
19
20     dctx->dstream.cbc = NULL;
21 #if defined(SPARC_DES_CAPABLE)
22     if (SPARC_DES_CAPABLE) {
23         if (ctx->mode == EVP_CIPH_CBC_MODE) {
24             des_t4_key_expand(&deskey[0], ks);
25             dctx->dstream.cbc = ctx->enc ? des_t4_cbc_encrypt :
26                                            des_t4_cbc_decrypt;
27             return 1;
28         }
29     }
30 #endif
31     DES_set_key_unchecked(deskey, ks);
32     return 1;
33 }
34
35 static int cipher_hw_des_ecb_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
36                                     const unsigned char *in, size_t len)
37 {
38     size_t i, bl = ctx->blocksize;
39     DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
40
41     if (len < bl)
42         return 1;
43     for (i = 0, len -= bl; i <= len; i += bl)
44         DES_ecb_encrypt((const_DES_cblock *)(in + i),
45                         (const_DES_cblock *)(out + i), key, ctx->enc);
46     return 1;
47 }
48
49 static int cipher_hw_des_cbc_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
50                                     const unsigned char *in, size_t len)
51 {
52     DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
53
54     while (len >= MAXCHUNK) {
55         DES_ncbc_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv,
56                          ctx->enc);
57         len -= MAXCHUNK;
58         in += MAXCHUNK;
59         out += MAXCHUNK;
60     }
61     if (len > 0)
62         DES_ncbc_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv,
63                          ctx->enc);
64     return 1;
65 }
66
67 static int cipher_hw_des_ofb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
68                                       const unsigned char *in, size_t len)
69 {
70     int num = ctx->num;
71     DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
72
73     while (len >= MAXCHUNK) {
74         DES_ofb64_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, &num);
75         len -= MAXCHUNK;
76         in += MAXCHUNK;
77         out += MAXCHUNK;
78     }
79     if (len > 0) {
80         DES_ofb64_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, &num);
81     }
82     ctx->num = num;
83     return 1;
84 }
85
86 static int cipher_hw_des_cfb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
87                                       const unsigned char *in, size_t len)
88 {
89     size_t chunk = MAXCHUNK;
90     DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
91     int num = ctx->num;
92
93     if (len < chunk)
94         chunk = len;
95     while (len > 0 && len >= chunk) {
96         DES_cfb64_encrypt(in, out, (long)chunk, key, (DES_cblock *)ctx->iv,
97                           &num, ctx->enc);
98         len -= chunk;
99         in += chunk;
100         out += chunk;
101         if (len < chunk)
102             chunk = len;
103     }
104     ctx->num = num;
105     return 1;
106 }
107
108 /*
109  * Although we have a CFB-r implementation for DES, it doesn't pack the right
110  * way, so wrap it here
111  */
112 static int cipher_hw_des_cfb1_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
113                                      const unsigned char *in, size_t inl)
114 {
115     size_t n, chunk = MAXCHUNK / 8;
116     DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
117     unsigned char c[1], d[1];
118
119     if (inl < chunk)
120         chunk = inl;
121
122     while (inl && inl >= chunk) {
123         for (n = 0; n < chunk * 8; ++n) {
124             c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
125             DES_cfb_encrypt(c, d, 1, 1, key, (DES_cblock *)ctx->iv, ctx->enc);
126             out[n / 8] =
127                 (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) |
128                 ((d[0] & 0x80) >> (unsigned int)(n % 8));
129         }
130         inl -= chunk;
131         in += chunk;
132         out += chunk;
133         if (inl < chunk)
134             chunk = inl;
135     }
136
137     return 1;
138 }
139
140 static int cipher_hw_des_cfb8_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
141                                      const unsigned char *in, size_t inl)
142 {
143     DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
144
145     while (inl >= MAXCHUNK) {
146         DES_cfb_encrypt(in, out, 8, (long)MAXCHUNK, key,
147                         (DES_cblock *)ctx->iv, ctx->enc);
148         inl -= MAXCHUNK;
149         in += MAXCHUNK;
150         out += MAXCHUNK;
151     }
152     if (inl > 0)
153         DES_cfb_encrypt(in, out, 8, (long)inl, key,
154                         (DES_cblock *)ctx->iv, ctx->enc);
155     return 1;
156 }
157
158 #define PROV_CIPHER_HW_des_mode(mode)                                          \
159 static const PROV_CIPHER_HW des_##mode = {                                     \
160     cipher_hw_des_initkey,                                                     \
161     cipher_hw_des_##mode##_cipher                                              \
162 };                                                                             \
163 const PROV_CIPHER_HW *PROV_CIPHER_HW_des_##mode(void)                          \
164 {                                                                              \
165     return &des_##mode;                                                        \
166 }
167
168 PROV_CIPHER_HW_des_mode(ecb)
169 PROV_CIPHER_HW_des_mode(cbc)
170 PROV_CIPHER_HW_des_mode(ofb64)
171 PROV_CIPHER_HW_des_mode(cfb64)
172 PROV_CIPHER_HW_des_mode(cfb1)
173 PROV_CIPHER_HW_des_mode(cfb8)