1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
* Diffie-Hellman parameter generation, key generation, and secret derivation.
7
* KEA secret generation and verification.
9
* $Id: dh.c,v 1.12 2012/06/14 18:55:10 wtc%google.com Exp $
11
#ifdef FREEBL_NO_DEPEND
24
#define KEA_DERIVED_SECRET_LEN 128
26
/* Lengths are in bytes. */
28
dh_GetSecretKeyLen(unsigned int primeLen)
30
/* Based on Table 2 in NIST SP 800-57. */
31
if (primeLen >= 1920) { /* 15360 bits */
32
return 64; /* 512 bits */
34
if (primeLen >= 960) { /* 7680 bits */
35
return 48; /* 384 bits */
37
if (primeLen >= 384) { /* 3072 bits */
38
return 32; /* 256 bits */
40
if (primeLen >= 256) { /* 2048 bits */
41
return 28; /* 224 bits */
43
return 20; /* 160 bits */
47
DH_GenParam(int primeLen, DHParams **params)
51
unsigned char *pb = NULL;
52
unsigned char *ab = NULL;
53
unsigned long counter = 0;
54
mp_int p, q, a, h, psub1, test;
56
SECStatus rv = SECSuccess;
57
if (!params || primeLen < 0) {
58
PORT_SetError(SEC_ERROR_INVALID_ARGS);
61
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
63
PORT_SetError(SEC_ERROR_NO_MEMORY);
66
dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams));
68
PORT_SetError(SEC_ERROR_NO_MEMORY);
69
PORT_FreeArena(arena, PR_TRUE);
72
dhparams->arena = arena;
77
MP_DIGITS(&psub1) = 0;
79
CHECK_MPI_OK( mp_init(&p) );
80
CHECK_MPI_OK( mp_init(&q) );
81
CHECK_MPI_OK( mp_init(&a) );
82
CHECK_MPI_OK( mp_init(&h) );
83
CHECK_MPI_OK( mp_init(&psub1) );
84
CHECK_MPI_OK( mp_init(&test) );
85
/* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
86
pb = PORT_Alloc(primeLen);
87
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) );
88
pb[0] |= 0x80; /* set high-order bit */
89
pb[primeLen-1] |= 0x01; /* set low-order bit */
90
CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) );
91
CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter) );
92
/* construct Sophie-Germain prime q = (p-1)/2. */
93
CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
94
CHECK_MPI_OK( mp_div_2(&psub1, &q) );
95
/* construct a generator from the prime. */
96
ab = PORT_Alloc(primeLen);
97
/* generate a candidate number a in p's field */
98
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(ab, primeLen) );
99
CHECK_MPI_OK( mp_read_unsigned_octets(&a, ab, primeLen) );
100
/* force a < p (note that quot(a/p) <= 1) */
101
if ( mp_cmp(&a, &p) > 0 )
102
CHECK_MPI_OK( mp_sub(&a, &p, &a) );
104
/* check that a is in the range [2..p-1] */
105
if ( mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) {
106
/* a is outside of the allowed range. Set a=3 and keep going. */
109
/* if a**q mod p != 1 then a is a generator */
110
CHECK_MPI_OK( mp_exptmod(&a, &q, &p, &test) );
111
if ( mp_cmp_d(&test, 1) != 0 )
113
/* increment the candidate and try again. */
114
CHECK_MPI_OK( mp_add_d(&a, 1, &a) );
116
MPINT_TO_SECITEM(&p, &dhparams->prime, arena);
117
MPINT_TO_SECITEM(&a, &dhparams->base, arena);
126
if (pb) PORT_ZFree(pb, primeLen);
127
if (ab) PORT_ZFree(ab, primeLen);
129
MP_TO_SEC_ERROR(err);
133
PORT_FreeArena(arena, PR_TRUE);
138
DH_NewKey(DHParams *params, DHPrivateKey **privKey)
143
mp_err err = MP_OKAY;
144
SECStatus rv = SECSuccess;
145
if (!params || !privKey) {
146
PORT_SetError(SEC_ERROR_INVALID_ARGS);
149
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
151
PORT_SetError(SEC_ERROR_NO_MEMORY);
154
key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey));
156
PORT_SetError(SEC_ERROR_NO_MEMORY);
157
PORT_FreeArena(arena, PR_TRUE);
165
CHECK_MPI_OK( mp_init(&g) );
166
CHECK_MPI_OK( mp_init(&xa) );
167
CHECK_MPI_OK( mp_init(&p) );
168
CHECK_MPI_OK( mp_init(&Ya) );
169
/* Set private key's p */
170
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, ¶ms->prime) );
171
SECITEM_TO_MPINT(key->prime, &p);
172
/* Set private key's g */
173
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, ¶ms->base) );
174
SECITEM_TO_MPINT(key->base, &g);
175
/* Generate private key xa */
176
SECITEM_AllocItem(arena, &key->privateValue,
177
dh_GetSecretKeyLen(params->prime.len));
178
RNG_GenerateGlobalRandomBytes(key->privateValue.data,
179
key->privateValue.len);
180
SECITEM_TO_MPINT( key->privateValue, &xa );
182
CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
183
/* Compute public key Ya = g ** xa mod p */
184
CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) );
185
MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena);
193
MP_TO_SEC_ERROR(err);
197
PORT_FreeArena(arena, PR_TRUE);
202
DH_Derive(SECItem *publicValue,
204
SECItem *privateValue,
205
SECItem *derivedSecret,
206
unsigned int outBytes)
208
mp_int p, Xa, Yb, ZZ;
209
mp_err err = MP_OKAY;
212
unsigned char *secret = NULL;
213
if (!publicValue || !prime || !privateValue || !derivedSecret) {
214
PORT_SetError(SEC_ERROR_INVALID_ARGS);
217
memset(derivedSecret, 0, sizeof *derivedSecret);
222
CHECK_MPI_OK( mp_init(&p) );
223
CHECK_MPI_OK( mp_init(&Xa) );
224
CHECK_MPI_OK( mp_init(&Yb) );
225
CHECK_MPI_OK( mp_init(&ZZ) );
226
SECITEM_TO_MPINT(*publicValue, &Yb);
227
SECITEM_TO_MPINT(*privateValue, &Xa);
228
SECITEM_TO_MPINT(*prime, &p);
229
/* ZZ = (Yb)**Xa mod p */
230
CHECK_MPI_OK( mp_exptmod(&Yb, &Xa, &p, &ZZ) );
231
/* number of bytes in the derived secret */
232
len = mp_unsigned_octet_size(&ZZ);
237
/* allocate a buffer which can hold the entire derived secret. */
238
secret = PORT_Alloc(len);
239
/* grab the derived secret */
240
err = mp_to_unsigned_octets(&ZZ, secret, len);
241
if (err >= 0) err = MP_OKAY;
243
** if outBytes is 0 take all of the bytes from the derived secret.
244
** if outBytes is not 0 take exactly outBytes from the derived secret, zero
245
** pad at the beginning if necessary, and truncate beginning bytes
252
SECITEM_AllocItem(NULL, derivedSecret, nb);
254
unsigned int offset = nb - len;
255
memset(derivedSecret->data, 0, offset);
256
memcpy(derivedSecret->data + offset, secret, len);
258
memcpy(derivedSecret->data, secret + len - nb, nb);
266
/* free the buffer allocated for the full secret. */
267
PORT_ZFree(secret, len);
270
MP_TO_SEC_ERROR(err);
271
if (derivedSecret->data)
272
PORT_ZFree(derivedSecret->data, derivedSecret->len);
279
KEA_Derive(SECItem *prime,
284
SECItem *derivedSecret)
286
mp_int p, Y, R, r, x, t, u, w;
288
unsigned char *secret = NULL;
289
unsigned int len = 0, offset;
290
if (!prime || !public1 || !public2 || !private1 || !private2 ||
292
PORT_SetError(SEC_ERROR_INVALID_ARGS);
295
memset(derivedSecret, 0, sizeof *derivedSecret);
304
CHECK_MPI_OK( mp_init(&p) );
305
CHECK_MPI_OK( mp_init(&Y) );
306
CHECK_MPI_OK( mp_init(&R) );
307
CHECK_MPI_OK( mp_init(&r) );
308
CHECK_MPI_OK( mp_init(&x) );
309
CHECK_MPI_OK( mp_init(&t) );
310
CHECK_MPI_OK( mp_init(&u) );
311
CHECK_MPI_OK( mp_init(&w) );
312
SECITEM_TO_MPINT(*prime, &p);
313
SECITEM_TO_MPINT(*public1, &Y);
314
SECITEM_TO_MPINT(*public2, &R);
315
SECITEM_TO_MPINT(*private1, &r);
316
SECITEM_TO_MPINT(*private2, &x);
317
/* t = DH(Y, r, p) = Y ** r mod p */
318
CHECK_MPI_OK( mp_exptmod(&Y, &r, &p, &t) );
319
/* u = DH(R, x, p) = R ** x mod p */
320
CHECK_MPI_OK( mp_exptmod(&R, &x, &p, &u) );
321
/* w = (t + u) mod p */
322
CHECK_MPI_OK( mp_addmod(&t, &u, &p, &w) );
323
/* allocate a buffer for the full derived secret */
324
len = mp_unsigned_octet_size(&w);
325
secret = PORT_Alloc(len);
326
/* grab the secret */
327
err = mp_to_unsigned_octets(&w, secret, len);
328
if (err > 0) err = MP_OKAY;
329
/* allocate output buffer */
330
SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN);
331
memset(derivedSecret->data, 0, derivedSecret->len);
332
/* copy in the 128 lsb of the secret */
333
if (len >= KEA_DERIVED_SECRET_LEN) {
334
memcpy(derivedSecret->data, secret + (len - KEA_DERIVED_SECRET_LEN),
335
KEA_DERIVED_SECRET_LEN);
337
offset = KEA_DERIVED_SECRET_LEN - len;
338
memcpy(derivedSecret->data + offset, secret, len);
350
PORT_ZFree(secret, len);
352
MP_TO_SEC_ERROR(err);
359
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
363
int cmp = 1; /* default is false */
364
if (!Y || !prime || !subPrime) {
365
PORT_SetError(SEC_ERROR_INVALID_ARGS);
372
CHECK_MPI_OK( mp_init(&p) );
373
CHECK_MPI_OK( mp_init(&q) );
374
CHECK_MPI_OK( mp_init(&y) );
375
CHECK_MPI_OK( mp_init(&r) );
376
SECITEM_TO_MPINT(*prime, &p);
377
SECITEM_TO_MPINT(*subPrime, &q);
378
SECITEM_TO_MPINT(*Y, &y);
379
/* compute r = y**q mod p */
380
CHECK_MPI_OK( mp_exptmod(&y, &q, &p, &r) );
382
cmp = mp_cmp_d(&r, 1);
389
MP_TO_SEC_ERROR(err);
392
return (cmp == 0) ? PR_TRUE : PR_FALSE;