~ubuntu-branches/ubuntu/maverick/krb5/maverick

« back to all changes in this revision

Viewing changes to src/lib/crypto/des/d3_aead.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2009-05-07 16:16:34 UTC
  • mfrom: (13.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090507161634-xqyk0s9na0le4flj
Tags: 1.7dfsg~beta1-4
When  decrypting the TGS response fails with the subkey, try with the
session key to work around Heimdal bug, Closes: #527353 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 by the Massachusetts Institute of Technology.
 
3
 * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
 
4
 * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
 
5
 *
 
6
 * Export of this software from the United States of America may
 
7
 *   require a specific license from the United States Government.
 
8
 *   It is the responsibility of any person or organization contemplating
 
9
 *   export to obtain such a license before exporting.
 
10
 * 
 
11
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 
12
 * distribute this software and its documentation for any purpose and
 
13
 * without fee is hereby granted, provided that the above copyright
 
14
 * notice appear in all copies and that both that copyright notice and
 
15
 * this permission notice appear in supporting documentation, and that
 
16
 * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
 
17
 * in advertising or publicity pertaining to distribution of the software
 
18
 * without specific, written prior permission.  Richard P. Basch,
 
19
 * Lehman Brothers and M.I.T. make no representations about the suitability
 
20
 * of this software for any purpose.  It is provided "as is" without
 
21
 * express or implied warranty.
 
22
 */
 
23
 
 
24
#include "des_int.h"
 
25
#include "f_tables.h"
 
26
#include "../aead.h"
 
27
 
 
28
void
 
29
krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data,
 
30
                             unsigned long num_data,
 
31
                             const mit_des_key_schedule ks1,
 
32
                             const mit_des_key_schedule ks2,
 
33
                             const mit_des_key_schedule ks3,
 
34
                             mit_des_cblock ivec)
 
35
{
 
36
    unsigned DES_INT32 left, right;
 
37
    const unsigned DES_INT32 *kp1, *kp2, *kp3;
 
38
    const unsigned char *ip;
 
39
    unsigned char *op;
 
40
    struct iov_block_state input_pos, output_pos;
 
41
    unsigned char iblock[MIT_DES_BLOCK_LENGTH];
 
42
    unsigned char oblock[MIT_DES_BLOCK_LENGTH];
 
43
 
 
44
    IOV_BLOCK_STATE_INIT(&input_pos);
 
45
    IOV_BLOCK_STATE_INIT(&output_pos);
 
46
 
 
47
    /*
 
48
     * Get key pointer here.  This won't need to be reinitialized
 
49
     */
 
50
    kp1 = (const unsigned DES_INT32 *)ks1;
 
51
    kp2 = (const unsigned DES_INT32 *)ks2;
 
52
    kp3 = (const unsigned DES_INT32 *)ks3;
 
53
 
 
54
    /*
 
55
     * Initialize left and right with the contents of the initial
 
56
     * vector.
 
57
     */
 
58
    if (ivec != NULL)
 
59
        ip = ivec;
 
60
    else
 
61
        ip = mit_des_zeroblock;
 
62
    GET_HALF_BLOCK(left, ip);
 
63
    GET_HALF_BLOCK(right, ip);
 
64
 
 
65
    /*
 
66
     * Suitably initialized, now work the length down 8 bytes
 
67
     * at a time.
 
68
     */
 
69
    for (;;) {
 
70
        unsigned DES_INT32 temp;
 
71
 
 
72
        ip = iblock;
 
73
        op = oblock;
 
74
 
 
75
        if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
 
76
            break;
 
77
 
 
78
        if (input_pos.iov_pos == num_data)
 
79
            break;
 
80
 
 
81
        GET_HALF_BLOCK(temp, ip);
 
82
        left  ^= temp;
 
83
        GET_HALF_BLOCK(temp, ip);
 
84
        right ^= temp;
 
85
 
 
86
        /*
 
87
         * Encrypt what we have
 
88
         */
 
89
        DES_DO_ENCRYPT(left, right, kp1);
 
90
        DES_DO_DECRYPT(left, right, kp2);
 
91
        DES_DO_ENCRYPT(left, right, kp3);
 
92
 
 
93
        /*
 
94
         * Copy the results out
 
95
         */
 
96
        PUT_HALF_BLOCK(left, op);
 
97
        PUT_HALF_BLOCK(right, op);
 
98
 
 
99
        krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
 
100
    }
 
101
 
 
102
    if (ivec != NULL)
 
103
        memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH);
 
104
}
 
105
 
 
106
void
 
107
krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data,
 
108
                             unsigned long num_data,
 
109
                             const mit_des_key_schedule ks1,
 
110
                             const mit_des_key_schedule ks2,
 
111
                             const mit_des_key_schedule ks3,
 
112
                             mit_des_cblock ivec)
 
113
{
 
114
    unsigned DES_INT32 left, right;
 
115
    const unsigned DES_INT32 *kp1, *kp2, *kp3;
 
116
    const unsigned char *ip;
 
117
    unsigned DES_INT32 ocipherl, ocipherr;
 
118
    unsigned DES_INT32 cipherl, cipherr;
 
119
    unsigned char *op;
 
120
    struct iov_block_state input_pos, output_pos;
 
121
    unsigned char iblock[MIT_DES_BLOCK_LENGTH];
 
122
    unsigned char oblock[MIT_DES_BLOCK_LENGTH];
 
123
 
 
124
    IOV_BLOCK_STATE_INIT(&input_pos);
 
125
    IOV_BLOCK_STATE_INIT(&output_pos);
 
126
 
 
127
    /*
 
128
     * Get key pointer here.  This won't need to be reinitialized
 
129
     */
 
130
    kp1 = (const unsigned DES_INT32 *)ks1;
 
131
    kp2 = (const unsigned DES_INT32 *)ks2;
 
132
    kp3 = (const unsigned DES_INT32 *)ks3;
 
133
 
 
134
    /*
 
135
     * Decrypting is harder than encrypting because of
 
136
     * the necessity of remembering a lot more things.
 
137
     * Should think about this a little more...
 
138
     */
 
139
 
 
140
    if (num_data == 0)
 
141
        return;
 
142
 
 
143
    /*
 
144
     * Prime the old cipher with ivec.
 
145
     */
 
146
    if (ivec != NULL)
 
147
        ip = ivec;
 
148
    else
 
149
        ip = mit_des_zeroblock;
 
150
    GET_HALF_BLOCK(ocipherl, ip);
 
151
    GET_HALF_BLOCK(ocipherr, ip);
 
152
 
 
153
    /*
 
154
     * Now do this in earnest until we run out of length.
 
155
     */
 
156
    for (;;) {
 
157
        /*
 
158
         * Read a block from the input into left and
 
159
         * right.  Save this cipher block for later.
 
160
         */
 
161
 
 
162
        if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
 
163
            break;
 
164
 
 
165
        if (input_pos.iov_pos == num_data)
 
166
            break;
 
167
 
 
168
        ip = iblock;
 
169
        op = oblock;
 
170
 
 
171
        GET_HALF_BLOCK(left, ip);
 
172
        GET_HALF_BLOCK(right, ip);
 
173
        cipherl = left;
 
174
        cipherr = right;
 
175
 
 
176
        /*
 
177
         * Decrypt this.
 
178
         */
 
179
        DES_DO_DECRYPT(left, right, kp3);
 
180
        DES_DO_ENCRYPT(left, right, kp2);
 
181
        DES_DO_DECRYPT(left, right, kp1);
 
182
 
 
183
        /*
 
184
         * Xor with the old cipher to get plain
 
185
         * text.  Output 8 or less bytes of this.
 
186
         */
 
187
        left ^= ocipherl;
 
188
        right ^= ocipherr;
 
189
 
 
190
        PUT_HALF_BLOCK(left, op);
 
191
        PUT_HALF_BLOCK(right, op);
 
192
 
 
193
        /*
 
194
         * Save current cipher block here
 
195
         */
 
196
        ocipherl = cipherl;
 
197
        ocipherr = cipherr;
 
198
 
 
199
        krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
 
200
    }
 
201
 
 
202
    if (ivec != NULL) {
 
203
        op = ivec;
 
204
        PUT_HALF_BLOCK(ocipherl,op);
 
205
        PUT_HALF_BLOCK(ocipherr, op);
 
206
    }
 
207
}