2N/A/*
2N/A * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * Copyright (C) 1998 by the FundsXpress, INC.
2N/A *
2N/A * All rights reserved.
2N/A *
2N/A * Export of this software from the United States of America may require
2N/A * a specific license from the United States Government. It is the
2N/A * responsibility of any person or organization contemplating export to
2N/A * obtain such a license before exporting.
2N/A *
2N/A * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
2N/A * distribute this software and its documentation for any purpose and
2N/A * without fee is hereby granted, provided that the above copyright
2N/A * notice appear in all copies and that both that copyright notice and
2N/A * this permission notice appear in supporting documentation, and that
2N/A * the name of FundsXpress. not be used in advertising or publicity pertaining
2N/A * to distribution of the software without specific, written prior
2N/A * permission. FundsXpress makes no representations about the suitability of
2N/A * this software for any purpose. It is provided "as is" without express
2N/A * or implied warranty.
2N/A *
2N/A * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2N/A * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2N/A * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2N/A */
2N/A
2N/A#include "k5-int.h"
2N/A
2N/A/*
2N/A * Solaris Kerberos
2N/A * krb5_string_to_key/krb5_use_enctype are needed by Samba
2N/A */
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_encrypt(krb5_context context, krb5_const_pointer inptr,
2N/A krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
2N/A krb5_pointer ivec)
2N/A{
2N/A krb5_data inputd, ivecd;
2N/A krb5_enc_data outputd;
2N/A size_t blocksize, outlen;
2N/A krb5_error_code ret;
2N/A
2N/A if (ivec) {
2N/A if ((ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize)))
2N/A return(ret);
2N/A
2N/A ivecd.length = blocksize;
2N/A ivecd.data = ivec;
2N/A }
2N/A
2N/A /* size is the length of the input cleartext data */
2N/A inputd.length = size;
2N/A inputd.data = (char*)inptr;
2N/A
2N/A /* The size of the output buffer isn't part of the old api. Not too
2N/A safe. So, we assume here that it's big enough. */
2N/A if ((ret = krb5_c_encrypt_length(context, eblock->key->enctype, size,
2N/A &outlen)))
2N/A return(ret);
2N/A
2N/A outputd.ciphertext.length = outlen;
2N/A outputd.ciphertext.data = outptr;
2N/A
2N/A return(krb5_c_encrypt(context, eblock->key, 0, ivec?&ivecd:0,
2N/A &inputd, &outputd));
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_decrypt(krb5_context context, krb5_const_pointer inptr,
2N/A krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
2N/A krb5_pointer ivec)
2N/A{
2N/A krb5_enc_data inputd;
2N/A krb5_data outputd, ivecd;
2N/A size_t blocksize;
2N/A krb5_error_code ret;
2N/A
2N/A if (ivec) {
2N/A if ((ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize)))
2N/A return(ret);
2N/A
2N/A ivecd.length = blocksize;
2N/A ivecd.data = ivec;
2N/A }
2N/A
2N/A /* size is the length of the input ciphertext data */
2N/A inputd.enctype = eblock->key->enctype;
2N/A inputd.ciphertext.length = size;
2N/A /* Solaris Kerberos */
2N/A inputd.ciphertext.data = (char*)inptr;
2N/A
2N/A /* we don't really know how big this is, but the code tends to assume
2N/A that the output buffer size should be the same as the input
2N/A buffer size */
2N/A outputd.length = size;
2N/A outputd.data = outptr;
2N/A
2N/A return(krb5_c_decrypt(context, eblock->key, 0, ivec?&ivecd:0,
2N/A &inputd, &outputd));
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_process_key(krb5_context context, krb5_encrypt_block *eblock,
2N/A const krb5_keyblock *key)
2N/A{
2N/A eblock->key = (krb5_keyblock *) key;
2N/A
2N/A return(0);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_finish_key(krb5_context context, krb5_encrypt_block *eblock)
2N/A{
2N/A return(0);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock,
2N/A krb5_keyblock *keyblock, const krb5_data *data,
2N/A const krb5_data *salt)
2N/A{
2N/A return(krb5_c_string_to_key(context, eblock->crypto_entry, data, salt,
2N/A keyblock));
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock,
2N/A const krb5_keyblock *keyblock, krb5_pointer *ptr)
2N/A{
2N/A krb5_data data;
2N/A
2N/A data.length = keyblock->length;
2N/A data.data = (char *) keyblock->contents;
2N/A
2N/A return(krb5_c_random_seed(context, &data));
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock,
2N/A krb5_pointer *ptr)
2N/A{
2N/A return(0);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_random_key(krb5_context context, const krb5_encrypt_block *eblock,
2N/A krb5_pointer ptr, krb5_keyblock **keyblock)
2N/A{
2N/A krb5_keyblock *key;
2N/A krb5_error_code ret;
2N/A
2N/A if ((key = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL)
2N/A return(ENOMEM);
2N/A
2N/A if ((ret = krb5_c_make_random_key(context, eblock->crypto_entry, key)))
2N/A free(key);
2N/A
2N/A *keyblock = key;
2N/A
2N/A return(ret);
2N/A}
2N/A
2N/Akrb5_enctype KRB5_CALLCONV
2N/Akrb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock)
2N/A{
2N/A return(eblock->crypto_entry);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock,
2N/A krb5_enctype enctype)
2N/A{
2N/A eblock->crypto_entry = enctype;
2N/A
2N/A return(0);
2N/A}
2N/A
2N/Asize_t KRB5_CALLCONV
2N/Akrb5_encrypt_size(size_t length, krb5_enctype crypto)
2N/A{
2N/A size_t ret;
2N/A
2N/A if (krb5_c_encrypt_length(/* XXX */ 0, crypto, length, &ret))
2N/A return(-1); /* XXX */
2N/A
2N/A return(ret);
2N/A}
2N/A
2N/Asize_t KRB5_CALLCONV
2N/Akrb5_checksum_size(krb5_context context, krb5_cksumtype ctype)
2N/A{
2N/A size_t ret;
2N/A
2N/A if (krb5_c_checksum_length(context, ctype, &ret))
2N/A return(-1); /* XXX */
2N/A
2N/A return(ret);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype,
2N/A krb5_const_pointer in, size_t in_length,
2N/A krb5_const_pointer seed, size_t seed_length,
2N/A krb5_checksum *outcksum)
2N/A{
2N/A krb5_data input;
2N/A krb5_keyblock key;
2N/A krb5_error_code ret;
2N/A krb5_checksum cksum;
2N/A
2N/A /* Solaris Kerberos */
2N/A memset(&key, 0, sizeof (krb5_keyblock));
2N/A
2N/A /* Solaris Kerberos */
2N/A input.data = (char*)in;
2N/A input.length = in_length;
2N/A
2N/A key.length = seed_length;
2N/A /* Solaris Kerberos */
2N/A key.contents = (unsigned char*)seed;
2N/A
2N/A if ((ret = krb5_c_make_checksum(context, ctype, &key, 0, &input, &cksum)))
2N/A return(ret);
2N/A
2N/A if (outcksum->length < cksum.length) {
2N/A memset(cksum.contents, 0, cksum.length);
2N/A free(cksum.contents);
2N/A return(KRB5_BAD_MSIZE);
2N/A }
2N/A
2N/A outcksum->magic = cksum.magic;
2N/A outcksum->checksum_type = cksum.checksum_type;
2N/A memcpy(outcksum->contents, cksum.contents, cksum.length);
2N/A outcksum->length = cksum.length;
2N/A
2N/A free(cksum.contents);
2N/A
2N/A return(0);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
2N/A const krb5_checksum *cksum, krb5_const_pointer in,
2N/A size_t in_length, krb5_const_pointer seed,
2N/A size_t seed_length)
2N/A{
2N/A krb5_data input;
2N/A krb5_keyblock key;
2N/A krb5_error_code ret;
2N/A krb5_boolean valid;
2N/A
2N/A /* Solaris Kerberos */
2N/A memset(&key, 0, sizeof (krb5_keyblock));
2N/A
2N/A /* Solaris Kerberos */
2N/A input.data = (char*)in;
2N/A input.length = in_length;
2N/A
2N/A key.length = seed_length;
2N/A /* Solaris Kerberos */
2N/A key.contents = (unsigned char*)seed;
2N/A
2N/A if ((ret = krb5_c_verify_checksum(context, &key, 0, &input, cksum,
2N/A &valid)))
2N/A return(ret);
2N/A
2N/A if (!valid)
2N/A return(KRB5KRB_AP_ERR_BAD_INTEGRITY);
2N/A
2N/A return(0);
2N/A}
2N/A
2N/Akrb5_error_code KRB5_CALLCONV
2N/Akrb5_random_confounder(size_t size, krb5_pointer ptr)
2N/A{
2N/A krb5_data random_data;
2N/A
2N/A random_data.length = size;
2N/A random_data.data = ptr;
2N/A
2N/A return(krb5_c_random_make_octets(/* XXX */ 0, &random_data));
2N/A}
2N/A
2N/Akrb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key,
2N/A krb5_pointer ivec, krb5_data *data,
2N/A krb5_enc_data *enc_data)
2N/A{
2N/A krb5_error_code ret;
2N/A size_t enclen, blocksize;
2N/A krb5_data ivecd;
2N/A
2N/A if ((ret = krb5_c_encrypt_length(context, key->enctype, data->length,
2N/A &enclen)))
2N/A return(ret);
2N/A
2N/A if (ivec) {
2N/A if ((ret = krb5_c_block_size(context, key->enctype, &blocksize)))
2N/A return(ret);
2N/A
2N/A ivecd.length = blocksize;
2N/A ivecd.data = ivec;
2N/A }
2N/A
2N/A enc_data->magic = KV5M_ENC_DATA;
2N/A enc_data->kvno = 0;
2N/A enc_data->enctype = key->enctype;
2N/A enc_data->ciphertext.length = enclen;
2N/A if ((enc_data->ciphertext.data = malloc(enclen)) == NULL)
2N/A return(ENOMEM);
2N/A
2N/A if ((ret = krb5_c_encrypt(context, key, 0, ivec?&ivecd:0, data, enc_data)))
2N/A free(enc_data->ciphertext.data);
2N/A
2N/A return(ret);
2N/A}
2N/A
2N/Akrb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key,
2N/A krb5_pointer ivec, krb5_enc_data *enc_data,
2N/A krb5_data *data)
2N/A{
2N/A krb5_error_code ret;
2N/A krb5_data ivecd;
2N/A size_t blocksize;
2N/A
2N/A if (ivec) {
2N/A if ((ret = krb5_c_block_size(context, key->enctype, &blocksize)))
2N/A return(ret);
2N/A
2N/A ivecd.length = blocksize;
2N/A ivecd.data = ivec;
2N/A }
2N/A
2N/A data->length = enc_data->ciphertext.length;
2N/A if ((data->data = (char *) malloc(data->length)) == NULL)
2N/A return(ENOMEM);
2N/A
2N/A if ((ret = krb5_c_decrypt(context, key, 0, ivec?&ivecd:0, enc_data, data)))
2N/A free(data->data);
2N/A
2N/A /* Solaris Kerberos */
2N/A return(ret);
2N/A}
2N/A
2N/Akrb5_boolean KRB5_CALLCONV
2N/Avalid_enctype(krb5_enctype etype)
2N/A{
2N/A return krb5_c_valid_enctype(etype);
2N/A}