17c478bdstevel@tonic-gate/*
2e753f46Will Fiveash * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
37c478bdstevel@tonic-gate * Use is subject to license terms.
47c478bdstevel@tonic-gate */
57c478bdstevel@tonic-gate
67c478bdstevel@tonic-gate
77c478bdstevel@tonic-gate/*
87c478bdstevel@tonic-gate * Copyright (C) 1998 by the FundsXpress, INC.
97c478bdstevel@tonic-gate *
107c478bdstevel@tonic-gate * All rights reserved.
117c478bdstevel@tonic-gate *
127c478bdstevel@tonic-gate * Export of this software from the United States of America may require
137c478bdstevel@tonic-gate * a specific license from the United States Government.  It is the
147c478bdstevel@tonic-gate * responsibility of any person or organization contemplating export to
157c478bdstevel@tonic-gate * obtain such a license before exporting.
167c478bdstevel@tonic-gate *
177c478bdstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
187c478bdstevel@tonic-gate * distribute this software and its documentation for any purpose and
197c478bdstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
207c478bdstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
217c478bdstevel@tonic-gate * this permission notice appear in supporting documentation, and that
227c478bdstevel@tonic-gate * the name of FundsXpress. not be used in advertising or publicity pertaining
237c478bdstevel@tonic-gate * to distribution of the software without specific, written prior
247c478bdstevel@tonic-gate * permission.  FundsXpress makes no representations about the suitability of
257c478bdstevel@tonic-gate * this software for any purpose.  It is provided "as is" without express
267c478bdstevel@tonic-gate * or implied warranty.
277c478bdstevel@tonic-gate *
287c478bdstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
297c478bdstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
307c478bdstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
317c478bdstevel@tonic-gate */
327c478bdstevel@tonic-gate
33159d09aMark Phalan#include "k5-int.h"
34159d09aMark Phalan#include "old.h"
357c478bdstevel@tonic-gate
367c478bdstevel@tonic-gate/*ARGSUSED*/
377c478bdstevel@tonic-gatekrb5_error_code
38505d05cgtbkrb5_old_decrypt(krb5_context context,
39159d09aMark Phalan		 const struct krb5_enc_provider *enc,
40159d09aMark Phalan		 const struct krb5_hash_provider *hash,
41159d09aMark Phalan		 const krb5_keyblock *key,
42159d09aMark Phalan		 krb5_keyusage usage,
43159d09aMark Phalan		 const krb5_data *ivec,
44159d09aMark Phalan		 const krb5_data *input,
45159d09aMark Phalan		 krb5_data *arg_output)
467c478bdstevel@tonic-gate{
477c478bdstevel@tonic-gate    krb5_error_code ret;
487c478bdstevel@tonic-gate    size_t blocksize, hashsize, plainsize;
497c478bdstevel@tonic-gate    unsigned char *cn;
507c478bdstevel@tonic-gate    krb5_data output, cksum, crcivec;
517c478bdstevel@tonic-gate    int alloced;
527c478bdstevel@tonic-gate    unsigned char orig_cksum[128], new_cksum[128];
537c478bdstevel@tonic-gate
54505d05cgtb    blocksize = enc->block_size;
55505d05cgtb    hashsize = hash->hashsize;
567c478bdstevel@tonic-gate
57e753f46Will Fiveash    /* Verify input and output lengths. */
58e753f46Will Fiveash    if (input->length < blocksize + hashsize || input->length % blocksize != 0)
59e753f46Will Fiveash        return(KRB5_BAD_MSIZE);
607c478bdstevel@tonic-gate    plainsize = input->length - blocksize - hashsize;
617c478bdstevel@tonic-gate    if (arg_output->length < plainsize)
627c478bdstevel@tonic-gate	return(KRB5_BAD_MSIZE);
637c478bdstevel@tonic-gate
647c478bdstevel@tonic-gate    if (arg_output->length < input->length) {
657c478bdstevel@tonic-gate	output.length = input->length;
667c478bdstevel@tonic-gate
677c478bdstevel@tonic-gate	if ((output.data = (char *) MALLOC(output.length)) == NULL) {
687c478bdstevel@tonic-gate	    return(ENOMEM);
697c478bdstevel@tonic-gate	}
707c478bdstevel@tonic-gate
717c478bdstevel@tonic-gate	alloced = 1;
727c478bdstevel@tonic-gate    } else {
737c478bdstevel@tonic-gate	output.length = input->length;
747c478bdstevel@tonic-gate
757c478bdstevel@tonic-gate	output.data = arg_output->data;
767c478bdstevel@tonic-gate
777c478bdstevel@tonic-gate	alloced = 0;
787c478bdstevel@tonic-gate    }
797c478bdstevel@tonic-gate
807c478bdstevel@tonic-gate    /* decrypt it */
817c478bdstevel@tonic-gate
827c478bdstevel@tonic-gate    /* save last ciphertext block in case we decrypt in place */
837c478bdstevel@tonic-gate    if (ivec != NULL && ivec->length == blocksize) {
847c478bdstevel@tonic-gate	cn = MALLOC(blocksize);
857c478bdstevel@tonic-gate	if (cn == NULL) {
867c478bdstevel@tonic-gate	    ret = ENOMEM;
877c478bdstevel@tonic-gate	    goto cleanup;
887c478bdstevel@tonic-gate	}
897c478bdstevel@tonic-gate	(void) memcpy(cn, input->data + input->length - blocksize, blocksize);
907c478bdstevel@tonic-gate    } else
917c478bdstevel@tonic-gate	cn = NULL;
927c478bdstevel@tonic-gate
937c478bdstevel@tonic-gate    /* XXX this is gross, but I don't have much choice */
947c478bdstevel@tonic-gate    if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) {
957c478bdstevel@tonic-gate	crcivec.length = key->length;
967c478bdstevel@tonic-gate	crcivec.data = (char *) key->contents;
977c478bdstevel@tonic-gate	ivec = &crcivec;
987c478bdstevel@tonic-gate    }
997c478bdstevel@tonic-gate
1007c478bdstevel@tonic-gate    if ((ret = ((*(enc->decrypt))(context, key, ivec, input, &output))))
1017c478bdstevel@tonic-gate	goto cleanup;
1027c478bdstevel@tonic-gate
1037c478bdstevel@tonic-gate    /* verify the checksum */
1047c478bdstevel@tonic-gate
1057c478bdstevel@tonic-gate    (void) memcpy(orig_cksum, output.data+blocksize, hashsize);
1067c478bdstevel@tonic-gate    (void) memset(output.data+blocksize, 0, hashsize);
1077c478bdstevel@tonic-gate
1087c478bdstevel@tonic-gate    cksum.length = hashsize;
1097c478bdstevel@tonic-gate    cksum.data = (char *)new_cksum;
1107c478bdstevel@tonic-gate
1117c478bdstevel@tonic-gate    if ((ret = ((*(hash->hash))(context, 1, &output, &cksum))))
1127c478bdstevel@tonic-gate	goto cleanup;
1137c478bdstevel@tonic-gate
1147c478bdstevel@tonic-gate    if (memcmp(cksum.data, orig_cksum, cksum.length) != 0) {
1157c478bdstevel@tonic-gate	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1167c478bdstevel@tonic-gate	goto cleanup;
1177c478bdstevel@tonic-gate    }
1187c478bdstevel@tonic-gate
1197c478bdstevel@tonic-gate    /* copy the plaintext around */
1207c478bdstevel@tonic-gate
1217c478bdstevel@tonic-gate    if (alloced) {
1227c478bdstevel@tonic-gate	(void) memcpy(arg_output->data, output.data+blocksize+hashsize,
1237c478bdstevel@tonic-gate	       plainsize);
1247c478bdstevel@tonic-gate    } else {
1257c478bdstevel@tonic-gate	(void) memmove(arg_output->data, arg_output->data+blocksize+hashsize,
1267c478bdstevel@tonic-gate		plainsize);
1277c478bdstevel@tonic-gate    }
1287c478bdstevel@tonic-gate    arg_output->length = plainsize;
1297c478bdstevel@tonic-gate
1307c478bdstevel@tonic-gate    /* update ivec */
1317c478bdstevel@tonic-gate    if (cn != NULL)
1327c478bdstevel@tonic-gate	(void) memcpy(ivec->data, cn, blocksize);
1337c478bdstevel@tonic-gate
1347c478bdstevel@tonic-gate    ret = 0;
1357c478bdstevel@tonic-gate
1367c478bdstevel@tonic-gatecleanup:
1377c478bdstevel@tonic-gate    if (alloced) {
1387c478bdstevel@tonic-gate	(void) memset(output.data, 0, output.length);
1397c478bdstevel@tonic-gate	FREE(output.data, output.length);
1407c478bdstevel@tonic-gate    }
1417c478bdstevel@tonic-gate
1427c478bdstevel@tonic-gate    if (cn != NULL)
1437c478bdstevel@tonic-gate	FREE(cn, blocksize);
1447c478bdstevel@tonic-gate    (void) memset(new_cksum, 0, hashsize);
1457c478bdstevel@tonic-gate
1467c478bdstevel@tonic-gate    return(ret);
1477c478bdstevel@tonic-gate}
148