xref: /illumos-gate/usr/src/uts/common/gssapi/mechs/krb5/crypto/old/old_decrypt.c (revision 505d05c73a6e56769f263d4803b22eddd168ee24)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * Copyright (C) 1998 by the FundsXpress, INC.
10  *
11  * All rights reserved.
12  *
13  * Export of this software from the United States of America may require
14  * a specific license from the United States Government.  It is the
15  * responsibility of any person or organization contemplating export to
16  * obtain such a license before exporting.
17  *
18  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19  * distribute this software and its documentation for any purpose and
20  * without fee is hereby granted, provided that the above copyright
21  * notice appear in all copies and that both that copyright notice and
22  * this permission notice appear in supporting documentation, and that
23  * the name of FundsXpress. not be used in advertising or publicity pertaining
24  * to distribution of the software without specific, written prior
25  * permission.  FundsXpress makes no representations about the suitability of
26  * this software for any purpose.  It is provided "as is" without express
27  * or implied warranty.
28  *
29  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  */
33 
34 #include <k5-int.h>
35 #include <old.h>
36 
37 /*ARGSUSED*/
38 krb5_error_code
39 krb5_old_decrypt(krb5_context context,
40 		krb5_const struct krb5_enc_provider *enc,
41 		krb5_const struct krb5_hash_provider *hash,
42 		krb5_const krb5_keyblock *key,
43 		krb5_keyusage usage,
44 		krb5_const krb5_data *ivec,
45 		krb5_const krb5_data *input,
46 		krb5_data *arg_output)
47 {
48     krb5_error_code ret;
49     size_t blocksize, hashsize, plainsize;
50     unsigned char *cn;
51     krb5_data output, cksum, crcivec;
52     int alloced;
53     unsigned char orig_cksum[128], new_cksum[128];
54 
55 
56     blocksize = enc->block_size;
57     hashsize = hash->hashsize;
58 
59     plainsize = input->length - blocksize - hashsize;
60 
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