os/ossrv/ssl/libcrypto/src/crypto/dsa/dsa_ossl.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* crypto/dsa/dsa_ossl.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
sl@0
    59
/* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
sl@0
    60
/*
sl@0
    61
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
    62
 */
sl@0
    63
sl@0
    64
#include <stdio.h>
sl@0
    65
#include "cryptlib.h"
sl@0
    66
#include <openssl/bn.h>
sl@0
    67
#include <openssl/dsa.h>
sl@0
    68
#include <openssl/rand.h>
sl@0
    69
#include <openssl/asn1.h>
sl@0
    70
#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
sl@0
    71
#include "libcrypto_wsd_macros.h"
sl@0
    72
#include "libcrypto_wsd.h"
sl@0
    73
#endif
sl@0
    74
sl@0
    75
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
sl@0
    76
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
sl@0
    77
static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
sl@0
    78
		  DSA *dsa);
sl@0
    79
static int dsa_init(DSA *dsa);
sl@0
    80
static int dsa_finish(DSA *dsa);
sl@0
    81
sl@0
    82
#ifndef EMULATOR
sl@0
    83
static DSA_METHOD openssl_dsa_meth = {
sl@0
    84
"OpenSSL DSA method",
sl@0
    85
dsa_do_sign,
sl@0
    86
dsa_sign_setup,
sl@0
    87
dsa_do_verify,
sl@0
    88
NULL, /* dsa_mod_exp, */
sl@0
    89
NULL, /* dsa_bn_mod_exp, */
sl@0
    90
dsa_init,
sl@0
    91
dsa_finish,
sl@0
    92
0,
sl@0
    93
NULL,
sl@0
    94
NULL,
sl@0
    95
NULL
sl@0
    96
};
sl@0
    97
#else
sl@0
    98
GET_STATIC_VAR_FROM_TLS(openssl_dsa_meth,dsa_ossl,DSA_METHOD)
sl@0
    99
#define openssl_dsa_meth (*GET_WSD_VAR_NAME(openssl_dsa_meth,dsa_ossl, s)())
sl@0
   100
const DSA_METHOD temp_s_openssl_dsa_meth = {
sl@0
   101
"OpenSSL DSA method",
sl@0
   102
dsa_do_sign,
sl@0
   103
dsa_sign_setup,
sl@0
   104
dsa_do_verify,
sl@0
   105
NULL, /* dsa_mod_exp, */
sl@0
   106
NULL, /* dsa_bn_mod_exp, */
sl@0
   107
dsa_init,
sl@0
   108
dsa_finish,
sl@0
   109
0,
sl@0
   110
NULL,
sl@0
   111
NULL,
sl@0
   112
NULL
sl@0
   113
};
sl@0
   114
#endif
sl@0
   115
sl@0
   116
/* These macro wrappers replace attempts to use the dsa_mod_exp() and
sl@0
   117
 * bn_mod_exp() handlers in the DSA_METHOD structure. We avoid the problem of
sl@0
   118
 * having a the macro work as an expression by bundling an "err_instr". So;
sl@0
   119
 * 
sl@0
   120
 *     if (!dsa->meth->bn_mod_exp(dsa, r,dsa->g,&k,dsa->p,ctx,
sl@0
   121
 *                 dsa->method_mont_p)) goto err;
sl@0
   122
 *
sl@0
   123
 * can be replaced by;
sl@0
   124
 *
sl@0
   125
 *     DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, &k, dsa->p, ctx,
sl@0
   126
 *                 dsa->method_mont_p);
sl@0
   127
 */
sl@0
   128
sl@0
   129
#define DSA_MOD_EXP(err_instr,dsa,rr,a1,p1,a2,p2,m,ctx,in_mont) \
sl@0
   130
	do { \
sl@0
   131
	int _tmp_res53; \
sl@0
   132
	if((dsa)->meth->dsa_mod_exp) \
sl@0
   133
		_tmp_res53 = (dsa)->meth->dsa_mod_exp((dsa), (rr), (a1), (p1), \
sl@0
   134
				(a2), (p2), (m), (ctx), (in_mont)); \
sl@0
   135
	else \
sl@0
   136
		_tmp_res53 = BN_mod_exp2_mont((rr), (a1), (p1), (a2), (p2), \
sl@0
   137
				(m), (ctx), (in_mont)); \
sl@0
   138
	if(!_tmp_res53) err_instr; \
sl@0
   139
	} while(0)
sl@0
   140
#define DSA_BN_MOD_EXP(err_instr,dsa,r,a,p,m,ctx,m_ctx) \
sl@0
   141
	do { \
sl@0
   142
	int _tmp_res53; \
sl@0
   143
	if((dsa)->meth->bn_mod_exp) \
sl@0
   144
		_tmp_res53 = (dsa)->meth->bn_mod_exp((dsa), (r), (a), (p), \
sl@0
   145
				(m), (ctx), (m_ctx)); \
sl@0
   146
	else \
sl@0
   147
		_tmp_res53 = BN_mod_exp_mont((r), (a), (p), (m), (ctx), (m_ctx)); \
sl@0
   148
	if(!_tmp_res53) err_instr; \
sl@0
   149
	} while(0)
sl@0
   150
sl@0
   151
EXPORT_C const DSA_METHOD *DSA_OpenSSL(void)
sl@0
   152
{
sl@0
   153
	return &openssl_dsa_meth;
sl@0
   154
}
sl@0
   155
sl@0
   156
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
sl@0
   157
	{
sl@0
   158
	BIGNUM *kinv=NULL,*r=NULL,*s=NULL;
sl@0
   159
	BIGNUM m;
sl@0
   160
	BIGNUM xr;
sl@0
   161
	BN_CTX *ctx=NULL;
sl@0
   162
	int i,reason=ERR_R_BN_LIB;
sl@0
   163
	DSA_SIG *ret=NULL;
sl@0
   164
sl@0
   165
	BN_init(&m);
sl@0
   166
	BN_init(&xr);
sl@0
   167
sl@0
   168
	if (!dsa->p || !dsa->q || !dsa->g)
sl@0
   169
		{
sl@0
   170
		reason=DSA_R_MISSING_PARAMETERS;
sl@0
   171
		goto err;
sl@0
   172
		}
sl@0
   173
sl@0
   174
	s=BN_new();
sl@0
   175
	if (s == NULL) goto err;
sl@0
   176
sl@0
   177
	i=BN_num_bytes(dsa->q); /* should be 20 */
sl@0
   178
	if ((dlen > i) || (dlen > 50))
sl@0
   179
		{
sl@0
   180
		reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE;
sl@0
   181
		goto err;
sl@0
   182
		}
sl@0
   183
sl@0
   184
	ctx=BN_CTX_new();
sl@0
   185
	if (ctx == NULL) goto err;
sl@0
   186
sl@0
   187
	if ((dsa->kinv == NULL) || (dsa->r == NULL))
sl@0
   188
		{
sl@0
   189
		if (!DSA_sign_setup(dsa,ctx,&kinv,&r)) goto err;
sl@0
   190
		}
sl@0
   191
	else
sl@0
   192
		{
sl@0
   193
		kinv=dsa->kinv;
sl@0
   194
		dsa->kinv=NULL;
sl@0
   195
		r=dsa->r;
sl@0
   196
		dsa->r=NULL;
sl@0
   197
		}
sl@0
   198
sl@0
   199
	if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err;
sl@0
   200
sl@0
   201
	/* Compute  s = inv(k) (m + xr) mod q */
sl@0
   202
	if (!BN_mod_mul(&xr,dsa->priv_key,r,dsa->q,ctx)) goto err;/* s = xr */
sl@0
   203
	if (!BN_add(s, &xr, &m)) goto err;		/* s = m + xr */
sl@0
   204
	if (BN_cmp(s,dsa->q) > 0)
sl@0
   205
		BN_sub(s,s,dsa->q);
sl@0
   206
	if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err;
sl@0
   207
sl@0
   208
	ret=DSA_SIG_new();
sl@0
   209
	if (ret == NULL) goto err;
sl@0
   210
	ret->r = r;
sl@0
   211
	ret->s = s;
sl@0
   212
	
sl@0
   213
err:
sl@0
   214
	if (!ret)
sl@0
   215
		{
sl@0
   216
		DSAerr(DSA_F_DSA_DO_SIGN,reason);
sl@0
   217
		BN_free(r);
sl@0
   218
		BN_free(s);
sl@0
   219
		}
sl@0
   220
	if (ctx != NULL) BN_CTX_free(ctx);
sl@0
   221
	BN_clear_free(&m);
sl@0
   222
	BN_clear_free(&xr);
sl@0
   223
	if (kinv != NULL) /* dsa->kinv is NULL now if we used it */
sl@0
   224
	    BN_clear_free(kinv);
sl@0
   225
	return(ret);
sl@0
   226
	}
sl@0
   227
sl@0
   228
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
sl@0
   229
	{
sl@0
   230
	BN_CTX *ctx;
sl@0
   231
	BIGNUM k,kq,*K,*kinv=NULL,*r=NULL;
sl@0
   232
	int ret=0;
sl@0
   233
sl@0
   234
	if (!dsa->p || !dsa->q || !dsa->g)
sl@0
   235
		{
sl@0
   236
		DSAerr(DSA_F_DSA_SIGN_SETUP,DSA_R_MISSING_PARAMETERS);
sl@0
   237
		return 0;
sl@0
   238
		}
sl@0
   239
sl@0
   240
	BN_init(&k);
sl@0
   241
	BN_init(&kq);
sl@0
   242
sl@0
   243
	if (ctx_in == NULL)
sl@0
   244
		{
sl@0
   245
		if ((ctx=BN_CTX_new()) == NULL) goto err;
sl@0
   246
		}
sl@0
   247
	else
sl@0
   248
		ctx=ctx_in;
sl@0
   249
sl@0
   250
	if ((r=BN_new()) == NULL) goto err;
sl@0
   251
sl@0
   252
	/* Get random k */
sl@0
   253
	do
sl@0
   254
		if (!BN_rand_range(&k, dsa->q)) goto err;
sl@0
   255
	while (BN_is_zero(&k));
sl@0
   256
	if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0)
sl@0
   257
		{
sl@0
   258
		BN_set_flags(&k, BN_FLG_CONSTTIME);
sl@0
   259
		}
sl@0
   260
sl@0
   261
	if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
sl@0
   262
		{
sl@0
   263
		if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
sl@0
   264
						CRYPTO_LOCK_DSA,
sl@0
   265
						dsa->p, ctx))
sl@0
   266
			goto err;
sl@0
   267
		}
sl@0
   268
sl@0
   269
	/* Compute r = (g^k mod p) mod q */
sl@0
   270
sl@0
   271
	if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0)
sl@0
   272
		{
sl@0
   273
		if (!BN_copy(&kq, &k)) goto err;
sl@0
   274
sl@0
   275
		/* We do not want timing information to leak the length of k,
sl@0
   276
		 * so we compute g^k using an equivalent exponent of fixed length.
sl@0
   277
		 *
sl@0
   278
		 * (This is a kludge that we need because the BN_mod_exp_mont()
sl@0
   279
		 * does not let us specify the desired timing behaviour.) */
sl@0
   280
sl@0
   281
		if (!BN_add(&kq, &kq, dsa->q)) goto err;
sl@0
   282
		if (BN_num_bits(&kq) <= BN_num_bits(dsa->q))
sl@0
   283
			{
sl@0
   284
			if (!BN_add(&kq, &kq, dsa->q)) goto err;
sl@0
   285
			}
sl@0
   286
sl@0
   287
		K = &kq;
sl@0
   288
		}
sl@0
   289
	else
sl@0
   290
		{
sl@0
   291
		K = &k;
sl@0
   292
		}
sl@0
   293
	DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, K, dsa->p, ctx,
sl@0
   294
			dsa->method_mont_p);
sl@0
   295
	if (!BN_mod(r,r,dsa->q,ctx)) goto err;
sl@0
   296
sl@0
   297
	/* Compute  part of 's = inv(k) (m + xr) mod q' */
sl@0
   298
	if ((kinv=BN_mod_inverse(NULL,&k,dsa->q,ctx)) == NULL) goto err;
sl@0
   299
sl@0
   300
	if (*kinvp != NULL) BN_clear_free(*kinvp);
sl@0
   301
	*kinvp=kinv;
sl@0
   302
	kinv=NULL;
sl@0
   303
	if (*rp != NULL) BN_clear_free(*rp);
sl@0
   304
	*rp=r;
sl@0
   305
	ret=1;
sl@0
   306
err:
sl@0
   307
	if (!ret)
sl@0
   308
		{
sl@0
   309
		DSAerr(DSA_F_DSA_SIGN_SETUP,ERR_R_BN_LIB);
sl@0
   310
		if (kinv != NULL) BN_clear_free(kinv);
sl@0
   311
		if (r != NULL) BN_clear_free(r);
sl@0
   312
		}
sl@0
   313
	if (ctx_in == NULL) BN_CTX_free(ctx);
sl@0
   314
	if (kinv != NULL) BN_clear_free(kinv);
sl@0
   315
	BN_clear_free(&k);
sl@0
   316
	BN_clear_free(&kq);
sl@0
   317
	return(ret);
sl@0
   318
	}
sl@0
   319
sl@0
   320
static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
sl@0
   321
		  DSA *dsa)
sl@0
   322
	{
sl@0
   323
	BN_CTX *ctx;
sl@0
   324
	BIGNUM u1,u2,t1;
sl@0
   325
	BN_MONT_CTX *mont=NULL;
sl@0
   326
	int ret = -1;
sl@0
   327
	if (!dsa->p || !dsa->q || !dsa->g)
sl@0
   328
		{
sl@0
   329
		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MISSING_PARAMETERS);
sl@0
   330
		return -1;
sl@0
   331
		}
sl@0
   332
sl@0
   333
	if (BN_num_bits(dsa->q) != 160)
sl@0
   334
		{
sl@0
   335
		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_BAD_Q_VALUE);
sl@0
   336
		return -1;
sl@0
   337
		}
sl@0
   338
sl@0
   339
	if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS)
sl@0
   340
		{
sl@0
   341
		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MODULUS_TOO_LARGE);
sl@0
   342
		return -1;
sl@0
   343
		}
sl@0
   344
sl@0
   345
	BN_init(&u1);
sl@0
   346
	BN_init(&u2);
sl@0
   347
	BN_init(&t1);
sl@0
   348
sl@0
   349
	if ((ctx=BN_CTX_new()) == NULL) goto err;
sl@0
   350
sl@0
   351
	if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
sl@0
   352
	    BN_ucmp(sig->r, dsa->q) >= 0)
sl@0
   353
		{
sl@0
   354
		ret = 0;
sl@0
   355
		goto err;
sl@0
   356
		}
sl@0
   357
	if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
sl@0
   358
	    BN_ucmp(sig->s, dsa->q) >= 0)
sl@0
   359
		{
sl@0
   360
		ret = 0;
sl@0
   361
		goto err;
sl@0
   362
		}
sl@0
   363
sl@0
   364
	/* Calculate W = inv(S) mod Q
sl@0
   365
	 * save W in u2 */
sl@0
   366
	if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err;
sl@0
   367
sl@0
   368
	/* save M in u1 */
sl@0
   369
	if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err;
sl@0
   370
sl@0
   371
	/* u1 = M * w mod q */
sl@0
   372
	if (!BN_mod_mul(&u1,&u1,&u2,dsa->q,ctx)) goto err;
sl@0
   373
sl@0
   374
	/* u2 = r * w mod q */
sl@0
   375
	if (!BN_mod_mul(&u2,sig->r,&u2,dsa->q,ctx)) goto err;
sl@0
   376
sl@0
   377
sl@0
   378
	if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
sl@0
   379
		{
sl@0
   380
		mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
sl@0
   381
					CRYPTO_LOCK_DSA, dsa->p, ctx);
sl@0
   382
		if (!mont)
sl@0
   383
			goto err;
sl@0
   384
		}
sl@0
   385
sl@0
   386
sl@0
   387
	DSA_MOD_EXP(goto err, dsa, &t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, mont);
sl@0
   388
	/* BN_copy(&u1,&t1); */
sl@0
   389
	/* let u1 = u1 mod q */
sl@0
   390
	if (!BN_mod(&u1,&t1,dsa->q,ctx)) goto err;
sl@0
   391
sl@0
   392
	/* V is now in u1.  If the signature is correct, it will be
sl@0
   393
	 * equal to R. */
sl@0
   394
	ret=(BN_ucmp(&u1, sig->r) == 0);
sl@0
   395
sl@0
   396
	err:
sl@0
   397
	/* XXX: surely this is wrong - if ret is 0, it just didn't verify;
sl@0
   398
	   there is no error in BN. Test should be ret == -1 (Ben) */
sl@0
   399
	if (ret != 1) DSAerr(DSA_F_DSA_DO_VERIFY,ERR_R_BN_LIB);
sl@0
   400
	if (ctx != NULL) BN_CTX_free(ctx);
sl@0
   401
	BN_free(&u1);
sl@0
   402
	BN_free(&u2);
sl@0
   403
	BN_free(&t1);
sl@0
   404
	return(ret);
sl@0
   405
	}
sl@0
   406
sl@0
   407
static int dsa_init(DSA *dsa)
sl@0
   408
{
sl@0
   409
	dsa->flags|=DSA_FLAG_CACHE_MONT_P;
sl@0
   410
	return(1);
sl@0
   411
}
sl@0
   412
sl@0
   413
static int dsa_finish(DSA *dsa)
sl@0
   414
{
sl@0
   415
	if(dsa->method_mont_p)
sl@0
   416
		BN_MONT_CTX_free(dsa->method_mont_p);
sl@0
   417
	return(1);
sl@0
   418
}
sl@0
   419