/**********
 * Copyright (c) 2003-2004 Greg Parker.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY GREG PARKER ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **********/

#include "cryptlib.h"
#include "cryptorsrc.h"
#include "des.h"
#include "des_locl.h"
#include "assert.h"


static MemHandle DES_SPtrans0_h = NULL;
static MemHandle DES_SPtrans1_h = NULL;
static MemHandle DES_SPtrans2_h = NULL;
static MemHandle DES_SPtrans3_h = NULL;
static MemHandle DES_SPtrans4_h = NULL;
static MemHandle DES_SPtrans5_h = NULL;
static MemHandle DES_SPtrans6_h = NULL;
static MemHandle DES_SPtrans7_h = NULL;

DES_LONG *DES_SPtrans0 = NULL;
DES_LONG *DES_SPtrans1 = NULL;
DES_LONG *DES_SPtrans2 = NULL;
DES_LONG *DES_SPtrans3 = NULL;
DES_LONG *DES_SPtrans4 = NULL;
DES_LONG *DES_SPtrans5 = NULL;
DES_LONG *DES_SPtrans6 = NULL;
DES_LONG *DES_SPtrans7 = NULL;

static int des_tables_inited = 0;

static void des_init_tables(void) DES_SEGMENT;
static void des_init_tables(void)
{
    if (des_tables_inited) return;
    
    // fixme error handling
    DES_SPtrans0_h = DmGetResource('DLST', DES_SPtrans0_id);
    DES_SPtrans1_h = DmGetResource('DLST', DES_SPtrans1_id);
    DES_SPtrans2_h = DmGetResource('DLST', DES_SPtrans2_id);
    DES_SPtrans3_h = DmGetResource('DLST', DES_SPtrans3_id);
    DES_SPtrans4_h = DmGetResource('DLST', DES_SPtrans4_id);
    DES_SPtrans5_h = DmGetResource('DLST', DES_SPtrans5_id);
    DES_SPtrans6_h = DmGetResource('DLST', DES_SPtrans6_id);
    DES_SPtrans7_h = DmGetResource('DLST', DES_SPtrans7_id);

    des_tables_inited = 1;
}


void des_lock_tables(void)
{
    // fixme lock-once version

    if (des_tables_inited) return;

    des_init_tables();

    DES_SPtrans0 = MemHandleLock(DES_SPtrans0_h);
    DES_SPtrans1 = MemHandleLock(DES_SPtrans1_h);
    DES_SPtrans2 = MemHandleLock(DES_SPtrans2_h);
    DES_SPtrans3 = MemHandleLock(DES_SPtrans3_h);
    DES_SPtrans4 = MemHandleLock(DES_SPtrans4_h);
    DES_SPtrans5 = MemHandleLock(DES_SPtrans5_h);
    DES_SPtrans6 = MemHandleLock(DES_SPtrans6_h);
    DES_SPtrans7 = MemHandleLock(DES_SPtrans7_h);

    // DLST resource is prefixed with 4-byte word count
    // DES table should be 0x40 words long, plus the count word

    // verify handle sizes
    assert(MemHandleSize(DES_SPtrans0_h) == 4*(1+0x40));
    assert(MemHandleSize(DES_SPtrans1_h) == 4*(1+0x40));
    assert(MemHandleSize(DES_SPtrans2_h) == 4*(1+0x40));
    assert(MemHandleSize(DES_SPtrans3_h) == 4*(1+0x40));
    assert(MemHandleSize(DES_SPtrans4_h) == 4*(1+0x40));
    assert(MemHandleSize(DES_SPtrans5_h) == 4*(1+0x40));
    assert(MemHandleSize(DES_SPtrans6_h) == 4*(1+0x40));
    assert(MemHandleSize(DES_SPtrans7_h) == 4*(1+0x40));

    // verify word counts
    assert(DES_SPtrans0[0] == 0x40);
    assert(DES_SPtrans1[0] == 0x40);
    assert(DES_SPtrans2[0] == 0x40);
    assert(DES_SPtrans3[0] == 0x40);
    assert(DES_SPtrans4[0] == 0x40);
    assert(DES_SPtrans5[0] == 0x40);
    assert(DES_SPtrans6[0] == 0x40);
    assert(DES_SPtrans7[0] == 0x40);

    // skip word count
    DES_SPtrans0 += 1;
    DES_SPtrans1 += 1;
    DES_SPtrans2 += 1;
    DES_SPtrans3 += 1;
    DES_SPtrans4 += 1;
    DES_SPtrans5 += 1;
    DES_SPtrans6 += 1;
    DES_SPtrans7 += 1;
}


void des_unlock_tables(void)
{
    // fixme lock-once version
    return;
    MemHandleUnlock(DES_SPtrans0_h); DES_SPtrans0 = NULL;
    MemHandleUnlock(DES_SPtrans1_h); DES_SPtrans1 = NULL;
    MemHandleUnlock(DES_SPtrans2_h); DES_SPtrans2 = NULL;
    MemHandleUnlock(DES_SPtrans3_h); DES_SPtrans3 = NULL;
    MemHandleUnlock(DES_SPtrans4_h); DES_SPtrans4 = NULL;
    MemHandleUnlock(DES_SPtrans5_h); DES_SPtrans5 = NULL;
    MemHandleUnlock(DES_SPtrans6_h); DES_SPtrans6 = NULL;
    MemHandleUnlock(DES_SPtrans7_h); DES_SPtrans7 = NULL;
}
