Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ec.c
00001 /** 00002 * @file ec.c 00003 * @brief ECC (Elliptic Curve Cryptography) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneCrypto Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include <stdlib.h> 00034 #include "crypto.h" 00035 #include "ec.h" 00036 #include "debug.h" 00037 00038 //Check crypto library configuration 00039 #if (EC_SUPPORT == ENABLED) 00040 00041 //EC Public Key OID (1.2.840.10045.2.1) 00042 const uint8_t EC_PUBLIC_KEY_OID[7] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01}; 00043 00044 00045 /** 00046 * @brief Initialize EC domain parameters 00047 * @param[in] params Pointer to the EC domain parameters to be initialized 00048 **/ 00049 00050 void ecInitDomainParameters(EcDomainParameters *params) 00051 { 00052 //Initialize structure 00053 params->type = EC_CURVE_TYPE_NONE; 00054 params->mod = NULL; 00055 00056 //Initialize EC domain parameters 00057 mpiInit(¶ms->p); 00058 mpiInit(¶ms->a); 00059 mpiInit(¶ms->b); 00060 ecInit(¶ms->g); 00061 mpiInit(¶ms->q); 00062 } 00063 00064 00065 /** 00066 * @brief Release EC domain parameters 00067 * @param[in] params Pointer to the EC domain parameters to free 00068 **/ 00069 00070 void ecFreeDomainParameters(EcDomainParameters *params) 00071 { 00072 //Release previously allocated resources 00073 mpiFree(¶ms->p); 00074 mpiFree(¶ms->a); 00075 mpiFree(¶ms->b); 00076 ecFree(¶ms->g); 00077 mpiFree(¶ms->q); 00078 } 00079 00080 00081 /** 00082 * @brief Load EC domain parameters 00083 * @param[out] params Pointer to the structure to be initialized 00084 * @param[in] curveInfo Elliptic curve parameters 00085 * @return Error code 00086 **/ 00087 00088 error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo) 00089 { 00090 error_t error; 00091 00092 //Debug message 00093 TRACE_DEBUG("Loading %s EC domain parameters...\r\n", curveInfo->name); 00094 00095 //Curve type 00096 params->type = curveInfo->type; 00097 00098 //Import prime modulus 00099 MPI_CHECK(mpiReadRaw(¶ms->p, curveInfo->p, curveInfo->pLen)); 00100 //Import parameter a 00101 MPI_CHECK(mpiReadRaw(¶ms->a, curveInfo->a, curveInfo->aLen)); 00102 //Import parameter b 00103 MPI_CHECK(mpiReadRaw(¶ms->b, curveInfo->b, curveInfo->bLen)); 00104 //Import the x-coordinate of the base point G 00105 MPI_CHECK(mpiReadRaw(¶ms->g.x, curveInfo->gx, curveInfo->gxLen)); 00106 //Import the y-coordinate of the base point G 00107 MPI_CHECK(mpiReadRaw(¶ms->g.y, curveInfo->gy, curveInfo->gyLen)); 00108 //Import base point order q 00109 MPI_CHECK(mpiReadRaw(¶ms->q, curveInfo->q, curveInfo->qLen)); 00110 00111 //Normalize base point G 00112 MPI_CHECK(mpiSetValue(¶ms->g.z, 1)); 00113 00114 //Fast modular reduction 00115 params->mod = curveInfo->mod; 00116 00117 //Debug message 00118 TRACE_DEBUG(" p:\r\n"); 00119 TRACE_DEBUG_MPI(" ", ¶ms->p); 00120 TRACE_DEBUG(" a:\r\n"); 00121 TRACE_DEBUG_MPI(" ", ¶ms->a); 00122 TRACE_DEBUG(" b:\r\n"); 00123 TRACE_DEBUG_MPI(" ", ¶ms->b); 00124 TRACE_DEBUG(" Gx:\r\n"); 00125 TRACE_DEBUG_MPI(" ", ¶ms->g.x); 00126 TRACE_DEBUG(" Gy:\r\n"); 00127 TRACE_DEBUG_MPI(" ", ¶ms->g.y); 00128 TRACE_DEBUG(" q:\r\n"); 00129 TRACE_DEBUG_MPI(" ", ¶ms->q); 00130 00131 end: 00132 //Return status code 00133 return error; 00134 } 00135 00136 00137 /** 00138 * @brief Initialize elliptic curve point 00139 * @param[in,out] r Pointer to the EC point to be initialized 00140 **/ 00141 00142 void ecInit(EcPoint *r) 00143 { 00144 //Initialize structure 00145 mpiInit(&r->x); 00146 mpiInit(&r->y); 00147 mpiInit(&r->z); 00148 } 00149 00150 00151 /** 00152 * @brief Release an elliptic curve point 00153 * @param[in,out] r Pointer to the EC point to initialize to free 00154 **/ 00155 00156 void ecFree(EcPoint *r) 00157 { 00158 //Release previously allocated resources 00159 mpiFree(&r->x); 00160 mpiFree(&r->y); 00161 mpiFree(&r->z); 00162 } 00163 00164 00165 /** 00166 * @brief Copy EC point 00167 * @param[out] r Destination EC point 00168 * @param[in] s Source EC point 00169 * @return Error code 00170 **/ 00171 00172 error_t ecCopy(EcPoint *r, const EcPoint *s) 00173 { 00174 error_t error; 00175 00176 //R and S are the same instance? 00177 if(r == s) 00178 return NO_ERROR; 00179 00180 //Copy coordinates 00181 MPI_CHECK(mpiCopy(&r->x, &s->x)); 00182 MPI_CHECK(mpiCopy(&r->y, &s->y)); 00183 MPI_CHECK(mpiCopy(&r->z, &s->z)); 00184 00185 end: 00186 //Return status code 00187 return error; 00188 } 00189 00190 00191 /** 00192 * @brief Convert an octet string to an EC point 00193 * @param[in] params EC domain parameters 00194 * @param[out] r EC point resulting from the conversion 00195 * @param[in] data Pointer to the octet string 00196 * @param[in] length Length of the octet string 00197 * @return Error code 00198 **/ 00199 00200 error_t ecImport(const EcDomainParameters *params, 00201 EcPoint *r, const uint8_t *data, size_t length) 00202 { 00203 error_t error; 00204 size_t k; 00205 00206 //Get the length in octets of the prime 00207 k = mpiGetByteLength(¶ms->p); 00208 00209 //Check the length of the octet string 00210 if(length != (k * 2 + 1)) 00211 return ERROR_DECODING_FAILED; 00212 00213 //Compressed point representation is not supported 00214 if(data[0] != 0x04) 00215 return ERROR_ILLEGAL_PARAMETER; 00216 00217 //Convert the x-coordinate to a multiple precision integer 00218 error = mpiReadRaw(&r->x, data + 1, k); 00219 //Any error to report? 00220 if(error) 00221 return error; 00222 00223 //Convert the y-coordinate to a multiple precision integer 00224 error = mpiReadRaw(&r->y, data + k + 1, k); 00225 //Any error to report? 00226 if(error) 00227 return error; 00228 00229 //Successful processing 00230 return NO_ERROR; 00231 } 00232 00233 00234 /** 00235 * @brief Convert an EC point to an octet string 00236 * @param[in] params EC domain parameters 00237 * @param[in] a EC point to be converted 00238 * @param[out] data Pointer to the octet string 00239 * @param[out] length Length of the resulting octet string 00240 * @return Error code 00241 **/ 00242 00243 error_t ecExport(const EcDomainParameters *params, 00244 const EcPoint *a, uint8_t *data, size_t *length) 00245 { 00246 error_t error; 00247 size_t k; 00248 00249 //Get the length in octets of the prime 00250 k = mpiGetByteLength(¶ms->p); 00251 00252 //Point compression is not used 00253 data[0] = 0x04; 00254 00255 //Convert the x-coordinate to an octet string 00256 error = mpiWriteRaw(&a->x, data + 1, k); 00257 //Conversion failed? 00258 if(error) 00259 return error; 00260 00261 //Convert the y-coordinate to an octet string 00262 error = mpiWriteRaw(&a->y, data + k + 1, k); 00263 //Conversion failed? 00264 if(error) 00265 return error; 00266 00267 //Return the total number of bytes that have been written 00268 *length = k * 2 + 1; 00269 //Successful processing 00270 return NO_ERROR; 00271 } 00272 00273 00274 /** 00275 * @brief Compute projective representation 00276 * @param[in] params EC domain parameters 00277 * @param[out] r Projective representation of the point 00278 * @param[in] s Affine representation of the point 00279 * @return Error code 00280 **/ 00281 00282 error_t ecProjectify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s) 00283 { 00284 error_t error; 00285 00286 //Copy point 00287 EC_CHECK(ecCopy(r, s)); 00288 //Map the point to projective space 00289 MPI_CHECK(mpiSetValue(&r->z, 1)); 00290 00291 end: 00292 //Return status code 00293 return error; 00294 } 00295 00296 00297 /** 00298 * @brief Recover affine representation 00299 * @param[in] params EC domain parameters 00300 * @param[out] r Affine representation of the point 00301 * @param[in] s Projective representation of the point 00302 * @return Error code 00303 **/ 00304 00305 error_t ecAffinify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s) 00306 { 00307 error_t error; 00308 Mpi a; 00309 Mpi b; 00310 00311 //Point at the infinity? 00312 if(!mpiCompInt(&s->z, 0)) 00313 return ERROR_INVALID_PARAMETER; 00314 00315 //Initialize multiple precision integers 00316 mpiInit(&a); 00317 mpiInit(&b); 00318 00319 //Compute a = 1/Sz mod p 00320 MPI_CHECK(mpiInvMod(&a, &s->z, ¶ms->p)); 00321 00322 //Set Rx = a^2 * Sx mod p 00323 EC_CHECK(ecSqrMod(params, &b, &a)); 00324 EC_CHECK(ecMulMod(params, &r->x, &b, &s->x)); 00325 00326 //Set Ry = a^3 * Sy mod p 00327 EC_CHECK(ecMulMod(params, &b, &b, &a)); 00328 EC_CHECK(ecMulMod(params, &r->y, &b, &s->y)); 00329 00330 //Set Rz = 1 00331 MPI_CHECK(mpiSetValue(&r->z, 1)); 00332 00333 end: 00334 //Release multiple precision integers 00335 mpiFree(&a); 00336 mpiFree(&b); 00337 00338 //Return status code 00339 return error; 00340 } 00341 00342 00343 /** 00344 * @brief Check whether the affine point S is on the curve 00345 * @param[in] params EC domain parameters 00346 * @param[in] s Affine representation of the point 00347 * @return TRUE if the affine point S is on the curve, else FALSE 00348 **/ 00349 00350 bool_t ecIsPointAffine(const EcDomainParameters *params, const EcPoint *s) 00351 { 00352 error_t error; 00353 Mpi t1; 00354 Mpi t2; 00355 00356 //Initialize multiple precision integers 00357 mpiInit(&t1); 00358 mpiInit(&t2); 00359 00360 //Compute t1 = (Sx^3 + a * Sx + b) mod p 00361 EC_CHECK(ecSqrMod(params, &t1, &s->x)); 00362 EC_CHECK(ecMulMod(params, &t1, &t1, &s->x)); 00363 EC_CHECK(ecMulMod(params, &t2, ¶ms->a, &s->x)); 00364 EC_CHECK(ecAddMod(params, &t1, &t1, &t2)); 00365 EC_CHECK(ecAddMod(params, &t1, &t1, ¶ms->b)); 00366 00367 //Compute t2 = Sy^2 00368 EC_CHECK(ecSqrMod(params, &t2, &s->y)); 00369 00370 //Check whether the point is on the elliptic curve 00371 if(mpiComp(&t1, &t2)) 00372 error = ERROR_FAILURE; 00373 00374 end: 00375 //Release multiple precision integers 00376 mpiFree(&t1); 00377 mpiFree(&t2); 00378 00379 //Return TRUE if the affine point S is on the curve, else FALSE 00380 return error ? FALSE : TRUE; 00381 } 00382 00383 00384 /** 00385 * @brief Point doubling 00386 * @param[in] params EC domain parameters 00387 * @param[out] r Resulting point R = 2S 00388 * @param[in] s Point S 00389 * @return Error code 00390 **/ 00391 00392 error_t ecDouble(const EcDomainParameters *params, EcPoint *r, const EcPoint *s) 00393 { 00394 error_t error; 00395 Mpi t1; 00396 Mpi t2; 00397 Mpi t3; 00398 Mpi t4; 00399 Mpi t5; 00400 00401 //Initialize multiple precision integers 00402 mpiInit(&t1); 00403 mpiInit(&t2); 00404 mpiInit(&t3); 00405 mpiInit(&t4); 00406 mpiInit(&t5); 00407 00408 //Set t1 = Sx 00409 MPI_CHECK(mpiCopy(&t1, &s->x)); 00410 //Set t2 = Sy 00411 MPI_CHECK(mpiCopy(&t2, &s->y)); 00412 //Set t3 = Sz 00413 MPI_CHECK(mpiCopy(&t3, &s->z)); 00414 00415 //Point at the infinity? 00416 if(!mpiCompInt(&t3, 0)) 00417 { 00418 //Set R = (1, 1, 0) 00419 MPI_CHECK(mpiSetValue(&r->x, 1)); 00420 MPI_CHECK(mpiSetValue(&r->y, 1)); 00421 MPI_CHECK(mpiSetValue(&r->z, 0)); 00422 } 00423 else 00424 { 00425 //SECP K1 elliptic curve? 00426 if(params->type == EC_CURVE_TYPE_SECP_K1) 00427 { 00428 //Compute t5 = t1^2 00429 EC_CHECK(ecSqrMod(params, &t5, &t1)); 00430 //Compute t4 = 3 * t5 00431 EC_CHECK(ecAddMod(params, &t4, &t5, &t5)); 00432 EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); 00433 } 00434 //SECP R1 elliptic curve? 00435 else if(params->type == EC_CURVE_TYPE_SECP_R1) 00436 { 00437 //Compute t4 = t3^2 00438 EC_CHECK(ecSqrMod(params, &t4, &t3)); 00439 //Compute t5 = t1 - t4 00440 EC_CHECK(ecSubMod(params, &t5, &t1, &t4)); 00441 //Compute t4 = t1 + t4 00442 EC_CHECK(ecAddMod(params, &t4, &t1, &t4)); 00443 //Compute t5 = t4 * t5 00444 EC_CHECK(ecMulMod(params, &t5, &t4, &t5)); 00445 //Compute t4 = 3 * t5 00446 EC_CHECK(ecAddMod(params, &t4, &t5, &t5)); 00447 EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); 00448 } 00449 else 00450 { 00451 //Compute t4 = t3^4 00452 EC_CHECK(ecSqrMod(params, &t4, &t3)); 00453 EC_CHECK(ecSqrMod(params, &t4, &t4)); 00454 //Compute t4 = a * t4 00455 EC_CHECK(ecMulMod(params, &t4, &t4, ¶ms->a)); 00456 //Compute t5 = t1^2 00457 EC_CHECK(ecSqrMod(params, &t5, &t1)); 00458 //Compute t4 = t4 + 3 * t5 00459 EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); 00460 EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); 00461 EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); 00462 } 00463 00464 //Compute t3 = t3 * t2 00465 EC_CHECK(ecMulMod(params, &t3, &t3, &t2)); 00466 //Compute t3 = 2 * t3 00467 EC_CHECK(ecAddMod(params, &t3, &t3, &t3)); 00468 //Compute t2 = t2^2 00469 EC_CHECK(ecSqrMod(params, &t2, &t2)); 00470 //Compute t5 = t1 * t2 00471 EC_CHECK(ecMulMod(params, &t5, &t1, &t2)); 00472 //Compute t5 = 4 * t5 00473 EC_CHECK(ecAddMod(params, &t5, &t5, &t5)); 00474 EC_CHECK(ecAddMod(params, &t5, &t5, &t5)); 00475 //Compute t1 = t4^2 00476 EC_CHECK(ecSqrMod(params, &t1, &t4)); 00477 //Compute t1 = t1 - 2 * t5 00478 EC_CHECK(ecSubMod(params, &t1, &t1, &t5)); 00479 EC_CHECK(ecSubMod(params, &t1, &t1, &t5)); 00480 //Compute t2 = t2^2 00481 EC_CHECK(ecSqrMod(params, &t2, &t2)); 00482 //Compute t2 = 8 * t2 00483 EC_CHECK(ecAddMod(params, &t2, &t2, &t2)); 00484 EC_CHECK(ecAddMod(params, &t2, &t2, &t2)); 00485 EC_CHECK(ecAddMod(params, &t2, &t2, &t2)); 00486 //Compute t5 = t5 - t1 00487 EC_CHECK(ecSubMod(params, &t5, &t5, &t1)); 00488 //Compute t5 = t4 * t5 00489 EC_CHECK(ecMulMod(params, &t5, &t4, &t5)); 00490 //Compute t2 = t5 - t2 00491 EC_CHECK(ecSubMod(params, &t2, &t5, &t2)); 00492 00493 //Set Rx = t1 00494 MPI_CHECK(mpiCopy(&r->x, &t1)); 00495 //Set Ry = t2 00496 MPI_CHECK(mpiCopy(&r->y, &t2)); 00497 //Set Rz = t3 00498 MPI_CHECK(mpiCopy(&r->z, &t3)); 00499 } 00500 00501 end: 00502 //Release multiple precision integers 00503 mpiFree(&t1); 00504 mpiFree(&t2); 00505 mpiFree(&t3); 00506 mpiFree(&t4); 00507 mpiFree(&t5); 00508 00509 //Return status code 00510 return error; 00511 } 00512 00513 00514 /** 00515 * @brief Point addition (helper routine) 00516 * @param[in] params EC domain parameters 00517 * @param[out] r Resulting point R = S + T 00518 * @param[in] s First operand 00519 * @param[in] t Second operand 00520 * @return Error code 00521 **/ 00522 00523 error_t ecAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t) 00524 { 00525 error_t error; 00526 Mpi t1; 00527 Mpi t2; 00528 Mpi t3; 00529 Mpi t4; 00530 Mpi t5; 00531 Mpi t6; 00532 Mpi t7; 00533 00534 //Initialize multiple precision integers 00535 mpiInit(&t1); 00536 mpiInit(&t2); 00537 mpiInit(&t3); 00538 mpiInit(&t4); 00539 mpiInit(&t5); 00540 mpiInit(&t6); 00541 mpiInit(&t7); 00542 00543 //Set t1 = Sx 00544 MPI_CHECK(mpiCopy(&t1, &s->x)); 00545 //Set t2 = Sy 00546 MPI_CHECK(mpiCopy(&t2, &s->y)); 00547 //Set t3 = Sz 00548 MPI_CHECK(mpiCopy(&t3, &s->z)); 00549 //Set t4 = Tx 00550 MPI_CHECK(mpiCopy(&t4, &t->x)); 00551 //Set t5 = Ty 00552 MPI_CHECK(mpiCopy(&t5, &t->y)); 00553 00554 //Check whether Tz != 1 00555 if(mpiCompInt(&t->z, 1)) 00556 { 00557 //Compute t6 = Tz 00558 MPI_CHECK(mpiCopy(&t6, &t->z)); 00559 //Compute t7 = t6^2 00560 EC_CHECK(ecSqrMod(params, &t7, &t6)); 00561 //Compute t1 = t1 * t7 00562 EC_CHECK(ecMulMod(params, &t1, &t1, &t7)); 00563 //Compute t7 = t6 * t7 00564 EC_CHECK(ecMulMod(params, &t7, &t6, &t7)); 00565 //Compute t2 = t2 * t7 00566 EC_CHECK(ecMulMod(params, &t2, &t2, &t7)); 00567 } 00568 00569 //Compute t7 = t3^2 00570 EC_CHECK(ecSqrMod(params, &t7, &t3)); 00571 //Compute t4 = t4 * t7 00572 EC_CHECK(ecMulMod(params, &t4, &t4, &t7)); 00573 //Compute t7 = t3 * t7 00574 EC_CHECK(ecMulMod(params, &t7, &t3, &t7)); 00575 //Compute t5 = t5 * t7 00576 EC_CHECK(ecMulMod(params, &t5, &t5, &t7)); 00577 //Compute t4 = t1 - t4 00578 EC_CHECK(ecSubMod(params, &t4, &t1, &t4)); 00579 //Compute t5 = t2 - t5 00580 EC_CHECK(ecSubMod(params, &t5, &t2, &t5)); 00581 00582 //Check whether t4 == 0 00583 if(!mpiCompInt(&t4, 0)) 00584 { 00585 //Check whether t5 == 0 00586 if(!mpiCompInt(&t5, 0)) 00587 { 00588 //Set R = (0, 0, 0) 00589 MPI_CHECK(mpiSetValue(&r->x, 0)); 00590 MPI_CHECK(mpiSetValue(&r->y, 0)); 00591 MPI_CHECK(mpiSetValue(&r->z, 0)); 00592 } 00593 else 00594 { 00595 //Set R = (1, 1, 0) 00596 MPI_CHECK(mpiSetValue(&r->x, 1)); 00597 MPI_CHECK(mpiSetValue(&r->y, 1)); 00598 MPI_CHECK(mpiSetValue(&r->z, 0)); 00599 } 00600 } 00601 else 00602 { 00603 //Compute t1 = 2 * t1 - t4 00604 EC_CHECK(ecAddMod(params, &t1, &t1, &t1)); 00605 EC_CHECK(ecSubMod(params, &t1, &t1, &t4)); 00606 //Compute t2 = 2 * t2 - t5 00607 EC_CHECK(ecAddMod(params, &t2, &t2, &t2)); 00608 EC_CHECK(ecSubMod(params, &t2, &t2, &t5)); 00609 00610 //Check whether Tz != 1 00611 if(mpiCompInt(&t->z, 1)) 00612 { 00613 //Compute t3 = t3 * t6 00614 EC_CHECK(ecMulMod(params, &t3, &t3, &t6)); 00615 } 00616 00617 //Compute t3 = t3 * t4 00618 EC_CHECK(ecMulMod(params, &t3, &t3, &t4)); 00619 //Compute t7 = t4^2 00620 EC_CHECK(ecSqrMod(params, &t7, &t4)); 00621 //Compute t4 = t4 * t7 00622 EC_CHECK(ecMulMod(params, &t4, &t4, &t7)); 00623 //Compute t7 = t1 * t7 00624 EC_CHECK(ecMulMod(params, &t7, &t1, &t7)); 00625 //Compute t1 = t5^2 00626 EC_CHECK(ecSqrMod(params, &t1, &t5)); 00627 //Compute t1 = t1 - t7 00628 EC_CHECK(ecSubMod(params, &t1, &t1, &t7)); 00629 //Compute t7 = t7 - 2 * t1 00630 EC_CHECK(ecAddMod(params, &t6, &t1, &t1)); 00631 EC_CHECK(ecSubMod(params, &t7, &t7, &t6)); 00632 //Compute t5 = t5 * t7 00633 EC_CHECK(ecMulMod(params, &t5, &t5, &t7)); 00634 //Compute t4 = t2 * t4 00635 EC_CHECK(ecMulMod(params, &t4, &t2, &t4)); 00636 //Compute t2 = t5 - t4 00637 EC_CHECK(ecSubMod(params, &t2, &t5, &t4)); 00638 00639 //Compute t2 = t2 / 2 00640 if(mpiIsEven(&t2)) 00641 { 00642 MPI_CHECK(mpiShiftRight(&t2, 1)); 00643 } 00644 else 00645 { 00646 MPI_CHECK(mpiAdd(&t2, &t2, ¶ms->p)); 00647 MPI_CHECK(mpiShiftRight(&t2, 1)); 00648 } 00649 00650 //Set Rx = t1 00651 MPI_CHECK(mpiCopy(&r->x, &t1)); 00652 //Set Ry = t2 00653 MPI_CHECK(mpiCopy(&r->y, &t2)); 00654 //Set Rz = t3 00655 MPI_CHECK(mpiCopy(&r->z, &t3)); 00656 } 00657 00658 end: 00659 //Release multiple precision integers 00660 mpiFree(&t1); 00661 mpiFree(&t2); 00662 mpiFree(&t3); 00663 mpiFree(&t4); 00664 mpiFree(&t5); 00665 mpiFree(&t6); 00666 mpiFree(&t7); 00667 00668 //Return status code 00669 return error; 00670 } 00671 00672 00673 /** 00674 * @brief Point addition 00675 * @param[in] params EC domain parameters 00676 * @param[out] r Resulting point R = S + T 00677 * @param[in] s First operand 00678 * @param[in] t Second operand 00679 * @return Error code 00680 **/ 00681 00682 error_t ecFullAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t) 00683 { 00684 error_t error; 00685 00686 //Check whether Sz == 0 00687 if(!mpiCompInt(&s->z, 0)) 00688 { 00689 //Set R = T 00690 MPI_CHECK(mpiCopy(&r->x, &t->x)); 00691 MPI_CHECK(mpiCopy(&r->y, &t->y)); 00692 MPI_CHECK(mpiCopy(&r->z, &t->z)); 00693 } 00694 //Check whether Tz == 0 00695 else if(!mpiCompInt(&t->z, 0)) 00696 { 00697 //Set R = S 00698 MPI_CHECK(mpiCopy(&r->x, &s->x)); 00699 MPI_CHECK(mpiCopy(&r->y, &s->y)); 00700 MPI_CHECK(mpiCopy(&r->z, &s->z)); 00701 } 00702 else 00703 { 00704 //Compute R = S + T 00705 EC_CHECK(ecAdd(params, r, s, t)); 00706 00707 //Check whether R == (0, 0, 0) 00708 if(!mpiCompInt(&r->x, 0) && !mpiCompInt(&r->y, 0) && !mpiCompInt(&r->z, 0)) 00709 { 00710 //Compute R = 2 * S 00711 EC_CHECK(ecDouble(params, r, s)); 00712 } 00713 } 00714 00715 end: 00716 //Return status code 00717 return error; 00718 } 00719 00720 00721 /** 00722 * @brief Point subtraction 00723 * @param[in] params EC domain parameters 00724 * @param[out] r Resulting point R = S - T 00725 * @param[in] s First operand 00726 * @param[in] t Second operand 00727 * @return Error code 00728 **/ 00729 00730 error_t ecFullSub(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t) 00731 { 00732 error_t error; 00733 EcPoint u; 00734 00735 //Initialize EC point 00736 ecInit(&u); 00737 00738 //Set Ux = Tx and Uz = Tz 00739 MPI_CHECK(mpiCopy(&u.x, &t->x)); 00740 MPI_CHECK(mpiCopy(&u.z, &t->z)); 00741 //Set Uy = p - Ty 00742 MPI_CHECK(mpiSub(&u.y, ¶ms->p, &t->y)); 00743 00744 //Compute R = S + U 00745 EC_CHECK(ecFullAdd(params, r, s, &u)); 00746 00747 end: 00748 //Release EC point 00749 ecFree(&u); 00750 00751 //Return status code 00752 return error; 00753 } 00754 00755 00756 /** 00757 * @brief Scalar multiplication 00758 * @param[in] params EC domain parameters 00759 * @param[out] r Resulting point R = d.S 00760 * @param[in] d An integer d such as 0 <= d < p 00761 * @param[in] s EC point 00762 * @return Error code 00763 **/ 00764 00765 error_t ecMult(const EcDomainParameters *params, EcPoint *r, const Mpi *d, const EcPoint *s) 00766 { 00767 error_t error; 00768 uint_t i; 00769 Mpi h; 00770 00771 //Initialize multiple precision integer 00772 mpiInit(&h); 00773 00774 //Check whether d == 0 00775 if(!mpiCompInt(d, 0)) 00776 { 00777 //Set R = (1, 1, 0) 00778 MPI_CHECK(mpiSetValue(&r->x, 1)); 00779 MPI_CHECK(mpiSetValue(&r->y, 1)); 00780 MPI_CHECK(mpiSetValue(&r->z, 0)); 00781 } 00782 //Check whether d == 1 00783 else if(!mpiCompInt(d, 1)) 00784 { 00785 //Set R = S 00786 MPI_CHECK(mpiCopy(&r->x, &s->x)); 00787 MPI_CHECK(mpiCopy(&r->y, &s->y)); 00788 MPI_CHECK(mpiCopy(&r->z, &s->z)); 00789 } 00790 //Check whether Sz == 0 00791 else if(!mpiCompInt(&s->z, 0)) 00792 { 00793 //Set R = (1, 1, 0) 00794 MPI_CHECK(mpiSetValue(&r->x, 1)); 00795 MPI_CHECK(mpiSetValue(&r->y, 1)); 00796 MPI_CHECK(mpiSetValue(&r->z, 0)); 00797 } 00798 else 00799 { 00800 //Check whether Sz != 1 00801 if(mpiCompInt(&s->z, 1)) 00802 { 00803 //Normalize S 00804 EC_CHECK(ecAffinify(params, r, s)); 00805 EC_CHECK(ecProjectify(params, r, r)); 00806 } 00807 else 00808 { 00809 //Set R = S 00810 MPI_CHECK(mpiCopy(&r->x, &s->x)); 00811 MPI_CHECK(mpiCopy(&r->y, &s->y)); 00812 MPI_CHECK(mpiCopy(&r->z, &s->z)); 00813 } 00814 00815 //Left-to-right binary method 00816 #if 0 00817 for(i = mpiGetBitLength(d) - 1; i >= 1; i--) 00818 { 00819 //Point doubling 00820 EC_CHECK(ecDouble(params, r, r)); 00821 00822 if(mpiGetBitValue(d, i - 1)) 00823 { 00824 //Compute R = R + S 00825 EC_CHECK(ecFullAdd(params, r, r, s)); 00826 } 00827 } 00828 //Fast left-to-right binary method 00829 #else 00830 //Precompute h = 3 * d 00831 MPI_CHECK(mpiAdd(&h, d, d)); 00832 MPI_CHECK(mpiAdd(&h, &h, d)); 00833 00834 //Scalar multiplication 00835 for(i = mpiGetBitLength(&h) - 2; i >= 1; i--) 00836 { 00837 //Point doubling 00838 EC_CHECK(ecDouble(params, r, r)); 00839 00840 //Check whether h(i) == 1 and k(i) == 0 00841 if(mpiGetBitValue(&h, i) && !mpiGetBitValue(d, i)) 00842 { 00843 //Compute R = R + S 00844 EC_CHECK(ecFullAdd(params, r, r, s)); 00845 } 00846 //Check whether h(i) == 0 and k(i) == 1 00847 else if(!mpiGetBitValue(&h, i) && mpiGetBitValue(d, i)) 00848 { 00849 //Compute R = R - S 00850 EC_CHECK(ecFullSub(params, r, r, s)); 00851 } 00852 } 00853 #endif 00854 } 00855 00856 end: 00857 //Release multiple precision integer 00858 mpiFree(&h); 00859 00860 //Return status code 00861 return error; 00862 } 00863 00864 00865 /** 00866 * @brief An auxiliary function for the twin multiplication 00867 * @param[in] t An integer T such as 0 <= T <= 31 00868 * @return Output value 00869 **/ 00870 00871 uint_t ecTwinMultF(uint_t t) 00872 { 00873 if(18 <= t && t < 22) 00874 return 9; 00875 else if(14 <= t && t < 18) 00876 return 10; 00877 else if(22 <= t && t < 24) 00878 return 11; 00879 else if(4 <= t && t < 12) 00880 return 14; 00881 else 00882 return 12; 00883 } 00884 00885 00886 /** 00887 * @brief Twin multiplication 00888 * @param[in] params EC domain parameters 00889 * @param[out] r Resulting point R = d0.S + d1.T 00890 * @param[in] d0 An integer d such as 0 <= d0 < p 00891 * @param[in] s EC point 00892 * @param[in] d1 An integer d such as 0 <= d1 < p 00893 * @param[in] t EC point 00894 * @return Error code 00895 **/ 00896 00897 error_t ecTwinMult(const EcDomainParameters *params, EcPoint *r, 00898 const Mpi *d0, const EcPoint *s, const Mpi *d1, const EcPoint *t) 00899 { 00900 error_t error; 00901 int_t k; 00902 uint_t m; 00903 uint_t m0; 00904 uint_t m1; 00905 uint_t c0; 00906 uint_t c1; 00907 uint_t h0; 00908 uint_t h1; 00909 int_t u0; 00910 int_t u1; 00911 EcPoint spt; 00912 EcPoint smt; 00913 00914 //Initialize EC points 00915 ecInit(&spt); 00916 ecInit(&smt); 00917 00918 //Precompute SpT = S + T 00919 EC_CHECK(ecFullAdd(params, &spt, s, t)); 00920 //Precompute SmT = S - T 00921 EC_CHECK(ecFullSub(params, &smt, s, t)); 00922 00923 //Let m0 be the bit length of d0 00924 m0 = mpiGetBitLength(d0); 00925 //Let m1 be the bit length of d1 00926 m1 = mpiGetBitLength(d1); 00927 //Let m = MAX(m0, m1) 00928 m = MAX(m0, m1); 00929 00930 //Let c be a 2 x 6 binary matrix 00931 c0 = mpiGetBitValue(d0, m - 4); 00932 c0 |= mpiGetBitValue(d0, m - 3) << 1; 00933 c0 |= mpiGetBitValue(d0, m - 2) << 2; 00934 c0 |= mpiGetBitValue(d0, m - 1) << 3; 00935 c1 = mpiGetBitValue(d1, m - 4); 00936 c1 |= mpiGetBitValue(d1, m - 3) << 1; 00937 c1 |= mpiGetBitValue(d1, m - 2) << 2; 00938 c1 |= mpiGetBitValue(d1, m - 1) << 3; 00939 00940 //Set R = (1, 1, 0) 00941 MPI_CHECK(mpiSetValue(&r->x, 1)); 00942 MPI_CHECK(mpiSetValue(&r->y, 1)); 00943 MPI_CHECK(mpiSetValue(&r->z, 0)); 00944 00945 //Calculate both multiplications at the same time 00946 for(k = m; k >= 0; k--) 00947 { 00948 //Compute h(0) = 16 * c(0,1) + 8 * c(0,2) + 4 * c(0,3) + 2 * c(0,4) + c(0,5) 00949 h0 = c0 & 0x1F; 00950 //Check whether c(0,0) == 1 00951 if(c0 & 0x20) 00952 h0 = 31 - h0; 00953 00954 //Compute h(1) = 16 * c(1,1) + 8 * c(1,2) + 4 * c(1,3) + 2 * c(1,4) + c(1,5) 00955 h1 = c1 & 0x1F; 00956 //Check whether c(1,0) == 1 00957 if(c1 & 0x20) 00958 h1 = 31 - h1; 00959 00960 //Compute u(0) 00961 if(h0 < ecTwinMultF(h1)) 00962 u0 = 0; 00963 else if(c0 & 0x20) 00964 u0 = -1; 00965 else 00966 u0 = 1; 00967 00968 //Compute u(1) 00969 if(h1 < ecTwinMultF(h0)) 00970 u1 = 0; 00971 else if(c1 & 0x20) 00972 u1 = -1; 00973 else 00974 u1 = 1; 00975 00976 //Update c matrix 00977 c0 <<= 1; 00978 c0 |= mpiGetBitValue(d0, k - 5); 00979 c0 ^= u0 ? 0x20 : 0x00; 00980 c1 <<= 1; 00981 c1 |= mpiGetBitValue(d1, k - 5); 00982 c1 ^= u1 ? 0x20 : 0x00; 00983 00984 //Point doubling 00985 EC_CHECK(ecDouble(params, r, r)); 00986 00987 //Check u(0) and u(1) 00988 if(u0 == -1 && u1 == -1) 00989 { 00990 //Compute R = R - SpT 00991 EC_CHECK(ecFullSub(params, r, r, &spt)); 00992 } 00993 else if(u0 == -1 && u1 == 0) 00994 { 00995 //Compute R = R - S 00996 EC_CHECK(ecFullSub(params, r, r, s)); 00997 } 00998 else if(u0 == -1 && u1 == 1) 00999 { 01000 //Compute R = R - SmT 01001 EC_CHECK(ecFullSub(params, r, r, &smt)); 01002 } 01003 else if(u0 == 0 && u1 == -1) 01004 { 01005 //Compute R = R - T 01006 EC_CHECK(ecFullSub(params, r, r, t)); 01007 } 01008 else if(u0 == 0 && u1 == 1) 01009 { 01010 //Compute R = R + T 01011 EC_CHECK(ecFullAdd(params, r, r, t)); 01012 } 01013 else if(u0 == 1 && u1 == -1) 01014 { 01015 //Compute R = R + SmT 01016 EC_CHECK(ecFullAdd(params, r, r, &smt)); 01017 } 01018 else if(u0 == 1 && u1 == 0) 01019 { 01020 //Compute R = R + S 01021 EC_CHECK(ecFullAdd(params, r, r, s)); 01022 } 01023 else if(u0 == 1 && u1 == 1) 01024 { 01025 //Compute R = R + SpT 01026 EC_CHECK(ecFullAdd(params, r, r, &spt)); 01027 } 01028 } 01029 01030 end: 01031 //Release EC points 01032 ecFree(&spt); 01033 ecFree(&smt); 01034 01035 //Return status code 01036 return error; 01037 } 01038 01039 01040 /** 01041 * @brief Fast modular addition 01042 * @param[in] params EC domain parameters 01043 * @param[out] r Resulting integer R = (A + B) mod p 01044 * @param[in] a An integer such as 0 <= A < p 01045 * @param[in] b An integer such as 0 <= B < p 01046 * @return Error code 01047 **/ 01048 01049 error_t ecAddMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b) 01050 { 01051 error_t error; 01052 01053 //Compute R = A + B 01054 MPI_CHECK(mpiAdd(r, a, b)); 01055 01056 //Compute R = (A + B) mod p 01057 if(mpiComp(r, ¶ms->p) >= 0) 01058 { 01059 MPI_CHECK(mpiSub(r, r, ¶ms->p)); 01060 } 01061 01062 end: 01063 //Return status code 01064 return error; 01065 } 01066 01067 01068 /** 01069 * @brief Fast modular subtraction 01070 * @param[in] params EC domain parameters 01071 * @param[out] r Resulting integer R = (A - B) mod p 01072 * @param[in] a An integer such as 0 <= A < p 01073 * @param[in] b An integer such as 0 <= B < p 01074 * @return Error code 01075 **/ 01076 01077 error_t ecSubMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b) 01078 { 01079 error_t error; 01080 01081 //Compute R = A - B 01082 MPI_CHECK(mpiSub(r, a, b)); 01083 01084 //Compute R = (A - B) mod p 01085 if(mpiCompInt(r, 0) < 0) 01086 { 01087 MPI_CHECK(mpiAdd(r, r, ¶ms->p)); 01088 } 01089 01090 end: 01091 //Return status code 01092 return error; 01093 } 01094 01095 01096 /** 01097 * @brief Fast modular multiplication 01098 * @param[in] params EC domain parameters 01099 * @param[out] r Resulting integer R = (A * B) mod p 01100 * @param[in] a An integer such as 0 <= A < p 01101 * @param[in] b An integer such as 0 <= B < p 01102 * @return Error code 01103 **/ 01104 01105 error_t ecMulMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b) 01106 { 01107 error_t error; 01108 01109 //Compute R = A * B 01110 MPI_CHECK(mpiMul(r, a, b)); 01111 01112 //Compute R = (A * B) mod p 01113 if(params->mod != NULL) 01114 { 01115 MPI_CHECK(params->mod(r, ¶ms->p)); 01116 } 01117 else 01118 { 01119 MPI_CHECK(mpiMod(r, r, ¶ms->p)); 01120 } 01121 01122 end: 01123 //Return status code 01124 return error; 01125 } 01126 01127 01128 /** 01129 * @brief Fast modular squaring 01130 * @param[in] params EC domain parameters 01131 * @param[out] r Resulting integer R = (A ^ 2) mod p 01132 * @param[in] a An integer such as 0 <= A < p 01133 * @return Error code 01134 **/ 01135 01136 error_t ecSqrMod(const EcDomainParameters *params, Mpi *r, const Mpi *a) 01137 { 01138 error_t error; 01139 01140 //Compute R = A ^ 2 01141 MPI_CHECK(mpiMul(r, a, a)); 01142 01143 //Compute R = (A ^ 2) mod p 01144 if(params->mod != NULL) 01145 { 01146 MPI_CHECK(params->mod(r, ¶ms->p)); 01147 } 01148 else 01149 { 01150 MPI_CHECK(mpiMod(r, r, ¶ms->p)); 01151 } 01152 01153 end: 01154 //Return status code 01155 return error; 01156 } 01157 01158 #endif 01159
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2