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) |
174 | |