1 /*
2  * Copyright 2019-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 #include "prov/ciphercommon.h"
11 
12 /*-
13  * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
14  * Used if there is no special hardware implementations.
15  */
ossl_cipher_hw_generic_cbc(PROV_CIPHER_CTX * dat,unsigned char * out,const unsigned char * in,size_t len)16 int ossl_cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out,
17                                const unsigned char *in, size_t len)
18 {
19     if (dat->stream.cbc)
20         (*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc);
21     else if (dat->enc)
22         CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block);
23     else
24         CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block);
25 
26     return 1;
27 }
28 
ossl_cipher_hw_generic_ecb(PROV_CIPHER_CTX * dat,unsigned char * out,const unsigned char * in,size_t len)29 int ossl_cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out,
30                                const unsigned char *in, size_t len)
31 {
32     size_t i, bl = dat->blocksize;
33 
34     if (len < bl)
35         return 1;
36 
37     if (dat->stream.ecb) {
38         (*dat->stream.ecb) (in, out, len, dat->ks, dat->enc);
39     }
40     else {
41         for (i = 0, len -= bl; i <= len; i += bl)
42             (*dat->block) (in + i, out + i, dat->ks);
43     }
44 
45     return 1;
46 }
47 
ossl_cipher_hw_generic_ofb128(PROV_CIPHER_CTX * dat,unsigned char * out,const unsigned char * in,size_t len)48 int ossl_cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out,
49                                   const unsigned char *in, size_t len)
50 {
51     int num = dat->num;
52 
53     CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block);
54     dat->num = num;
55 
56     return 1;
57 }
58 
ossl_cipher_hw_generic_cfb128(PROV_CIPHER_CTX * dat,unsigned char * out,const unsigned char * in,size_t len)59 int ossl_cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out,
60                                   const unsigned char *in, size_t len)
61 {
62     int num = dat->num;
63 
64     CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
65                           dat->block);
66     dat->num = num;
67 
68     return 1;
69 }
70 
ossl_cipher_hw_generic_cfb8(PROV_CIPHER_CTX * dat,unsigned char * out,const unsigned char * in,size_t len)71 int ossl_cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out,
72                                 const unsigned char *in, size_t len)
73 {
74     int num = dat->num;
75 
76     CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
77                             dat->block);
78     dat->num = num;
79 
80     return 1;
81 }
82 
ossl_cipher_hw_generic_cfb1(PROV_CIPHER_CTX * dat,unsigned char * out,const unsigned char * in,size_t len)83 int ossl_cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out,
84                                 const unsigned char *in, size_t len)
85 {
86     int num = dat->num;
87 
88     if (dat->use_bits) {
89         CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num,
90                                 dat->enc, dat->block);
91         dat->num = num;
92         return 1;
93     }
94 
95     while (len >= MAXBITCHUNK) {
96         CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks,
97                                 dat->iv, &num, dat->enc, dat->block);
98         len -= MAXBITCHUNK;
99         out += MAXBITCHUNK;
100         in  += MAXBITCHUNK;
101     }
102     if (len)
103         CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num,
104                                 dat->enc, dat->block);
105 
106     dat->num = num;
107 
108     return 1;
109 }
110 
ossl_cipher_hw_generic_ctr(PROV_CIPHER_CTX * dat,unsigned char * out,const unsigned char * in,size_t len)111 int ossl_cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out,
112                                const unsigned char *in, size_t len)
113 {
114     unsigned int num = dat->num;
115 
116     if (dat->stream.ctr)
117         CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf,
118                                     &num, dat->stream.ctr);
119     else
120         CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf,
121                               &num, dat->block);
122     dat->num = num;
123 
124     return 1;
125 }
126 
127 /*-
128  * The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
129  * Used if there is no special hardware implementations.
130  */
131 
ossl_cipher_hw_chunked_cbc(PROV_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)132 int ossl_cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
133                                const unsigned char *in, size_t inl)
134 {
135     while (inl >= MAXCHUNK) {
136         ossl_cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK);
137         inl -= MAXCHUNK;
138         in  += MAXCHUNK;
139         out += MAXCHUNK;
140     }
141     if (inl > 0)
142         ossl_cipher_hw_generic_cbc(ctx, out, in, inl);
143     return 1;
144 }
145 
ossl_cipher_hw_chunked_cfb8(PROV_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)146 int ossl_cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out,
147                                 const unsigned char *in, size_t inl)
148 {
149     size_t chunk = MAXCHUNK;
150 
151     if (inl < chunk)
152         chunk = inl;
153     while (inl > 0 && inl >= chunk) {
154         ossl_cipher_hw_generic_cfb8(ctx, out, in, inl);
155         inl -= chunk;
156         in += chunk;
157         out += chunk;
158         if (inl < chunk)
159             chunk = inl;
160     }
161     return 1;
162 }
163 
ossl_cipher_hw_chunked_cfb128(PROV_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)164 int ossl_cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
165                                   const unsigned char *in, size_t inl)
166 {
167     size_t chunk = MAXCHUNK;
168 
169     if (inl < chunk)
170         chunk = inl;
171     while (inl > 0 && inl >= chunk) {
172         ossl_cipher_hw_generic_cfb128(ctx, out, in, inl);
173         inl -= chunk;
174         in += chunk;
175         out += chunk;
176         if (inl < chunk)
177             chunk = inl;
178     }
179     return 1;
180 }
181 
ossl_cipher_hw_chunked_ofb128(PROV_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)182 int ossl_cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
183                                   const unsigned char *in, size_t inl)
184 {
185     while (inl >= MAXCHUNK) {
186         ossl_cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK);
187         inl -= MAXCHUNK;
188         in  += MAXCHUNK;
189         out += MAXCHUNK;
190     }
191     if (inl > 0)
192         ossl_cipher_hw_generic_ofb128(ctx, out, in, inl);
193     return 1;
194 }
195