dss.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* 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: dss.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT
*
* FILE STATUS:
*
* DESCRIPTION: Cryptographic Toolkit Functions File
* Digital Signature Algorithms
* PUBLIC FUNCTIONS:
* uchar *RVAL )
* int GenDSSKey( u_int16_t dss_p_bytes, uchar *dss_p,
* uchar *dss_q, uchar *dss_g,
* uchar *dss_x, uchar *dss_y,
* uchar *XKEY )
*
* int GenDSSNumber( uchar *dss_k, uchar dss_q,
* uchar *KKEY )
* int GenDSSParameters( u_int16_t dss_p_bytes, uchar *dss_p,
* uchar *dss_q, uchar *dss_g,
* uchar *RVAL );
*
* Copyright (c) Cylink Corporation 1996. All rights reserved.
*
* REVISION HISTORY:
*
*
****************************************************************************/
#pragma ident "%Z%%M% %I% %E% SMI"
/****************************************************************************
* INCLUDE FILES
****************************************************************************/
#include "port_before.h"
#include "cylink.h"
#include "ctk_endian.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 "toolkit.h"
#include "cencrint.h"
#define INITIALIZ_PQG /*TKL01101*/
#include "dssnum.h" /*TKL01101*/
#include "sha.h"
#include "port_after.h"
#define BEGIN_PROCESSING do {
#define END_PROCESSING } while (0);
#define ERROR_BREAK break
#define CONTINUE continue
#define BEGIN_LOOP do {
#define END_LOOP } while (1);
#define BREAK break
/****************************************************************************
* NAME: int GenDSSSignature( u_int16_t dss_p_bytes,
* uchar *dss_p,
* uchar *dss_q,
* uchar *dss_g,
* uchar *dss_x,
* uchar *dss_k,
* uchar *r,
* uchar *s,
* uchar *hash_result)
*
* DESCRIPTION: Compute a DSS Signature
*
* INPUTS:
* PARAMETERS:
* u_int16_t dss_p_bytes Length of dss_p
* uchar *dss_p Pointer to p prime
* uchar *dss_q Pointer to q prime
* uchar *dss_g Pointer to g
* uchar *dss_x Pointer to secret number
* uchar *dss_k Pointer to random secret number
* uchar *hash_result Pointer to message hashing result
*
*
* OUTPUT:
* PARAMETERS:
* uchar *r Pointer to r part of signature
* uchar *s Pointer to s part of signature
*
* RETURN:
* E_SUCCESS No errors
* E_DSS_LEN Invalid length for dss_p
* 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)
* 08 Dec 94 GKL Changed Expo call
*
****************************************************************************/
uchar *r,
uchar *s,
{
{
return status;
}
{
return status;
}
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
}
{
if( dss_p_a )
if( dss_g_a )
if( dss_q_a )
if( dss_x_a )
{
}
if( dss_k_a )
{
}
if( hash_result_a )
{
}
if( r_a )
{
}
if( s_a )
{
}
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
}
return status; /* ERR_ALLOC insufficient memory */
}
/* Compute DSS r value */
SHA_LENGTH, /* r_temp=(dss_g^dss_k)mod(dss_p)*/
{
}
SHA_LENGTH, /* r=(r_temp)mod(dss_q) */
{
}
/* Compute k modulo inverse value */
{
}
/* Compute DSS s value */
r_a,
{
}
/* Add( temp, hash_result_a,
SHA_LENGTH, dss_q_a, temp ); temp=(temp+hash_result)mod(dss_q)*/
SHA_LENGTH, dss_q_a );
temp,
{
}
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
BigSwap(r, SHA_LENGTH);
BigSwap(s, SHA_LENGTH);
}
return status;
}
/****************************************************************************
* NAME: int VerDSSSignature( u_int16_t dss_p_bytes,
* uchar *dss_p,
* uchar *dss_q,
* uchar *dss_g,
* uchar *dss_y,
* uchar *r,
* uchar *s,
* uchar *hash_result)
*
* DESCRIPTION: Verify a DSS Signature
*
* INPUTS:
* PARAMETERS:
* u_int16_t dss_p_bytes Length of dss_p
* uchar *dss_p Pointer to p prime
* uchar *dss_q Pointer to q prime
* uchar *dss_g Pointer to g
* uchar *dss_y Pointer to public number
* uchar *hash_result Pointer to message hashing result
* OUTPUT:
* PARAMETERS:
*
* RETURN:
* SUCCESS No errors
* ERR_SIGNATURE Signature is not valid
* ERR_DSS_LEN Invalid length for dss_p
* 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)
* 08 Dec 94 GKL Changed Expo call
* 21 Aug 96 AAB DoubleExpo call
****************************************************************************/
uchar *r,
uchar *s,
{
ord *v;
{
return status;
}
{
return status;
}
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
BigSwap(r, SHA_LENGTH);
BigSwap(s, SHA_LENGTH);
}
{
if( dss_p_a )
{
}
if( dss_g_a )
{
}
if ( dss_q_a )
{
}
if( dss_y_a )
{
}
if( hash_result_a )
{
}
if( r_a )
{
}
if( s_a )
{
}
if( v )
{
free ( v );
}
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
BigSwap(r, SHA_LENGTH);
BigSwap(s, SHA_LENGTH);
}
return status; /* ERR_ALLOC insufficient memory */
}
s_a,
w )) !=SUCCESS )
{
}
w,
{
}
r_a,
w,
{
}
/* v = dss_g_a^u1*dss_y_a^u2 moddss_p_a */
SHA_LENGTH, u1,
SHA_LENGTH, u2,
{
}
v,
v )) != SUCCESS )
{
}
{
}
free ( v );
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
BigSwap(r, SHA_LENGTH);
BigSwap(s, SHA_LENGTH);
}
return status;
}
/****************************************************************************
* NAME: int GenDSSKey( u_int16_t dss_p_bytes,
* uchar *dss_p,
* uchar *dss_q,
* uchar *dss_g,
* uchar *dss_x,
* uchar *dss_y,
* uchar *XKEY )
*
*
*
* INPUTS:
* PARAMETERS:
* u_int16_t dss_p_bytes Length of modulo
* uchar *dss_p Pointer to modulo
* uchar *dss_q Pointer to modulo
* uchar *dss_g Pointer to public key
* uchar *XKEY Pointer to user supplied random number
*
*
* OUTPUT:
* PARAMETERS:
* uchar *dss_x Pointer to secret key
* uchar *dss_y Pointer to public key
* uchar *XKEY Pointer to updated number
*
* 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)
* 08 Dec 94 GKL Changed Expo call
*
****************************************************************************/
{
{
return status;
}
{
return status;
}
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
}
{
if( dss_p_a )
if( dss_g_a )
if( dss_q_a )
if( dss_x_a )
{
}
if( dss_y_a )
{
}
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
}
return status; /* ERR_ALLOC insufficient memory */
}
SHAInit ( &hash_context );
!= SUCCESS )
{
}
{
}
{
}
{
if( XKEY_a )
{
return status; /* ERR_ALLOC insufficient memory */
}
}
{
}
if (DataOrder)
{
if (dss_p)
if (dss_q)
if (dss_g)
}
return status;
}
/****************************************************************************
* NAME: int GenDSSNumber( uchar *dss_k,
* uchar *dss_q,
* uchar *KKEY )
*
* DESCRIPTION: Generate secret number
*
* INPUTS:
* PARAMETERS:
* uchar *KKEY Pointer to input random number
* uchar *dss_q Pointer to modulo
*
*
* OUTPUT:
* PARAMETERS:
* uchar *dss_x Pointer to secret number
* uchar *KKEY Pointer to updated KKEY
*
* RETURN:
* SUCCESS No errors
* 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)
*
****************************************************************************/
{
if (DataOrder)
{
if (dss_q)
}
{
if( dss_q_a )
if( dss_k_a )
{
}
if (DataOrder)
{
if (dss_q)
}
return status; /* ERR_ALLOC insufficient memory */
}
SHAInitK ( &hash_context );
!= SUCCESS )
{
}
{
}
{
}
{
if ( KKEY_a )
{
}
return status; /* ERR_ALLOC insufficient memory */
}
if (DataOrder)
{
if (dss_q)
}
return status;
}
/****************************************************************************
* NAME: int GenDSSParameters( u_int16_t dss_p_bytes,
* uchar *dss_p,
* uchar *dss_q,
* uchar *dss_g,
* uchar *RVAL,
* YIELD_context *yield_cont )
*
* DESCRIPTION: Generate DSS Common Parameters
*
* INPUTS:
* PARAMETERS:
* u_int16_t dss_p_bytes Number of bytes in dss_p
* uchar *RVAL Pointer to user supplied random number
* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used)
* OUTPUT:
* PARAMETERS:
* uchar *dss_p Pointer to N-byte prime number
* uchar *dss_q Pointer to SHA_LENGTH prime number
* uchar *dss_g Pointer to N-byte number
* RETURN:
* SUCCESS No errors
* ERR_INPUT_LEN Invalid length for input data(zero bytes)
* ERR_DSS_LEN; Invalid length for dss_p
* 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)
* 08 Dec 94 GKL Added YIELD_context
*
****************************************************************************/
{
if ( dss_p_bytes == 0 ) /* invalid length for input data (zero bytes) */
{
return status;
}
{
return status;
}
{
return status;
}
{
if( e )
free ( e );
if( one )
if( c )
free ( c );
if( w )
free ( w );
if( c1 )
if( dss_p_a )
{
}
if( dss_q_a )
{
}
if( dss_g_a )
{
}
if( RVAL_a )
{
}
return status; /* ERR_ALLOC insufficient memory */
}
one[0] = 1;
BEGIN_PROCESSING /* Generate DSS Common Parameters */
/* generate prime number of length 160-bit */
do
{
/* compute message digest from seed */
{
break; /* error */
}
/* compute message digest from seed */
{
break; /* error */
}
{
}
/* set least and most significant bits */
dss_q_a[0] |= 0x01;
!= SUCCESS ); /* perform a robust primality test */
{
}
/* dss_q2 = 2 * dss_q */
count = 0;
offset = 2;
do /* find dss_p */
{
/* generate random number by dss_p bytes */
for ( k = 0; k <= n; k++ )
{
/* v = ofone + seed */
!= SUCCESS ) /* compute message digest */
{
break; /* error */
}
}
{
break; /* error */
}
/* set most significant bit */
memcpy( c, w, dss_p_bytes);
/* c1 = c mod(dss_q2) */
SHA_LENGTH + sizeof(ord),
{
break; /* error */
}
/* c1 = c1 - 1*/
/* dss_p = w - c1 */
{
== SUCCESS ) /* perform a robust primality test */
{
break;
}
}
count++;
} while ( count < 4096);
{
}
{
BREAK; /*TKL00501*/
}
{
}
e )) != SUCCESS ) /* e = dss_p / dss_q */
{
}
!= SUCCESS ) /* dss_g = e ^ u mod(dss_p) */
{
}
{
{
if ( dss_g_a[i] != 0 )
{
break;
}
}
if ( i == (dss_p_bytes / sizeof(ord)) )
{
}
}
BREAK; /*TKL00501*/
END_PROCESSING /* Generate DSS Common Parameters */
free ( e );
free ( c );
free ( w );
if (DataOrder)
{
}
return status;
}
/****************************************************************************
* NAME: int GetDSSPQG(u_int16_t dss_p_bytes,
* uchar *dss_p,
* uchar *dss_q,
* uchar *dss_g)
*
* DESCRIPTION: Copy Cylink DSS P,Q,G numbers to *dss_p,*dss_q,*dss_g
*
* INPUTS:
* PARAMETERS:
* u_int16_t dss_p_bytes Number of bytes in dss_p
* uchar *dss_p Pointer to N-byte buffer
* uchar *dss_q Pointer to SHA_LENGTH-byte buffer
* uchar *dss_g Pointer to N-byte buffer
* OUTPUT:
* RETURN:
* SUCCESS No errors
* ERR_DSS_LEN; Invalid length for dss_p
* REVISION HISTORY:
*
* 22 Apr 95 GKL Initial release LOG TKL01201
*
****************************************************************************/
{
{
return status;
}
{
return status;
}
if (DataOrder)
{
}
return status;
}