NetBSD/crypto/dist/bind/lib/cylink/rand.c

337 lines
12 KiB
C

/* $NetBSD: rand.c,v 1.1.1.1 2001/01/27 08:08:39 itojun Exp $ */
/*
* Cylink Corporation © 1998
*
* This software is licensed by Cylink to the Internet Software Consortium to
* promote implementation of royalty free public key cryptography within IETF
* standards. Cylink wishes to expressly thank the contributions of Dr.
* Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for
* their contributions to Internet Security. In accordance with the terms of
* this license, ISC is authorized to distribute and sublicense this software
* for the practice of IETF standards.
*
* The software includes BigNum, written by Colin Plumb and licensed by Philip
* R. Zimmermann for royalty free use and distribution with Cylink's
* software. Use of BigNum as a stand alone product or component is
* specifically prohibited.
*
* Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS",
* WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN
* PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK
* MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*
* Cylink or its representatives shall not be liable for tort, indirect,
* special or consequential damages such as loss of profits or loss of
* goodwill from the use or inability to use the software for any purpose or
* for any reason whatsoever.
*
* EXPORT LAW: Export of the Foundations Suite may be subject to compliance
* with the rules and regulations promulgated from time to time by the Bureau
* of Export Administration, United States Department of Commerce, which
* restrict the export and re-export of certain products and technical data.
* If the export of the Foundations Suite is controlled under such rules and
* regulations, then the Foundations Suite shall not be exported or
* re-exported, directly or indirectly, (a) without all export or re-export
* licenses and governmental approvals required by any applicable laws, or (b)
* in violation of any applicable prohibition against the export or re-export
* of any part of the Foundations Suite. All export licenses for software
* containing the Foundations Suite are the sole responsibility of the licensee.
*/
/****************************************************************************
* FILENAME: rand.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
*
* FILE STATUS:
*
* DESCRIPTION: Cryptographic Toolkit Functions File
* Random Number Generation Files
* PUBLIC FUNCTIONS:
* int InitRand( u_int16_t SEED_bytes, uchar *SEED,
* uchar *RVAL )
* int GenRand( u_int16_t A_bytes, uchar *A,
* uchar *RVAL )
* int MyGenRand( u_int16_t A_bytes,
* ord *A,
* ord *RVAL )
* Copyright (c) Cylink Corporation 1994. All rights reserved.
*
* REVISION HISTORY:
*
* 24 Sep 94 KPZ Initial release
* 10 Oct 94 KPZ Added Shamir Key Sharing functions
* 10 Oct 94 KPZ Modified SHA functions for arbitrary message length
* 12 Oct 94 KPZ Modified SHA functions (new standard)
* 14 Oct 94 GKL Second version (big endian support)
* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
*
****************************************************************************/
/****************************************************************************
* INCLUDE FILES
****************************************************************************/
#include "port_before.h"
/* system files */
#ifdef VXD
#include <vtoolsc.h>
#else
#include <stdlib.h>
#include <string.h>
#endif
/* program files */
#ifdef VXD
#include "tkvxd.h"
#endif
#include "cylink.h"
#include "ctk_endian.h"
#include "toolkit.h"
#include "cencrint.h"
#include "sha.h"
#include "c_asm.h"
#include "port_after.h"
extern u_int16_t DataOrder;
/****************************************************************************
* PUBLIC FUNCTIONS DEFINITIONS
****************************************************************************/
/****************************************************************************
* NAME: int InitRand( u_int16_t SEED_bytes,
* uchar *SEED,
* uchar *RVAL)
*
* DESCRIPTION: Initialize Random number Generator
*
* INPUTS:
* PARAMETERS:
* u_int16_t SEED_bytes Length of SEED
* uchar *SEED Pointer to SEED value
*
* OUTPUT:
* PARAMETERS:
* uchar *RVAL Pointer to RVAL
*
* RETURN:
* SUCCESS No errors
* ERR_INPUT_LEN Invalid length for input data
* ERR_DATA Generic data error
* REVISION HISTORY:
*
* 24 Sep 94 KPZ Initial release
*
****************************************************************************/
int InitRand( u_int16_t SEED_bytes,
uchar *SEED,
uchar *RVAL )
{
int status = SUCCESS; /* function return status */
if ( SEED_bytes == 0 )
{
status = ERR_INPUT_LEN;
return status;
}
if ( SEED_bytes < SHA_LENGTH )
{
status = ERR_DATA;
return status;
}
memcpy( RVAL, SEED, SHA_LENGTH);
return status;
}
/****************************************************************************
* NAME: int GenRand( u_int16_t A_bytes,
* uchar *A,
* uchar *RVAL)
*
* DESCRIPTION: Generate random number.
*
* INPUTS:
* PARAMETERS:
* u_int16_t A_bytes Length of A
* uchar *A Pointer to A value
*
* OUTPUT:
* PARAMETERS:
* uchar *RVAL Pointer to RVAL
*
* RETURN:
* SUCCESS No errors
* ERR_INPUT_LEN Invalid length for input data
* ERR_DATA Generic data error
* ERR_ALLOC Insufficient memory
* REVISION HISTORY:
*
* 24 Sep 94 KPZ Initial release
* 14 Oct 94 GKL Second version (big endian support)
* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC)
*
****************************************************************************/
int GenRand( u_int16_t A_bytes,
uchar *A,
uchar *RVAL )
{
int status = SUCCESS; /* function return status */
ord *RVAL_a;
SHA_context hash_context; /* SHA context structure */
uchar M[DSS_LENGTH_MIN]; /* message block */
uchar hash_result[SHA_LENGTH];
u_int16_t i;
u_int16_t sha_block; /* number of sha blocks */
u_int16_t sha_rem; /* size of last block */
if ( A_bytes == 0 )
{
status = ERR_INPUT_LEN;
return status;
}
sha_block = (u_int16_t) (A_bytes / SHA_LENGTH); /* number of sha blocks */
sha_rem = (u_int16_t) (A_bytes % SHA_LENGTH); /* size of last block */
if ( sha_rem == 0 ) /* last block = SHA_LENGTH */
{
sha_block--;
}
for ( i = 0; i <= sha_block; i++)
{
SHAInit ( &hash_context );
memcpy( M, RVAL, SHA_LENGTH);
memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH );
if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN ))
!= SUCCESS )
{
return status; /* error */
}
if ( (status=MySHAFinal (&hash_context, hash_result )) != SUCCESS )
{
return status; /* error */
}
BigSwap(RVAL, SHA_LENGTH);
ALIGN_CALLOC_COPY(RVAL, RVAL_a, SHA_LENGTH);
if ( status != SUCCESS )
{
ALIGN_COPY_FREE(RVAL_a,RVAL,SHA_LENGTH);
BigSwap(RVAL, SHA_LENGTH);
return status; /* ERR_ALLOC insufficient memory */
}
Sum_Q( RVAL_a, 1, SHA_LENGTH / sizeof(ord) );
Sum_big( RVAL_a, /* RVAL=RVAL+hash_result*/
(ord *)hash_result,
RVAL_a, SHA_LENGTH / sizeof(ord) );
ALIGN_COPY_FREE(RVAL_a,RVAL,SHA_LENGTH);
BigSwap(RVAL, SHA_LENGTH);
#ifdef CTK_BIG_ENDIAN
ByteSwap(hash_result,SHA_LENGTH);
#endif
BigSwap(hash_result, SHA_LENGTH);
if ( i == sha_block && sha_rem != 0 ) /* last block < SHA_LENGTH*/
{
memcpy( A + i * SHA_LENGTH, hash_result,
sha_rem * sizeof (uchar));
}
else /* last block = SHA_LENGTH*/
{
memcpy( A + i * SHA_LENGTH, hash_result,
SHA_LENGTH * sizeof (uchar));
}
}
return status;
}
/****************************************************************************
* NAME: int MyGenRand( u_int16_t A_bytes,
* ord *A,
* ord *RVAL)
*
* DESCRIPTION: Generate random number.
*
* INPUTS:
* PARAMETERS:
* u_int16_t A_bytes Length of A
* ord *A Pointer to A value
*
* OUTPUT:
* PARAMETERS:
* ord *RVAL Pointer to RVAL
*
* RETURN:
* SUCCESS No errors
* ERR_INPUT_LEN Invalid length for input data
* ERR_DATA Generic data error
* REVISION HISTORY:
*
* 24 Sep 94 KPZ Initial release
* 14 Oct 94 GKL Second version (big endian support)
*
****************************************************************************/
int MyGenRand( u_int16_t A_bytes,
ord *A,
ord *RVAL )
{
int status = SUCCESS; /* function return status */
SHA_context hash_context; /* SHA context structure */
uchar M[DSS_LENGTH_MIN]; /* message block */
uchar hash_result[SHA_LENGTH];
u_int16_t i;
u_int16_t sha_block; /* number of sha blocks */
u_int16_t sha_rem; /* size of last block */
if ( A_bytes == 0 )
{
status = ERR_INPUT_LEN;
return status;
}
sha_block = (u_int16_t) (A_bytes / SHA_LENGTH); /* number of sha blocks */
sha_rem = (u_int16_t) (A_bytes % SHA_LENGTH); /* size of last block */
if ( sha_rem == 0 ) /* last block = SHA_LENGTH */
{
sha_block--;
}
for ( i = 0; i <= sha_block; i++)
{
SHAInit ( &hash_context );
memcpy( M, RVAL, SHA_LENGTH);
memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH );
if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN ))
!= SUCCESS )
{
return status; /* error */
}
if ( (status=MySHAFinal (&hash_context, hash_result )) != SUCCESS )
{
return status; /* error */
}
#ifdef CTK_BIG_ENDIAN
ByteSwap((uchar*)RVAL,SHA_LENGTH);
#endif
BigSwap((uchar*)RVAL, SHA_LENGTH);
Sum_Q(RVAL, 1,SHA_LENGTH / sizeof(ord));
Sum_big( RVAL, /* RVAL=RVAL+hash_result*/
(ord*)hash_result,
RVAL, SHA_LENGTH / sizeof(ord) );
BigSwap((uchar*)RVAL, SHA_LENGTH);
#ifdef CTK_BIG_ENDIAN
ByteSwap((uchar*)RVAL,SHA_LENGTH);
#endif
if ( i == sha_block && sha_rem != 0 ) /* last block < SHA_LENGTH*/
{
memcpy( &A[ i*SHA_LENGTH / sizeof(ord)], hash_result,
sha_rem * sizeof (uchar));
}
else /* last block = SHA_LENGTH*/
{
memcpy( &A[ i*SHA_LENGTH / sizeof(ord)], hash_result,
SHA_LENGTH * sizeof (uchar));
}
}
return status;
}