/*
 * Copyright (c) 2011 QUALCOMM Incorporated.  All rights reserved.
 * The file License.txt specifies the terms for use, modification,
 * and redistribution.
 *
 * File: sslplus_utils.c
 *
 * Revisions:
 *
 *     09/05/99  [LGL]
 *             - File added.
 *
 */


/* ======================================================================
     This is just a concatenation of functions to support SSLPlus. We
     put them all here and #ifdef it on SSLPlus to have only one file
     to include and to not have to vary the files included in the 
     Makefile.  If you're not using SSLPlus from Certicom this 
     file compiles to nothing.
   ====================================================================== */


#include "config.h"

#include "sslplus_utils.h"

#ifdef QPOP_SSLPLUS /* Exclude WHOLE file if no SSLPLUS */

/*+
Release: SSL Plus 3.0.2 (July 6, 1999) 
 
Certicom, the Certicom logo, SSL Plus, and Security Builder are trademarks of
Certicom Corp.  Copyright (c) 1997-1999 Certicom Corp.  Portions are 
Copyright 1997-1998, Consensus Development Corporation, a wholly owned
subsidiary of Certicom Coryp.  All rights reserved.  
Contains an implementation of NR signatures, licensed under U.S.
patent 5,600,725.  Protected by U.S. patents 5,787,028; 4,745,568;
5,761,305.  Patents pending.
-*/

#include <stdlib.h>
#include <string.h>

#if defined(VXWORKS)
#  include <types/vxTypes.h>
#  include <types/vxTypesOld.h>
#endif

#include <time.h>

#include "cdglobal.h"

/*
 * Simple callbacks
 *
 * These callbacks just serve as glue between the OS APIs
 * and SSL Plus.
 *
 * Your programs can probably use these callbacks unmodified.
 */

void* CD_malloc(uint32 size)
{
  /* Note that SessDB relies on this function returning storage
     allocated by malloc()
   */
  return malloc(size == 0 ? 1 : size);
}

void CD_free(void *block)
{   free(block);
}

void* CD_realloc(void *block, uint32 newSize)
{   if (block == 0)
        return CD_malloc(newSize);
    else
        return realloc(block, newSize == 0 ? 1 : newSize);
}

void CD_memset(void *block, uint8 value, uint32 length)
{   memset(block, value, length);
}

/* Even though it's called memcpy, it needs to handle overlapping regions */
void CD_memcpy(void *dest, void *src, uint32 length)
{   memmove(dest, src, length);
}

int CD_memcmp(void *a, void *b, uint32 length)
{   return memcmp(a, b, length);
}

#if MAC
/* Seconds between 1/1/1904 and 1/1/1970; we should adjust for UTC vs. local as well */
#  define EPOCH_DIFFERENCE  (-2082844800)
#else
#  define EPOCH_DIFFERENCE  0
#endif

uint32
CD_time(void)
{   return time(0) + EPOCH_DIFFERENCE;
}

/* ======================================================================

   ====================================================================== */


#include <gdbm.h>
#include <sys/stat.h>

#include <stdio.h> /* For debugging */
extern FILE *g_pTrace; /* For debugging */

/* /Bug:/todo: find the right path */
#define TLS_SESS_DB "/tmp/sessdb"


/*
 * Structure to hold full context for session database turns out to be simple
 */
struct sSessDBType
{
  GDBM_FILE m_dbm;
};


/*
 * The private add call back per-SSLPlus spec
 */
static SSLErr Add2SessDB(
    SSLBuffer Key,
    SSLBuffer Data,
    void     *pDB)
{
    datum dKey, dData;
    int nRet;
    SSLErr nReturn;

    fprintf(g_pTrace, "Sess Add %x %x %x\n", pDB, ((long *)Key.data)[0], ((long *)Key.data)[1]);

    dKey.dptr = Key.data;
    dKey.dsize = Key.length;

    dData.dptr = Data.data;
    dData.dsize = Data.length;

    /* SSLPlus docs just say return any error on failure */
    nReturn = SSLSessionNotFoundErr;
    if(pDB) {
        nRet = gdbm_store(((SessDBType*)pDB)->m_dbm,
             dKey,
             dData,
             GDBM_REPLACE);


        if(nRet == 0)
            nReturn = SSLNoErr;
    }
    return(nReturn);
}

  
/*
 * The private Get call back per-SSLPlus spec
 */
static SSLErr GetSessDB(
    SSLBuffer  Key,
    SSLBuffer *pData,
    void      *pDB)
{
    datum  dKey, dData;
    SSLErr nReturn;   

    fprintf(g_pTrace, "Sess Get %x %x %x\n", pDB, ((long *)Key.data)[0], ((long *)Key.data)[1]);

    dKey.dptr = Key.data;
    dKey.dsize = Key.length;

    nReturn = SSLSessionNotFoundErr;
    if(pDB) {
        dData = gdbm_fetch(((SessDBType*)pDB)->m_dbm, dKey);

        if(dData.dptr != NULL) {
            /* DBM returns malloced data. CD_malloc as we implement
               it here also returns malloced data so all is happy
               if we just pass the pointer on
             */
            pData->data   = dData.dptr;
            pData->length = dData.dsize;
            nReturn       = SSLNoErr;   
        }
    }
    return(nReturn);
}
 

/*
 * The private delete call back per SSLPlus spec
 */
static SSLErr DeleteSessDB(
    SSLBuffer Key,
    void     *pDB)
{
    datum  dKey;
    SSLErr nReturn;   

    fprintf(g_pTrace, "Sess Del %x %x %x\n", pDB, ((long *)Key.data)[0], ((long *)Key.data)[1]);

    dKey.dptr = Key.data;
    dKey.dsize = Key.length;

    nReturn = SSLSessionNotFoundErr;
    if(pDB && gdbm_delete(((SessDBType*)pDB)->m_dbm, dKey) == 0)
        nReturn = SSLNoErr;

    return(nReturn);
}

  
/*
 * Public entry point - see .h file
 */
SessDBType *OpenSessDB(SSLContext *pCtx)
{
    SessDBType *pSessDB = (SessDBType *)malloc(sizeof(SessDBType));
    fprintf(g_pTrace, "Sess Open\n");

    if(pSessDB) {
        pSessDB->m_dbm = gdbm_open(TLS_SESS_DB, 512, GDBM_WRCREAT, S_IRUSR|S_IWUSR, NULL);
        if(pSessDB->m_dbm) {
            /* Now register the call backs */
            SSLSetAddSessionFunc(pCtx, Add2SessDB);
            SSLSetGetSessionFunc(pCtx, GetSessDB);
            SSLSetDeleteSessionFunc(pCtx, DeleteSessDB);
            SSLSetSessionRef(pCtx, pSessDB);
            fprintf(g_pTrace, "Sess Open call backs registered\n");
        } else {
            free(pSessDB);
            pSessDB = NULL;
        }
    }
    return(pSessDB);
}


/*
 * Public entry point - see .h file
 */
void CloseSessDB(SessDBType *pSessDB)
{
    fprintf(g_pTrace, "Sess Close\n");
    if(pSessDB) {
        gdbm_close(pSessDB->m_dbm);
        free((void *)pSessDB);
    }
}
 



SSLErr ConfigureContextDH( SSLContext *ctx )
{
    SSLErr                          err;
    extern unsigned char            prime1024[1024/8];
    EZDiffieHellmanParametersInfo   dhKey;
    unsigned char                   generator[1] = { 2 };
    SSLDHParams                     dhParams = 0;

    /* Set up for Diffie-Hellman */
    dhKey.p.length = sizeof(prime1024);
    dhKey.g.length = sizeof(generator);
    dhKey.p.data = prime1024;
    dhKey.g.data = generator;
    dhKey.exponentSize = 128;
    
    if ((err = EZCreateObject(&dhParams)) != 0)
        goto fail;
    
    if ((err = EZSetDHParameters(dhParams, &dhKey)) != 0)
        goto fail;
    
    if ((err = SSLSetDHParams(ctx, &dhParams)) != 0)
        goto fail;

    dhParams = 0;       /* We don't want to free it: the toolkit owns it now */

fail:
    if (dhParams)
        EZDestroyObject(&dhParams);

    return err;
}



/*+
Release: SSL Plus 3.0.2 (July 6, 1999) 
 
Certicom, the Certicom logo, SSL Plus, and Security Builder are trademarks of
Certicom Corp.  Copyright (c) 1997-1999 Certicom Corp.  Portions are 
Copyright 1997-1998, Consensus Development Corporation, a wholly owned
subsidiary of Certicom Coryp.  All rights reserved.  
Contains an implementation of NR signatures, licensed under U.S.
patent 5,600,725.  Protected by U.S. patents 5,787,028; 4,745,568;
5,761,305.  Patents pending.
-*/

/****

These groups were generated by Colin Plumb and are taken from
the following posting to sci.crypt:

    Date: 15 Jun 1996 21:25:18 -0600
    From: colin@nyx10.cs.du.edu (Colin Plumb)
    Subject: Re: Diffie-Hellman public values
    Organization: University of Denver, Dept. of Math & Comp. Sci.
    Newsgroups: sci.crypt
    
    In article <4ptjjn$9h8@net.auckland.ac.nz>,
    Peter Gutmann <pgut001@cs.auckland.ac.nz> wrote:
    > Does anyone know of any recognised, non-draft standard with published values
    > for 512, 1024, 2048, and 4096-bit primes suitable for DH?
    
    Since I came up with the primes for SKIP (which are the same ones as
    in PGPfone), perhaps I can help.  I didn't know of any either, so I
    devised a simple variant of Kravitz' "kosherizer" for generating SHA
    keys.  The process is as follows:
    
    - Pick a seed value, a string of bytes.
    - Take the SHA.1 hash of the seed value, and make that the low 160 bits
      of the number.
    - Increment the last byte of the seed value (carrying to the second-last
      byte as needed) and hash again.  This produces bits 160..319.
    - Repeat until you have enough bits.
    - Set the two most significant bits to force the number into the desired
      range.
    - Search for the next largest p with q = (p-1)/2 also prime.  This lets you
      use short exponents safely and 2 as a generator, which offer speed
      advantages in practice.
    
    Unless you assume that I can break SHA.1 and pick an innocuous-looking
    seed value which generates a sneakily easy-to-take-discrete-logs number,
    this generates a prime which is random except for the parameters I searched
    for, namely two MSBs set to 1 (to make it large) and a strong prime.
    
    The seed value was chosen by Philip Zimmermann.  It is the 79 ASCII bytes
    of a quote from Gandhi:
    
    Whatever you do will be insignificant, but it is very important that you do it.
    
    This technique is documented in the PGPfone manual and the SKIP draft.
    I designed it to be simple and defensible, and follow Kravitz where
    there was no reason to differ.  Using linear search speeds up the
    generation of the primes greatly, so people *can* verify these results,
    without hurting the numbers as far as I am aware, although they are just
    slightly less uniform.
    
    The primes I have generated from this seed are listed below as C arrays of
    big-endian bytes.
    
    > While I'm on the lookout for magic numbers, does anyone have test vectors for
    > DESX?
    
    If you have DES, I'm sure you can generate them manually.
    --
            -Colin

****/

/*
 * These time figures, except for the 4096-bit prime, are for
 * a 50 MHz SPARC processor.
 */
/* 256-bit time = 2 sec. */
unsigned char prime256[256/8] = {
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x28, 0x54, 0x03
};

/* 512-bit time = 22 sec. */
unsigned char prime512[512/8] = {
        0xF5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
        0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
        0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
        0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2A, 0x05, 0x5F
};

/* 768-bit time = 105 sec. (1:45) */
unsigned char prime768[768/8] = {
        0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
        0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
        0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
        0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
        0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
        0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
        0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
        0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2B, 0x1A, 0xB3
};

/* 1024-bit time = 499 sec.  (8:19) */
unsigned char prime1024[1024/8] = {
        0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
        0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
        0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
        0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
        0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
        0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
        0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
        0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
        0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
        0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
        0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
        0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2F, 0x78, 0xC7
};

/* 1280-bit time = 632 sec. (10:32) */
unsigned char prime1280[1280/8] = {
        0xE1, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
        0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
        0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
        0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
        0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
        0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
        0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
        0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
        0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
        0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
        0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
        0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
        0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
        0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
        0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
        0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2C, 0xA6, 0x6F
};

/* 1536-bit time = 10787 sec. (2:59:47) */
unsigned char prime1536[1536/8] = {
        0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
        0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
        0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
        0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
        0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
        0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
        0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
        0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
        0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
        0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
        0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
        0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
        0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
        0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
        0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
        0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
        0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
        0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
        0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
        0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x58, 0x7C, 0x47
};

/* 2048-bit time = 5010 sec. (1:23:30) */
unsigned char prime2048[2048/8] = {
        0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
        0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
        0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
        0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
        0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
        0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
        0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
        0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
        0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
        0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
        0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
        0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
        0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
        0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
        0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
        0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
        0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
        0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
        0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
        0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
        0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
        0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
        0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
        0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
        0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
        0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
        0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
        0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x32, 0x0B, 0x3B
};

/* 3072-bit time = 58391 sec. (16:13:11) */
unsigned char prime3072[3072/8] = {
        0xCC, 0x1D, 0x77, 0x57, 0x24, 0x38, 0x4A, 0xE2,
        0xC4, 0xF0, 0xE8, 0x8E, 0x13, 0x67, 0x97, 0x4E,
        0x92, 0x13, 0x61, 0xF6, 0xDB, 0xEB, 0x25, 0x0E,
        0x17, 0xFD, 0xF6, 0x98, 0xF7, 0xC8, 0x7C, 0x79,
        0xB0, 0x72, 0x1D, 0x38, 0x75, 0xFB, 0xF6, 0xC1,
        0x73, 0xC4, 0x83, 0x11, 0x26, 0x2B, 0x43, 0x60,
        0xC3, 0xE3, 0xE8, 0xD6, 0x0A, 0xFD, 0xA1, 0x28,
        0x26, 0x0B, 0xAE, 0xA9, 0xAE, 0xB3, 0x65, 0x0F,
        0xA2, 0x00, 0x53, 0x01, 0xA0, 0x7C, 0xD6, 0xAB,
        0xA3, 0x12, 0x1E, 0xFA, 0x0F, 0x2A, 0xCE, 0x1F,
        0x74, 0x84, 0x4F, 0xCA, 0xF3, 0x17, 0xF3, 0xA4,
        0x40, 0xE9, 0xD7, 0xD2, 0x77, 0xB6, 0x42, 0x2D,
        0x02, 0x36, 0xC1, 0x26, 0xCB, 0x68, 0x5E, 0x9D,
        0x7C, 0x98, 0x09, 0x0A, 0x8D, 0x7E, 0x2D, 0xED,
        0xE4, 0x5D, 0x79, 0xF5, 0xD4, 0x92, 0x4F, 0x9B,
        0x18, 0x8E, 0xFC, 0x2A, 0xA7, 0x4B, 0x7C, 0x32,
        0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
        0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
        0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
        0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
        0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
        0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
        0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
        0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
        0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
        0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
        0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
        0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
        0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
        0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
        0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
        0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
        0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
        0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
        0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
        0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
        0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
        0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
        0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
        0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
        0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
        0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
        0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
        0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x4C, 0x32, 0x6F
};

/*
 * This prime was generated on a 275 MHz DEC Alpha - and it took 76 hours
 * (more than 3 days) on *that*.  It performed 59592 modular exponentiations
 * (dots printed) before it found the prime.  You *can* verify it yourself,
 * and I hope that someone does, but be warned!  It will take a *long*
 * time.  (You can time the dots and multiply by 60,000 to estimate
 * how long.)  Another run, started several days earlier on a 50 MHz SPARC,
 * has used 12 days and 18 hours *of CPU time* and is not finished yet.
 */
/* 4096-bit time = 274903.168 sec. (76:21:43) */
unsigned char prime4096[4096/8] = {
        0xF9, 0x18, 0xA0, 0x7E, 0x5A, 0x06, 0x61, 0x7A,
        0x43, 0x90, 0x95, 0xDC, 0x05, 0x6C, 0x87, 0x86,
        0xEC, 0x61, 0xEC, 0xCD, 0x45, 0x1F, 0x0E, 0xD8,
        0xE0, 0xA3, 0x79, 0xC6, 0xC9, 0xDC, 0x7A, 0x0B,
        0xAC, 0xE4, 0x3F, 0xE3, 0x46, 0x94, 0xB6, 0x30,
        0x4A, 0x53, 0xD7, 0x7C, 0x02, 0x16, 0x48, 0x80,
        0xB5, 0x15, 0xE5, 0x29, 0x99, 0xA9, 0x9F, 0x07,
        0x74, 0xD3, 0xFF, 0xE3, 0xA1, 0xC5, 0x96, 0x20,
        0x4E, 0x98, 0x65, 0xB8, 0xD8, 0x0D, 0xEE, 0x10,
        0x5D, 0xAB, 0xB6, 0x17, 0x1C, 0x51, 0xD8, 0x50,
        0xCA, 0x22, 0x57, 0x43, 0x29, 0xBE, 0x95, 0xE8,
        0x56, 0x2B, 0x38, 0x78, 0x5C, 0x0B, 0xDB, 0xF8,
        0x4C, 0x4D, 0xD5, 0xE3, 0xAA, 0x46, 0xCC, 0xFB,
        0xCE, 0x17, 0xE8, 0x2A, 0x9D, 0x14, 0x61, 0xE3,
        0x84, 0xA9, 0x4F, 0xD1, 0x83, 0x84, 0xA8, 0x79,
        0xB6, 0xEF, 0x8F, 0xA7, 0x43, 0x46, 0x08, 0xC6,
        0xCC, 0x1D, 0x77, 0x57, 0x24, 0x38, 0x4A, 0xE2,
        0xC4, 0xF0, 0xE8, 0x8E, 0x13, 0x67, 0x97, 0x4E,
        0x92, 0x13, 0x61, 0xF6, 0xDB, 0xEB, 0x25, 0x0E,
        0x17, 0xFD, 0xF6, 0x98, 0xF7, 0xC8, 0x7C, 0x79,
        0xB0, 0x72, 0x1D, 0x38, 0x75, 0xFB, 0xF6, 0xC1,
        0x73, 0xC4, 0x83, 0x11, 0x26, 0x2B, 0x43, 0x60,
        0xC3, 0xE3, 0xE8, 0xD6, 0x0A, 0xFD, 0xA1, 0x28,
        0x26, 0x0B, 0xAE, 0xA9, 0xAE, 0xB3, 0x65, 0x0F,
        0xA2, 0x00, 0x53, 0x01, 0xA0, 0x7C, 0xD6, 0xAB,
        0xA3, 0x12, 0x1E, 0xFA, 0x0F, 0x2A, 0xCE, 0x1F,
        0x74, 0x84, 0x4F, 0xCA, 0xF3, 0x17, 0xF3, 0xA4,
        0x40, 0xE9, 0xD7, 0xD2, 0x77, 0xB6, 0x42, 0x2D,
        0x02, 0x36, 0xC1, 0x26, 0xCB, 0x68, 0x5E, 0x9D,
        0x7C, 0x98, 0x09, 0x0A, 0x8D, 0x7E, 0x2D, 0xED,
        0xE4, 0x5D, 0x79, 0xF5, 0xD4, 0x92, 0x4F, 0x9B,
        0x18, 0x8E, 0xFC, 0x2A, 0xA7, 0x4B, 0x7C, 0x32,
        0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
        0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
        0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
        0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
        0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
        0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
        0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
        0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
        0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
        0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
        0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
        0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
        0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
        0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
        0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
        0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
        0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
        0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
        0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
        0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
        0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
        0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
        0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
        0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
        0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
        0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
        0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
        0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
        0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
        0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
        0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
        0xA2, 0x5E, 0xC3, 0x55, 0xEB, 0x3D, 0xD6, 0x17
};





/*+
Release: SSL Plus 3.0.2 (July 6, 1999) 
 
Certicom, the Certicom logo, SSL Plus, and Security Builder are trademarks of
Certicom Corp.  Copyright (c) 1997-1999 Certicom Corp.  Portions are 
Copyright 1997-1998, Consensus Development Corporation, a wholly owned
subsidiary of Certicom Coryp.  All rights reserved.  
Contains an implementation of NR signatures, licensed under U.S.
patent 5,600,725.  Protected by U.S. patents 5,787,028; 4,745,568;
5,761,305.  Patents pending.
-*/

#include "ezcrypto.h"
#include "srand.h"      /* SSL Plus randomness toolkit */

#if !PALM
#include <stdio.h>
#endif


/* maybe declare these externally */

int SeedRandom(RandomObj *rand, const char *randomPoolFile);

static int UpdateRandomCallback(void* data, unsigned int length, void *ref);



/* CreateRandomObj allocates and initializes a RandomObj; here, we
 * create a new EZCrypto random generation algorithm object.  */
int CreateRandomObj(RandomObj **rand)
{
    int err;

    *rand = CD_malloc(sizeof(RandomObj));
    if ( *rand == 0 ) {
        return -1;  /* probably some other error would be better */
    }
    
    err = EZCreateObject(&((**rand).ezRandom));
    if (err) {
      goto exit;
    }

    err = EZInitRandom((**rand).ezRandom);
        if (err) {
          goto exit;
        }

 exit:
    return err;
}

/*
 * Destroy the algorithm object
 */
int DestroyRandomObj(RandomObj *rand)
{
  EZDestroyObject(&rand->ezRandom);
  rand->ezRandom = 0;
  CD_free(rand);    /* free the structure's memory itself */
  return 0;
}





/* configures the given context with the given random number settings */
SSLErr ConfigureContextForRandom( SSLContext *ctx, const char *randomPoolFilename,
                                    RandomObj **randomObj )
{
    SSLErr  err;

    err = CreateRandomObj(randomObj);
    if (err) return err;

    err = SeedRandom(*randomObj, randomPoolFilename);
    if (err) return err;

    err = SSLSetRandomRef(ctx, *randomObj);
    if ( err != SSLNoErr) {
        return err;
    }

    err = SSLSetRandomFunc(ctx, RandomCallback);
    if ( err != SSLNoErr) {
        return err;
    }

    return SSLNoErr;
}

/*
 * This is the callback used by the SSL toolkit when it needs
 * random data.
 */
SSLErr RandomCallback(SSLBuffer data, void *randomRef)
{
    RandomObj       *randomObj = (RandomObj*)randomRef;
    int             result;
    EZCryptoObj     random = randomObj->ezRandom;

    if ((result = EZGenerateRandom(random, data.data, data.length)) != 0)
        return ERR(SSLUnknownErr);

    return SSLNoErr;
}


/*
 * SeedRandom intializes a random object
 *
 * Two sources are used: a random pool file, which should
 * be one created by this function; this allows us to keep
 * some of the benefits of our full random seeding from
 * execution to execution.
 *
 * The other is a platform-specific set of entropy collection.
 * This is represented by the SeedRandomValues() call, which
 * collects this data and passes it back through a callback,
 * where we use it to update the random object. It can do
 * two levels of seeding: fast, when we've loaded random
 * data from the file, or full, when we need to start up
 * with all the entropy we can.
 */

#define POOL_FILE_SIZE  128 /* 1024 bits of random data */

int SeedRandom(RandomObj *rand, const char *randomPoolFile)
{   int             err;
    FILE            *f = 0;
    unsigned char   randomData[POOL_FILE_SIZE];
    int             doFullSeed = 1;

    if (randomPoolFile != 0 && *randomPoolFile != '\0')
    {   f = fopen(randomPoolFile, "rb+"); /* Open for reading & writing, binary mode; don't create */
        if (!f)     /* Maybe it doesn't exist */
            f = fopen(randomPoolFile, "wb+");
        if (f)
        {   if (fread(randomData, 1, POOL_FILE_SIZE, f) == POOL_FILE_SIZE)
                doFullSeed = 0;     /* If we can read the random pool, we'll only do
                                        a "fast seed" */
        }
    }

    /* Call the platform-specific random seeding function to collect entropic data */
    /* /Bug: we need to fix this. It get run time error on old Linux */
    /*  err = SeedRandomValues(doFullSeed, UpdateRandomCallback, rand);
    if (err)
        goto fail; */

    if (f) {
        /* If we loaded data, this will write out a new block of random data,
            updated with our fast seed; if the file was newly created, we'll
            write out the results of a full seed. */
        err = EZGenerateRandom(rand->ezRandom, randomData, POOL_FILE_SIZE);
        if ( err ) {
            goto fail;
        }
        if (fseek(f, 0, SEEK_SET) != 0)
            goto fail;
        if (fwrite(randomData, 1, POOL_FILE_SIZE, f) == POOL_FILE_SIZE)
        {   fclose(f);
            f = 0;      /* Keeps us from trying to close it again */
        }
    }

fail:
    /* If f is non-zero, it is still open and we encountered an error,
        so the file should be deleted, too, as it may not contain
        valid updated random data. */
    if (f)
    {   fclose(f);
        remove(randomPoolFile);
    }

    return err;
}

/*
 * This is the callback from SeedRandomValues
 */
static int
UpdateRandomCallback(void* data, unsigned int length, void *ref)
{   RandomObj       *rand = (RandomObj*)ref;
    
    return UpdateRandomObject(data, length, rand);
}

/*
 * This updates the random object with the input entropic data.
 */
int
UpdateRandomObject(void *data, unsigned int length, RandomObj *rand)
{
  int err;
  err = EZSeedRandom(rand->ezRandom, data, length);
  return err;
}

/* ======================================================================
   ====================================================================== */


#endif /* QPOP_SSLPLUS */     






