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 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