xref: /illumos-gate/usr/src/uts/common/gssapi/mechs/krb5/crypto/old/old_decrypt.c (revision 159d09a20817016f09b3ea28d1bdada4a336bb91)
1 /*
2  * Copyright 2008 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
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     plainsize = input->length - blocksize - hashsize;
58 
59     if (arg_output->length < plainsize)
60 	return(KRB5_BAD_MSIZE);
61 
62     if (arg_output->length < input->length) {
63 	output.length = input->length;
64 
65 	if ((output.data = (char *) MALLOC(output.length)) == NULL) {
66 	    return(ENOMEM);
67 	}
68 
69 	alloced = 1;
70     } else {
71 	output.length = input->length;
72 
73 	output.data = arg_output->data;
74 
75 	alloced = 0;
76     }
77 
78     /* decrypt it */
79 
80     /* save last ciphertext block in case we decrypt in place */
81     if (ivec != NULL && ivec->length == blocksize) {
82 	cn = MALLOC(blocksize);
83 	if (cn == NULL) {
84 	    ret = ENOMEM;
85 	    goto cleanup;
86 	}
87 	(void) memcpy(cn, input->data + input->length - blocksize, blocksize);
88     } else
89 	cn = NULL;
90 
91     /* XXX this is gross, but I don't have much choice */
92     if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) {
93 	crcivec.length = key->length;
94 	crcivec.data = (char *) key->contents;
95 	ivec = &crcivec;
96     }
97 
98     if ((ret = ((*(enc->decrypt))(context, key, ivec, input, &output))))
99 	goto cleanup;
100 
101     /* verify the checksum */
102 
103     (void) memcpy(orig_cksum, output.data+blocksize, hashsize);
104     (void) memset(output.data+blocksize, 0, hashsize);
105 
106     cksum.length = hashsize;
107     cksum.data = (char *)new_cksum;
108 
109     if ((ret = ((*(hash->hash))(context, 1, &output, &cksum))))
110 	goto cleanup;
111 
112     if (memcmp(cksum.data, orig_cksum, cksum.length) != 0) {
113 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
114 	goto cleanup;
115     }
116 
117     /* copy the plaintext around */
118 
119     if (alloced) {
120 	(void) memcpy(arg_output->data, output.data+blocksize+hashsize,
121 	       plainsize);
122     } else {
123 	(void) memmove(arg_output->data, arg_output->data+blocksize+hashsize,
124 		plainsize);
125     }
126     arg_output->length = plainsize;
127 
128     /* update ivec */
129     if (cn != NULL)
130 	(void) memcpy(ivec->data, cn, blocksize);
131 
132     ret = 0;
133 
134 cleanup:
135     if (alloced) {
136 	(void) memset(output.data, 0, output.length);
137 	FREE(output.data, output.length);
138     }
139 
140     if (cn != NULL)
141 	FREE(cn, blocksize);
142     (void) memset(new_cksum, 0, hashsize);
143 
144     return(ret);
145 }
146