diff options
Diffstat (limited to 'usr/src/lib/libresolv2/common/cylink/dss.c')
-rw-r--r-- | usr/src/lib/libresolv2/common/cylink/dss.c | 1209 |
1 files changed, 1209 insertions, 0 deletions
diff --git a/usr/src/lib/libresolv2/common/cylink/dss.c b/usr/src/lib/libresolv2/common/cylink/dss.c new file mode 100644 index 0000000000..fe907a6f21 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/dss.c @@ -0,0 +1,1209 @@ +/* + * 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 <sys/types.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 + + +extern u_int16_t DataOrder; + +/**************************************************************************** +* 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 +* +****************************************************************************/ + +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) + +{ + int status = SUCCESS; /* function return status */ + ord r_temp[DSS_LENGTH_MAX]; /* r intermidiate value */ + ord k_inverse[SHA_LENGTH+1]; + ord temp[SHA_LENGTH+1]; /* intermidiate values */ + ord *dss_p_a; + ord *dss_g_a; + ord *dss_q_a; + ord *dss_x_a; + ord *dss_k_a; + ord *hash_result_a; + ord *r_a; + ord *s_a; + + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + } + + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + + ALIGN_CALLOC_COPY(dss_x, dss_x_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(dss_k, dss_k_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(hash_result, hash_result_a, SHA_LENGTH); + ALIGN_CALLOC(r, r_a, SHA_LENGTH); + ALIGN_CALLOC(s, s_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( dss_p_a ) + DSS_ALIGN_FREE(dss_p_a,dss_p); + if( dss_g_a ) + DSS_ALIGN_FREE(dss_g_a,dss_g); + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_x_a ) + { + memset ( dss_x_a , 0 , SHA_LENGTH ); + ALIGN_FREE(dss_x_a); + } + if( dss_k_a ) + { + ALIGN_FREE(dss_k_a); + } + if( hash_result_a ) + { + ALIGN_FREE(hash_result_a); + } + if( r_a ) + { + ALIGN_COPY_FREE(r_a,r,SHA_LENGTH); + } + if( s_a ) + { + ALIGN_COPY_FREE(s_a,s,SHA_LENGTH); + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + +/* Compute DSS r value */ + BEGIN_PROCESSING + if (( status = Expo ( dss_p_bytes, + dss_g_a, + SHA_LENGTH, /* r_temp=(dss_g^dss_k)mod(dss_p)*/ + dss_k_a, + dss_p_bytes, + dss_p_a, + r_temp )) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( dss_p_bytes, + r_temp, + SHA_LENGTH, /* r=(r_temp)mod(dss_q) */ + dss_q_a, + r_a )) != SUCCESS ) + { + ERROR_BREAK; + } +/* Compute k modulo inverse value */ + if (( status = Inverse( SHA_LENGTH, /* k_inverse=dss_k^(-1)mod(dss_q)*/ + dss_k_a, + SHA_LENGTH, + dss_q_a, + k_inverse )) != SUCCESS ) + { + ERROR_BREAK; + } +/* Compute DSS s value */ + if (( status = Mul ( SHA_LENGTH, /* temp=(dss_x*r)mod(dss_q) */ + dss_x_a, + SHA_LENGTH, + r_a, + SHA_LENGTH, + dss_q_a, + temp )) != SUCCESS ) + { + ERROR_BREAK; + } + + /* Add( temp, hash_result_a, + SHA_LENGTH, dss_q_a, temp ); temp=(temp+hash_result)mod(dss_q)*/ + + Add( temp, hash_result_a, + SHA_LENGTH, dss_q_a ); + if (( status = Mul ( SHA_LENGTH, /* s=(temp*k_inverse)mod(dss_q) */ + temp, + SHA_LENGTH, + k_inverse, + SHA_LENGTH, + dss_q_a, + s_a )) != SUCCESS ) + { + ERROR_BREAK; + } + END_PROCESSING + + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_FREE(dss_x_a); + ALIGN_FREE(dss_k_a); + ALIGN_FREE(hash_result_a); + ALIGN_COPY_FREE(r_a,r,SHA_LENGTH); + ALIGN_COPY_FREE(s_a,s,SHA_LENGTH); + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + 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 +****************************************************************************/ + +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) +{ + int status = SUCCESS; /* function return status */ + ord w[(SHA_LENGTH / sizeof(ord)) + 1]; + ord u1[SHA_LENGTH / sizeof(ord)]; + ord u2[SHA_LENGTH / sizeof(ord)]; + ord *v; + ord *dss_p_a; + ord *dss_g_a; + ord *dss_q_a; + ord *dss_y_a; + ord *hash_result_a; + ord *r_a; + ord *s_a; + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + + ALIGN_CALLOC_COPY(dss_y, dss_y_a, dss_p_bytes); + ALIGN_CALLOC_COPY(hash_result, hash_result_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(r, r_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(s, s_a, SHA_LENGTH); + CALLOC(v,ord,dss_p_bytes); + + if ( status != SUCCESS ) + { + if( dss_p_a ) + { + DSS_ALIGN_FREE(dss_p_a,dss_p); + } + if( dss_g_a ) + { + DSS_ALIGN_FREE(dss_g_a,dss_g); + } + if ( dss_q_a ) + { + DSS_ALIGN_FREE(dss_q_a,dss_q); + } + if( dss_y_a ) + { + ALIGN_FREE(dss_y_a); + } + if( hash_result_a ) + { + ALIGN_FREE(hash_result_a); + } + if( r_a ) + { + ALIGN_FREE(r_a); + } + if( s_a ) + { + ALIGN_FREE(s_a); + } + if( v ) + { + free ( v ); + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + if (( status = Inverse( SHA_LENGTH, /* w=dss_k^(-1)mod(dss_q)*/ + s_a, + SHA_LENGTH, + dss_q_a, + w )) !=SUCCESS ) + { + ERROR_BREAK; + } + if (( status = Mul ( SHA_LENGTH, /* u1=(hash_result_*w)mod(dss_q) */ + hash_result_a, + SHA_LENGTH, + w, + SHA_LENGTH, + dss_q_a, + u1 )) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = Mul ( SHA_LENGTH, /* u2=(r*w)mod(dss_q) */ + r_a, + SHA_LENGTH, + w, + SHA_LENGTH, + dss_q_a, + u2 )) != SUCCESS ) + { + ERROR_BREAK; + } + /* v = dss_g_a^u1*dss_y_a^u2 moddss_p_a */ + if((status = DoubleExpo( dss_p_bytes, dss_g_a, + SHA_LENGTH, u1, + dss_p_bytes, dss_y_a, + SHA_LENGTH, u2, + dss_p_bytes, dss_p_a, v)) != SUCCESS ) + { + + ERROR_BREAK; + } + if (( status = PartReduct ( dss_p_bytes, /*v = v mod(dss_q)*/ + v, + SHA_LENGTH, + dss_q_a, + v )) != SUCCESS ) + { + ERROR_BREAK; + } + + if (( status = memcmp( r_a, v, SHA_LENGTH)) != 0) /*if v=r sign valid */ + { + status = ERR_SIGNATURE; /* signature is not valid */ + ERROR_BREAK; + } + END_PROCESSING + free ( v ); + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_FREE(dss_y_a); + ALIGN_FREE(hash_result_a); + ALIGN_FREE(r_a); + ALIGN_FREE(s_a); + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + 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 ) +* +* +* DESCRIPTION: Compute DSS public/secret number pair. +* +* 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 +* +****************************************************************************/ + +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 status = SUCCESS; /* function return status */ + SHA_context hash_context; /* SHA context structure */ + uchar M[DSS_LENGTH_MIN]; /* message block */ + ord *dss_p_a; + ord *dss_q_a; + ord *dss_g_a; + ord *dss_x_a; + ord *dss_y_a; + ord *XKEY_a; + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + } + + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + ALIGN_CALLOC(dss_x, dss_x_a, SHA_LENGTH); + ALIGN_CALLOC(dss_y, dss_y_a, dss_p_bytes); + if ( status != SUCCESS ) + { + if( dss_p_a ) + DSS_ALIGN_FREE(dss_p_a,dss_p); + if( dss_g_a ) + DSS_ALIGN_FREE(dss_g_a,dss_g); + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_x_a ) + { + memset(dss_x_a, 0, SHA_LENGTH ); + ALIGN_COPY_FREE(dss_x_a,dss_x,SHA_LENGTH); + } + if( dss_y_a ) + { + ALIGN_COPY_FREE(dss_y_a,dss_y,dss_p_bytes); + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + SHAInit ( &hash_context ); + memcpy( M, XKEY, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + ERROR_BREAK; + } + if ( (status = MySHAFinal (&hash_context, (uchar *)dss_x_a)) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( SHA_LENGTH, /* dss_x = dss_x mod(dss_q)*/ + dss_x_a, + SHA_LENGTH, + dss_q_a, + dss_x_a )) != SUCCESS ) + { + ERROR_BREAK; + } + + BigSwap(XKEY, SHA_LENGTH); + ALIGN_CALLOC_COPY(XKEY, XKEY_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( XKEY_a ) + { + ALIGN_COPY_FREE(XKEY_a,XKEY,SHA_LENGTH); + BigSwap(XKEY, SHA_LENGTH); + return status; /* ERR_ALLOC insufficient memory */ + } + } + + Sum_Q((ord*)XKEY_a, 1, SHA_LENGTH / sizeof (ord) ); + + Sum_big( XKEY_a, dss_x_a, /* XKEY=XKEY+dss_x */ + XKEY_a, SHA_LENGTH / sizeof(ord) ); + + ALIGN_COPY_FREE(XKEY_a,XKEY,SHA_LENGTH); + BigSwap(XKEY, SHA_LENGTH); + + if (( status = Expo ( dss_p_bytes, /*dss_y = g^dss_x mod(dss_p)*/ + dss_g_a, + SHA_LENGTH, + dss_x_a, + dss_p_bytes, + dss_p_a, + dss_y_a)) != SUCCESS ) /*TKL00601*/ + { + ERROR_BREAK; + } + END_PROCESSING + + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_COPY_FREE(dss_x_a,dss_x,SHA_LENGTH); + ALIGN_COPY_FREE(dss_y_a,dss_y,dss_p_bytes); + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_y, dss_p_bytes); + } + + 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) +* +****************************************************************************/ + +int GenDSSNumber( uchar *dss_k, + uchar *dss_q, + uchar *KKEY ) +{ + + int status = SUCCESS; /* function return status */ + ord *dss_k_a; + ord *dss_q_a; + ord *KKEY_a; + SHA_context hash_context; /* SHA context structure*/ + uchar M[DSS_LENGTH_MIN]; /* message block */ + + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + } + + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + ALIGN_CALLOC(dss_k, dss_k_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_k_a ) + { + ALIGN_COPY_FREE(dss_k_a,dss_k,SHA_LENGTH); + } + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + SHAInitK ( &hash_context ); + memcpy( M, KKEY, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + ERROR_BREAK; + } + if ( (status = MySHAFinal (&hash_context, (uchar *)dss_k_a)) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( SHA_LENGTH, /* dss_k = dss_k mod(dss_q)*/ + dss_k_a, + SHA_LENGTH, + dss_q_a, + dss_k_a )) != SUCCESS ) + { + ERROR_BREAK; + } + BigSwap(KKEY, SHA_LENGTH); + ALIGN_CALLOC_COPY(KKEY, KKEY_a, SHA_LENGTH ); + if ( status != SUCCESS ) + { + if ( KKEY_a ) + { + ALIGN_COPY_FREE(KKEY_a,KKEY,SHA_LENGTH); + BigSwap(KKEY, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + Sum_Q( KKEY_a, 1, SHA_LENGTH / sizeof(ord)); + + Sum_big( KKEY_a, dss_k_a, /* KKEY=KKEY+dss_k*/ + KKEY_a, SHA_LENGTH / sizeof(ord) ); + + ALIGN_COPY_FREE(KKEY_a,KKEY,SHA_LENGTH); + BigSwap(KKEY, SHA_LENGTH); + + END_PROCESSING + + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + + ALIGN_COPY_FREE(dss_k_a,dss_k,SHA_LENGTH); + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + } + + 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 +* +****************************************************************************/ + + int GenDSSParameters( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *RVAL, + YIELD_context *yield_cont ) /*TKL00701*/ +{ + int status = SUCCESS; /* function return status */ + ord seed[SHA_LENGTH / sizeof (ord)]; + ord u[SHA_LENGTH / sizeof (ord)]; /* work buffers */ + ord u1[SHA_LENGTH / sizeof (ord)]; + ord *dss_p_a; + ord *dss_q_a; + ord *dss_g_a; + ord *RVAL_a; + ord ofone[SHA_LENGTH / sizeof(ord)]; + ord dss_q2[SHA_LENGTH / sizeof(ord) + 1]; /* dss_q2 = 2 * q */ + ord v[SHA_LENGTH / sizeof(ord)]; + ord *w, *c, *c1, *one, *e; /* Pointers to work buffers */ + u_int16_t i, n, count, offset, k; /* counters */ + u_int16_t dss_p_longs; /* number of longs */ + if ( dss_p_bytes == 0 ) /* invalid length for input data (zero bytes) */ + { + status = ERR_INPUT_LEN; + return status; + } + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 4 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + n = (u_int16_t) (dss_p_bytes / SHA_LENGTH); /* SHA passes count */ + dss_p_longs = (u_int16_t) (dss_p_bytes / sizeof(ord)); /* number of long in dss_p */ + CALLOC(w, ord, (n + 1) * SHA_LENGTH); + CALLOC(c, ord, dss_p_bytes); + CALLOC(c1, ord, dss_p_bytes); + CALLOC(one, ord, dss_p_bytes); + CALLOC(e,ord, dss_p_bytes - SHA_LENGTH + sizeof(ord)); + ALIGN_CALLOC_MOVE(RVAL, RVAL_a, SHA_LENGTH); + ALIGN_CALLOC(dss_p, dss_p_a, dss_p_bytes); + ALIGN_CALLOC(dss_q, dss_q_a, SHA_LENGTH); + ALIGN_CALLOC(dss_g, dss_g_a, dss_p_bytes); + if ( status != SUCCESS ) + { + if( e ) + free ( e ); + if( one ) + free ( one ); + if( c ) + free ( c ); + if( w ) + free ( w ); + if( c1 ) + free ( c1 ); + if( dss_p_a ) + { + ALIGN_COPY_FREE(dss_p_a, dss_p, dss_p_bytes); + } + if( dss_q_a ) + { + ALIGN_COPY_FREE(dss_q_a, dss_q, SHA_LENGTH); + } + if( dss_g_a ) + { + ALIGN_COPY_FREE(dss_g_a, dss_g, dss_p_bytes); + } + if( RVAL_a ) + { + ALIGN_MOVE_FREE(RVAL_a, RVAL, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + one[0] = 1; + BEGIN_PROCESSING /* Generate DSS Common Parameters */ + + BEGIN_LOOP /* Generate prime & dss_p */ /*TKL00501*/ + /* generate prime number of length 160-bit */ + do + { + MyGenRand( SHA_LENGTH, seed, RVAL_a); /* generate random number */ + /* compute message digest from seed */ + if ( (status = MySHA((uchar *)seed, SHA_LENGTH, (uchar *)u)) != SUCCESS ) + { + break; /* error */ + } + memcpy(ofone, seed,SHA_LENGTH); + Sum_Q( ofone, 1, SHA_LENGTH / sizeof(ord) ); + /* compute message digest from seed */ + if ( (status = MySHA( (uchar *)ofone, SHA_LENGTH,(uchar *)dss_q_a)) != SUCCESS ) + { + break; /* error */ + } + + for ( i = 0; i < (SHA_LENGTH / sizeof(ord)); i++ ) /* dss_q = dss_q ^ u */ + { + dss_q_a[i] = dss_q_a[i] ^ u[i]; + } + /* set least and most significant bits */ + dss_q_a[SHA_LENGTH / sizeof(ord) - 1] |= ((ord)1 << (BITS_COUNT-1)); + dss_q_a[0] |= 0x01; + } while ( VerPrime( SHA_LENGTH, dss_q_a, TEST_COUNT, RVAL_a, yield_cont) /*TKL00701*/ + != SUCCESS ); /* perform a robust primality test */ + if (status != SUCCESS ) + { + ERROR_BREAK; + } + /* dss_q2 = 2 * dss_q */ + memcpy( dss_q2, dss_q_a, SHA_LENGTH ); + dss_q2[SHA_LENGTH / sizeof(ord)] = 0; + LShiftL_big( dss_q2, SHA_LENGTH / sizeof(ord) +1, 1 ); + count = 0; + offset = 2; + memset( ofone, 0, SHA_LENGTH ); + do /* find dss_p */ + { + /* generate random number by dss_p bytes */ + for ( k = 0; k <= n; k++ ) + { + ofone[0] = offset + k; + /* v = ofone + seed */ + Sum_big( seed, ofone, v, SHA_LENGTH / sizeof(ord) ); + if ( (status = MySHA ( (uchar *)v, SHA_LENGTH, + (uchar *)( w + (SHA_LENGTH / sizeof(ord)) * k ))) + != SUCCESS ) /* compute message digest */ + { + break; /* error */ + } + } + if (status != SUCCESS ) + { + break; /* error */ + } + /* set most significant bit */ + w[dss_p_longs - 1] |= ((ord)1 << (BITS_COUNT-1)); + memcpy( c, w, dss_p_bytes); + /* c1 = c mod(dss_q2) */ + if( (status = PartReduct( dss_p_bytes, c, + SHA_LENGTH + sizeof(ord), + dss_q2, c1)) != SUCCESS ) + { + break; /* error */ + } + /* c1 = c1 - 1*/ + Sub_big( c1, one, c1, dss_p_longs ); + /* dss_p = w - c1 */ + Sub_big( w, c1, dss_p_a, dss_p_longs ); + if ( dss_p_a[dss_p_bytes / sizeof(ord) - 1] >= (ord)((ord)1 << (BITS_COUNT-1)) ) + { + if ( VerPrime ( dss_p_bytes, dss_p_a, TEST_COUNT, RVAL_a, yield_cont) /*TKL00701*/ + == SUCCESS ) /* perform a robust primality test */ + { + break; + } + } + count++; + offset = (u_int16_t) (offset + n + 1); + } while ( count < 4096); + if (status != SUCCESS ) + { + ERROR_BREAK; + } + if (count != 4096) /*TKL00501*/ + { + BREAK; /*TKL00501*/ + } + END_LOOP /* Generate dss_p */ /*TKL00501*/ + + if (status != SUCCESS ) + { + ERROR_BREAK; + } + dss_p_a[0] -= 1; /* dss_p = dss_p - 1 */ + if ( (status= DivRem (dss_p_bytes, dss_p_a, SHA_LENGTH, dss_q_a, u1, + e )) != SUCCESS ) /* e = dss_p / dss_q */ + { + ERROR_BREAK; + } + dss_p_a[0] += 1; /* dss_p = dss_p + 1 */ + + BEGIN_LOOP /* Generate dss_g */ /*TKL00501*/ + MyGenRand( SHA_LENGTH, u, RVAL_a ); /*generate random number*/ + u[SHA_LENGTH / sizeof(ord) - 1] &= ~((ord)1 << (BITS_COUNT-1)); /* u < dss_q */ + if ( (status = Expo( SHA_LENGTH, u, (u_int16_t)(dss_p_bytes - SHA_LENGTH + + sizeof(ord)), e, dss_p_bytes, dss_p_a, dss_g_a )) + != SUCCESS ) /* dss_g = e ^ u mod(dss_p) */ + { + ERROR_BREAK; + } + if ( dss_g_a[0] == 1 ) /* check dss_g == 1 */ + { + for ( i = 1; i < (dss_p_bytes / sizeof(ord)); i++ ) + { + if ( dss_g_a[i] != 0 ) + { + break; + } + } + if ( i == (dss_p_bytes / sizeof(ord)) ) + { + CONTINUE; + } + } + BREAK; /*TKL00501*/ + END_LOOP /* Generate dss_g */ /*TKL00501*/ + END_PROCESSING /* Generate DSS Common Parameters */ + free ( e ); + free ( one ); + free ( c ); + free ( w ); + free ( c1 ); + ALIGN_COPY_FREE(dss_p_a, dss_p, dss_p_bytes); + ALIGN_COPY_FREE(dss_q_a, dss_q, SHA_LENGTH); + ALIGN_COPY_FREE(dss_g_a, dss_g, dss_p_bytes); + ALIGN_MOVE_FREE(RVAL_a, RVAL, SHA_LENGTH); + if (DataOrder) + { + BigSwap(dss_p, dss_p_bytes); + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_g, dss_p_bytes); + } + 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 +* +****************************************************************************/ +int GetDSSPQG(u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g) +{ + int status = SUCCESS; /* function return status */ + ord *dss_p_a; + ord *dss_g_a; + + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + dss_p_a = &DSS_P_NUMBERS[DSS_NUM_INDEX[(dss_p_bytes-DSS_LENGTH_MIN)/LENGTH_STEP]]; + dss_g_a = &DSS_G_NUMBERS[DSS_NUM_INDEX[(dss_p_bytes-DSS_LENGTH_MIN)/LENGTH_STEP]]; + OrdByte(dss_p_a,dss_p_bytes,dss_p); + OrdByte(dss_g_a,dss_p_bytes,dss_g); + OrdByte(DSS_Q_NUMBER,SHA_LENGTH,dss_q); + if (DataOrder) + { + BigSwap(dss_p, dss_p_bytes); + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_g, dss_p_bytes); + } + + return status; +} + + |