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