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 void
krb5_old_encrypt_length(const struct krb5_enc_provider * enc,const struct krb5_hash_provider * hash,size_t inputlen,size_t * length)37 krb5_old_encrypt_length(const struct krb5_enc_provider *enc,
38 			const struct krb5_hash_provider *hash,
39 			size_t inputlen,
40 			size_t *length)
41 {
42     size_t blocksize, hashsize;
43 
44     blocksize = enc->block_size;
45     hashsize = hash->hashsize;
46 
47     *length = krb5_roundup(blocksize+hashsize+inputlen, blocksize);
48 }
49 
50 /*ARGSUSED*/
51 krb5_error_code
krb5_old_encrypt(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 * output)52 krb5_old_encrypt(krb5_context context,
53 		 const struct krb5_enc_provider *enc,
54 		 const struct krb5_hash_provider *hash,
55 		 const krb5_keyblock *key,
56 		 krb5_keyusage usage,
57 		 const krb5_data *ivec,
58 		 const krb5_data *input,
59 		 krb5_data *output)
60 {
61     krb5_error_code ret;
62     size_t blocksize, hashsize, enclen;
63     krb5_data datain, crcivec;
64     int real_ivec;
65 
66     blocksize = enc->block_size;
67     hashsize = hash->hashsize;
68 
69     krb5_old_encrypt_length(enc, hash, input->length, &enclen);
70 
71     if (output->length < enclen)
72 	return(KRB5_BAD_MSIZE);
73 
74     output->length = enclen;
75 
76     /* fill in confounded, padded, plaintext buffer with zero checksum */
77 
78     (void) memset(output->data, 0, output->length);
79 
80     datain.length = blocksize;
81     datain.data = (char *) output->data;
82 
83     if ((ret = krb5_c_random_make_octets(context, &datain)))
84 	return(ret);
85     (void) memcpy(output->data+blocksize+hashsize, input->data, input->length);
86 
87     /* compute the checksum */
88 
89     datain.length = hashsize;
90     datain.data = output->data+blocksize;
91 
92     if ((ret = ((*(hash->hash))(context, 1, output, &datain))))
93 	goto cleanup;
94 
95     /* encrypt it */
96 
97     /* XXX this is gross, but I don't have much choice */
98     if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) {
99 	crcivec.length = key->length;
100 	crcivec.data = (char *) key->contents;
101 	ivec = &crcivec;
102 	real_ivec = 0;
103     } else
104 	real_ivec = 1;
105 
106     if ((ret = ((*(enc->encrypt))(context, key, ivec, output, output))))
107 	goto cleanup;
108 
109     /* update ivec */
110     if (real_ivec && ivec != NULL && ivec->length == blocksize)
111 	(void) memcpy(ivec->data, output->data + output->length - blocksize,
112 	       blocksize);
113 cleanup:
114     if (ret)
115 	(void) memset(output->data, 0, output->length);
116 
117     return(ret);
118 }
119