|
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 /* |
|
60 * The loopback field is NULL if uctx is uninitialized (no encrypt or decrypt |
|
61 * operation has taken place), or is a pointer to the structure address if uctx |
|
62 * is initialized. If an application copies the state (not a valid operation, |
|
63 * but one which happens to works with some other enc providers), we can detect |
|
64 * it via the loopback field and return a sane error code. |
|
65 */ |
|
66 struct arcfour_state { |
|
67 struct arcfour_state *loopback; |
|
68 int op_type; /* encrypt, decrypt */ |
|
69 crypto_ctx_t uctx; /* ucrypto context */ |
|
70 }; |
|
71 #define ENCRYPT_OP 1 |
|
72 #define DECRYPT_OP 2 |
|
73 |
|
74 #define RC4_KEY_SIZE 16 |
|
75 #define RC4_BLOCK_SIZE 1 |
|
76 |
|
77 static krb5_error_code |
|
78 k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, |
|
79 size_t num_data, int op_type) |
|
80 { |
|
81 int ret = 0; |
|
82 crypto_ctx_t local_uctx, *uctx; /* ucrypto context */ |
|
83 size_t len, i; |
|
84 struct arcfour_state *arcstate; |
|
85 krb5_boolean do_init = TRUE; |
|
86 |
|
87 arcstate = (state != NULL) ? (struct arcfour_state *)state->data : NULL; |
|
88 if (arcstate != NULL) { |
|
89 /* |
|
90 * If loopback points to arcstate we know that uctx has been init'ed |
|
91 * but if it doesn't and it isn't NULL then arcstate has been corrupted |
|
92 * which means we can't trust that uctx is valid. |
|
93 */ |
|
94 if (arcstate->loopback == arcstate) |
|
95 do_init = FALSE; |
|
96 else if (arcstate->loopback != NULL) |
|
97 return KRB5_CRYPTO_INTERNAL; |
|
98 |
|
99 uctx = &arcstate->uctx; |
|
100 } else { |
|
101 /* Use the local ucrypto context, will need to be cleaned up in this |
|
102 * function. */ |
|
103 uctx = &local_uctx; |
|
104 } |
|
105 |
|
106 if (do_init) { |
|
107 if (op_type == ENCRYPT_OP) { |
|
108 if (ucrypto_encrypt_init(uctx, CRYPTO_RC4, |
|
109 key->keyblock.contents, |
|
110 key->keyblock.length, |
|
111 NULL, 0) != CRYPTO_SUCCESS) { |
|
112 return KRB5_CRYPTO_INTERNAL; |
|
113 } |
|
114 } else { |
|
115 if (ucrypto_decrypt_init(uctx, CRYPTO_RC4, |
|
116 key->keyblock.contents, |
|
117 key->keyblock.length, |
|
118 NULL, 0) != CRYPTO_SUCCESS) { |
|
119 return KRB5_CRYPTO_INTERNAL; |
|
120 } |
|
121 } |
|
122 |
|
123 /* Saved ucrypto context is init'ed, mark as initialized. */ |
|
124 if (arcstate) { |
|
125 arcstate->loopback = arcstate; |
|
126 arcstate->op_type = op_type; |
|
127 } |
|
128 } |
|
129 |
|
130 for (i = 0; i < num_data; i++) { |
|
131 krb5_crypto_iov *iov = &data[i]; |
|
132 |
|
133 if (ENCRYPT_IOV(iov)) { |
|
134 len = (size_t)iov->data.length; |
|
135 |
|
136 if (op_type == ENCRYPT_OP) { |
|
137 if (ucrypto_encrypt_update(uctx, |
|
138 (const uchar_t *)iov->data.data, |
|
139 len, |
|
140 (uchar_t *)iov->data.data, |
|
141 &len) != CRYPTO_SUCCESS) { |
|
142 ret = KRB5_CRYPTO_INTERNAL; |
|
143 break; |
|
144 } |
|
145 } else { |
|
146 if (ucrypto_decrypt_update(uctx, |
|
147 (const uchar_t *)iov->data.data, |
|
148 len, |
|
149 (uchar_t *)iov->data.data, |
|
150 &len) != CRYPTO_SUCCESS) { |
|
151 ret = KRB5_CRYPTO_INTERNAL; |
|
152 break; |
|
153 } |
|
154 } |
|
155 } |
|
156 } |
|
157 |
|
158 if (!arcstate) { |
|
159 /* Local ucrypto context is not saved, clean it up now. */ |
|
160 len = 0; |
|
161 if (op_type == ENCRYPT_OP) |
|
162 (void)ucrypto_encrypt_final(uctx, NULL, &len); |
|
163 else |
|
164 (void)ucrypto_decrypt_final(uctx, NULL, &len); |
|
165 } |
|
166 |
|
167 return ret; |
|
168 } |
|
169 |
|
170 static krb5_error_code |
|
171 k5_arcfour_encrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, |
|
172 size_t num_data) |
|
173 { |
|
174 return k5_arcfour_docrypt(key, state, data, num_data, ENCRYPT_OP); |
|
175 } |
|
176 |
|
177 static krb5_error_code |
|
178 k5_arcfour_decrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, |
|
179 size_t num_data) |
|
180 { |
|
181 return k5_arcfour_docrypt(key, state, data, num_data, DECRYPT_OP); |
|
182 } |
|
183 |
|
184 static krb5_error_code |
|
185 krb5int_arcfour_init_state(const krb5_keyblock *key, krb5_keyusage usage, |
|
186 krb5_data *state) |
|
187 { |
|
188 struct arcfour_state *arcstate; |
|
189 |
|
190 arcstate = calloc(1, sizeof (*arcstate)); |
|
191 if (arcstate == NULL) |
|
192 return ENOMEM; |
|
193 |
|
194 state->data = (char *)arcstate; |
|
195 state->length = sizeof (*arcstate); |
|
196 |
|
197 return 0; |
|
198 } |
|
199 |
|
200 static void |
|
201 krb5int_arcfour_free_state(krb5_data *state) |
|
202 { |
|
203 struct arcfour_state *arcstate = (struct arcfour_state *)state->data; |
|
204 |
|
205 /* If arcstate->loopback == arcstate then the ucrypto context was init'ed |
|
206 * and uctx clean up is required. */ |
|
207 if (arcstate && arcstate->loopback == arcstate) { |
|
208 size_t len = 0; |
|
209 |
|
210 if (arcstate->op_type == ENCRYPT_OP) |
|
211 (void) ucrypto_encrypt_final(&arcstate->uctx, NULL, &len); |
|
212 else |
|
213 (void) ucrypto_decrypt_final(&arcstate->uctx, NULL, &len); |
|
214 } |
|
215 |
|
216 free(arcstate); |
|
217 state->data = NULL; |
|
218 state->length = 0; |
|
219 |
|
220 return; |
|
221 } |
|
222 |
|
223 const struct krb5_enc_provider krb5int_enc_arcfour = { |
|
224 /* This seems to work... although I am not sure what the |
|
225 implications are in other places in the kerberos library */ |
|
226 RC4_BLOCK_SIZE, |
|
227 /* Keysize is arbitrary in arcfour, but the constraints of the |
|
228 system, and to attempt to work with the MSFT system forces us |
|
229 to 16byte/128bit. Since there is no parity in the key, the |
|
230 byte and length are the same. */ |
|
231 RC4_KEY_SIZE, RC4_KEY_SIZE, |
|
232 k5_arcfour_encrypt, |
|
233 k5_arcfour_decrypt, |
|
234 NULL, |
|
235 krb5int_arcfour_init_state, |
|
236 krb5int_arcfour_free_state |
|
237 }; |