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 void
krb5int_des3_cbc_encrypt(krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule ks1,const mit_des_key_schedule ks2,const mit_des_key_schedule ks3,mit_des_cblock ivec)32 krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
33 const mit_des_key_schedule ks1,
34 const mit_des_key_schedule ks2,
35 const mit_des_key_schedule ks3,
36 mit_des_cblock ivec)
37 {
38 unsigned DES_INT32 left, right;
39 const unsigned DES_INT32 *kp1, *kp2, *kp3;
40 const unsigned char *ip;
41 struct iov_cursor cursor;
42 unsigned char block[MIT_DES_BLOCK_LENGTH];
43
44 /* Get key pointers here. These won't need to be reinitialized. */
45 kp1 = (const unsigned DES_INT32 *)ks1;
46 kp2 = (const unsigned DES_INT32 *)ks2;
47 kp3 = (const unsigned DES_INT32 *)ks3;
48
49 /* Initialize left and right with the contents of the initial vector. */
50 ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
51 left = load_32_be(ip);
52 right = load_32_be(ip + 4);
53
54 k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
55 while (k5_iov_cursor_get(&cursor, block)) {
56 /* xor this block with the previous ciphertext. */
57 left ^= load_32_be(block);
58 right ^= load_32_be(block + 4);
59
60 /* Encrypt what we have and store it back into block. */
61 DES_DO_ENCRYPT(left, right, kp1);
62 DES_DO_DECRYPT(left, right, kp2);
63 DES_DO_ENCRYPT(left, right, kp3);
64 store_32_be(left, block);
65 store_32_be(right, block + 4);
66
67 k5_iov_cursor_put(&cursor, block);
68 }
69
70 if (ivec != NULL) {
71 store_32_be(left, ivec);
72 store_32_be(right, ivec + 4);
73 }
74 }
75
76 void
krb5int_des3_cbc_decrypt(krb5_crypto_iov * data,unsigned long num_data,const mit_des_key_schedule ks1,const mit_des_key_schedule ks2,const mit_des_key_schedule ks3,mit_des_cblock ivec)77 krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
78 const mit_des_key_schedule ks1,
79 const mit_des_key_schedule ks2,
80 const mit_des_key_schedule ks3,
81 mit_des_cblock ivec)
82 {
83 unsigned DES_INT32 left, right;
84 const unsigned DES_INT32 *kp1, *kp2, *kp3;
85 const unsigned char *ip;
86 unsigned DES_INT32 ocipherl, ocipherr;
87 unsigned DES_INT32 cipherl, cipherr;
88 struct iov_cursor cursor;
89 unsigned char block[MIT_DES_BLOCK_LENGTH];
90
91 /* Get key pointers here. These won't need to be reinitialized. */
92 kp1 = (const unsigned DES_INT32 *)ks1;
93 kp2 = (const unsigned DES_INT32 *)ks2;
94 kp3 = (const unsigned DES_INT32 *)ks3;
95
96 /*
97 * Decrypting is harder than encrypting because of
98 * the necessity of remembering a lot more things.
99 * Should think about this a little more...
100 */
101
102 /* Prime the old cipher with ivec.*/
103 ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
104 ocipherl = load_32_be(ip);
105 ocipherr = load_32_be(ip + 4);
106
107 k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
108 while (k5_iov_cursor_get(&cursor, block)) {
109 /* Split this block into left and right. */
110 cipherl = left = load_32_be(block);
111 cipherr = right = load_32_be(block + 4);
112
113 /* Decrypt and xor with the old cipher to get plain text. */
114 DES_DO_DECRYPT(left, right, kp3);
115 DES_DO_ENCRYPT(left, right, kp2);
116 DES_DO_DECRYPT(left, right, kp1);
117 left ^= ocipherl;
118 right ^= ocipherr;
119
120 /* Store the encrypted halves back into block. */
121 store_32_be(left, block);
122 store_32_be(right, block + 4);
123
124 /* Save current cipher block halves. */
125 ocipherl = cipherl;
126 ocipherr = cipherr;
127
128 k5_iov_cursor_put(&cursor, block);
129 }
130
131 if (ivec != NULL) {
132 store_32_be(ocipherl, ivec);
133 store_32_be(ocipherr, ivec + 4);
134 }
135 }
136
137 #endif /* K5_BUILTIN_DES */
138