security/nss/lib/freebl/dh.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     5 /*
     6  * Diffie-Hellman parameter generation, key generation, and secret derivation.
     7  * KEA secret generation and verification.
     8  */
     9 #ifdef FREEBL_NO_DEPEND
    10 #include "stubs.h"
    11 #endif
    13 #include "prerr.h"
    14 #include "secerr.h"
    16 #include "blapi.h"
    17 #include "secitem.h"
    18 #include "mpi.h"
    19 #include "mpprime.h"
    20 #include "secmpi.h"
    22 #define KEA_DERIVED_SECRET_LEN 128
    24 /* Lengths are in bytes. */
    25 static unsigned int
    26 dh_GetSecretKeyLen(unsigned int primeLen)
    27 {
    28     /* Based on Table 2 in NIST SP 800-57. */
    29     if (primeLen >= 1920) { /* 15360 bits */
    30         return 64;  /* 512 bits */
    31     }
    32     if (primeLen >= 960) { /* 7680 bits */
    33         return 48;  /* 384 bits */
    34     }
    35     if (primeLen >= 384) { /* 3072 bits */
    36         return 32;  /* 256 bits */
    37     }
    38     if (primeLen >= 256) { /* 2048 bits */
    39         return 28;  /* 224 bits */
    40     }
    41     return 20;  /* 160 bits */
    42 }
    44 SECStatus 
    45 DH_GenParam(int primeLen, DHParams **params)
    46 {
    47     PLArenaPool *arena;
    48     DHParams *dhparams;
    49     unsigned char *pb = NULL;
    50     unsigned char *ab = NULL;
    51     unsigned long counter = 0;
    52     mp_int p, q, a, h, psub1, test;
    53     mp_err err = MP_OKAY;
    54     SECStatus rv = SECSuccess;
    55     if (!params || primeLen < 0) {
    56 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
    57 	return SECFailure;
    58     }
    59     arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
    60     if (!arena) {
    61 	PORT_SetError(SEC_ERROR_NO_MEMORY);
    62 	return SECFailure;
    63     }
    64     dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams));
    65     if (!dhparams) {
    66 	PORT_SetError(SEC_ERROR_NO_MEMORY);
    67 	PORT_FreeArena(arena, PR_TRUE);
    68 	return SECFailure;
    69     }
    70     dhparams->arena = arena;
    71     MP_DIGITS(&p) = 0;
    72     MP_DIGITS(&q) = 0;
    73     MP_DIGITS(&a) = 0;
    74     MP_DIGITS(&h) = 0;
    75     MP_DIGITS(&psub1) = 0;
    76     MP_DIGITS(&test) = 0;
    77     CHECK_MPI_OK( mp_init(&p) );
    78     CHECK_MPI_OK( mp_init(&q) );
    79     CHECK_MPI_OK( mp_init(&a) );
    80     CHECK_MPI_OK( mp_init(&h) );
    81     CHECK_MPI_OK( mp_init(&psub1) );
    82     CHECK_MPI_OK( mp_init(&test) );
    83     /* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
    84     pb = PORT_Alloc(primeLen);
    85     CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) );
    86     pb[0]          |= 0x80; /* set high-order bit */
    87     pb[primeLen-1] |= 0x01; /* set low-order bit  */
    88     CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) );
    89     CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter) );
    90     /* construct Sophie-Germain prime q = (p-1)/2. */
    91     CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
    92     CHECK_MPI_OK( mp_div_2(&psub1, &q)    );
    93     /* construct a generator from the prime. */
    94     ab = PORT_Alloc(primeLen);
    95     /* generate a candidate number a in p's field */
    96     CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(ab, primeLen) );
    97     CHECK_MPI_OK( mp_read_unsigned_octets(&a, ab, primeLen) );
    98     /* force a < p (note that quot(a/p) <= 1) */
    99     if ( mp_cmp(&a, &p) > 0 )
   100 	CHECK_MPI_OK( mp_sub(&a, &p, &a) );
   101     do {
   102 	/* check that a is in the range [2..p-1] */
   103 	if ( mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) {
   104 	    /* a is outside of the allowed range.  Set a=3 and keep going. */
   105             mp_set(&a, 3);
   106 	}
   107 	/* if a**q mod p != 1 then a is a generator */
   108 	CHECK_MPI_OK( mp_exptmod(&a, &q, &p, &test) );
   109 	if ( mp_cmp_d(&test, 1) != 0 )
   110 	    break;
   111 	/* increment the candidate and try again. */
   112 	CHECK_MPI_OK( mp_add_d(&a, 1, &a) );
   113     } while (PR_TRUE);
   114     MPINT_TO_SECITEM(&p, &dhparams->prime, arena);
   115     MPINT_TO_SECITEM(&a, &dhparams->base, arena);
   116     *params = dhparams;
   117 cleanup:
   118     mp_clear(&p);
   119     mp_clear(&q);
   120     mp_clear(&a);
   121     mp_clear(&h);
   122     mp_clear(&psub1);
   123     mp_clear(&test);
   124     if (pb) PORT_ZFree(pb, primeLen);
   125     if (ab) PORT_ZFree(ab, primeLen);
   126     if (err) {
   127 	MP_TO_SEC_ERROR(err);
   128 	rv = SECFailure;
   129     }
   130     if (rv)
   131 	PORT_FreeArena(arena, PR_TRUE);
   132     return rv;
   133 }
   135 SECStatus 
   136 DH_NewKey(DHParams *params, DHPrivateKey **privKey)
   137 {
   138     PLArenaPool *arena;
   139     DHPrivateKey *key;
   140     mp_int g, xa, p, Ya;
   141     mp_err   err = MP_OKAY;
   142     SECStatus rv = SECSuccess;
   143     if (!params || !privKey) {
   144 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   145 	return SECFailure;
   146     }
   147     arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
   148     if (!arena) {
   149 	PORT_SetError(SEC_ERROR_NO_MEMORY);
   150 	return SECFailure;
   151     }
   152     key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey));
   153     if (!key) {
   154 	PORT_SetError(SEC_ERROR_NO_MEMORY);
   155 	PORT_FreeArena(arena, PR_TRUE);
   156 	return SECFailure;
   157     }
   158     key->arena = arena;
   159     MP_DIGITS(&g)  = 0;
   160     MP_DIGITS(&xa) = 0;
   161     MP_DIGITS(&p)  = 0;
   162     MP_DIGITS(&Ya) = 0;
   163     CHECK_MPI_OK( mp_init(&g)  );
   164     CHECK_MPI_OK( mp_init(&xa) );
   165     CHECK_MPI_OK( mp_init(&p)  );
   166     CHECK_MPI_OK( mp_init(&Ya) );
   167     /* Set private key's p */
   168     CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, &params->prime) );
   169     SECITEM_TO_MPINT(key->prime, &p);
   170     /* Set private key's g */
   171     CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, &params->base) );
   172     SECITEM_TO_MPINT(key->base, &g);
   173     /* Generate private key xa */
   174     SECITEM_AllocItem(arena, &key->privateValue,
   175                       dh_GetSecretKeyLen(params->prime.len));
   176     RNG_GenerateGlobalRandomBytes(key->privateValue.data, 
   177                                   key->privateValue.len);
   178     SECITEM_TO_MPINT( key->privateValue, &xa );
   179     /* xa < p */
   180     CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
   181     /* Compute public key Ya = g ** xa mod p */
   182     CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) );
   183     MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena);
   184     *privKey = key;
   185 cleanup:
   186     mp_clear(&g);
   187     mp_clear(&xa);
   188     mp_clear(&p);
   189     mp_clear(&Ya);
   190     if (err) {
   191 	MP_TO_SEC_ERROR(err);
   192 	rv = SECFailure;
   193     }
   194     if (rv)
   195 	PORT_FreeArena(arena, PR_TRUE);
   196     return rv;
   197 }
   199 SECStatus 
   200 DH_Derive(SECItem *publicValue, 
   201           SECItem *prime, 
   202           SECItem *privateValue, 
   203           SECItem *derivedSecret, 
   204           unsigned int outBytes)
   205 {
   206     mp_int p, Xa, Yb, ZZ, psub1;
   207     mp_err err = MP_OKAY;
   208     int len = 0;
   209     unsigned int nb;
   210     unsigned char *secret = NULL;
   211     if (!publicValue || !prime || !privateValue || !derivedSecret) {
   212 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   213 	return SECFailure;
   214     }
   215     memset(derivedSecret, 0, sizeof *derivedSecret);
   216     MP_DIGITS(&p)  = 0;
   217     MP_DIGITS(&Xa) = 0;
   218     MP_DIGITS(&Yb) = 0;
   219     MP_DIGITS(&ZZ) = 0;
   220     MP_DIGITS(&psub1) = 0;
   221     CHECK_MPI_OK( mp_init(&p)  );
   222     CHECK_MPI_OK( mp_init(&Xa) );
   223     CHECK_MPI_OK( mp_init(&Yb) );
   224     CHECK_MPI_OK( mp_init(&ZZ) );
   225     CHECK_MPI_OK( mp_init(&psub1) );
   226     SECITEM_TO_MPINT(*publicValue,  &Yb);
   227     SECITEM_TO_MPINT(*privateValue, &Xa);
   228     SECITEM_TO_MPINT(*prime,        &p);
   229     CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
   231     /* We assume that the modulus, p, is a safe prime. That is, p = 2q+1 where
   232      * q is also a prime. Thus the orders of the subgroups are factors of 2q:
   233      * namely 1, 2, q and 2q.
   234      *
   235      * We check that the peer's public value isn't zero (which isn't in the
   236      * group), one (subgroup of order one) or p-1 (subgroup of order 2). We
   237      * also check that the public value is less than p, to avoid being fooled
   238      * by values like p+1 or 2*p-1.
   239      *
   240      * Thus we must be operating in the subgroup of size q or 2q. */
   241     if (mp_cmp_d(&Yb, 1) <= 0 ||
   242 	mp_cmp(&Yb, &psub1) >= 0) {
   243 	err = MP_BADARG;
   244 	goto cleanup;
   245     }
   247     /* ZZ = (Yb)**Xa mod p */
   248     CHECK_MPI_OK( mp_exptmod(&Yb, &Xa, &p, &ZZ) );
   249     /* number of bytes in the derived secret */
   250     len = mp_unsigned_octet_size(&ZZ);
   251     if (len <= 0) {
   252         err = MP_BADARG;
   253         goto cleanup;
   254     }
   255     /* allocate a buffer which can hold the entire derived secret. */
   256     secret = PORT_Alloc(len);
   257     /* grab the derived secret */
   258     err = mp_to_unsigned_octets(&ZZ, secret, len);
   259     if (err >= 0) err = MP_OKAY;
   260     /* 
   261     ** if outBytes is 0 take all of the bytes from the derived secret.
   262     ** if outBytes is not 0 take exactly outBytes from the derived secret, zero
   263     ** pad at the beginning if necessary, and truncate beginning bytes 
   264     ** if necessary.
   265     */
   266     if (outBytes > 0)
   267 	nb = outBytes;
   268     else
   269 	nb = len;
   270     SECITEM_AllocItem(NULL, derivedSecret, nb);
   271     if (len < nb) {
   272 	unsigned int offset = nb - len;
   273 	memset(derivedSecret->data, 0, offset);
   274 	memcpy(derivedSecret->data + offset, secret, len);
   275     } else {
   276 	memcpy(derivedSecret->data, secret + len - nb, nb);
   277     }
   278 cleanup:
   279     mp_clear(&p);
   280     mp_clear(&Xa);
   281     mp_clear(&Yb);
   282     mp_clear(&ZZ);
   283     mp_clear(&psub1);
   284     if (secret) {
   285 	/* free the buffer allocated for the full secret. */
   286 	PORT_ZFree(secret, len);
   287     }
   288     if (err) {
   289 	MP_TO_SEC_ERROR(err);
   290 	if (derivedSecret->data) 
   291 	    PORT_ZFree(derivedSecret->data, derivedSecret->len);
   292 	return SECFailure;
   293     }
   294     return SECSuccess;
   295 }
   297 SECStatus 
   298 KEA_Derive(SECItem *prime, 
   299            SECItem *public1, 
   300            SECItem *public2, 
   301            SECItem *private1, 
   302            SECItem *private2,
   303            SECItem *derivedSecret)
   304 {
   305     mp_int p, Y, R, r, x, t, u, w;
   306     mp_err err;
   307     unsigned char *secret = NULL;
   308     unsigned int len = 0, offset;
   309     if (!prime || !public1 || !public2 || !private1 || !private2 ||
   310         !derivedSecret) {
   311 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   312 	return SECFailure;
   313     }
   314     memset(derivedSecret, 0, sizeof *derivedSecret);
   315     MP_DIGITS(&p) = 0;
   316     MP_DIGITS(&Y) = 0;
   317     MP_DIGITS(&R) = 0;
   318     MP_DIGITS(&r) = 0;
   319     MP_DIGITS(&x) = 0;
   320     MP_DIGITS(&t) = 0;
   321     MP_DIGITS(&u) = 0;
   322     MP_DIGITS(&w) = 0;
   323     CHECK_MPI_OK( mp_init(&p) );
   324     CHECK_MPI_OK( mp_init(&Y) );
   325     CHECK_MPI_OK( mp_init(&R) );
   326     CHECK_MPI_OK( mp_init(&r) );
   327     CHECK_MPI_OK( mp_init(&x) );
   328     CHECK_MPI_OK( mp_init(&t) );
   329     CHECK_MPI_OK( mp_init(&u) );
   330     CHECK_MPI_OK( mp_init(&w) );
   331     SECITEM_TO_MPINT(*prime,    &p);
   332     SECITEM_TO_MPINT(*public1,  &Y);
   333     SECITEM_TO_MPINT(*public2,  &R);
   334     SECITEM_TO_MPINT(*private1, &r);
   335     SECITEM_TO_MPINT(*private2, &x);
   336     /* t = DH(Y, r, p) = Y ** r mod p */
   337     CHECK_MPI_OK( mp_exptmod(&Y, &r, &p, &t) );
   338     /* u = DH(R, x, p) = R ** x mod p */
   339     CHECK_MPI_OK( mp_exptmod(&R, &x, &p, &u) );
   340     /* w = (t + u) mod p */
   341     CHECK_MPI_OK( mp_addmod(&t, &u, &p, &w) );
   342     /* allocate a buffer for the full derived secret */
   343     len = mp_unsigned_octet_size(&w);
   344     secret = PORT_Alloc(len);
   345     /* grab the secret */
   346     err = mp_to_unsigned_octets(&w, secret, len);
   347     if (err > 0) err = MP_OKAY;
   348     /* allocate output buffer */
   349     SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN);
   350     memset(derivedSecret->data, 0, derivedSecret->len);
   351     /* copy in the 128 lsb of the secret */
   352     if (len >= KEA_DERIVED_SECRET_LEN) {
   353 	memcpy(derivedSecret->data, secret + (len - KEA_DERIVED_SECRET_LEN),
   354 	       KEA_DERIVED_SECRET_LEN);
   355     } else {
   356 	offset = KEA_DERIVED_SECRET_LEN - len;
   357 	memcpy(derivedSecret->data + offset, secret, len);
   358     }
   359 cleanup:
   360     mp_clear(&p);
   361     mp_clear(&Y);
   362     mp_clear(&R);
   363     mp_clear(&r);
   364     mp_clear(&x);
   365     mp_clear(&t);
   366     mp_clear(&u);
   367     mp_clear(&w);
   368     if (secret)
   369 	PORT_ZFree(secret, len);
   370     if (err) {
   371 	MP_TO_SEC_ERROR(err);
   372 	return SECFailure;
   373     }
   374     return SECSuccess;
   375 }
   377 PRBool 
   378 KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
   379 {
   380     mp_int p, q, y, r;
   381     mp_err err;
   382     int cmp = 1;  /* default is false */
   383     if (!Y || !prime || !subPrime) {
   384 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   385 	return SECFailure;
   386     }
   387     MP_DIGITS(&p) = 0;
   388     MP_DIGITS(&q) = 0;
   389     MP_DIGITS(&y) = 0;
   390     MP_DIGITS(&r) = 0;
   391     CHECK_MPI_OK( mp_init(&p) );
   392     CHECK_MPI_OK( mp_init(&q) );
   393     CHECK_MPI_OK( mp_init(&y) );
   394     CHECK_MPI_OK( mp_init(&r) );
   395     SECITEM_TO_MPINT(*prime,    &p);
   396     SECITEM_TO_MPINT(*subPrime, &q);
   397     SECITEM_TO_MPINT(*Y,        &y);
   398     /* compute r = y**q mod p */
   399     CHECK_MPI_OK( mp_exptmod(&y, &q, &p, &r) );
   400     /* compare to 1 */
   401     cmp = mp_cmp_d(&r, 1);
   402 cleanup:
   403     mp_clear(&p);
   404     mp_clear(&q);
   405     mp_clear(&y);
   406     mp_clear(&r);
   407     if (err) {
   408 	MP_TO_SEC_ERROR(err);
   409 	return PR_FALSE;
   410     }
   411     return (cmp == 0) ? PR_TRUE : PR_FALSE;
   412 }

mercurial