2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2N/A/*
2N/A * lib/crypto/aead.h
2N/A *
2N/A * Copyright 2008, 2009 by the Massachusetts Institute of Technology.
2N/A * All Rights Reserved.
2N/A *
2N/A * Export of this software from the United States of America may
2N/A * require a specific license from the United States Government.
2N/A * It is the responsibility of any person or organization contemplating
2N/A * export to 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 M.I.T. not be used in advertising or publicity pertaining
2N/A * to distribution of the software without specific, written prior
2N/A * permission. Furthermore if you modify this software you must label
2N/A * your software as modified software and not distribute it in such a
2N/A * fashion that it might be confused with the original M.I.T. software.
2N/A * M.I.T. 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
2N/A#include "k5-int.h"
2N/A#include "cksumtypes.h"
2N/A#include "etypes.h"
2N/A
2N/A/* AEAD helpers */
2N/A
2N/Akrb5_crypto_iov *
2N/Akrb5int_c_locate_iov(krb5_crypto_iov *data,
2N/A size_t num_data,
2N/A krb5_cryptotype type);
2N/A
2N/A#define ENCRYPT_CONF_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_HEADER)
2N/A
2N/A#define ENCRYPT_DATA_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_DATA || \
2N/A (_iov)->flags == KRB5_CRYPTO_TYPE_PADDING)
2N/A
2N/A#define ENCRYPT_IOV(_iov) (ENCRYPT_CONF_IOV(_iov) || ENCRYPT_DATA_IOV(_iov))
2N/A
2N/A#define SIGN_IOV(_iov) (ENCRYPT_IOV(_iov) || \
2N/A (_iov)->flags == KRB5_CRYPTO_TYPE_SIGN_ONLY )
2N/A
2N/Astruct iov_block_state {
2N/A size_t iov_pos; /* index into iov array */
2N/A size_t data_pos; /* index into iov contents */
2N/A unsigned int ignore_header : 1; /* have/should we process HEADER */
2N/A unsigned int include_sign_only : 1; /* should we process SIGN_ONLY blocks */
2N/A unsigned int pad_to_boundary : 1; /* should we zero fill blocks until next buffer */
2N/A};
2N/A
2N/A#define IOV_BLOCK_STATE_INIT(_state) ((_state)->iov_pos = \
2N/A (_state)->data_pos = \
2N/A (_state)->ignore_header = \
2N/A (_state)->include_sign_only = \
2N/A (_state)->pad_to_boundary = 0)
2N/A
2N/Akrb5_boolean
2N/Akrb5int_c_iov_get_block(unsigned char *block,
2N/A size_t block_size,
2N/A const krb5_crypto_iov *data,
2N/A size_t num_data,
2N/A struct iov_block_state *iov_state);
2N/A
2N/Akrb5_boolean
2N/Akrb5int_c_iov_put_block(const krb5_crypto_iov *data,
2N/A size_t num_data,
2N/A unsigned char *block,
2N/A size_t block_size,
2N/A struct iov_block_state *iov_state);
2N/A
2N/Akrb5_error_code
2N/Akrb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, krb5_key key,
2N/A krb5_keyusage keyusage, const krb5_data *ivec,
2N/A krb5_crypto_iov *data, size_t num_data);
2N/A
2N/Aunsigned int
2N/Akrb5int_c_padding_length(const struct krb5_keytypes *ktp, size_t data_length);
2N/A
2N/A/*
2N/A * Returns an alias into the current buffer if the next block is fully
2N/A * contained within; otherwise makes a copy of the next block and returns an
2N/A * alias to storage. After calling this function, encrypt the returned block
2N/A * in place and then call iov_store_block (with a separate output cursor) to
2N/A * store the result back into the iov if necessary. Returns NULL if there
2N/A * is no next block.
2N/A */
2N/Astatic inline unsigned char *
2N/Aiov_next_block(unsigned char *storage, size_t len,
2N/A const krb5_crypto_iov *data, size_t num_data,
2N/A struct iov_block_state *pos)
2N/A{
2N/A const krb5_crypto_iov *iov = &data[pos->iov_pos];
2N/A unsigned char *block;
2N/A
2N/A if (pos->iov_pos < num_data && iov->data.length - pos->data_pos >= len) {
2N/A /* Return an alias to memory inside the current iov. */
2N/A block = (unsigned char *) iov->data.data + pos->data_pos;
2N/A pos->data_pos += len;
2N/A return block;
2N/A }
2N/A /* Do it the slow way and return a copy into storage. */
2N/A if (krb5int_c_iov_get_block(storage, len, data, num_data, pos))
2N/A return storage;
2N/A return NULL;
2N/A}
2N/A
2N/A/*
2N/A * Store a block retrieved with iov_next_block if necessary, and advance the
2N/A * output cursor.
2N/A */
2N/Astatic inline void
2N/Aiov_store_block(const krb5_crypto_iov *data, size_t num_data,
2N/A unsigned char *block, unsigned char *storage, size_t len,
2N/A struct iov_block_state *pos)
2N/A{
2N/A if (block == storage) {
2N/A /* We got the block the slow way; put it back that way too. */
2N/A krb5int_c_iov_put_block(data, num_data, storage, len, pos);
2N/A } else {
2N/A /* It's already stored; we just have to advance the output cursor. */
2N/A pos->data_pos += len;
2N/A }
2N/A}