security/nss/lib/freebl/ecl/ecp_aff.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 #include "ecp.h"
     6 #include "mplogic.h"
     7 #include <stdlib.h>
     9 /* Checks if point P(px, py) is at infinity.  Uses affine coordinates. */
    10 mp_err
    11 ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py)
    12 {
    14 	if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
    15 		return MP_YES;
    16 	} else {
    17 		return MP_NO;
    18 	}
    20 }
    22 /* Sets P(px, py) to be the point at infinity.  Uses affine coordinates. */
    23 mp_err
    24 ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py)
    25 {
    26 	mp_zero(px);
    27 	mp_zero(py);
    28 	return MP_OKAY;
    29 }
    31 /* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P, 
    32  * Q, and R can all be identical. Uses affine coordinates. Assumes input
    33  * is already field-encoded using field_enc, and returns output that is
    34  * still field-encoded. */
    35 mp_err
    36 ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
    37 				  const mp_int *qy, mp_int *rx, mp_int *ry,
    38 				  const ECGroup *group)
    39 {
    40 	mp_err res = MP_OKAY;
    41 	mp_int lambda, temp, tempx, tempy;
    43 	MP_DIGITS(&lambda) = 0;
    44 	MP_DIGITS(&temp) = 0;
    45 	MP_DIGITS(&tempx) = 0;
    46 	MP_DIGITS(&tempy) = 0;
    47 	MP_CHECKOK(mp_init(&lambda));
    48 	MP_CHECKOK(mp_init(&temp));
    49 	MP_CHECKOK(mp_init(&tempx));
    50 	MP_CHECKOK(mp_init(&tempy));
    51 	/* if P = inf, then R = Q */
    52 	if (ec_GFp_pt_is_inf_aff(px, py) == 0) {
    53 		MP_CHECKOK(mp_copy(qx, rx));
    54 		MP_CHECKOK(mp_copy(qy, ry));
    55 		res = MP_OKAY;
    56 		goto CLEANUP;
    57 	}
    58 	/* if Q = inf, then R = P */
    59 	if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) {
    60 		MP_CHECKOK(mp_copy(px, rx));
    61 		MP_CHECKOK(mp_copy(py, ry));
    62 		res = MP_OKAY;
    63 		goto CLEANUP;
    64 	}
    65 	/* if px != qx, then lambda = (py-qy) / (px-qx) */
    66 	if (mp_cmp(px, qx) != 0) {
    67 		MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth));
    68 		MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth));
    69 		MP_CHECKOK(group->meth->
    70 				   field_div(&tempy, &tempx, &lambda, group->meth));
    71 	} else {
    72 		/* if py != qy or qy = 0, then R = inf */
    73 		if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
    74 			mp_zero(rx);
    75 			mp_zero(ry);
    76 			res = MP_OKAY;
    77 			goto CLEANUP;
    78 		}
    79 		/* lambda = (3qx^2+a) / (2qy) */
    80 		MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth));
    81 		MP_CHECKOK(mp_set_int(&temp, 3));
    82 		if (group->meth->field_enc) {
    83 			MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
    84 		}
    85 		MP_CHECKOK(group->meth->
    86 				   field_mul(&tempx, &temp, &tempx, group->meth));
    87 		MP_CHECKOK(group->meth->
    88 				   field_add(&tempx, &group->curvea, &tempx, group->meth));
    89 		MP_CHECKOK(mp_set_int(&temp, 2));
    90 		if (group->meth->field_enc) {
    91 			MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
    92 		}
    93 		MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth));
    94 		MP_CHECKOK(group->meth->
    95 				   field_div(&tempx, &tempy, &lambda, group->meth));
    96 	}
    97 	/* rx = lambda^2 - px - qx */
    98 	MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
    99 	MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth));
   100 	MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth));
   101 	/* ry = (x1-x2) * lambda - y1 */
   102 	MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth));
   103 	MP_CHECKOK(group->meth->
   104 			   field_mul(&tempy, &lambda, &tempy, group->meth));
   105 	MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth));
   106 	MP_CHECKOK(mp_copy(&tempx, rx));
   107 	MP_CHECKOK(mp_copy(&tempy, ry));
   109   CLEANUP:
   110 	mp_clear(&lambda);
   111 	mp_clear(&temp);
   112 	mp_clear(&tempx);
   113 	mp_clear(&tempy);
   114 	return res;
   115 }
   117 /* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
   118  * identical. Uses affine coordinates. Assumes input is already
   119  * field-encoded using field_enc, and returns output that is still
   120  * field-encoded. */
   121 mp_err
   122 ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
   123 				  const mp_int *qy, mp_int *rx, mp_int *ry,
   124 				  const ECGroup *group)
   125 {
   126 	mp_err res = MP_OKAY;
   127 	mp_int nqy;
   129 	MP_DIGITS(&nqy) = 0;
   130 	MP_CHECKOK(mp_init(&nqy));
   131 	/* nqy = -qy */
   132 	MP_CHECKOK(group->meth->field_neg(qy, &nqy, group->meth));
   133 	res = group->point_add(px, py, qx, &nqy, rx, ry, group);
   134   CLEANUP:
   135 	mp_clear(&nqy);
   136 	return res;
   137 }
   139 /* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
   140  * affine coordinates. Assumes input is already field-encoded using
   141  * field_enc, and returns output that is still field-encoded. */
   142 mp_err
   143 ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
   144 				  mp_int *ry, const ECGroup *group)
   145 {
   146 	return ec_GFp_pt_add_aff(px, py, px, py, rx, ry, group);
   147 }
   149 /* by default, this routine is unused and thus doesn't need to be compiled */
   150 #ifdef ECL_ENABLE_GFP_PT_MUL_AFF
   151 /* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and 
   152  * R can be identical. Uses affine coordinates. Assumes input is already
   153  * field-encoded using field_enc, and returns output that is still
   154  * field-encoded. */
   155 mp_err
   156 ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
   157 				  mp_int *rx, mp_int *ry, const ECGroup *group)
   158 {
   159 	mp_err res = MP_OKAY;
   160 	mp_int k, k3, qx, qy, sx, sy;
   161 	int b1, b3, i, l;
   163 	MP_DIGITS(&k) = 0;
   164 	MP_DIGITS(&k3) = 0;
   165 	MP_DIGITS(&qx) = 0;
   166 	MP_DIGITS(&qy) = 0;
   167 	MP_DIGITS(&sx) = 0;
   168 	MP_DIGITS(&sy) = 0;
   169 	MP_CHECKOK(mp_init(&k));
   170 	MP_CHECKOK(mp_init(&k3));
   171 	MP_CHECKOK(mp_init(&qx));
   172 	MP_CHECKOK(mp_init(&qy));
   173 	MP_CHECKOK(mp_init(&sx));
   174 	MP_CHECKOK(mp_init(&sy));
   176 	/* if n = 0 then r = inf */
   177 	if (mp_cmp_z(n) == 0) {
   178 		mp_zero(rx);
   179 		mp_zero(ry);
   180 		res = MP_OKAY;
   181 		goto CLEANUP;
   182 	}
   183 	/* Q = P, k = n */
   184 	MP_CHECKOK(mp_copy(px, &qx));
   185 	MP_CHECKOK(mp_copy(py, &qy));
   186 	MP_CHECKOK(mp_copy(n, &k));
   187 	/* if n < 0 then Q = -Q, k = -k */
   188 	if (mp_cmp_z(n) < 0) {
   189 		MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth));
   190 		MP_CHECKOK(mp_neg(&k, &k));
   191 	}
   192 #ifdef ECL_DEBUG				/* basic double and add method */
   193 	l = mpl_significant_bits(&k) - 1;
   194 	MP_CHECKOK(mp_copy(&qx, &sx));
   195 	MP_CHECKOK(mp_copy(&qy, &sy));
   196 	for (i = l - 1; i >= 0; i--) {
   197 		/* S = 2S */
   198 		MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
   199 		/* if k_i = 1, then S = S + Q */
   200 		if (mpl_get_bit(&k, i) != 0) {
   201 			MP_CHECKOK(group->
   202 					   point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
   203 		}
   204 	}
   205 #else							/* double and add/subtract method from
   206 								 * standard */
   207 	/* k3 = 3 * k */
   208 	MP_CHECKOK(mp_set_int(&k3, 3));
   209 	MP_CHECKOK(mp_mul(&k, &k3, &k3));
   210 	/* S = Q */
   211 	MP_CHECKOK(mp_copy(&qx, &sx));
   212 	MP_CHECKOK(mp_copy(&qy, &sy));
   213 	/* l = index of high order bit in binary representation of 3*k */
   214 	l = mpl_significant_bits(&k3) - 1;
   215 	/* for i = l-1 downto 1 */
   216 	for (i = l - 1; i >= 1; i--) {
   217 		/* S = 2S */
   218 		MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
   219 		b3 = MP_GET_BIT(&k3, i);
   220 		b1 = MP_GET_BIT(&k, i);
   221 		/* if k3_i = 1 and k_i = 0, then S = S + Q */
   222 		if ((b3 == 1) && (b1 == 0)) {
   223 			MP_CHECKOK(group->
   224 					   point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
   225 			/* if k3_i = 0 and k_i = 1, then S = S - Q */
   226 		} else if ((b3 == 0) && (b1 == 1)) {
   227 			MP_CHECKOK(group->
   228 					   point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
   229 		}
   230 	}
   231 #endif
   232 	/* output S */
   233 	MP_CHECKOK(mp_copy(&sx, rx));
   234 	MP_CHECKOK(mp_copy(&sy, ry));
   236   CLEANUP:
   237 	mp_clear(&k);
   238 	mp_clear(&k3);
   239 	mp_clear(&qx);
   240 	mp_clear(&qy);
   241 	mp_clear(&sx);
   242 	mp_clear(&sy);
   243 	return res;
   244 }
   245 #endif
   247 /* Validates a point on a GFp curve. */
   248 mp_err 
   249 ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
   250 {
   251 	mp_err res = MP_NO;
   252 	mp_int accl, accr, tmp, pxt, pyt;
   254 	MP_DIGITS(&accl) = 0;
   255 	MP_DIGITS(&accr) = 0;
   256 	MP_DIGITS(&tmp) = 0;
   257 	MP_DIGITS(&pxt) = 0;
   258 	MP_DIGITS(&pyt) = 0;
   259 	MP_CHECKOK(mp_init(&accl));
   260 	MP_CHECKOK(mp_init(&accr));
   261 	MP_CHECKOK(mp_init(&tmp));
   262 	MP_CHECKOK(mp_init(&pxt));
   263 	MP_CHECKOK(mp_init(&pyt));
   265     /* 1: Verify that publicValue is not the point at infinity */
   266 	if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
   267 		res = MP_NO;
   268 		goto CLEANUP;
   269 	}
   270     /* 2: Verify that the coordinates of publicValue are elements 
   271      *    of the field.
   272      */
   273 	if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) || 
   274 		(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
   275 		res = MP_NO;
   276 		goto CLEANUP;
   277 	}
   278     /* 3: Verify that publicValue is on the curve. */
   279 	if (group->meth->field_enc) {
   280 		group->meth->field_enc(px, &pxt, group->meth);
   281 		group->meth->field_enc(py, &pyt, group->meth);
   282 	} else {
   283 		mp_copy(px, &pxt);
   284 		mp_copy(py, &pyt);
   285 	}
   286 	/* left-hand side: y^2  */
   287 	MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
   288 	/* right-hand side: x^3 + a*x + b = (x^2 + a)*x + b by Horner's rule */
   289 	MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
   290 	MP_CHECKOK( group->meth->field_add(&tmp, &group->curvea, &tmp, group->meth) );
   291 	MP_CHECKOK( group->meth->field_mul(&tmp, &pxt, &accr, group->meth) );
   292 	MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
   293 	/* check LHS - RHS == 0 */
   294 	MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) );
   295 	if (mp_cmp_z(&accr) != 0) {
   296 		res = MP_NO;
   297 		goto CLEANUP;
   298 	}
   299     /* 4: Verify that the order of the curve times the publicValue
   300      *    is the point at infinity.
   301      */
   302 	MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
   303 	if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
   304 		res = MP_NO;
   305 		goto CLEANUP;
   306 	}
   308 	res = MP_YES;
   310 CLEANUP:
   311 	mp_clear(&accl);
   312 	mp_clear(&accr);
   313 	mp_clear(&tmp);
   314 	mp_clear(&pxt);
   315 	mp_clear(&pyt);
   316 	return res;
   317 }

mercurial