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