3
* ***** BEGIN LICENSE BLOCK *****
4
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 1.1 (the "License"); you may not use this file except in compliance with
8
* the License. You may obtain a copy of the License at
9
* http://www.mozilla.org/MPL/
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
16
* The Original Code is the Netscape security libraries.
18
* The Initial Developer of the Original Code is
19
* Netscape Communications Corporation.
20
* Portions created by the Initial Developer are Copyright (C) 1994-2000
21
* the Initial Developer. All Rights Reserved.
25
* Alternatively, the contents of this file may be used under the terms of
26
* either the GNU General Public License Version 2 or later (the "GPL"), or
27
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the MPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the MPL, the GPL or the LGPL.
37
* ***** END LICENSE BLOCK ***** */
38
/* $Id: dsa.c,v 1.18 2005/10/12 00:48:25 wtchang%redhat.com Exp $ */
51
/* XXX to be replaced by define in blapit.h */
52
#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
54
/* DSA-specific random number function defined in prng_fips1861.c. */
56
DSA_GenerateGlobalRandomBytes(void *dest, size_t len, const unsigned char *q);
58
static void translate_mpi_error(mp_err err)
64
dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey,
65
const unsigned char *xb)
73
if (!params || !privKey) {
74
PORT_SetError(SEC_ERROR_INVALID_ARGS);
77
/* Initialize an arena for the DSA key. */
78
arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE);
80
PORT_SetError(SEC_ERROR_NO_MEMORY);
83
key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
85
PORT_SetError(SEC_ERROR_NO_MEMORY);
86
PORT_FreeArena(arena, PR_TRUE);
89
key->params.arena = arena;
90
/* Initialize MPI integers. */
95
CHECK_MPI_OK( mp_init(&p) );
96
CHECK_MPI_OK( mp_init(&g) );
97
CHECK_MPI_OK( mp_init(&x) );
98
CHECK_MPI_OK( mp_init(&y) );
99
/* Copy over the PQG params */
100
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.prime,
102
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
103
¶ms->subPrime) );
104
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, ¶ms->base) );
105
/* Convert stored p, g, and received x into MPI integers. */
106
SECITEM_TO_MPINT(params->prime, &p);
107
SECITEM_TO_MPINT(params->base, &g);
108
OCTETS_TO_MPINT(xb, &x, DSA_SUBPRIME_LEN);
109
/* Store x in private key */
110
SECITEM_AllocItem(arena, &key->privateValue, DSA_SUBPRIME_LEN);
111
memcpy(key->privateValue.data, xb, DSA_SUBPRIME_LEN);
112
/* Compute public key y = g**x mod p */
113
CHECK_MPI_OK( mp_exptmod(&g, &x, &p, &y) );
114
/* Store y in public key */
115
MPINT_TO_SECITEM(&y, &key->publicValue, arena);
124
PORT_FreeArena(key->params.arena, PR_TRUE);
126
translate_mpi_error(err);
133
** Generate and return a new DSA public and private key pair,
134
** both of which are encoded into a single DSAPrivateKey struct.
135
** "params" is a pointer to the PQG parameters for the domain
136
** Uses a random seed.
139
DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
142
unsigned char seed[DSA_SUBPRIME_LEN];
148
/* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
149
if (DSA_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN,
150
params->subPrime.data))
152
/* Disallow values of 0 and 1 for x. */
154
for (i = 0; i < DSA_SUBPRIME_LEN-1; i++) {
160
if (!good && seed[i] > 1) {
163
} while (!good && --retries > 0);
166
PORT_SetError(SEC_ERROR_NEED_RANDOM);
170
/* Generate a new DSA key using random seed. */
171
rv = dsa_NewKey(params, privKey, seed);
175
/* For FIPS compliance testing. Seed must be exactly 20 bytes long */
177
DSA_NewKeyFromSeed(const PQGParams *params,
178
const unsigned char *seed,
179
DSAPrivateKey **privKey)
182
rv = dsa_NewKey(params, privKey, seed);
187
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
188
const unsigned char *kb)
190
mp_int p, q, g; /* PQG parameters */
191
mp_int x, k; /* private key & pseudo-random integer */
192
mp_int r, s; /* tuple (r, s) is signature) */
193
mp_err err = MP_OKAY;
194
SECStatus rv = SECSuccess;
196
/* FIPS-compliance dictates that digest is a SHA1 hash. */
198
if (!key || !signature || !digest ||
199
(signature->len < DSA_SIGNATURE_LEN) ||
200
(digest->len != SHA1_LENGTH)) {
201
PORT_SetError(SEC_ERROR_INVALID_ARGS);
205
/* Initialize MPI integers. */
213
CHECK_MPI_OK( mp_init(&p) );
214
CHECK_MPI_OK( mp_init(&q) );
215
CHECK_MPI_OK( mp_init(&g) );
216
CHECK_MPI_OK( mp_init(&x) );
217
CHECK_MPI_OK( mp_init(&k) );
218
CHECK_MPI_OK( mp_init(&r) );
219
CHECK_MPI_OK( mp_init(&s) );
221
** Convert stored PQG and private key into MPI integers.
223
SECITEM_TO_MPINT(key->params.prime, &p);
224
SECITEM_TO_MPINT(key->params.subPrime, &q);
225
SECITEM_TO_MPINT(key->params.base, &g);
226
SECITEM_TO_MPINT(key->privateValue, &x);
227
OCTETS_TO_MPINT(kb, &k, DSA_SUBPRIME_LEN);
229
** FIPS 186-1, Section 5, Step 1
231
** r = (g**k mod p) mod q
233
CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
234
CHECK_MPI_OK( mp_mod(&r, &q, &r) ); /* r = r mod q */
236
** FIPS 186-1, Section 5, Step 2
238
** s = (k**-1 * (SHA1(M) + x*r)) mod q
240
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
241
CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
242
CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
243
CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
244
CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */
246
** verify r != 0 and s != 0
247
** mentioned as optional in FIPS 186-1.
249
if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
250
PORT_SetError(SEC_ERROR_NEED_RANDOM);
257
** Signature is tuple (r, s)
259
err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);
260
if (err < 0) goto cleanup;
261
err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,
263
if (err < 0) goto cleanup;
265
signature->len = DSA_SIGNATURE_LEN;
275
translate_mpi_error(err);
281
/* signature is caller-supplied buffer of at least 40 bytes.
282
** On input, signature->len == size of buffer to hold signature.
283
** digest->len == size of digest.
284
** On output, signature->len == size of signature in buffer.
285
** Uses a random seed.
288
DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
292
unsigned char kSeed[DSA_SUBPRIME_LEN];
298
rv = DSA_GenerateGlobalRandomBytes(kSeed, DSA_SUBPRIME_LEN,
299
key->params.subPrime.data);
300
if (rv != SECSuccess)
302
/* Disallow a value of 0 for k. */
304
for (i = 0; i < DSA_SUBPRIME_LEN; i++) {
311
PORT_SetError(SEC_ERROR_NEED_RANDOM);
315
rv = dsa_SignDigest(key, signature, digest, kSeed);
316
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
321
/* For FIPS compliance testing. Seed must be exactly 20 bytes. */
323
DSA_SignDigestWithSeed(DSAPrivateKey * key,
325
const SECItem * digest,
326
const unsigned char * seed)
329
rv = dsa_SignDigest(key, signature, digest, seed);
333
/* signature is caller-supplied buffer of at least 20 bytes.
334
** On input, signature->len == size of buffer to hold signature.
335
** digest->len == size of digest.
338
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
339
const SECItem *digest)
341
/* FIPS-compliance dictates that digest is a SHA1 hash. */
342
mp_int p, q, g; /* PQG parameters */
343
mp_int r_, s_; /* tuple (r', s') is received signature) */
344
mp_int u1, u2, v, w; /* intermediate values used in verification */
345
mp_int y; /* public key */
347
SECStatus verified = SECFailure;
350
if (!key || !signature || !digest ||
351
(signature->len != DSA_SIGNATURE_LEN) ||
352
(digest->len != SHA1_LENGTH)) {
353
PORT_SetError(SEC_ERROR_INVALID_ARGS);
356
/* Initialize MPI integers. */
367
CHECK_MPI_OK( mp_init(&p) );
368
CHECK_MPI_OK( mp_init(&q) );
369
CHECK_MPI_OK( mp_init(&g) );
370
CHECK_MPI_OK( mp_init(&y) );
371
CHECK_MPI_OK( mp_init(&r_) );
372
CHECK_MPI_OK( mp_init(&s_) );
373
CHECK_MPI_OK( mp_init(&u1) );
374
CHECK_MPI_OK( mp_init(&u2) );
375
CHECK_MPI_OK( mp_init(&v) );
376
CHECK_MPI_OK( mp_init(&w) );
378
** Convert stored PQG and public key into MPI integers.
380
SECITEM_TO_MPINT(key->params.prime, &p);
381
SECITEM_TO_MPINT(key->params.subPrime, &q);
382
SECITEM_TO_MPINT(key->params.base, &g);
383
SECITEM_TO_MPINT(key->publicValue, &y);
385
** Convert received signature (r', s') into MPI integers.
387
OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN);
388
OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN);
390
** Verify that 0 < r' < q and 0 < s' < q
392
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
393
mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) {
394
/* err is zero here. */
395
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
396
goto cleanup; /* will return verified == SECFailure */
399
** FIPS 186-1, Section 6, Step 1
401
** w = (s')**-1 mod q
403
CHECK_MPI_OK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */
405
** FIPS 186-1, Section 6, Step 2
407
** u1 = ((SHA1(M')) * w) mod q
409
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
410
CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
412
** FIPS 186-1, Section 6, Step 3
414
** u2 = ((r') * w) mod q
416
CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) );
418
** FIPS 186-1, Section 6, Step 4
420
** v = ((g**u1 * y**u2) mod p) mod q
422
CHECK_MPI_OK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
423
CHECK_MPI_OK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
424
CHECK_MPI_OK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */
425
CHECK_MPI_OK( mp_mod(&v, &q, &v) ); /* v = v mod q */
427
** Verification: v == r'
429
if (mp_cmp(&v, &r_)) {
430
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
431
verified = SECFailure; /* Signature failed to verify. */
433
verified = SECSuccess; /* Signature verified. */
447
translate_mpi_error(err);