security/nss/lib/freebl/ecl/ecl.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 "mpi.h"
     6 #include "mplogic.h"
     7 #include "ecl.h"
     8 #include "ecl-priv.h"
     9 #include "ec2.h"
    10 #include "ecp.h"
    11 #include <stdlib.h>
    12 #include <string.h>
    14 /* Allocate memory for a new ECGroup object. */
    15 ECGroup *
    16 ECGroup_new()
    17 {
    18 	mp_err res = MP_OKAY;
    19 	ECGroup *group;
    20 	group = (ECGroup *) malloc(sizeof(ECGroup));
    21 	if (group == NULL)
    22 		return NULL;
    23 	group->constructed = MP_YES;
    24         group->meth = NULL;
    25 	group->text = NULL;
    26 	MP_DIGITS(&group->curvea) = 0;
    27 	MP_DIGITS(&group->curveb) = 0;
    28 	MP_DIGITS(&group->genx) = 0;
    29 	MP_DIGITS(&group->geny) = 0;
    30 	MP_DIGITS(&group->order) = 0;
    31 	group->base_point_mul = NULL;
    32 	group->points_mul = NULL;
    33 	group->validate_point = NULL;
    34 	group->extra1 = NULL;
    35 	group->extra2 = NULL;
    36 	group->extra_free = NULL;
    37 	MP_CHECKOK(mp_init(&group->curvea));
    38 	MP_CHECKOK(mp_init(&group->curveb));
    39 	MP_CHECKOK(mp_init(&group->genx));
    40 	MP_CHECKOK(mp_init(&group->geny));
    41 	MP_CHECKOK(mp_init(&group->order));
    43   CLEANUP:
    44 	if (res != MP_OKAY) {
    45 		ECGroup_free(group);
    46 		return NULL;
    47 	}
    48 	return group;
    49 }
    51 /* Construct a generic ECGroup for elliptic curves over prime fields. */
    52 ECGroup *
    53 ECGroup_consGFp(const mp_int *irr, const mp_int *curvea,
    54 				const mp_int *curveb, const mp_int *genx,
    55 				const mp_int *geny, const mp_int *order, int cofactor)
    56 {
    57 	mp_err res = MP_OKAY;
    58 	ECGroup *group = NULL;
    60 	group = ECGroup_new();
    61 	if (group == NULL)
    62 		return NULL;
    64 	group->meth = GFMethod_consGFp(irr);
    65 	if (group->meth == NULL) {
    66 		res = MP_MEM;
    67 		goto CLEANUP;
    68 	}
    69 	MP_CHECKOK(mp_copy(curvea, &group->curvea));
    70 	MP_CHECKOK(mp_copy(curveb, &group->curveb));
    71 	MP_CHECKOK(mp_copy(genx, &group->genx));
    72 	MP_CHECKOK(mp_copy(geny, &group->geny));
    73 	MP_CHECKOK(mp_copy(order, &group->order));
    74 	group->cofactor = cofactor;
    75 	group->point_add = &ec_GFp_pt_add_aff;
    76 	group->point_sub = &ec_GFp_pt_sub_aff;
    77 	group->point_dbl = &ec_GFp_pt_dbl_aff;
    78 	group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
    79 	group->base_point_mul = NULL;
    80 	group->points_mul = &ec_GFp_pts_mul_jac;
    81 	group->validate_point = &ec_GFp_validate_point;
    83   CLEANUP:
    84 	if (res != MP_OKAY) {
    85 		ECGroup_free(group);
    86 		return NULL;
    87 	}
    88 	return group;
    89 }
    91 /* Construct a generic ECGroup for elliptic curves over prime fields with
    92  * field arithmetic implemented in Montgomery coordinates. */
    93 ECGroup *
    94 ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea,
    95 					 const mp_int *curveb, const mp_int *genx,
    96 					 const mp_int *geny, const mp_int *order, int cofactor)
    97 {
    98 	mp_err res = MP_OKAY;
    99 	ECGroup *group = NULL;
   101 	group = ECGroup_new();
   102 	if (group == NULL)
   103 		return NULL;
   105 	group->meth = GFMethod_consGFp_mont(irr);
   106 	if (group->meth == NULL) {
   107 		res = MP_MEM;
   108 		goto CLEANUP;
   109 	}
   110 	MP_CHECKOK(group->meth->
   111 			   field_enc(curvea, &group->curvea, group->meth));
   112 	MP_CHECKOK(group->meth->
   113 			   field_enc(curveb, &group->curveb, group->meth));
   114 	MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth));
   115 	MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth));
   116 	MP_CHECKOK(mp_copy(order, &group->order));
   117 	group->cofactor = cofactor;
   118 	group->point_add = &ec_GFp_pt_add_aff;
   119 	group->point_sub = &ec_GFp_pt_sub_aff;
   120 	group->point_dbl = &ec_GFp_pt_dbl_aff;
   121 	group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
   122 	group->base_point_mul = NULL;
   123 	group->points_mul = &ec_GFp_pts_mul_jac;
   124 	group->validate_point = &ec_GFp_validate_point;
   126   CLEANUP:
   127 	if (res != MP_OKAY) {
   128 		ECGroup_free(group);
   129 		return NULL;
   130 	}
   131 	return group;
   132 }
   134 #ifdef NSS_ECC_MORE_THAN_SUITE_B
   135 /* Construct a generic ECGroup for elliptic curves over binary polynomial
   136  * fields. */
   137 ECGroup *
   138 ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5],
   139 				 const mp_int *curvea, const mp_int *curveb,
   140 				 const mp_int *genx, const mp_int *geny,
   141 				 const mp_int *order, int cofactor)
   142 {
   143 	mp_err res = MP_OKAY;
   144 	ECGroup *group = NULL;
   146 	group = ECGroup_new();
   147 	if (group == NULL)
   148 		return NULL;
   150 	group->meth = GFMethod_consGF2m(irr, irr_arr);
   151 	if (group->meth == NULL) {
   152 		res = MP_MEM;
   153 		goto CLEANUP;
   154 	}
   155 	MP_CHECKOK(mp_copy(curvea, &group->curvea));
   156 	MP_CHECKOK(mp_copy(curveb, &group->curveb));
   157 	MP_CHECKOK(mp_copy(genx, &group->genx));
   158 	MP_CHECKOK(mp_copy(geny, &group->geny));
   159 	MP_CHECKOK(mp_copy(order, &group->order));
   160 	group->cofactor = cofactor;
   161 	group->point_add = &ec_GF2m_pt_add_aff;
   162 	group->point_sub = &ec_GF2m_pt_sub_aff;
   163 	group->point_dbl = &ec_GF2m_pt_dbl_aff;
   164 	group->point_mul = &ec_GF2m_pt_mul_mont;
   165 	group->base_point_mul = NULL;
   166 	group->points_mul = &ec_pts_mul_basic;
   167 	group->validate_point = &ec_GF2m_validate_point;
   169   CLEANUP:
   170 	if (res != MP_OKAY) {
   171 		ECGroup_free(group);
   172 		return NULL;
   173 	}
   174 	return group;
   175 }
   176 #endif
   178 /* Construct ECGroup from hex parameters and name, if any. Called by
   179  * ECGroup_fromHex and ECGroup_fromName. */
   180 ECGroup *
   181 ecgroup_fromNameAndHex(const ECCurveName name,
   182 					   const ECCurveParams * params)
   183 {
   184 	mp_int irr, curvea, curveb, genx, geny, order;
   185 	int bits;
   186 	ECGroup *group = NULL;
   187 	mp_err res = MP_OKAY;
   189 	/* initialize values */
   190 	MP_DIGITS(&irr) = 0;
   191 	MP_DIGITS(&curvea) = 0;
   192 	MP_DIGITS(&curveb) = 0;
   193 	MP_DIGITS(&genx) = 0;
   194 	MP_DIGITS(&geny) = 0;
   195 	MP_DIGITS(&order) = 0;
   196 	MP_CHECKOK(mp_init(&irr));
   197 	MP_CHECKOK(mp_init(&curvea));
   198 	MP_CHECKOK(mp_init(&curveb));
   199 	MP_CHECKOK(mp_init(&genx));
   200 	MP_CHECKOK(mp_init(&geny));
   201 	MP_CHECKOK(mp_init(&order));
   202 	MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
   203 	MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
   204 	MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
   205 	MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
   206 	MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
   207 	MP_CHECKOK(mp_read_radix(&order, params->order, 16));
   209 	/* determine number of bits */
   210 	bits = mpl_significant_bits(&irr) - 1;
   211 	if (bits < MP_OKAY) {
   212 		res = bits;
   213 		goto CLEANUP;
   214 	}
   216 	/* determine which optimizations (if any) to use */
   217 	if (params->field == ECField_GFp) {
   218 	    switch (name) {
   219 #ifdef NSS_ECC_MORE_THAN_SUITE_B
   220 #ifdef ECL_USE_FP
   221 		case ECCurve_SECG_PRIME_160R1:
   222 			group =
   223 				ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
   224 								&order, params->cofactor);
   225 			if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   226 			MP_CHECKOK(ec_group_set_secp160r1_fp(group));
   227 			break;
   228 #endif
   229 		case ECCurve_SECG_PRIME_192R1:
   230 #ifdef ECL_USE_FP
   231 			group =
   232 				ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
   233 								&order, params->cofactor);
   234 			if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   235 			MP_CHECKOK(ec_group_set_nistp192_fp(group));
   236 #else
   237 			group =
   238 				ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
   239 								&order, params->cofactor);
   240 			if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   241 			MP_CHECKOK(ec_group_set_gfp192(group, name));
   242 #endif
   243 			break;
   244 		case ECCurve_SECG_PRIME_224R1:
   245 #ifdef ECL_USE_FP
   246 			group =
   247 				ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
   248 								&order, params->cofactor);
   249 			if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   250 			MP_CHECKOK(ec_group_set_nistp224_fp(group));
   251 #else
   252 			group =
   253 				ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
   254 								&order, params->cofactor);
   255 			if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   256 			MP_CHECKOK(ec_group_set_gfp224(group, name));
   257 #endif
   258 			break;
   259 #endif /* NSS_ECC_MORE_THAN_SUITE_B */
   260 		case ECCurve_SECG_PRIME_256R1:
   261 			group =
   262 				ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
   263 								&order, params->cofactor);
   264 			if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   265 			MP_CHECKOK(ec_group_set_gfp256(group, name));
   266 			MP_CHECKOK(ec_group_set_gfp256_32(group, name));
   267 			break;
   268 		case ECCurve_SECG_PRIME_521R1:
   269 			group =
   270 				ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
   271 								&order, params->cofactor);
   272 			if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   273 			MP_CHECKOK(ec_group_set_gfp521(group, name));
   274 			break;
   275 		default:
   276 			/* use generic arithmetic */
   277 			group =
   278 				ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
   279 									 &order, params->cofactor);
   280 			if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   281 		}
   282 #ifdef NSS_ECC_MORE_THAN_SUITE_B
   283 	} else if (params->field == ECField_GF2m) {
   284 		group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor);
   285 		if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
   286 		if ((name == ECCurve_NIST_K163) ||
   287 		    (name == ECCurve_NIST_B163) ||
   288 		    (name == ECCurve_SECG_CHAR2_163R1)) {
   289 			MP_CHECKOK(ec_group_set_gf2m163(group, name));
   290 		} else if ((name == ECCurve_SECG_CHAR2_193R1) ||
   291 		           (name == ECCurve_SECG_CHAR2_193R2)) {
   292 			MP_CHECKOK(ec_group_set_gf2m193(group, name));
   293 		} else if ((name == ECCurve_NIST_K233) ||
   294 		           (name == ECCurve_NIST_B233)) {
   295 			MP_CHECKOK(ec_group_set_gf2m233(group, name));
   296 		}
   297 #endif
   298 	} else {
   299 		res = MP_UNDEF;
   300 		goto CLEANUP;
   301 	}
   303 	/* set name, if any */
   304 	if ((group != NULL) && (params->text != NULL)) {
   305 		group->text = strdup(params->text);
   306 		if (group->text == NULL) {
   307 			res = MP_MEM;
   308 		}
   309 	}
   311   CLEANUP:
   312 	mp_clear(&irr);
   313 	mp_clear(&curvea);
   314 	mp_clear(&curveb);
   315 	mp_clear(&genx);
   316 	mp_clear(&geny);
   317 	mp_clear(&order);
   318 	if (res != MP_OKAY) {
   319 		ECGroup_free(group);
   320 		return NULL;
   321 	}
   322 	return group;
   323 }
   325 /* Construct ECGroup from hexadecimal representations of parameters. */
   326 ECGroup *
   327 ECGroup_fromHex(const ECCurveParams * params)
   328 {
   329 	return ecgroup_fromNameAndHex(ECCurve_noName, params);
   330 }
   332 /* Construct ECGroup from named parameters. */
   333 ECGroup *
   334 ECGroup_fromName(const ECCurveName name)
   335 {
   336 	ECGroup *group = NULL;
   337 	ECCurveParams *params = NULL;
   338 	mp_err res = MP_OKAY;
   340 	params = EC_GetNamedCurveParams(name);
   341 	if (params == NULL) {
   342 		res = MP_UNDEF;
   343 		goto CLEANUP;
   344 	}
   346 	/* construct actual group */
   347 	group = ecgroup_fromNameAndHex(name, params);
   348 	if (group == NULL) {
   349 		res = MP_UNDEF;
   350 		goto CLEANUP;
   351 	}
   353   CLEANUP:
   354 	EC_FreeCurveParams(params);
   355 	if (res != MP_OKAY) {
   356 		ECGroup_free(group);
   357 		return NULL;
   358 	}
   359 	return group;
   360 }
   362 /* Validates an EC public key as described in Section 5.2.2 of X9.62. */
   363 mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const 
   364 					mp_int *py)
   365 {
   366     /* 1: Verify that publicValue is not the point at infinity */
   367     /* 2: Verify that the coordinates of publicValue are elements 
   368      *    of the field.
   369      */
   370     /* 3: Verify that publicValue is on the curve. */
   371     /* 4: Verify that the order of the curve times the publicValue
   372      *    is the point at infinity.
   373      */
   374 	return group->validate_point(px, py, group);
   375 }
   377 /* Free the memory allocated (if any) to an ECGroup object. */
   378 void
   379 ECGroup_free(ECGroup *group)
   380 {
   381 	if (group == NULL)
   382 		return;
   383 	GFMethod_free(group->meth);
   384 	if (group->constructed == MP_NO)
   385 		return;
   386 	mp_clear(&group->curvea);
   387 	mp_clear(&group->curveb);
   388 	mp_clear(&group->genx);
   389 	mp_clear(&group->geny);
   390 	mp_clear(&group->order);
   391 	if (group->text != NULL)
   392 		free(group->text);
   393 	if (group->extra_free != NULL)
   394 		group->extra_free(group);
   395 	free(group);
   396 }

mercurial