This commit was manufactured by cvs2svn to create tag
[krb5.git] / src / lib / crypto / dk / dk_decrypt.c
1 /*
2  * Copyright (C) 1998 by the FundsXpress, INC.
3  * 
4  * All rights reserved.
5  * 
6  * Export of this software from the United States of America may require
7  * a specific license from the United States Government.  It is the
8  * responsibility of any person or organization contemplating export to
9  * 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 FundsXpress. not be used in advertising or publicity pertaining
17  * to distribution of the software without specific, written prior
18  * permission.  FundsXpress makes no representations about the suitability of
19  * this software for any purpose.  It is provided "as is" without express
20  * or implied warranty.
21  * 
22  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
24  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25  */
26
27 #include "k5-int.h"
28 #include "dk.h"
29
30 #define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
31
32 static krb5_error_code
33 krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
34                                  const struct krb5_hash_provider *hash,
35                                  const krb5_keyblock *key,
36                                  krb5_keyusage usage,
37                                  const krb5_data *ivec,
38                                  const krb5_data *input,
39                                  krb5_data *output,
40                                  size_t hmacsize);
41
42 krb5_error_code
43 krb5_dk_decrypt(enc, hash, key, usage, ivec, input, output)
44      const struct krb5_enc_provider *enc;
45      const struct krb5_hash_provider *hash;
46      const krb5_keyblock *key;
47      krb5_keyusage usage;
48      const krb5_data *ivec;
49      const krb5_data *input;
50      krb5_data *output;
51 {
52     return krb5_dk_decrypt_maybe_trunc_hmac(enc, hash, key, usage,
53                                             ivec, input, output, 0);
54 }
55
56 krb5_error_code
57 krb5int_aes_dk_decrypt(enc, hash, key, usage, ivec, input, output)
58      const struct krb5_enc_provider *enc;
59      const struct krb5_hash_provider *hash;
60      const krb5_keyblock *key;
61      krb5_keyusage usage;
62      const krb5_data *ivec;
63      const krb5_data *input;
64      krb5_data *output;
65 {
66     return krb5_dk_decrypt_maybe_trunc_hmac(enc, hash, key, usage,
67                                             ivec, input, output, 96 / 8);
68 }
69
70 static krb5_error_code
71 krb5_dk_decrypt_maybe_trunc_hmac(enc, hash, key, usage, ivec, input, output,
72                                  hmacsize)
73      const struct krb5_enc_provider *enc;
74      const struct krb5_hash_provider *hash;
75      const krb5_keyblock *key;
76      krb5_keyusage usage;
77      const krb5_data *ivec;
78      const krb5_data *input;
79      krb5_data *output;
80      size_t hmacsize;
81 {
82     krb5_error_code ret;
83     size_t hashsize, blocksize, keybytes, keylength, enclen, plainlen;
84     unsigned char *plaindata, *kedata, *kidata, *cksum, *cn;
85     krb5_keyblock ke, ki;
86     krb5_data d1, d2;
87     unsigned char constantdata[K5CLENGTH];
88
89     /* allocate and set up ciphertext and to-be-derived keys */
90
91     (*(hash->hash_size))(&hashsize);
92     (*(enc->block_size))(&blocksize);
93     (*(enc->keysize))(&keybytes, &keylength);
94
95     if (hmacsize == 0)
96         hmacsize = hashsize;
97     else if (hmacsize > hashsize)
98         return KRB5KRB_AP_ERR_BAD_INTEGRITY;
99
100     enclen = input->length - hmacsize;
101
102     if ((kedata = (unsigned char *) malloc(keylength)) == NULL)
103         return(ENOMEM);
104     if ((kidata = (unsigned char *) malloc(keylength)) == NULL) {
105         free(kedata);
106         return(ENOMEM);
107     }
108     if ((plaindata = (unsigned char *) malloc(enclen)) == NULL) {
109         free(kidata);
110         free(kedata);
111         return(ENOMEM);
112     }
113     if ((cksum = (unsigned char *) malloc(hashsize)) == NULL) {
114         free(plaindata);
115         free(kidata);
116         free(kedata);
117         return(ENOMEM);
118     }
119
120     ke.contents = kedata;
121     ke.length = keylength;
122     ki.contents = kidata;
123     ki.length = keylength;
124
125     /* derive the keys */
126
127     d1.data = (char *) constantdata;
128     d1.length = K5CLENGTH;
129
130     d1.data[0] = (usage>>24)&0xff;
131     d1.data[1] = (usage>>16)&0xff;
132     d1.data[2] = (usage>>8)&0xff;
133     d1.data[3] = usage&0xff;
134
135     d1.data[4] = (char) 0xAA;
136
137     if ((ret = krb5_derive_key(enc, key, &ke, &d1)) != 0)
138         goto cleanup;
139
140     d1.data[4] = 0x55;
141
142     if ((ret = krb5_derive_key(enc, key, &ki, &d1)) != 0)
143         goto cleanup;
144
145     /* decrypt the ciphertext */
146
147     d1.length = enclen;
148     d1.data = input->data;
149
150     d2.length = enclen;
151     d2.data = (char *) plaindata;
152
153     if ((ret = ((*(enc->decrypt))(&ke, ivec, &d1, &d2))) != 0)
154         goto cleanup;
155
156     if (ivec != NULL && ivec->length == blocksize)
157         cn = (unsigned char *) d1.data + d1.length - blocksize;
158     else
159         cn = NULL;
160
161     /* verify the hash */
162
163     d1.length = hashsize;
164     d1.data = (char *) cksum;
165
166     if ((ret = krb5_hmac(hash, &ki, 1, &d2, &d1)) != 0)
167         goto cleanup;
168
169     if (memcmp(cksum, input->data+enclen, hmacsize) != 0) {
170         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
171         goto cleanup;
172     }
173
174     /* because this encoding isn't self-describing wrt length, the
175        best we can do here is to compute the length minus the
176        confounder. */
177
178     plainlen = enclen - blocksize;
179
180     if (output->length < plainlen)
181         return(KRB5_BAD_MSIZE);
182
183     output->length = plainlen;
184
185     memcpy(output->data, d2.data+blocksize, output->length);
186
187     if (cn != NULL)
188         memcpy(ivec->data, cn, blocksize);
189
190     ret = 0;
191
192 cleanup:
193     memset(kedata, 0, keylength);
194     memset(kidata, 0, keylength);
195     memset(plaindata, 0, enclen);
196     memset(cksum, 0, hashsize);
197
198     free(cksum);
199     free(plaindata);
200     free(kidata);
201     free(kedata);
202
203     return(ret);
204 }
205
206 #ifdef ATHENA_DES3_KLUDGE
207 krb5_error_code
208 krb5_marc_dk_decrypt(enc, hash, key, usage, ivec, input, output)
209      const struct krb5_enc_provider *enc;
210      const struct krb5_hash_provider *hash;
211      const krb5_keyblock *key;
212      krb5_keyusage usage;
213      const krb5_data *ivec;
214      const krb5_data *input;
215      krb5_data *output;
216 {
217     krb5_error_code ret;
218     size_t hashsize, blocksize, keybytes, keylength, enclen, plainlen;
219     unsigned char *plaindata, *kedata, *kidata, *cksum, *cn;
220     krb5_keyblock ke, ki;
221     krb5_data d1, d2;
222     unsigned char constantdata[K5CLENGTH];
223
224     /* allocate and set up ciphertext and to-be-derived keys */
225
226     (*(hash->hash_size))(&hashsize);
227     (*(enc->block_size))(&blocksize);
228     (*(enc->keysize))(&keybytes, &keylength);
229
230     enclen = input->length - hashsize;
231
232     if ((kedata = (unsigned char *) malloc(keylength)) == NULL)
233         return(ENOMEM);
234     if ((kidata = (unsigned char *) malloc(keylength)) == NULL) {
235         free(kedata);
236         return(ENOMEM);
237     }
238     if ((plaindata = (unsigned char *) malloc(enclen)) == NULL) {
239         free(kidata);
240         free(kedata);
241         return(ENOMEM);
242     }
243     if ((cksum = (unsigned char *) malloc(hashsize)) == NULL) {
244         free(plaindata);
245         free(kidata);
246         free(kedata);
247         return(ENOMEM);
248     }
249
250     ke.contents = kedata;
251     ke.length = keylength;
252     ki.contents = kidata;
253     ki.length = keylength;
254
255     /* derive the keys */
256
257     d1.data = constantdata;
258     d1.length = K5CLENGTH;
259
260     d1.data[0] = (usage>>24)&0xff;
261     d1.data[1] = (usage>>16)&0xff;
262     d1.data[2] = (usage>>8)&0xff;
263     d1.data[3] = usage&0xff;
264
265     d1.data[4] = 0xAA;
266
267     if ((ret = krb5_derive_key(enc, key, &ke, &d1)) != 0)
268         goto cleanup;
269
270     d1.data[4] = 0x55;
271
272     if ((ret = krb5_derive_key(enc, key, &ki, &d1)) != 0)
273         goto cleanup;
274
275     /* decrypt the ciphertext */
276
277     d1.length = enclen;
278     d1.data = input->data;
279
280     d2.length = enclen;
281     d2.data = plaindata;
282
283     if ((ret = ((*(enc->decrypt))(&ke, ivec, &d1, &d2))) != 0)
284         goto cleanup;
285
286     if (ivec != NULL && ivec->length == blocksize)
287         cn = d1.data + d1.length - blocksize;
288     else
289         cn = NULL;
290
291     /* verify the hash */
292
293     d1.length = hashsize;
294     d1.data = cksum;
295
296     if ((ret = krb5_hmac(hash, &ki, 1, &d2, &d1)) != 0)
297         goto cleanup;
298
299     if (memcmp(cksum, input->data+enclen, hashsize) != 0) {
300         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
301         goto cleanup;
302     }
303
304     /* because this encoding isn't self-describing wrt length, the
305        best we can do here is to compute the length minus the
306        confounder. */
307
308     /* get the real plaintext length and copy the data into the output */
309
310     plainlen = ((((plaindata+blocksize)[0])<<24) |
311                 (((plaindata+blocksize)[1])<<16) |
312                 (((plaindata+blocksize)[2])<<8) |
313                 ((plaindata+blocksize)[3]));
314
315     if (plainlen > (enclen - blocksize - 4))
316         return(KRB5_BAD_MSIZE);
317
318     if (output->length < plainlen)
319         return(KRB5_BAD_MSIZE);
320
321     output->length = plainlen;
322
323     memcpy(output->data, d2.data+4+blocksize, output->length);
324
325     if (cn != NULL)
326         memcpy(ivec->data, cn, blocksize);
327
328     ret = 0;
329
330 cleanup:
331     memset(kedata, 0, keylength);
332     memset(kidata, 0, keylength);
333     memset(plaindata, 0, enclen);
334     memset(cksum, 0, hashsize);
335
336     free(cksum);
337     free(plaindata);
338     free(kidata);
339     free(kedata);
340
341     return(ret);
342 }
343 #endif /* ATHENA_DES3_KLUDGE */