~ubuntu-branches/ubuntu/precise/nss/precise-security

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/freebl/dh.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-11-14 14:58:07 UTC
  • mfrom: (1.1.19)
  • Revision ID: package-import@ubuntu.com-20131114145807-ay302kimn72ovt88
Tags: 3.15.3-0ubuntu0.12.04.1
* SECURITY UPDATE: New upstream release to fix multiple security issues
  and add TLSv1.2 support.
  - CVE-2013-1739
  - CVE-2013-1741
  - CVE-2013-5605
  - CVE-2013-5606
* Adjusted packaging for 3.15.3:
  - debian/patches/*: refreshed.
  - debian/patches/lower-dhe-priority.patch: removed, no longer needed,
    was a workaround for an old version of firefox.
  - debian/libnss3.symbols: added new symbols.
  - debian/rules: updated for new source layout.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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/. */
4
 
 
5
 
/*
6
 
 * Diffie-Hellman parameter generation, key generation, and secret derivation.
7
 
 * KEA secret generation and verification.
8
 
 *
9
 
 * $Id: dh.c,v 1.12 2012/06/14 18:55:10 wtc%google.com Exp $
10
 
 */
11
 
#ifdef FREEBL_NO_DEPEND
12
 
#include "stubs.h"
13
 
#endif
14
 
 
15
 
#include "prerr.h"
16
 
#include "secerr.h"
17
 
 
18
 
#include "blapi.h"
19
 
#include "secitem.h"
20
 
#include "mpi.h"
21
 
#include "mpprime.h"
22
 
#include "secmpi.h"
23
 
 
24
 
#define KEA_DERIVED_SECRET_LEN 128
25
 
 
26
 
/* Lengths are in bytes. */
27
 
static unsigned int
28
 
dh_GetSecretKeyLen(unsigned int primeLen)
29
 
{
30
 
    /* Based on Table 2 in NIST SP 800-57. */
31
 
    if (primeLen >= 1920) { /* 15360 bits */
32
 
        return 64;  /* 512 bits */
33
 
    }
34
 
    if (primeLen >= 960) { /* 7680 bits */
35
 
        return 48;  /* 384 bits */
36
 
    }
37
 
    if (primeLen >= 384) { /* 3072 bits */
38
 
        return 32;  /* 256 bits */
39
 
    }
40
 
    if (primeLen >= 256) { /* 2048 bits */
41
 
        return 28;  /* 224 bits */
42
 
    }
43
 
    return 20;  /* 160 bits */
44
 
}
45
 
 
46
 
SECStatus 
47
 
DH_GenParam(int primeLen, DHParams **params)
48
 
{
49
 
    PRArenaPool *arena;
50
 
    DHParams *dhparams;
51
 
    unsigned char *pb = NULL;
52
 
    unsigned char *ab = NULL;
53
 
    unsigned long counter = 0;
54
 
    mp_int p, q, a, h, psub1, test;
55
 
    mp_err err = MP_OKAY;
56
 
    SECStatus rv = SECSuccess;
57
 
    if (!params || primeLen < 0) {
58
 
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
59
 
        return SECFailure;
60
 
    }
61
 
    arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
62
 
    if (!arena) {
63
 
        PORT_SetError(SEC_ERROR_NO_MEMORY);
64
 
        return SECFailure;
65
 
    }
66
 
    dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams));
67
 
    if (!dhparams) {
68
 
        PORT_SetError(SEC_ERROR_NO_MEMORY);
69
 
        PORT_FreeArena(arena, PR_TRUE);
70
 
        return SECFailure;
71
 
    }
72
 
    dhparams->arena = arena;
73
 
    MP_DIGITS(&p) = 0;
74
 
    MP_DIGITS(&q) = 0;
75
 
    MP_DIGITS(&a) = 0;
76
 
    MP_DIGITS(&h) = 0;
77
 
    MP_DIGITS(&psub1) = 0;
78
 
    MP_DIGITS(&test) = 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) );
103
 
    do {
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. */
107
 
            mp_set(&a, 3);
108
 
        }
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 )
112
 
            break;
113
 
        /* increment the candidate and try again. */
114
 
        CHECK_MPI_OK( mp_add_d(&a, 1, &a) );
115
 
    } while (PR_TRUE);
116
 
    MPINT_TO_SECITEM(&p, &dhparams->prime, arena);
117
 
    MPINT_TO_SECITEM(&a, &dhparams->base, arena);
118
 
    *params = dhparams;
119
 
cleanup:
120
 
    mp_clear(&p);
121
 
    mp_clear(&q);
122
 
    mp_clear(&a);
123
 
    mp_clear(&h);
124
 
    mp_clear(&psub1);
125
 
    mp_clear(&test);
126
 
    if (pb) PORT_ZFree(pb, primeLen);
127
 
    if (ab) PORT_ZFree(ab, primeLen);
128
 
    if (err) {
129
 
        MP_TO_SEC_ERROR(err);
130
 
        rv = SECFailure;
131
 
    }
132
 
    if (rv)
133
 
        PORT_FreeArena(arena, PR_TRUE);
134
 
    return rv;
135
 
}
136
 
 
137
 
SECStatus 
138
 
DH_NewKey(DHParams *params, DHPrivateKey **privKey)
139
 
{
140
 
    PRArenaPool *arena;
141
 
    DHPrivateKey *key;
142
 
    mp_int g, xa, p, Ya;
143
 
    mp_err   err = MP_OKAY;
144
 
    SECStatus rv = SECSuccess;
145
 
    if (!params || !privKey) {
146
 
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
147
 
        return SECFailure;
148
 
    }
149
 
    arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
150
 
    if (!arena) {
151
 
        PORT_SetError(SEC_ERROR_NO_MEMORY);
152
 
        return SECFailure;
153
 
    }
154
 
    key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey));
155
 
    if (!key) {
156
 
        PORT_SetError(SEC_ERROR_NO_MEMORY);
157
 
        PORT_FreeArena(arena, PR_TRUE);
158
 
        return SECFailure;
159
 
    }
160
 
    key->arena = arena;
161
 
    MP_DIGITS(&g)  = 0;
162
 
    MP_DIGITS(&xa) = 0;
163
 
    MP_DIGITS(&p)  = 0;
164
 
    MP_DIGITS(&Ya) = 0;
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, &params->prime) );
171
 
    SECITEM_TO_MPINT(key->prime, &p);
172
 
    /* Set private key's g */
173
 
    CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, &params->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 );
181
 
    /* xa < p */
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);
186
 
    *privKey = key;
187
 
cleanup:
188
 
    mp_clear(&g);
189
 
    mp_clear(&xa);
190
 
    mp_clear(&p);
191
 
    mp_clear(&Ya);
192
 
    if (err) {
193
 
        MP_TO_SEC_ERROR(err);
194
 
        rv = SECFailure;
195
 
    }
196
 
    if (rv)
197
 
        PORT_FreeArena(arena, PR_TRUE);
198
 
    return rv;
199
 
}
200
 
 
201
 
SECStatus 
202
 
DH_Derive(SECItem *publicValue, 
203
 
          SECItem *prime, 
204
 
          SECItem *privateValue, 
205
 
          SECItem *derivedSecret, 
206
 
          unsigned int outBytes)
207
 
{
208
 
    mp_int p, Xa, Yb, ZZ;
209
 
    mp_err err = MP_OKAY;
210
 
    int len = 0;
211
 
    unsigned int nb;
212
 
    unsigned char *secret = NULL;
213
 
    if (!publicValue || !prime || !privateValue || !derivedSecret) {
214
 
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
215
 
        return SECFailure;
216
 
    }
217
 
    memset(derivedSecret, 0, sizeof *derivedSecret);
218
 
    MP_DIGITS(&p)  = 0;
219
 
    MP_DIGITS(&Xa) = 0;
220
 
    MP_DIGITS(&Yb) = 0;
221
 
    MP_DIGITS(&ZZ) = 0;
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);
233
 
    if (len <= 0) {
234
 
        err = MP_BADARG;
235
 
        goto cleanup;
236
 
    }
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;
242
 
    /* 
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 
246
 
    ** if necessary.
247
 
    */
248
 
    if (outBytes > 0)
249
 
        nb = outBytes;
250
 
    else
251
 
        nb = len;
252
 
    SECITEM_AllocItem(NULL, derivedSecret, nb);
253
 
    if (len < nb) {
254
 
        unsigned int offset = nb - len;
255
 
        memset(derivedSecret->data, 0, offset);
256
 
        memcpy(derivedSecret->data + offset, secret, len);
257
 
    } else {
258
 
        memcpy(derivedSecret->data, secret + len - nb, nb);
259
 
    }
260
 
cleanup:
261
 
    mp_clear(&p);
262
 
    mp_clear(&Xa);
263
 
    mp_clear(&Yb);
264
 
    mp_clear(&ZZ);
265
 
    if (secret) {
266
 
        /* free the buffer allocated for the full secret. */
267
 
        PORT_ZFree(secret, len);
268
 
    }
269
 
    if (err) {
270
 
        MP_TO_SEC_ERROR(err);
271
 
        if (derivedSecret->data) 
272
 
            PORT_ZFree(derivedSecret->data, derivedSecret->len);
273
 
        return SECFailure;
274
 
    }
275
 
    return SECSuccess;
276
 
}
277
 
 
278
 
SECStatus 
279
 
KEA_Derive(SECItem *prime, 
280
 
           SECItem *public1, 
281
 
           SECItem *public2, 
282
 
           SECItem *private1, 
283
 
           SECItem *private2,
284
 
           SECItem *derivedSecret)
285
 
{
286
 
    mp_int p, Y, R, r, x, t, u, w;
287
 
    mp_err err;
288
 
    unsigned char *secret = NULL;
289
 
    unsigned int len = 0, offset;
290
 
    if (!prime || !public1 || !public2 || !private1 || !private2 ||
291
 
        !derivedSecret) {
292
 
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
293
 
        return SECFailure;
294
 
    }
295
 
    memset(derivedSecret, 0, sizeof *derivedSecret);
296
 
    MP_DIGITS(&p) = 0;
297
 
    MP_DIGITS(&Y) = 0;
298
 
    MP_DIGITS(&R) = 0;
299
 
    MP_DIGITS(&r) = 0;
300
 
    MP_DIGITS(&x) = 0;
301
 
    MP_DIGITS(&t) = 0;
302
 
    MP_DIGITS(&u) = 0;
303
 
    MP_DIGITS(&w) = 0;
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);
336
 
    } else {
337
 
        offset = KEA_DERIVED_SECRET_LEN - len;
338
 
        memcpy(derivedSecret->data + offset, secret, len);
339
 
    }
340
 
cleanup:
341
 
    mp_clear(&p);
342
 
    mp_clear(&Y);
343
 
    mp_clear(&R);
344
 
    mp_clear(&r);
345
 
    mp_clear(&x);
346
 
    mp_clear(&t);
347
 
    mp_clear(&u);
348
 
    mp_clear(&w);
349
 
    if (secret)
350
 
        PORT_ZFree(secret, len);
351
 
    if (err) {
352
 
        MP_TO_SEC_ERROR(err);
353
 
        return SECFailure;
354
 
    }
355
 
    return SECSuccess;
356
 
}
357
 
 
358
 
PRBool 
359
 
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
360
 
{
361
 
    mp_int p, q, y, r;
362
 
    mp_err err;
363
 
    int cmp = 1;  /* default is false */
364
 
    if (!Y || !prime || !subPrime) {
365
 
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
366
 
        return SECFailure;
367
 
    }
368
 
    MP_DIGITS(&p) = 0;
369
 
    MP_DIGITS(&q) = 0;
370
 
    MP_DIGITS(&y) = 0;
371
 
    MP_DIGITS(&r) = 0;
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) );
381
 
    /* compare to 1 */
382
 
    cmp = mp_cmp_d(&r, 1);
383
 
cleanup:
384
 
    mp_clear(&p);
385
 
    mp_clear(&q);
386
 
    mp_clear(&y);
387
 
    mp_clear(&r);
388
 
    if (err) {
389
 
        MP_TO_SEC_ERROR(err);
390
 
        return PR_FALSE;
391
 
    }
392
 
    return (cmp == 0) ? PR_TRUE : PR_FALSE;
393
 
}