Changed the crypto make system to add build flexibility. The update cancels the requi...
[krb5.git] / src / lib / crypto / openssl / enc_provider / des3.c
1 /* lib/crypto/openssl/enc_provider/des3.c
2  */
3
4 #include "k5-int.h"
5 #include "des_int.h"
6 #include <aead.h>
7 #include <rand2key.h>
8 #include <openssl/evp.h>
9
10
11 #define DES_BLOCK_SIZE  8
12
13 static krb5_error_code
14 validate(krb5_key key, const krb5_data *ivec,
15                       const krb5_data *input, const krb5_data *output)
16 {
17     /* key->keyblock.enctype was checked by the caller */
18
19     if (key->keyblock.length != KRB5_MIT_DES3_KEYSIZE)
20         return(KRB5_BAD_KEYSIZE);
21     if ((input->length%DES_BLOCK_SIZE) != 0)
22         return(KRB5_BAD_MSIZE);
23     if (ivec && (ivec->length != 8))
24         return(KRB5_BAD_MSIZE);
25     if (input->length != output->length)
26         return(KRB5_BAD_MSIZE);
27
28     return 0;
29 }
30
31 static krb5_error_code
32 validate_iov(krb5_key key, const krb5_data *ivec,
33                           const krb5_crypto_iov *data, size_t num_data)
34 {
35     size_t i, input_length;
36
37     for (i = 0, input_length = 0; i < num_data; i++) {
38         const krb5_crypto_iov *iov = &data[i];
39         if (ENCRYPT_IOV(iov))
40             input_length += iov->data.length;
41     }
42
43     if (key->keyblock.length != KRB5_MIT_DES3_KEYSIZE)
44         return(KRB5_BAD_KEYSIZE);
45     if ((input_length%DES_BLOCK_SIZE) != 0)
46         return(KRB5_BAD_MSIZE);
47     if (ivec && (ivec->length != 8))
48         return(KRB5_BAD_MSIZE);
49
50     return 0;
51 }
52
53 static krb5_error_code
54 k5_des3_encrypt(krb5_key key, const krb5_data *ivec,
55                 const krb5_data *input, krb5_data *output)
56 {
57     int              ret = 0, tmp_len = 0;
58     unsigned int     tmp_buf_len = 0;
59     unsigned char   *keybuf  = NULL;
60     unsigned char   *tmp_buf = NULL;
61     EVP_CIPHER_CTX   ciph_ctx;
62
63     ret = validate(key, ivec, input, output);
64     if (ret)
65         return ret;
66
67     keybuf=key->keyblock.contents;
68     keybuf[key->keyblock.length] = '\0';
69
70     tmp_buf_len = output->length * 2;
71     tmp_buf = OPENSSL_malloc(tmp_buf_len);
72     if (!tmp_buf)
73         return ENOMEM;
74
75     EVP_CIPHER_CTX_init(&ciph_ctx);
76
77     ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL, keybuf,
78                              (ivec) ? (unsigned char*)ivec->data : NULL);
79     if (ret) {
80         EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
81         ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
82                                 (unsigned char *)input->data, input->length);
83         if (!ret || output->length < (unsigned int)tmp_len) {
84             ret = KRB5_CRYPTO_INTERNAL;
85         } else {
86             output->length = tmp_len;
87             ret = EVP_EncryptFinal_ex(&ciph_ctx, tmp_buf+tmp_len, &tmp_len);
88         }
89     }
90
91     EVP_CIPHER_CTX_cleanup(&ciph_ctx);
92
93     if (ret == 1)
94         memcpy(output->data,tmp_buf, output->length);
95
96     memset(tmp_buf, 0, tmp_buf_len);
97     OPENSSL_free(tmp_buf);
98
99     if (ret != 1)
100         return KRB5_CRYPTO_INTERNAL;
101
102     return 0;
103
104 }
105
106 static krb5_error_code
107 k5_des3_decrypt(krb5_key key, const krb5_data *ivec,
108                 const krb5_data *input, krb5_data *output)
109 {
110     int              ret = 0, tmp_len = 0;
111     unsigned int     tmp_buf_len = 0;
112     unsigned char   *keybuf  = NULL;
113     unsigned char   *tmp_buf = NULL;
114     EVP_CIPHER_CTX   ciph_ctx;
115
116     ret = validate(key, ivec, input, output);
117     if (ret)
118         return ret;
119
120     keybuf=key->keyblock.contents;
121     keybuf[key->keyblock.length] = '\0';
122
123     tmp_buf_len = output->length;
124     tmp_buf=OPENSSL_malloc(tmp_buf_len);
125     if (!tmp_buf)
126         return ENOMEM;
127
128     EVP_CIPHER_CTX_init(&ciph_ctx);
129
130     ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL, keybuf,
131                              (ivec) ? (unsigned char*)ivec->data: NULL);
132     if (ret) {
133         EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
134         ret = EVP_DecryptUpdate(&ciph_ctx, tmp_buf,  &tmp_len,
135                                 (unsigned char *)input->data, input->length);
136         if (!ret || output->length < (unsigned int)tmp_len) {
137             ret = KRB5_CRYPTO_INTERNAL;
138         } else {
139             output->length = tmp_len;
140             ret = EVP_DecryptFinal_ex(&ciph_ctx, tmp_buf+tmp_len, &tmp_len);
141         }
142     }
143
144     EVP_CIPHER_CTX_cleanup(&ciph_ctx);
145
146     if (ret == 1)
147         memcpy(output->data,tmp_buf, output->length);
148
149     memset(tmp_buf,0,tmp_buf_len);
150     OPENSSL_free(tmp_buf);
151
152     if (ret != 1)
153         return KRB5_CRYPTO_INTERNAL;
154     return 0;
155
156 }
157
158 static krb5_error_code
159 k5_des3_encrypt_iov(krb5_key key,
160                     const krb5_data *ivec,
161                     krb5_crypto_iov *data,
162                     size_t num_data)
163 {
164     int                    ret = 0;
165     int                    tmp_len = MIT_DES_BLOCK_LENGTH;
166     int                    oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
167     unsigned char         *iblock = NULL, *oblock = NULL;
168     unsigned char         *keybuf = NULL;
169     struct iov_block_state input_pos, output_pos;
170     EVP_CIPHER_CTX         ciph_ctx;
171
172     ret = validate_iov(key, ivec, data, num_data);
173     if (ret)
174         return ret;
175
176     iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH);
177     if (!iblock)
178         return ENOMEM;
179     oblock = OPENSSL_malloc(oblock_len);
180     if (!oblock){
181         OPENSSL_free(iblock);
182         return ENOMEM;
183     }
184
185     IOV_BLOCK_STATE_INIT(&input_pos);
186     IOV_BLOCK_STATE_INIT(&output_pos);
187
188     keybuf=key->keyblock.contents;
189     keybuf[key->keyblock.length] = '\0';
190
191     memset(oblock, 0, oblock_len);
192
193     EVP_CIPHER_CTX_init(&ciph_ctx);
194
195     ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
196                              keybuf, (ivec) ? (unsigned char*)ivec->data : NULL);
197     if (!ret){
198         EVP_CIPHER_CTX_cleanup(&ciph_ctx);
199         OPENSSL_free(iblock);
200         OPENSSL_free(oblock);
201         return KRB5_CRYPTO_INTERNAL;
202     }
203
204     EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
205
206     for (;;) {
207
208         if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH,
209                                      data, num_data, &input_pos))
210             break;
211
212         if (input_pos.iov_pos == num_data)
213             break;
214
215         ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &tmp_len,
216                                 (unsigned char *)iblock, input_pos.data_pos);
217         if (!ret) break;
218
219         krb5int_c_iov_put_block(data, num_data,
220                                 oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
221     }
222
223     if(ret) {
224         /*if (ivec != NULL && ivec->data)
225             memcpy(ivec->data, oblock, MIT_DES_BLOCK_LENGTH); */
226         ret = EVP_EncryptFinal_ex(&ciph_ctx, oblock+input_pos.data_pos, &tmp_len);
227     }
228
229     EVP_CIPHER_CTX_cleanup(&ciph_ctx);
230
231     memset(iblock,0,sizeof(iblock));
232     memset(oblock,0,sizeof(oblock));
233     OPENSSL_free(iblock);
234     OPENSSL_free(oblock);
235
236     if (ret != 1)
237         return KRB5_CRYPTO_INTERNAL;
238     return 0;
239 }
240
241 static krb5_error_code
242 k5_des3_decrypt_iov(krb5_key key,
243                     const krb5_data *ivec,
244                     krb5_crypto_iov *data,
245                     size_t num_data)
246 {
247     int                    ret = 0;
248     int                    tmp_len = MIT_DES_BLOCK_LENGTH;
249     int                    oblock_len = MIT_DES_BLOCK_LENGTH * num_data;
250     unsigned char         *iblock = NULL, *oblock = NULL;
251     unsigned char         *keybuf = NULL ;
252     struct iov_block_state input_pos, output_pos;
253     EVP_CIPHER_CTX         ciph_ctx;
254
255     ret = validate_iov(key, ivec, data, num_data);
256     if (ret)
257         return ret;
258
259     iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH);
260     if (!iblock)
261         return ENOMEM;
262     oblock = OPENSSL_malloc(oblock_len);
263     if (!oblock){
264         OPENSSL_free(iblock);
265         return ENOMEM;
266     }
267
268     IOV_BLOCK_STATE_INIT(&input_pos);
269     IOV_BLOCK_STATE_INIT(&output_pos);
270
271     keybuf=key->keyblock.contents;
272     keybuf[key->keyblock.length] = '\0';
273
274     memset(oblock, 0, oblock_len);
275
276     EVP_CIPHER_CTX_init(&ciph_ctx);
277
278     ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
279                              keybuf, (ivec) ? (unsigned char*)ivec->data : NULL);
280     if (!ret){
281         EVP_CIPHER_CTX_cleanup(&ciph_ctx);
282         OPENSSL_free(iblock);
283         OPENSSL_free(oblock);
284         return KRB5_CRYPTO_INTERNAL;
285     }
286
287     EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
288
289     for (;;) {
290
291         if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH,
292                                      data, num_data, &input_pos))
293             break;
294
295         if (input_pos.iov_pos == num_data)
296             break;
297
298         ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &tmp_len,
299                                 (unsigned char *)iblock, input_pos.data_pos);
300         if (!ret) break;
301
302         krb5int_c_iov_put_block(data, num_data,
303                                 oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
304     }
305
306     if(ret) {
307         /*if (ivec != NULL && ivec->data)
308             memcpy(ivec->data, oblock, MIT_DES_BLOCK_LENGTH); */
309         ret = EVP_DecryptFinal_ex(&ciph_ctx,
310                                   oblock + input_pos.data_pos, &tmp_len);
311     }
312
313     EVP_CIPHER_CTX_cleanup(&ciph_ctx);
314
315     memset(iblock,0,sizeof(iblock));
316     memset(oblock,0,sizeof(oblock));
317     OPENSSL_free(iblock);
318     OPENSSL_free(oblock);
319
320     if (ret != 1)
321         return KRB5_CRYPTO_INTERNAL;
322     return 0;
323 }
324
325 const struct krb5_enc_provider krb5int_enc_des3 = {
326     DES_BLOCK_SIZE,
327     KRB5_MIT_DES3_KEY_BYTES, KRB5_MIT_DES3_KEYSIZE,
328     k5_des3_encrypt,
329     k5_des3_decrypt,
330     krb5int_des3_make_key,
331     krb5int_des_init_state,
332     krb5int_default_free_state,
333     k5_des3_encrypt_iov,
334     k5_des3_decrypt_iov
335 };
336