/* $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 #else #include #include #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; }