1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3 * Copyright (C) 2008 by the Massachusetts Institute of Technology.
4 * Copyright 1995 by Richard P. Basch. All Rights Reserved.
5 * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used
18 * in advertising or publicity pertaining to distribution of the software
19 * without specific, written prior permission. Richard P. Basch,
20 * Lehman Brothers and M.I.T. make no representations about the suitability
21 * of this software for any purpose. It is provided "as is" without
22 * express or implied warranty.
23 */
24
25 #include "crypto_int.h"
26 #include "des_int.h"
27 #include "f_tables.h"
28
29 #ifdef K5_BUILTIN_DES
30
31 const mit_des_cblock mit_des_zeroblock /* = all zero */;
32
33 void
krb5int_des_cbc_encrypt(krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule schedule,mit_des_cblock ivec)34 krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
35 const mit_des_key_schedule schedule,
36 mit_des_cblock ivec)
37 {
38 unsigned DES_INT32 left, right;
39 const unsigned DES_INT32 *kp;
40 const unsigned char *ip;
41 struct iov_cursor cursor;
42 unsigned char block[MIT_DES_BLOCK_LENGTH];
43
44 /* Get key pointer here. This won't need to be reinitialized. */
45 kp = (const unsigned DES_INT32 *)schedule;
46
47 /* Initialize left and right with the contents of the initial vector. */
48 ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
49 left = load_32_be(ip);
50 right = load_32_be(ip + 4);
51
52 k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
53 while (k5_iov_cursor_get(&cursor, block)) {
54 /* Decompose this block and xor it with the previous ciphertext. */
55 left ^= load_32_be(block);
56 right ^= load_32_be(block + 4);
57
58 /* Encrypt what we have and put back into block. */
59 DES_DO_ENCRYPT(left, right, kp);
60 store_32_be(left, block);
61 store_32_be(right, block + 4);
62
63 k5_iov_cursor_put(&cursor, block);
64 }
65
66 if (ivec != NULL) {
67 store_32_be(left, ivec);
68 store_32_be(right, ivec + 4);
69 }
70 }
71
72 void
krb5int_des_cbc_decrypt(krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule schedule,mit_des_cblock ivec)73 krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
74 const mit_des_key_schedule schedule,
75 mit_des_cblock ivec)
76 {
77 unsigned DES_INT32 left, right;
78 const unsigned DES_INT32 *kp;
79 const unsigned char *ip;
80 unsigned DES_INT32 ocipherl, ocipherr;
81 unsigned DES_INT32 cipherl, cipherr;
82 struct iov_cursor cursor;
83 unsigned char block[MIT_DES_BLOCK_LENGTH];
84
85 /* Get key pointer here. This won't need to be reinitialized. */
86 kp = (const unsigned DES_INT32 *)schedule;
87
88 /*
89 * Decrypting is harder than encrypting because of
90 * the necessity of remembering a lot more things.
91 * Should think about this a little more...
92 */
93
94 /* Prime the old cipher with ivec. */
95 ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
96 ocipherl = load_32_be(ip);
97 ocipherr = load_32_be(ip + 4);
98
99 k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
100 while (k5_iov_cursor_get(&cursor, block)) {
101 /* Split this block into left and right. */
102 cipherl = left = load_32_be(block);
103 cipherr = right = load_32_be(block + 4);
104
105 /* Decrypt and xor with the old cipher to get plain text. */
106 DES_DO_DECRYPT(left, right, kp);
107 left ^= ocipherl;
108 right ^= ocipherr;
109
110 /* Store the encrypted halves back into block. */
111 store_32_be(left, block);
112 store_32_be(right, block + 4);
113
114 /* Save current cipher block halves. */
115 ocipherl = cipherl;
116 ocipherr = cipherr;
117
118 k5_iov_cursor_put(&cursor, block);
119 }
120
121 if (ivec != NULL) {
122 store_32_be(ocipherl, ivec);
123 store_32_be(ocipherr, ivec + 4);
124 }
125 }
126
127 void
krb5int_des_cbc_mac(const krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule schedule,mit_des_cblock ivec,mit_des_cblock out)128 krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data,
129 const mit_des_key_schedule schedule, mit_des_cblock ivec,
130 mit_des_cblock out)
131 {
132 unsigned DES_INT32 left, right;
133 const unsigned DES_INT32 *kp;
134 const unsigned char *ip;
135 struct iov_cursor cursor;
136 unsigned char block[MIT_DES_BLOCK_LENGTH];
137
138 /* Get key pointer here. This won't need to be reinitialized. */
139 kp = (const unsigned DES_INT32 *)schedule;
140
141 /* Initialize left and right with the contents of the initial vector. */
142 ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
143 left = load_32_be(ip);
144 right = load_32_be(ip + 4);
145
146 k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, TRUE);
147 while (k5_iov_cursor_get(&cursor, block)) {
148 /* Decompose this block and xor it with the previous ciphertext. */
149 left ^= load_32_be(block);
150 right ^= load_32_be(block + 4);
151
152 /* Encrypt what we have. */
153 DES_DO_ENCRYPT(left, right, kp);
154 }
155
156 /* Output the final ciphertext block. */
157 store_32_be(left, out);
158 store_32_be(right, out + 4);
159 }
160
161 #if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO)
krb5int_des_do_encrypt_2(unsigned DES_INT32 * left,unsigned DES_INT32 * right,const unsigned DES_INT32 * kp)162 void krb5int_des_do_encrypt_2 (unsigned DES_INT32 *left,
163 unsigned DES_INT32 *right,
164 const unsigned DES_INT32 *kp)
165 {
166 DES_DO_ENCRYPT_1 (*left, *right, kp);
167 }
168
krb5int_des_do_decrypt_2(unsigned DES_INT32 * left,unsigned DES_INT32 * right,const unsigned DES_INT32 * kp)169 void krb5int_des_do_decrypt_2 (unsigned DES_INT32 *left,
170 unsigned DES_INT32 *right,
171 const unsigned DES_INT32 *kp)
172 {
173 DES_DO_DECRYPT_1 (*left, *right, kp);
174 }
175 #endif
176
177 #endif /* K5_BUILTIN_DES */
178