1 /*
2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6
7 /*
8 * Copyright (C) 1998 by the FundsXpress, INC.
9 *
10 * All rights reserved.
11 *
12 * Export of this software from the United States of America may require
13 * a specific license from the United States Government. It is the
14 * responsibility of any person or organization contemplating export to
15 * obtain such a license before exporting.
16 *
17 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18 * distribute this software and its documentation for any purpose and
19 * without fee is hereby granted, provided that the above copyright
20 * notice appear in all copies and that both that copyright notice and
21 * this permission notice appear in supporting documentation, and that
22 * the name of FundsXpress. not be used in advertising or publicity pertaining
23 * to distribution of the software without specific, written prior
24 * permission. FundsXpress makes no representations about the suitability of
25 * this software for any purpose. It is provided "as is" without express
26 * or implied warranty.
27 *
28 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31 */
32
33 #include "k5-int.h"
34 #include "old.h"
35
36 /*ARGSUSED*/
37 krb5_error_code
krb5_old_decrypt(krb5_context context,const struct krb5_enc_provider * enc,const struct krb5_hash_provider * hash,const krb5_keyblock * key,krb5_keyusage usage,const krb5_data * ivec,const krb5_data * input,krb5_data * arg_output)38 krb5_old_decrypt(krb5_context context,
39 const struct krb5_enc_provider *enc,
40 const struct krb5_hash_provider *hash,
41 const krb5_keyblock *key,
42 krb5_keyusage usage,
43 const krb5_data *ivec,
44 const krb5_data *input,
45 krb5_data *arg_output)
46 {
47 krb5_error_code ret;
48 size_t blocksize, hashsize, plainsize;
49 unsigned char *cn;
50 krb5_data output, cksum, crcivec;
51 int alloced;
52 unsigned char orig_cksum[128], new_cksum[128];
53
54 blocksize = enc->block_size;
55 hashsize = hash->hashsize;
56
57 /* Verify input and output lengths. */
58 if (input->length < blocksize + hashsize || input->length % blocksize != 0)
59 return(KRB5_BAD_MSIZE);
60 plainsize = input->length - blocksize - hashsize;
61 if (arg_output->length < plainsize)
62 return(KRB5_BAD_MSIZE);
63
64 if (arg_output->length < input->length) {
65 output.length = input->length;
66
67 if ((output.data = (char *) MALLOC(output.length)) == NULL) {
68 return(ENOMEM);
69 }
70
71 alloced = 1;
72 } else {
73 output.length = input->length;
74
75 output.data = arg_output->data;
76
77 alloced = 0;
78 }
79
80 /* decrypt it */
81
82 /* save last ciphertext block in case we decrypt in place */
83 if (ivec != NULL && ivec->length == blocksize) {
84 cn = MALLOC(blocksize);
85 if (cn == NULL) {
86 ret = ENOMEM;
87 goto cleanup;
88 }
89 (void) memcpy(cn, input->data + input->length - blocksize, blocksize);
90 } else
91 cn = NULL;
92
93 /* XXX this is gross, but I don't have much choice */
94 if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) {
95 crcivec.length = key->length;
96 crcivec.data = (char *) key->contents;
97 ivec = &crcivec;
98 }
99
100 if ((ret = ((*(enc->decrypt))(context, key, ivec, input, &output))))
101 goto cleanup;
102
103 /* verify the checksum */
104
105 (void) memcpy(orig_cksum, output.data+blocksize, hashsize);
106 (void) memset(output.data+blocksize, 0, hashsize);
107
108 cksum.length = hashsize;
109 cksum.data = (char *)new_cksum;
110
111 if ((ret = ((*(hash->hash))(context, 1, &output, &cksum))))
112 goto cleanup;
113
114 if (memcmp(cksum.data, orig_cksum, cksum.length) != 0) {
115 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
116 goto cleanup;
117 }
118
119 /* copy the plaintext around */
120
121 if (alloced) {
122 (void) memcpy(arg_output->data, output.data+blocksize+hashsize,
123 plainsize);
124 } else {
125 (void) memmove(arg_output->data, arg_output->data+blocksize+hashsize,
126 plainsize);
127 }
128 arg_output->length = plainsize;
129
130 /* update ivec */
131 if (cn != NULL)
132 (void) memcpy(ivec->data, cn, blocksize);
133
134 ret = 0;
135
136 cleanup:
137 if (alloced) {
138 (void) memset(output.data, 0, output.length);
139 FREE(output.data, output.length);
140 }
141
142 if (cn != NULL)
143 FREE(cn, blocksize);
144 (void) memset(new_cksum, 0, hashsize);
145
146 return(ret);
147 }
148