|
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
|
2 /* lib/crypto/openssl/enc_provider/des.c */ |
|
3 /* |
|
4 * Copyright (C) 2009 by the Massachusetts Institute of Technology. |
|
5 * All rights reserved. |
|
6 * |
|
7 * Export of this software from the United States of America may |
|
8 * require a specific license from the United States Government. |
|
9 * It is the responsibility of any person or organization contemplating |
|
10 * export to obtain such a license before exporting. |
|
11 * |
|
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and |
|
13 * distribute this software and its documentation for any purpose and |
|
14 * without fee is hereby granted, provided that the above copyright |
|
15 * notice appear in all copies and that both that copyright notice and |
|
16 * this permission notice appear in supporting documentation, and that |
|
17 * the name of M.I.T. not be used in advertising or publicity pertaining |
|
18 * to distribution of the software without specific, written prior |
|
19 * permission. Furthermore if you modify this software you must label |
|
20 * your software as modified software and not distribute it in such a |
|
21 * fashion that it might be confused with the original M.I.T. software. |
|
22 * M.I.T. makes no representations about the suitability of |
|
23 * this software for any purpose. It is provided "as is" without express |
|
24 * or implied warranty. |
|
25 */ |
|
26 |
|
27 /* |
|
28 * Copyright (C) 1998 by the FundsXpress, INC. |
|
29 * |
|
30 * All rights reserved. |
|
31 * |
|
32 * Export of this software from the United States of America may require |
|
33 * a specific license from the United States Government. It is the |
|
34 * responsibility of any person or organization contemplating export to |
|
35 * obtain such a license before exporting. |
|
36 * |
|
37 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and |
|
38 * distribute this software and its documentation for any purpose and |
|
39 * without fee is hereby granted, provided that the above copyright |
|
40 * notice appear in all copies and that both that copyright notice and |
|
41 * this permission notice appear in supporting documentation, and that |
|
42 * the name of FundsXpress. not be used in advertising or publicity pertaining |
|
43 * to distribution of the software without specific, written prior |
|
44 * permission. FundsXpress makes no representations about the suitability of |
|
45 * this software for any purpose. It is provided "as is" without express |
|
46 * or implied warranty. |
|
47 * |
|
48 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
|
49 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
|
50 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
|
51 */ |
|
52 /* |
|
53 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. |
|
54 */ |
|
55 |
|
56 #include "crypto_int.h" |
|
57 #include <libucrypto.h> |
|
58 |
|
59 #define DES_BLOCK_SIZE 8 |
|
60 #define DES_KEY_SIZE 8 |
|
61 #define DES_KEY_BYTES 7 |
|
62 |
|
63 static krb5_error_code |
|
64 validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data, |
|
65 size_t num_data, size_t *inlen) |
|
66 { |
|
67 size_t input_length = iov_total_length(data, num_data, FALSE); |
|
68 |
|
69 if (key->keyblock.length != DES_KEY_SIZE) |
|
70 return KRB5_BAD_KEYSIZE; |
|
71 if ((input_length % DES_BLOCK_SIZE) != 0) |
|
72 return KRB5_BAD_MSIZE; |
|
73 if (ivec && (ivec->length != DES_BLOCK_SIZE)) |
|
74 return KRB5_BAD_MSIZE; |
|
75 |
|
76 if (inlen != NULL) |
|
77 *inlen = input_length; |
|
78 |
|
79 return 0; |
|
80 } |
|
81 |
|
82 static krb5_error_code |
|
83 k5_des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, |
|
84 size_t num_data) |
|
85 { |
|
86 int ret; |
|
87 size_t olen, dlen; |
|
88 uchar_t *obuf, *dbuf; |
|
89 uchar_t tmp_iv[DES_BLOCK_SIZE]; |
|
90 struct iov_cursor cursor; |
|
91 |
|
92 ret = validate(key, ivec, data, num_data, &dlen); |
|
93 if (ret != 0 || dlen == 0) |
|
94 return ret; |
|
95 |
|
96 if (ivec && ivec->data) |
|
97 memcpy(tmp_iv, ivec->data, ivec->length); |
|
98 else |
|
99 memset(tmp_iv, 0, sizeof(tmp_iv)); |
|
100 |
|
101 olen = dlen; |
|
102 obuf = malloc(olen); |
|
103 if (!obuf) |
|
104 return ENOMEM; |
|
105 |
|
106 dbuf = malloc(dlen); |
|
107 if (!dbuf){ |
|
108 free(obuf); |
|
109 return ENOMEM; |
|
110 } |
|
111 |
|
112 /* Init iov cursor to gather data for encypting (FALSE) */ |
|
113 k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE); |
|
114 /* Get all that data into dbuf */ |
|
115 k5_iov_cursor_get(&cursor, dbuf); |
|
116 |
|
117 if (ucrypto_encrypt(CRYPTO_DES_CBC, |
|
118 key->keyblock.contents, |
|
119 key->keyblock.length, |
|
120 tmp_iv, sizeof(tmp_iv), |
|
121 dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) { |
|
122 ret = KRB5_CRYPTO_INTERNAL; |
|
123 } else { |
|
124 k5_iov_cursor_put(&cursor, obuf); |
|
125 } |
|
126 |
|
127 /* |
|
128 * Updating the ivec arg, if present because of an old/obscure concept of |
|
129 * cipher state that is being used by only BSD rlogin. See RFCs 1391 and |
|
130 * 1392 in regards to the vague description of cipher state. |
|
131 */ |
|
132 if (!ret && ivec && ivec->data) { |
|
133 /* Copy last block of cipher text output */ |
|
134 memcpy(ivec->data, obuf + (dlen - DES_BLOCK_SIZE), DES_BLOCK_SIZE); |
|
135 } |
|
136 |
|
137 zapfree(obuf, olen); |
|
138 zapfree(dbuf, dlen); |
|
139 |
|
140 return ret; |
|
141 } |
|
142 |
|
143 static krb5_error_code |
|
144 k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, |
|
145 size_t num_data) |
|
146 { |
|
147 int ret; |
|
148 size_t olen, dlen; |
|
149 uchar_t *obuf, *dbuf; |
|
150 uchar_t tmp_iv[DES_BLOCK_SIZE]; |
|
151 struct iov_cursor cursor; |
|
152 |
|
153 ret = validate(key, ivec, data, num_data, &dlen); |
|
154 if (ret != 0 || dlen == 0) |
|
155 return ret; |
|
156 |
|
157 if (ivec && ivec->data) |
|
158 memcpy(tmp_iv, ivec->data, ivec->length); |
|
159 else |
|
160 memset(tmp_iv, 0, sizeof(tmp_iv)); |
|
161 |
|
162 olen = dlen; |
|
163 obuf = malloc(olen); |
|
164 if (!obuf) |
|
165 return ENOMEM; |
|
166 |
|
167 dbuf = malloc(dlen); |
|
168 if (!dbuf){ |
|
169 free(obuf); |
|
170 return ENOMEM; |
|
171 } |
|
172 |
|
173 /* Init iov cursor to gather cipher text for decrypting (FALSE) */ |
|
174 k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE); |
|
175 /* Gather all that cipher text into dbuf */ |
|
176 k5_iov_cursor_get(&cursor, dbuf); |
|
177 |
|
178 if (ucrypto_decrypt(CRYPTO_DES_CBC, |
|
179 key->keyblock.contents, |
|
180 key->keyblock.length, |
|
181 tmp_iv, sizeof(tmp_iv), |
|
182 dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) { |
|
183 ret = KRB5_CRYPTO_INTERNAL; |
|
184 } else { |
|
185 k5_iov_cursor_put(&cursor, obuf); |
|
186 } |
|
187 |
|
188 /* |
|
189 * Updating the ivec arg, if present because of an old/obscure concept of |
|
190 * cipher state that is being used by only BSD rlogin. See RFCs 1391 and |
|
191 * 1392 in regards to the vague description of cipher state. |
|
192 */ |
|
193 if (!ret && ivec && ivec->data) { |
|
194 /* Copy last block of cipher text input */ |
|
195 memcpy(ivec->data, dbuf + (dlen - DES_BLOCK_SIZE), DES_BLOCK_SIZE); |
|
196 } |
|
197 |
|
198 zapfree(obuf, olen); |
|
199 zapfree(dbuf, dlen); |
|
200 |
|
201 return ret; |
|
202 } |
|
203 |
|
204 static krb5_error_code |
|
205 k5_des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data, |
|
206 const krb5_data *ivec, krb5_data *output) |
|
207 { |
|
208 int ret; |
|
209 struct iov_cursor cursor; |
|
210 uchar_t blockY[DES_BLOCK_SIZE], blockB[DES_BLOCK_SIZE]; |
|
211 size_t olen; |
|
212 |
|
213 ret = validate(key, ivec, data, num_data, NULL); |
|
214 if (ret != 0) |
|
215 return ret; |
|
216 |
|
217 if (output->length != DES_BLOCK_SIZE) |
|
218 return KRB5_BAD_MSIZE; |
|
219 |
|
220 if (ivec != NULL) |
|
221 memcpy(blockY, ivec->data, DES_BLOCK_SIZE); |
|
222 else |
|
223 memset(blockY, 0, DES_BLOCK_SIZE); |
|
224 |
|
225 k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE); |
|
226 while (k5_iov_cursor_get(&cursor, blockB)) { |
|
227 store_64_n(load_64_n(blockB) ^ load_64_n(blockY), blockB); |
|
228 olen = sizeof(blockY); |
|
229 if (ucrypto_encrypt(CRYPTO_DES_ECB, |
|
230 key->keyblock.contents, |
|
231 key->keyblock.length, |
|
232 NULL, 0, |
|
233 blockB, sizeof(blockB), |
|
234 blockY, &olen) != CRYPTO_SUCCESS) { |
|
235 return KRB5_CRYPTO_INTERNAL; |
|
236 } |
|
237 } |
|
238 |
|
239 memcpy(output->data, blockY, DES_BLOCK_SIZE); |
|
240 return 0; |
|
241 } |
|
242 |
|
243 const struct krb5_enc_provider krb5int_enc_des = { |
|
244 DES_BLOCK_SIZE, |
|
245 DES_KEY_BYTES, DES_KEY_SIZE, |
|
246 k5_des_encrypt, |
|
247 k5_des_decrypt, |
|
248 k5_des_cbc_mac, |
|
249 krb5int_des_init_state, |
|
250 krb5int_default_free_state |
|
251 }; |