Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file ec.c
Sergunb 0:8918a71cdbe9 3 * @brief ECC (Elliptic Curve Cryptography)
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneCrypto Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include <stdlib.h>
Sergunb 0:8918a71cdbe9 34 #include "crypto.h"
Sergunb 0:8918a71cdbe9 35 #include "ec.h"
Sergunb 0:8918a71cdbe9 36 #include "debug.h"
Sergunb 0:8918a71cdbe9 37
Sergunb 0:8918a71cdbe9 38 //Check crypto library configuration
Sergunb 0:8918a71cdbe9 39 #if (EC_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 40
Sergunb 0:8918a71cdbe9 41 //EC Public Key OID (1.2.840.10045.2.1)
Sergunb 0:8918a71cdbe9 42 const uint8_t EC_PUBLIC_KEY_OID[7] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01};
Sergunb 0:8918a71cdbe9 43
Sergunb 0:8918a71cdbe9 44
Sergunb 0:8918a71cdbe9 45 /**
Sergunb 0:8918a71cdbe9 46 * @brief Initialize EC domain parameters
Sergunb 0:8918a71cdbe9 47 * @param[in] params Pointer to the EC domain parameters to be initialized
Sergunb 0:8918a71cdbe9 48 **/
Sergunb 0:8918a71cdbe9 49
Sergunb 0:8918a71cdbe9 50 void ecInitDomainParameters(EcDomainParameters *params)
Sergunb 0:8918a71cdbe9 51 {
Sergunb 0:8918a71cdbe9 52 //Initialize structure
Sergunb 0:8918a71cdbe9 53 params->type = EC_CURVE_TYPE_NONE;
Sergunb 0:8918a71cdbe9 54 params->mod = NULL;
Sergunb 0:8918a71cdbe9 55
Sergunb 0:8918a71cdbe9 56 //Initialize EC domain parameters
Sergunb 0:8918a71cdbe9 57 mpiInit(&params->p);
Sergunb 0:8918a71cdbe9 58 mpiInit(&params->a);
Sergunb 0:8918a71cdbe9 59 mpiInit(&params->b);
Sergunb 0:8918a71cdbe9 60 ecInit(&params->g);
Sergunb 0:8918a71cdbe9 61 mpiInit(&params->q);
Sergunb 0:8918a71cdbe9 62 }
Sergunb 0:8918a71cdbe9 63
Sergunb 0:8918a71cdbe9 64
Sergunb 0:8918a71cdbe9 65 /**
Sergunb 0:8918a71cdbe9 66 * @brief Release EC domain parameters
Sergunb 0:8918a71cdbe9 67 * @param[in] params Pointer to the EC domain parameters to free
Sergunb 0:8918a71cdbe9 68 **/
Sergunb 0:8918a71cdbe9 69
Sergunb 0:8918a71cdbe9 70 void ecFreeDomainParameters(EcDomainParameters *params)
Sergunb 0:8918a71cdbe9 71 {
Sergunb 0:8918a71cdbe9 72 //Release previously allocated resources
Sergunb 0:8918a71cdbe9 73 mpiFree(&params->p);
Sergunb 0:8918a71cdbe9 74 mpiFree(&params->a);
Sergunb 0:8918a71cdbe9 75 mpiFree(&params->b);
Sergunb 0:8918a71cdbe9 76 ecFree(&params->g);
Sergunb 0:8918a71cdbe9 77 mpiFree(&params->q);
Sergunb 0:8918a71cdbe9 78 }
Sergunb 0:8918a71cdbe9 79
Sergunb 0:8918a71cdbe9 80
Sergunb 0:8918a71cdbe9 81 /**
Sergunb 0:8918a71cdbe9 82 * @brief Load EC domain parameters
Sergunb 0:8918a71cdbe9 83 * @param[out] params Pointer to the structure to be initialized
Sergunb 0:8918a71cdbe9 84 * @param[in] curveInfo Elliptic curve parameters
Sergunb 0:8918a71cdbe9 85 * @return Error code
Sergunb 0:8918a71cdbe9 86 **/
Sergunb 0:8918a71cdbe9 87
Sergunb 0:8918a71cdbe9 88 error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo)
Sergunb 0:8918a71cdbe9 89 {
Sergunb 0:8918a71cdbe9 90 error_t error;
Sergunb 0:8918a71cdbe9 91
Sergunb 0:8918a71cdbe9 92 //Debug message
Sergunb 0:8918a71cdbe9 93 TRACE_DEBUG("Loading %s EC domain parameters...\r\n", curveInfo->name);
Sergunb 0:8918a71cdbe9 94
Sergunb 0:8918a71cdbe9 95 //Curve type
Sergunb 0:8918a71cdbe9 96 params->type = curveInfo->type;
Sergunb 0:8918a71cdbe9 97
Sergunb 0:8918a71cdbe9 98 //Import prime modulus
Sergunb 0:8918a71cdbe9 99 MPI_CHECK(mpiReadRaw(&params->p, curveInfo->p, curveInfo->pLen));
Sergunb 0:8918a71cdbe9 100 //Import parameter a
Sergunb 0:8918a71cdbe9 101 MPI_CHECK(mpiReadRaw(&params->a, curveInfo->a, curveInfo->aLen));
Sergunb 0:8918a71cdbe9 102 //Import parameter b
Sergunb 0:8918a71cdbe9 103 MPI_CHECK(mpiReadRaw(&params->b, curveInfo->b, curveInfo->bLen));
Sergunb 0:8918a71cdbe9 104 //Import the x-coordinate of the base point G
Sergunb 0:8918a71cdbe9 105 MPI_CHECK(mpiReadRaw(&params->g.x, curveInfo->gx, curveInfo->gxLen));
Sergunb 0:8918a71cdbe9 106 //Import the y-coordinate of the base point G
Sergunb 0:8918a71cdbe9 107 MPI_CHECK(mpiReadRaw(&params->g.y, curveInfo->gy, curveInfo->gyLen));
Sergunb 0:8918a71cdbe9 108 //Import base point order q
Sergunb 0:8918a71cdbe9 109 MPI_CHECK(mpiReadRaw(&params->q, curveInfo->q, curveInfo->qLen));
Sergunb 0:8918a71cdbe9 110
Sergunb 0:8918a71cdbe9 111 //Normalize base point G
Sergunb 0:8918a71cdbe9 112 MPI_CHECK(mpiSetValue(&params->g.z, 1));
Sergunb 0:8918a71cdbe9 113
Sergunb 0:8918a71cdbe9 114 //Fast modular reduction
Sergunb 0:8918a71cdbe9 115 params->mod = curveInfo->mod;
Sergunb 0:8918a71cdbe9 116
Sergunb 0:8918a71cdbe9 117 //Debug message
Sergunb 0:8918a71cdbe9 118 TRACE_DEBUG(" p:\r\n");
Sergunb 0:8918a71cdbe9 119 TRACE_DEBUG_MPI(" ", &params->p);
Sergunb 0:8918a71cdbe9 120 TRACE_DEBUG(" a:\r\n");
Sergunb 0:8918a71cdbe9 121 TRACE_DEBUG_MPI(" ", &params->a);
Sergunb 0:8918a71cdbe9 122 TRACE_DEBUG(" b:\r\n");
Sergunb 0:8918a71cdbe9 123 TRACE_DEBUG_MPI(" ", &params->b);
Sergunb 0:8918a71cdbe9 124 TRACE_DEBUG(" Gx:\r\n");
Sergunb 0:8918a71cdbe9 125 TRACE_DEBUG_MPI(" ", &params->g.x);
Sergunb 0:8918a71cdbe9 126 TRACE_DEBUG(" Gy:\r\n");
Sergunb 0:8918a71cdbe9 127 TRACE_DEBUG_MPI(" ", &params->g.y);
Sergunb 0:8918a71cdbe9 128 TRACE_DEBUG(" q:\r\n");
Sergunb 0:8918a71cdbe9 129 TRACE_DEBUG_MPI(" ", &params->q);
Sergunb 0:8918a71cdbe9 130
Sergunb 0:8918a71cdbe9 131 end:
Sergunb 0:8918a71cdbe9 132 //Return status code
Sergunb 0:8918a71cdbe9 133 return error;
Sergunb 0:8918a71cdbe9 134 }
Sergunb 0:8918a71cdbe9 135
Sergunb 0:8918a71cdbe9 136
Sergunb 0:8918a71cdbe9 137 /**
Sergunb 0:8918a71cdbe9 138 * @brief Initialize elliptic curve point
Sergunb 0:8918a71cdbe9 139 * @param[in,out] r Pointer to the EC point to be initialized
Sergunb 0:8918a71cdbe9 140 **/
Sergunb 0:8918a71cdbe9 141
Sergunb 0:8918a71cdbe9 142 void ecInit(EcPoint *r)
Sergunb 0:8918a71cdbe9 143 {
Sergunb 0:8918a71cdbe9 144 //Initialize structure
Sergunb 0:8918a71cdbe9 145 mpiInit(&r->x);
Sergunb 0:8918a71cdbe9 146 mpiInit(&r->y);
Sergunb 0:8918a71cdbe9 147 mpiInit(&r->z);
Sergunb 0:8918a71cdbe9 148 }
Sergunb 0:8918a71cdbe9 149
Sergunb 0:8918a71cdbe9 150
Sergunb 0:8918a71cdbe9 151 /**
Sergunb 0:8918a71cdbe9 152 * @brief Release an elliptic curve point
Sergunb 0:8918a71cdbe9 153 * @param[in,out] r Pointer to the EC point to initialize to free
Sergunb 0:8918a71cdbe9 154 **/
Sergunb 0:8918a71cdbe9 155
Sergunb 0:8918a71cdbe9 156 void ecFree(EcPoint *r)
Sergunb 0:8918a71cdbe9 157 {
Sergunb 0:8918a71cdbe9 158 //Release previously allocated resources
Sergunb 0:8918a71cdbe9 159 mpiFree(&r->x);
Sergunb 0:8918a71cdbe9 160 mpiFree(&r->y);
Sergunb 0:8918a71cdbe9 161 mpiFree(&r->z);
Sergunb 0:8918a71cdbe9 162 }
Sergunb 0:8918a71cdbe9 163
Sergunb 0:8918a71cdbe9 164
Sergunb 0:8918a71cdbe9 165 /**
Sergunb 0:8918a71cdbe9 166 * @brief Copy EC point
Sergunb 0:8918a71cdbe9 167 * @param[out] r Destination EC point
Sergunb 0:8918a71cdbe9 168 * @param[in] s Source EC point
Sergunb 0:8918a71cdbe9 169 * @return Error code
Sergunb 0:8918a71cdbe9 170 **/
Sergunb 0:8918a71cdbe9 171
Sergunb 0:8918a71cdbe9 172 error_t ecCopy(EcPoint *r, const EcPoint *s)
Sergunb 0:8918a71cdbe9 173 {
Sergunb 0:8918a71cdbe9 174 error_t error;
Sergunb 0:8918a71cdbe9 175
Sergunb 0:8918a71cdbe9 176 //R and S are the same instance?
Sergunb 0:8918a71cdbe9 177 if(r == s)
Sergunb 0:8918a71cdbe9 178 return NO_ERROR;
Sergunb 0:8918a71cdbe9 179
Sergunb 0:8918a71cdbe9 180 //Copy coordinates
Sergunb 0:8918a71cdbe9 181 MPI_CHECK(mpiCopy(&r->x, &s->x));
Sergunb 0:8918a71cdbe9 182 MPI_CHECK(mpiCopy(&r->y, &s->y));
Sergunb 0:8918a71cdbe9 183 MPI_CHECK(mpiCopy(&r->z, &s->z));
Sergunb 0:8918a71cdbe9 184
Sergunb 0:8918a71cdbe9 185 end:
Sergunb 0:8918a71cdbe9 186 //Return status code
Sergunb 0:8918a71cdbe9 187 return error;
Sergunb 0:8918a71cdbe9 188 }
Sergunb 0:8918a71cdbe9 189
Sergunb 0:8918a71cdbe9 190
Sergunb 0:8918a71cdbe9 191 /**
Sergunb 0:8918a71cdbe9 192 * @brief Convert an octet string to an EC point
Sergunb 0:8918a71cdbe9 193 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 194 * @param[out] r EC point resulting from the conversion
Sergunb 0:8918a71cdbe9 195 * @param[in] data Pointer to the octet string
Sergunb 0:8918a71cdbe9 196 * @param[in] length Length of the octet string
Sergunb 0:8918a71cdbe9 197 * @return Error code
Sergunb 0:8918a71cdbe9 198 **/
Sergunb 0:8918a71cdbe9 199
Sergunb 0:8918a71cdbe9 200 error_t ecImport(const EcDomainParameters *params,
Sergunb 0:8918a71cdbe9 201 EcPoint *r, const uint8_t *data, size_t length)
Sergunb 0:8918a71cdbe9 202 {
Sergunb 0:8918a71cdbe9 203 error_t error;
Sergunb 0:8918a71cdbe9 204 size_t k;
Sergunb 0:8918a71cdbe9 205
Sergunb 0:8918a71cdbe9 206 //Get the length in octets of the prime
Sergunb 0:8918a71cdbe9 207 k = mpiGetByteLength(&params->p);
Sergunb 0:8918a71cdbe9 208
Sergunb 0:8918a71cdbe9 209 //Check the length of the octet string
Sergunb 0:8918a71cdbe9 210 if(length != (k * 2 + 1))
Sergunb 0:8918a71cdbe9 211 return ERROR_DECODING_FAILED;
Sergunb 0:8918a71cdbe9 212
Sergunb 0:8918a71cdbe9 213 //Compressed point representation is not supported
Sergunb 0:8918a71cdbe9 214 if(data[0] != 0x04)
Sergunb 0:8918a71cdbe9 215 return ERROR_ILLEGAL_PARAMETER;
Sergunb 0:8918a71cdbe9 216
Sergunb 0:8918a71cdbe9 217 //Convert the x-coordinate to a multiple precision integer
Sergunb 0:8918a71cdbe9 218 error = mpiReadRaw(&r->x, data + 1, k);
Sergunb 0:8918a71cdbe9 219 //Any error to report?
Sergunb 0:8918a71cdbe9 220 if(error)
Sergunb 0:8918a71cdbe9 221 return error;
Sergunb 0:8918a71cdbe9 222
Sergunb 0:8918a71cdbe9 223 //Convert the y-coordinate to a multiple precision integer
Sergunb 0:8918a71cdbe9 224 error = mpiReadRaw(&r->y, data + k + 1, k);
Sergunb 0:8918a71cdbe9 225 //Any error to report?
Sergunb 0:8918a71cdbe9 226 if(error)
Sergunb 0:8918a71cdbe9 227 return error;
Sergunb 0:8918a71cdbe9 228
Sergunb 0:8918a71cdbe9 229 //Successful processing
Sergunb 0:8918a71cdbe9 230 return NO_ERROR;
Sergunb 0:8918a71cdbe9 231 }
Sergunb 0:8918a71cdbe9 232
Sergunb 0:8918a71cdbe9 233
Sergunb 0:8918a71cdbe9 234 /**
Sergunb 0:8918a71cdbe9 235 * @brief Convert an EC point to an octet string
Sergunb 0:8918a71cdbe9 236 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 237 * @param[in] a EC point to be converted
Sergunb 0:8918a71cdbe9 238 * @param[out] data Pointer to the octet string
Sergunb 0:8918a71cdbe9 239 * @param[out] length Length of the resulting octet string
Sergunb 0:8918a71cdbe9 240 * @return Error code
Sergunb 0:8918a71cdbe9 241 **/
Sergunb 0:8918a71cdbe9 242
Sergunb 0:8918a71cdbe9 243 error_t ecExport(const EcDomainParameters *params,
Sergunb 0:8918a71cdbe9 244 const EcPoint *a, uint8_t *data, size_t *length)
Sergunb 0:8918a71cdbe9 245 {
Sergunb 0:8918a71cdbe9 246 error_t error;
Sergunb 0:8918a71cdbe9 247 size_t k;
Sergunb 0:8918a71cdbe9 248
Sergunb 0:8918a71cdbe9 249 //Get the length in octets of the prime
Sergunb 0:8918a71cdbe9 250 k = mpiGetByteLength(&params->p);
Sergunb 0:8918a71cdbe9 251
Sergunb 0:8918a71cdbe9 252 //Point compression is not used
Sergunb 0:8918a71cdbe9 253 data[0] = 0x04;
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255 //Convert the x-coordinate to an octet string
Sergunb 0:8918a71cdbe9 256 error = mpiWriteRaw(&a->x, data + 1, k);
Sergunb 0:8918a71cdbe9 257 //Conversion failed?
Sergunb 0:8918a71cdbe9 258 if(error)
Sergunb 0:8918a71cdbe9 259 return error;
Sergunb 0:8918a71cdbe9 260
Sergunb 0:8918a71cdbe9 261 //Convert the y-coordinate to an octet string
Sergunb 0:8918a71cdbe9 262 error = mpiWriteRaw(&a->y, data + k + 1, k);
Sergunb 0:8918a71cdbe9 263 //Conversion failed?
Sergunb 0:8918a71cdbe9 264 if(error)
Sergunb 0:8918a71cdbe9 265 return error;
Sergunb 0:8918a71cdbe9 266
Sergunb 0:8918a71cdbe9 267 //Return the total number of bytes that have been written
Sergunb 0:8918a71cdbe9 268 *length = k * 2 + 1;
Sergunb 0:8918a71cdbe9 269 //Successful processing
Sergunb 0:8918a71cdbe9 270 return NO_ERROR;
Sergunb 0:8918a71cdbe9 271 }
Sergunb 0:8918a71cdbe9 272
Sergunb 0:8918a71cdbe9 273
Sergunb 0:8918a71cdbe9 274 /**
Sergunb 0:8918a71cdbe9 275 * @brief Compute projective representation
Sergunb 0:8918a71cdbe9 276 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 277 * @param[out] r Projective representation of the point
Sergunb 0:8918a71cdbe9 278 * @param[in] s Affine representation of the point
Sergunb 0:8918a71cdbe9 279 * @return Error code
Sergunb 0:8918a71cdbe9 280 **/
Sergunb 0:8918a71cdbe9 281
Sergunb 0:8918a71cdbe9 282 error_t ecProjectify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Sergunb 0:8918a71cdbe9 283 {
Sergunb 0:8918a71cdbe9 284 error_t error;
Sergunb 0:8918a71cdbe9 285
Sergunb 0:8918a71cdbe9 286 //Copy point
Sergunb 0:8918a71cdbe9 287 EC_CHECK(ecCopy(r, s));
Sergunb 0:8918a71cdbe9 288 //Map the point to projective space
Sergunb 0:8918a71cdbe9 289 MPI_CHECK(mpiSetValue(&r->z, 1));
Sergunb 0:8918a71cdbe9 290
Sergunb 0:8918a71cdbe9 291 end:
Sergunb 0:8918a71cdbe9 292 //Return status code
Sergunb 0:8918a71cdbe9 293 return error;
Sergunb 0:8918a71cdbe9 294 }
Sergunb 0:8918a71cdbe9 295
Sergunb 0:8918a71cdbe9 296
Sergunb 0:8918a71cdbe9 297 /**
Sergunb 0:8918a71cdbe9 298 * @brief Recover affine representation
Sergunb 0:8918a71cdbe9 299 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 300 * @param[out] r Affine representation of the point
Sergunb 0:8918a71cdbe9 301 * @param[in] s Projective representation of the point
Sergunb 0:8918a71cdbe9 302 * @return Error code
Sergunb 0:8918a71cdbe9 303 **/
Sergunb 0:8918a71cdbe9 304
Sergunb 0:8918a71cdbe9 305 error_t ecAffinify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Sergunb 0:8918a71cdbe9 306 {
Sergunb 0:8918a71cdbe9 307 error_t error;
Sergunb 0:8918a71cdbe9 308 Mpi a;
Sergunb 0:8918a71cdbe9 309 Mpi b;
Sergunb 0:8918a71cdbe9 310
Sergunb 0:8918a71cdbe9 311 //Point at the infinity?
Sergunb 0:8918a71cdbe9 312 if(!mpiCompInt(&s->z, 0))
Sergunb 0:8918a71cdbe9 313 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 314
Sergunb 0:8918a71cdbe9 315 //Initialize multiple precision integers
Sergunb 0:8918a71cdbe9 316 mpiInit(&a);
Sergunb 0:8918a71cdbe9 317 mpiInit(&b);
Sergunb 0:8918a71cdbe9 318
Sergunb 0:8918a71cdbe9 319 //Compute a = 1/Sz mod p
Sergunb 0:8918a71cdbe9 320 MPI_CHECK(mpiInvMod(&a, &s->z, &params->p));
Sergunb 0:8918a71cdbe9 321
Sergunb 0:8918a71cdbe9 322 //Set Rx = a^2 * Sx mod p
Sergunb 0:8918a71cdbe9 323 EC_CHECK(ecSqrMod(params, &b, &a));
Sergunb 0:8918a71cdbe9 324 EC_CHECK(ecMulMod(params, &r->x, &b, &s->x));
Sergunb 0:8918a71cdbe9 325
Sergunb 0:8918a71cdbe9 326 //Set Ry = a^3 * Sy mod p
Sergunb 0:8918a71cdbe9 327 EC_CHECK(ecMulMod(params, &b, &b, &a));
Sergunb 0:8918a71cdbe9 328 EC_CHECK(ecMulMod(params, &r->y, &b, &s->y));
Sergunb 0:8918a71cdbe9 329
Sergunb 0:8918a71cdbe9 330 //Set Rz = 1
Sergunb 0:8918a71cdbe9 331 MPI_CHECK(mpiSetValue(&r->z, 1));
Sergunb 0:8918a71cdbe9 332
Sergunb 0:8918a71cdbe9 333 end:
Sergunb 0:8918a71cdbe9 334 //Release multiple precision integers
Sergunb 0:8918a71cdbe9 335 mpiFree(&a);
Sergunb 0:8918a71cdbe9 336 mpiFree(&b);
Sergunb 0:8918a71cdbe9 337
Sergunb 0:8918a71cdbe9 338 //Return status code
Sergunb 0:8918a71cdbe9 339 return error;
Sergunb 0:8918a71cdbe9 340 }
Sergunb 0:8918a71cdbe9 341
Sergunb 0:8918a71cdbe9 342
Sergunb 0:8918a71cdbe9 343 /**
Sergunb 0:8918a71cdbe9 344 * @brief Check whether the affine point S is on the curve
Sergunb 0:8918a71cdbe9 345 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 346 * @param[in] s Affine representation of the point
Sergunb 0:8918a71cdbe9 347 * @return TRUE if the affine point S is on the curve, else FALSE
Sergunb 0:8918a71cdbe9 348 **/
Sergunb 0:8918a71cdbe9 349
Sergunb 0:8918a71cdbe9 350 bool_t ecIsPointAffine(const EcDomainParameters *params, const EcPoint *s)
Sergunb 0:8918a71cdbe9 351 {
Sergunb 0:8918a71cdbe9 352 error_t error;
Sergunb 0:8918a71cdbe9 353 Mpi t1;
Sergunb 0:8918a71cdbe9 354 Mpi t2;
Sergunb 0:8918a71cdbe9 355
Sergunb 0:8918a71cdbe9 356 //Initialize multiple precision integers
Sergunb 0:8918a71cdbe9 357 mpiInit(&t1);
Sergunb 0:8918a71cdbe9 358 mpiInit(&t2);
Sergunb 0:8918a71cdbe9 359
Sergunb 0:8918a71cdbe9 360 //Compute t1 = (Sx^3 + a * Sx + b) mod p
Sergunb 0:8918a71cdbe9 361 EC_CHECK(ecSqrMod(params, &t1, &s->x));
Sergunb 0:8918a71cdbe9 362 EC_CHECK(ecMulMod(params, &t1, &t1, &s->x));
Sergunb 0:8918a71cdbe9 363 EC_CHECK(ecMulMod(params, &t2, &params->a, &s->x));
Sergunb 0:8918a71cdbe9 364 EC_CHECK(ecAddMod(params, &t1, &t1, &t2));
Sergunb 0:8918a71cdbe9 365 EC_CHECK(ecAddMod(params, &t1, &t1, &params->b));
Sergunb 0:8918a71cdbe9 366
Sergunb 0:8918a71cdbe9 367 //Compute t2 = Sy^2
Sergunb 0:8918a71cdbe9 368 EC_CHECK(ecSqrMod(params, &t2, &s->y));
Sergunb 0:8918a71cdbe9 369
Sergunb 0:8918a71cdbe9 370 //Check whether the point is on the elliptic curve
Sergunb 0:8918a71cdbe9 371 if(mpiComp(&t1, &t2))
Sergunb 0:8918a71cdbe9 372 error = ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 373
Sergunb 0:8918a71cdbe9 374 end:
Sergunb 0:8918a71cdbe9 375 //Release multiple precision integers
Sergunb 0:8918a71cdbe9 376 mpiFree(&t1);
Sergunb 0:8918a71cdbe9 377 mpiFree(&t2);
Sergunb 0:8918a71cdbe9 378
Sergunb 0:8918a71cdbe9 379 //Return TRUE if the affine point S is on the curve, else FALSE
Sergunb 0:8918a71cdbe9 380 return error ? FALSE : TRUE;
Sergunb 0:8918a71cdbe9 381 }
Sergunb 0:8918a71cdbe9 382
Sergunb 0:8918a71cdbe9 383
Sergunb 0:8918a71cdbe9 384 /**
Sergunb 0:8918a71cdbe9 385 * @brief Point doubling
Sergunb 0:8918a71cdbe9 386 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 387 * @param[out] r Resulting point R = 2S
Sergunb 0:8918a71cdbe9 388 * @param[in] s Point S
Sergunb 0:8918a71cdbe9 389 * @return Error code
Sergunb 0:8918a71cdbe9 390 **/
Sergunb 0:8918a71cdbe9 391
Sergunb 0:8918a71cdbe9 392 error_t ecDouble(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Sergunb 0:8918a71cdbe9 393 {
Sergunb 0:8918a71cdbe9 394 error_t error;
Sergunb 0:8918a71cdbe9 395 Mpi t1;
Sergunb 0:8918a71cdbe9 396 Mpi t2;
Sergunb 0:8918a71cdbe9 397 Mpi t3;
Sergunb 0:8918a71cdbe9 398 Mpi t4;
Sergunb 0:8918a71cdbe9 399 Mpi t5;
Sergunb 0:8918a71cdbe9 400
Sergunb 0:8918a71cdbe9 401 //Initialize multiple precision integers
Sergunb 0:8918a71cdbe9 402 mpiInit(&t1);
Sergunb 0:8918a71cdbe9 403 mpiInit(&t2);
Sergunb 0:8918a71cdbe9 404 mpiInit(&t3);
Sergunb 0:8918a71cdbe9 405 mpiInit(&t4);
Sergunb 0:8918a71cdbe9 406 mpiInit(&t5);
Sergunb 0:8918a71cdbe9 407
Sergunb 0:8918a71cdbe9 408 //Set t1 = Sx
Sergunb 0:8918a71cdbe9 409 MPI_CHECK(mpiCopy(&t1, &s->x));
Sergunb 0:8918a71cdbe9 410 //Set t2 = Sy
Sergunb 0:8918a71cdbe9 411 MPI_CHECK(mpiCopy(&t2, &s->y));
Sergunb 0:8918a71cdbe9 412 //Set t3 = Sz
Sergunb 0:8918a71cdbe9 413 MPI_CHECK(mpiCopy(&t3, &s->z));
Sergunb 0:8918a71cdbe9 414
Sergunb 0:8918a71cdbe9 415 //Point at the infinity?
Sergunb 0:8918a71cdbe9 416 if(!mpiCompInt(&t3, 0))
Sergunb 0:8918a71cdbe9 417 {
Sergunb 0:8918a71cdbe9 418 //Set R = (1, 1, 0)
Sergunb 0:8918a71cdbe9 419 MPI_CHECK(mpiSetValue(&r->x, 1));
Sergunb 0:8918a71cdbe9 420 MPI_CHECK(mpiSetValue(&r->y, 1));
Sergunb 0:8918a71cdbe9 421 MPI_CHECK(mpiSetValue(&r->z, 0));
Sergunb 0:8918a71cdbe9 422 }
Sergunb 0:8918a71cdbe9 423 else
Sergunb 0:8918a71cdbe9 424 {
Sergunb 0:8918a71cdbe9 425 //SECP K1 elliptic curve?
Sergunb 0:8918a71cdbe9 426 if(params->type == EC_CURVE_TYPE_SECP_K1)
Sergunb 0:8918a71cdbe9 427 {
Sergunb 0:8918a71cdbe9 428 //Compute t5 = t1^2
Sergunb 0:8918a71cdbe9 429 EC_CHECK(ecSqrMod(params, &t5, &t1));
Sergunb 0:8918a71cdbe9 430 //Compute t4 = 3 * t5
Sergunb 0:8918a71cdbe9 431 EC_CHECK(ecAddMod(params, &t4, &t5, &t5));
Sergunb 0:8918a71cdbe9 432 EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
Sergunb 0:8918a71cdbe9 433 }
Sergunb 0:8918a71cdbe9 434 //SECP R1 elliptic curve?
Sergunb 0:8918a71cdbe9 435 else if(params->type == EC_CURVE_TYPE_SECP_R1)
Sergunb 0:8918a71cdbe9 436 {
Sergunb 0:8918a71cdbe9 437 //Compute t4 = t3^2
Sergunb 0:8918a71cdbe9 438 EC_CHECK(ecSqrMod(params, &t4, &t3));
Sergunb 0:8918a71cdbe9 439 //Compute t5 = t1 - t4
Sergunb 0:8918a71cdbe9 440 EC_CHECK(ecSubMod(params, &t5, &t1, &t4));
Sergunb 0:8918a71cdbe9 441 //Compute t4 = t1 + t4
Sergunb 0:8918a71cdbe9 442 EC_CHECK(ecAddMod(params, &t4, &t1, &t4));
Sergunb 0:8918a71cdbe9 443 //Compute t5 = t4 * t5
Sergunb 0:8918a71cdbe9 444 EC_CHECK(ecMulMod(params, &t5, &t4, &t5));
Sergunb 0:8918a71cdbe9 445 //Compute t4 = 3 * t5
Sergunb 0:8918a71cdbe9 446 EC_CHECK(ecAddMod(params, &t4, &t5, &t5));
Sergunb 0:8918a71cdbe9 447 EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
Sergunb 0:8918a71cdbe9 448 }
Sergunb 0:8918a71cdbe9 449 else
Sergunb 0:8918a71cdbe9 450 {
Sergunb 0:8918a71cdbe9 451 //Compute t4 = t3^4
Sergunb 0:8918a71cdbe9 452 EC_CHECK(ecSqrMod(params, &t4, &t3));
Sergunb 0:8918a71cdbe9 453 EC_CHECK(ecSqrMod(params, &t4, &t4));
Sergunb 0:8918a71cdbe9 454 //Compute t4 = a * t4
Sergunb 0:8918a71cdbe9 455 EC_CHECK(ecMulMod(params, &t4, &t4, &params->a));
Sergunb 0:8918a71cdbe9 456 //Compute t5 = t1^2
Sergunb 0:8918a71cdbe9 457 EC_CHECK(ecSqrMod(params, &t5, &t1));
Sergunb 0:8918a71cdbe9 458 //Compute t4 = t4 + 3 * t5
Sergunb 0:8918a71cdbe9 459 EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
Sergunb 0:8918a71cdbe9 460 EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
Sergunb 0:8918a71cdbe9 461 EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
Sergunb 0:8918a71cdbe9 462 }
Sergunb 0:8918a71cdbe9 463
Sergunb 0:8918a71cdbe9 464 //Compute t3 = t3 * t2
Sergunb 0:8918a71cdbe9 465 EC_CHECK(ecMulMod(params, &t3, &t3, &t2));
Sergunb 0:8918a71cdbe9 466 //Compute t3 = 2 * t3
Sergunb 0:8918a71cdbe9 467 EC_CHECK(ecAddMod(params, &t3, &t3, &t3));
Sergunb 0:8918a71cdbe9 468 //Compute t2 = t2^2
Sergunb 0:8918a71cdbe9 469 EC_CHECK(ecSqrMod(params, &t2, &t2));
Sergunb 0:8918a71cdbe9 470 //Compute t5 = t1 * t2
Sergunb 0:8918a71cdbe9 471 EC_CHECK(ecMulMod(params, &t5, &t1, &t2));
Sergunb 0:8918a71cdbe9 472 //Compute t5 = 4 * t5
Sergunb 0:8918a71cdbe9 473 EC_CHECK(ecAddMod(params, &t5, &t5, &t5));
Sergunb 0:8918a71cdbe9 474 EC_CHECK(ecAddMod(params, &t5, &t5, &t5));
Sergunb 0:8918a71cdbe9 475 //Compute t1 = t4^2
Sergunb 0:8918a71cdbe9 476 EC_CHECK(ecSqrMod(params, &t1, &t4));
Sergunb 0:8918a71cdbe9 477 //Compute t1 = t1 - 2 * t5
Sergunb 0:8918a71cdbe9 478 EC_CHECK(ecSubMod(params, &t1, &t1, &t5));
Sergunb 0:8918a71cdbe9 479 EC_CHECK(ecSubMod(params, &t1, &t1, &t5));
Sergunb 0:8918a71cdbe9 480 //Compute t2 = t2^2
Sergunb 0:8918a71cdbe9 481 EC_CHECK(ecSqrMod(params, &t2, &t2));
Sergunb 0:8918a71cdbe9 482 //Compute t2 = 8 * t2
Sergunb 0:8918a71cdbe9 483 EC_CHECK(ecAddMod(params, &t2, &t2, &t2));
Sergunb 0:8918a71cdbe9 484 EC_CHECK(ecAddMod(params, &t2, &t2, &t2));
Sergunb 0:8918a71cdbe9 485 EC_CHECK(ecAddMod(params, &t2, &t2, &t2));
Sergunb 0:8918a71cdbe9 486 //Compute t5 = t5 - t1
Sergunb 0:8918a71cdbe9 487 EC_CHECK(ecSubMod(params, &t5, &t5, &t1));
Sergunb 0:8918a71cdbe9 488 //Compute t5 = t4 * t5
Sergunb 0:8918a71cdbe9 489 EC_CHECK(ecMulMod(params, &t5, &t4, &t5));
Sergunb 0:8918a71cdbe9 490 //Compute t2 = t5 - t2
Sergunb 0:8918a71cdbe9 491 EC_CHECK(ecSubMod(params, &t2, &t5, &t2));
Sergunb 0:8918a71cdbe9 492
Sergunb 0:8918a71cdbe9 493 //Set Rx = t1
Sergunb 0:8918a71cdbe9 494 MPI_CHECK(mpiCopy(&r->x, &t1));
Sergunb 0:8918a71cdbe9 495 //Set Ry = t2
Sergunb 0:8918a71cdbe9 496 MPI_CHECK(mpiCopy(&r->y, &t2));
Sergunb 0:8918a71cdbe9 497 //Set Rz = t3
Sergunb 0:8918a71cdbe9 498 MPI_CHECK(mpiCopy(&r->z, &t3));
Sergunb 0:8918a71cdbe9 499 }
Sergunb 0:8918a71cdbe9 500
Sergunb 0:8918a71cdbe9 501 end:
Sergunb 0:8918a71cdbe9 502 //Release multiple precision integers
Sergunb 0:8918a71cdbe9 503 mpiFree(&t1);
Sergunb 0:8918a71cdbe9 504 mpiFree(&t2);
Sergunb 0:8918a71cdbe9 505 mpiFree(&t3);
Sergunb 0:8918a71cdbe9 506 mpiFree(&t4);
Sergunb 0:8918a71cdbe9 507 mpiFree(&t5);
Sergunb 0:8918a71cdbe9 508
Sergunb 0:8918a71cdbe9 509 //Return status code
Sergunb 0:8918a71cdbe9 510 return error;
Sergunb 0:8918a71cdbe9 511 }
Sergunb 0:8918a71cdbe9 512
Sergunb 0:8918a71cdbe9 513
Sergunb 0:8918a71cdbe9 514 /**
Sergunb 0:8918a71cdbe9 515 * @brief Point addition (helper routine)
Sergunb 0:8918a71cdbe9 516 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 517 * @param[out] r Resulting point R = S + T
Sergunb 0:8918a71cdbe9 518 * @param[in] s First operand
Sergunb 0:8918a71cdbe9 519 * @param[in] t Second operand
Sergunb 0:8918a71cdbe9 520 * @return Error code
Sergunb 0:8918a71cdbe9 521 **/
Sergunb 0:8918a71cdbe9 522
Sergunb 0:8918a71cdbe9 523 error_t ecAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Sergunb 0:8918a71cdbe9 524 {
Sergunb 0:8918a71cdbe9 525 error_t error;
Sergunb 0:8918a71cdbe9 526 Mpi t1;
Sergunb 0:8918a71cdbe9 527 Mpi t2;
Sergunb 0:8918a71cdbe9 528 Mpi t3;
Sergunb 0:8918a71cdbe9 529 Mpi t4;
Sergunb 0:8918a71cdbe9 530 Mpi t5;
Sergunb 0:8918a71cdbe9 531 Mpi t6;
Sergunb 0:8918a71cdbe9 532 Mpi t7;
Sergunb 0:8918a71cdbe9 533
Sergunb 0:8918a71cdbe9 534 //Initialize multiple precision integers
Sergunb 0:8918a71cdbe9 535 mpiInit(&t1);
Sergunb 0:8918a71cdbe9 536 mpiInit(&t2);
Sergunb 0:8918a71cdbe9 537 mpiInit(&t3);
Sergunb 0:8918a71cdbe9 538 mpiInit(&t4);
Sergunb 0:8918a71cdbe9 539 mpiInit(&t5);
Sergunb 0:8918a71cdbe9 540 mpiInit(&t6);
Sergunb 0:8918a71cdbe9 541 mpiInit(&t7);
Sergunb 0:8918a71cdbe9 542
Sergunb 0:8918a71cdbe9 543 //Set t1 = Sx
Sergunb 0:8918a71cdbe9 544 MPI_CHECK(mpiCopy(&t1, &s->x));
Sergunb 0:8918a71cdbe9 545 //Set t2 = Sy
Sergunb 0:8918a71cdbe9 546 MPI_CHECK(mpiCopy(&t2, &s->y));
Sergunb 0:8918a71cdbe9 547 //Set t3 = Sz
Sergunb 0:8918a71cdbe9 548 MPI_CHECK(mpiCopy(&t3, &s->z));
Sergunb 0:8918a71cdbe9 549 //Set t4 = Tx
Sergunb 0:8918a71cdbe9 550 MPI_CHECK(mpiCopy(&t4, &t->x));
Sergunb 0:8918a71cdbe9 551 //Set t5 = Ty
Sergunb 0:8918a71cdbe9 552 MPI_CHECK(mpiCopy(&t5, &t->y));
Sergunb 0:8918a71cdbe9 553
Sergunb 0:8918a71cdbe9 554 //Check whether Tz != 1
Sergunb 0:8918a71cdbe9 555 if(mpiCompInt(&t->z, 1))
Sergunb 0:8918a71cdbe9 556 {
Sergunb 0:8918a71cdbe9 557 //Compute t6 = Tz
Sergunb 0:8918a71cdbe9 558 MPI_CHECK(mpiCopy(&t6, &t->z));
Sergunb 0:8918a71cdbe9 559 //Compute t7 = t6^2
Sergunb 0:8918a71cdbe9 560 EC_CHECK(ecSqrMod(params, &t7, &t6));
Sergunb 0:8918a71cdbe9 561 //Compute t1 = t1 * t7
Sergunb 0:8918a71cdbe9 562 EC_CHECK(ecMulMod(params, &t1, &t1, &t7));
Sergunb 0:8918a71cdbe9 563 //Compute t7 = t6 * t7
Sergunb 0:8918a71cdbe9 564 EC_CHECK(ecMulMod(params, &t7, &t6, &t7));
Sergunb 0:8918a71cdbe9 565 //Compute t2 = t2 * t7
Sergunb 0:8918a71cdbe9 566 EC_CHECK(ecMulMod(params, &t2, &t2, &t7));
Sergunb 0:8918a71cdbe9 567 }
Sergunb 0:8918a71cdbe9 568
Sergunb 0:8918a71cdbe9 569 //Compute t7 = t3^2
Sergunb 0:8918a71cdbe9 570 EC_CHECK(ecSqrMod(params, &t7, &t3));
Sergunb 0:8918a71cdbe9 571 //Compute t4 = t4 * t7
Sergunb 0:8918a71cdbe9 572 EC_CHECK(ecMulMod(params, &t4, &t4, &t7));
Sergunb 0:8918a71cdbe9 573 //Compute t7 = t3 * t7
Sergunb 0:8918a71cdbe9 574 EC_CHECK(ecMulMod(params, &t7, &t3, &t7));
Sergunb 0:8918a71cdbe9 575 //Compute t5 = t5 * t7
Sergunb 0:8918a71cdbe9 576 EC_CHECK(ecMulMod(params, &t5, &t5, &t7));
Sergunb 0:8918a71cdbe9 577 //Compute t4 = t1 - t4
Sergunb 0:8918a71cdbe9 578 EC_CHECK(ecSubMod(params, &t4, &t1, &t4));
Sergunb 0:8918a71cdbe9 579 //Compute t5 = t2 - t5
Sergunb 0:8918a71cdbe9 580 EC_CHECK(ecSubMod(params, &t5, &t2, &t5));
Sergunb 0:8918a71cdbe9 581
Sergunb 0:8918a71cdbe9 582 //Check whether t4 == 0
Sergunb 0:8918a71cdbe9 583 if(!mpiCompInt(&t4, 0))
Sergunb 0:8918a71cdbe9 584 {
Sergunb 0:8918a71cdbe9 585 //Check whether t5 == 0
Sergunb 0:8918a71cdbe9 586 if(!mpiCompInt(&t5, 0))
Sergunb 0:8918a71cdbe9 587 {
Sergunb 0:8918a71cdbe9 588 //Set R = (0, 0, 0)
Sergunb 0:8918a71cdbe9 589 MPI_CHECK(mpiSetValue(&r->x, 0));
Sergunb 0:8918a71cdbe9 590 MPI_CHECK(mpiSetValue(&r->y, 0));
Sergunb 0:8918a71cdbe9 591 MPI_CHECK(mpiSetValue(&r->z, 0));
Sergunb 0:8918a71cdbe9 592 }
Sergunb 0:8918a71cdbe9 593 else
Sergunb 0:8918a71cdbe9 594 {
Sergunb 0:8918a71cdbe9 595 //Set R = (1, 1, 0)
Sergunb 0:8918a71cdbe9 596 MPI_CHECK(mpiSetValue(&r->x, 1));
Sergunb 0:8918a71cdbe9 597 MPI_CHECK(mpiSetValue(&r->y, 1));
Sergunb 0:8918a71cdbe9 598 MPI_CHECK(mpiSetValue(&r->z, 0));
Sergunb 0:8918a71cdbe9 599 }
Sergunb 0:8918a71cdbe9 600 }
Sergunb 0:8918a71cdbe9 601 else
Sergunb 0:8918a71cdbe9 602 {
Sergunb 0:8918a71cdbe9 603 //Compute t1 = 2 * t1 - t4
Sergunb 0:8918a71cdbe9 604 EC_CHECK(ecAddMod(params, &t1, &t1, &t1));
Sergunb 0:8918a71cdbe9 605 EC_CHECK(ecSubMod(params, &t1, &t1, &t4));
Sergunb 0:8918a71cdbe9 606 //Compute t2 = 2 * t2 - t5
Sergunb 0:8918a71cdbe9 607 EC_CHECK(ecAddMod(params, &t2, &t2, &t2));
Sergunb 0:8918a71cdbe9 608 EC_CHECK(ecSubMod(params, &t2, &t2, &t5));
Sergunb 0:8918a71cdbe9 609
Sergunb 0:8918a71cdbe9 610 //Check whether Tz != 1
Sergunb 0:8918a71cdbe9 611 if(mpiCompInt(&t->z, 1))
Sergunb 0:8918a71cdbe9 612 {
Sergunb 0:8918a71cdbe9 613 //Compute t3 = t3 * t6
Sergunb 0:8918a71cdbe9 614 EC_CHECK(ecMulMod(params, &t3, &t3, &t6));
Sergunb 0:8918a71cdbe9 615 }
Sergunb 0:8918a71cdbe9 616
Sergunb 0:8918a71cdbe9 617 //Compute t3 = t3 * t4
Sergunb 0:8918a71cdbe9 618 EC_CHECK(ecMulMod(params, &t3, &t3, &t4));
Sergunb 0:8918a71cdbe9 619 //Compute t7 = t4^2
Sergunb 0:8918a71cdbe9 620 EC_CHECK(ecSqrMod(params, &t7, &t4));
Sergunb 0:8918a71cdbe9 621 //Compute t4 = t4 * t7
Sergunb 0:8918a71cdbe9 622 EC_CHECK(ecMulMod(params, &t4, &t4, &t7));
Sergunb 0:8918a71cdbe9 623 //Compute t7 = t1 * t7
Sergunb 0:8918a71cdbe9 624 EC_CHECK(ecMulMod(params, &t7, &t1, &t7));
Sergunb 0:8918a71cdbe9 625 //Compute t1 = t5^2
Sergunb 0:8918a71cdbe9 626 EC_CHECK(ecSqrMod(params, &t1, &t5));
Sergunb 0:8918a71cdbe9 627 //Compute t1 = t1 - t7
Sergunb 0:8918a71cdbe9 628 EC_CHECK(ecSubMod(params, &t1, &t1, &t7));
Sergunb 0:8918a71cdbe9 629 //Compute t7 = t7 - 2 * t1
Sergunb 0:8918a71cdbe9 630 EC_CHECK(ecAddMod(params, &t6, &t1, &t1));
Sergunb 0:8918a71cdbe9 631 EC_CHECK(ecSubMod(params, &t7, &t7, &t6));
Sergunb 0:8918a71cdbe9 632 //Compute t5 = t5 * t7
Sergunb 0:8918a71cdbe9 633 EC_CHECK(ecMulMod(params, &t5, &t5, &t7));
Sergunb 0:8918a71cdbe9 634 //Compute t4 = t2 * t4
Sergunb 0:8918a71cdbe9 635 EC_CHECK(ecMulMod(params, &t4, &t2, &t4));
Sergunb 0:8918a71cdbe9 636 //Compute t2 = t5 - t4
Sergunb 0:8918a71cdbe9 637 EC_CHECK(ecSubMod(params, &t2, &t5, &t4));
Sergunb 0:8918a71cdbe9 638
Sergunb 0:8918a71cdbe9 639 //Compute t2 = t2 / 2
Sergunb 0:8918a71cdbe9 640 if(mpiIsEven(&t2))
Sergunb 0:8918a71cdbe9 641 {
Sergunb 0:8918a71cdbe9 642 MPI_CHECK(mpiShiftRight(&t2, 1));
Sergunb 0:8918a71cdbe9 643 }
Sergunb 0:8918a71cdbe9 644 else
Sergunb 0:8918a71cdbe9 645 {
Sergunb 0:8918a71cdbe9 646 MPI_CHECK(mpiAdd(&t2, &t2, &params->p));
Sergunb 0:8918a71cdbe9 647 MPI_CHECK(mpiShiftRight(&t2, 1));
Sergunb 0:8918a71cdbe9 648 }
Sergunb 0:8918a71cdbe9 649
Sergunb 0:8918a71cdbe9 650 //Set Rx = t1
Sergunb 0:8918a71cdbe9 651 MPI_CHECK(mpiCopy(&r->x, &t1));
Sergunb 0:8918a71cdbe9 652 //Set Ry = t2
Sergunb 0:8918a71cdbe9 653 MPI_CHECK(mpiCopy(&r->y, &t2));
Sergunb 0:8918a71cdbe9 654 //Set Rz = t3
Sergunb 0:8918a71cdbe9 655 MPI_CHECK(mpiCopy(&r->z, &t3));
Sergunb 0:8918a71cdbe9 656 }
Sergunb 0:8918a71cdbe9 657
Sergunb 0:8918a71cdbe9 658 end:
Sergunb 0:8918a71cdbe9 659 //Release multiple precision integers
Sergunb 0:8918a71cdbe9 660 mpiFree(&t1);
Sergunb 0:8918a71cdbe9 661 mpiFree(&t2);
Sergunb 0:8918a71cdbe9 662 mpiFree(&t3);
Sergunb 0:8918a71cdbe9 663 mpiFree(&t4);
Sergunb 0:8918a71cdbe9 664 mpiFree(&t5);
Sergunb 0:8918a71cdbe9 665 mpiFree(&t6);
Sergunb 0:8918a71cdbe9 666 mpiFree(&t7);
Sergunb 0:8918a71cdbe9 667
Sergunb 0:8918a71cdbe9 668 //Return status code
Sergunb 0:8918a71cdbe9 669 return error;
Sergunb 0:8918a71cdbe9 670 }
Sergunb 0:8918a71cdbe9 671
Sergunb 0:8918a71cdbe9 672
Sergunb 0:8918a71cdbe9 673 /**
Sergunb 0:8918a71cdbe9 674 * @brief Point addition
Sergunb 0:8918a71cdbe9 675 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 676 * @param[out] r Resulting point R = S + T
Sergunb 0:8918a71cdbe9 677 * @param[in] s First operand
Sergunb 0:8918a71cdbe9 678 * @param[in] t Second operand
Sergunb 0:8918a71cdbe9 679 * @return Error code
Sergunb 0:8918a71cdbe9 680 **/
Sergunb 0:8918a71cdbe9 681
Sergunb 0:8918a71cdbe9 682 error_t ecFullAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Sergunb 0:8918a71cdbe9 683 {
Sergunb 0:8918a71cdbe9 684 error_t error;
Sergunb 0:8918a71cdbe9 685
Sergunb 0:8918a71cdbe9 686 //Check whether Sz == 0
Sergunb 0:8918a71cdbe9 687 if(!mpiCompInt(&s->z, 0))
Sergunb 0:8918a71cdbe9 688 {
Sergunb 0:8918a71cdbe9 689 //Set R = T
Sergunb 0:8918a71cdbe9 690 MPI_CHECK(mpiCopy(&r->x, &t->x));
Sergunb 0:8918a71cdbe9 691 MPI_CHECK(mpiCopy(&r->y, &t->y));
Sergunb 0:8918a71cdbe9 692 MPI_CHECK(mpiCopy(&r->z, &t->z));
Sergunb 0:8918a71cdbe9 693 }
Sergunb 0:8918a71cdbe9 694 //Check whether Tz == 0
Sergunb 0:8918a71cdbe9 695 else if(!mpiCompInt(&t->z, 0))
Sergunb 0:8918a71cdbe9 696 {
Sergunb 0:8918a71cdbe9 697 //Set R = S
Sergunb 0:8918a71cdbe9 698 MPI_CHECK(mpiCopy(&r->x, &s->x));
Sergunb 0:8918a71cdbe9 699 MPI_CHECK(mpiCopy(&r->y, &s->y));
Sergunb 0:8918a71cdbe9 700 MPI_CHECK(mpiCopy(&r->z, &s->z));
Sergunb 0:8918a71cdbe9 701 }
Sergunb 0:8918a71cdbe9 702 else
Sergunb 0:8918a71cdbe9 703 {
Sergunb 0:8918a71cdbe9 704 //Compute R = S + T
Sergunb 0:8918a71cdbe9 705 EC_CHECK(ecAdd(params, r, s, t));
Sergunb 0:8918a71cdbe9 706
Sergunb 0:8918a71cdbe9 707 //Check whether R == (0, 0, 0)
Sergunb 0:8918a71cdbe9 708 if(!mpiCompInt(&r->x, 0) && !mpiCompInt(&r->y, 0) && !mpiCompInt(&r->z, 0))
Sergunb 0:8918a71cdbe9 709 {
Sergunb 0:8918a71cdbe9 710 //Compute R = 2 * S
Sergunb 0:8918a71cdbe9 711 EC_CHECK(ecDouble(params, r, s));
Sergunb 0:8918a71cdbe9 712 }
Sergunb 0:8918a71cdbe9 713 }
Sergunb 0:8918a71cdbe9 714
Sergunb 0:8918a71cdbe9 715 end:
Sergunb 0:8918a71cdbe9 716 //Return status code
Sergunb 0:8918a71cdbe9 717 return error;
Sergunb 0:8918a71cdbe9 718 }
Sergunb 0:8918a71cdbe9 719
Sergunb 0:8918a71cdbe9 720
Sergunb 0:8918a71cdbe9 721 /**
Sergunb 0:8918a71cdbe9 722 * @brief Point subtraction
Sergunb 0:8918a71cdbe9 723 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 724 * @param[out] r Resulting point R = S - T
Sergunb 0:8918a71cdbe9 725 * @param[in] s First operand
Sergunb 0:8918a71cdbe9 726 * @param[in] t Second operand
Sergunb 0:8918a71cdbe9 727 * @return Error code
Sergunb 0:8918a71cdbe9 728 **/
Sergunb 0:8918a71cdbe9 729
Sergunb 0:8918a71cdbe9 730 error_t ecFullSub(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Sergunb 0:8918a71cdbe9 731 {
Sergunb 0:8918a71cdbe9 732 error_t error;
Sergunb 0:8918a71cdbe9 733 EcPoint u;
Sergunb 0:8918a71cdbe9 734
Sergunb 0:8918a71cdbe9 735 //Initialize EC point
Sergunb 0:8918a71cdbe9 736 ecInit(&u);
Sergunb 0:8918a71cdbe9 737
Sergunb 0:8918a71cdbe9 738 //Set Ux = Tx and Uz = Tz
Sergunb 0:8918a71cdbe9 739 MPI_CHECK(mpiCopy(&u.x, &t->x));
Sergunb 0:8918a71cdbe9 740 MPI_CHECK(mpiCopy(&u.z, &t->z));
Sergunb 0:8918a71cdbe9 741 //Set Uy = p - Ty
Sergunb 0:8918a71cdbe9 742 MPI_CHECK(mpiSub(&u.y, &params->p, &t->y));
Sergunb 0:8918a71cdbe9 743
Sergunb 0:8918a71cdbe9 744 //Compute R = S + U
Sergunb 0:8918a71cdbe9 745 EC_CHECK(ecFullAdd(params, r, s, &u));
Sergunb 0:8918a71cdbe9 746
Sergunb 0:8918a71cdbe9 747 end:
Sergunb 0:8918a71cdbe9 748 //Release EC point
Sergunb 0:8918a71cdbe9 749 ecFree(&u);
Sergunb 0:8918a71cdbe9 750
Sergunb 0:8918a71cdbe9 751 //Return status code
Sergunb 0:8918a71cdbe9 752 return error;
Sergunb 0:8918a71cdbe9 753 }
Sergunb 0:8918a71cdbe9 754
Sergunb 0:8918a71cdbe9 755
Sergunb 0:8918a71cdbe9 756 /**
Sergunb 0:8918a71cdbe9 757 * @brief Scalar multiplication
Sergunb 0:8918a71cdbe9 758 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 759 * @param[out] r Resulting point R = d.S
Sergunb 0:8918a71cdbe9 760 * @param[in] d An integer d such as 0 <= d < p
Sergunb 0:8918a71cdbe9 761 * @param[in] s EC point
Sergunb 0:8918a71cdbe9 762 * @return Error code
Sergunb 0:8918a71cdbe9 763 **/
Sergunb 0:8918a71cdbe9 764
Sergunb 0:8918a71cdbe9 765 error_t ecMult(const EcDomainParameters *params, EcPoint *r, const Mpi *d, const EcPoint *s)
Sergunb 0:8918a71cdbe9 766 {
Sergunb 0:8918a71cdbe9 767 error_t error;
Sergunb 0:8918a71cdbe9 768 uint_t i;
Sergunb 0:8918a71cdbe9 769 Mpi h;
Sergunb 0:8918a71cdbe9 770
Sergunb 0:8918a71cdbe9 771 //Initialize multiple precision integer
Sergunb 0:8918a71cdbe9 772 mpiInit(&h);
Sergunb 0:8918a71cdbe9 773
Sergunb 0:8918a71cdbe9 774 //Check whether d == 0
Sergunb 0:8918a71cdbe9 775 if(!mpiCompInt(d, 0))
Sergunb 0:8918a71cdbe9 776 {
Sergunb 0:8918a71cdbe9 777 //Set R = (1, 1, 0)
Sergunb 0:8918a71cdbe9 778 MPI_CHECK(mpiSetValue(&r->x, 1));
Sergunb 0:8918a71cdbe9 779 MPI_CHECK(mpiSetValue(&r->y, 1));
Sergunb 0:8918a71cdbe9 780 MPI_CHECK(mpiSetValue(&r->z, 0));
Sergunb 0:8918a71cdbe9 781 }
Sergunb 0:8918a71cdbe9 782 //Check whether d == 1
Sergunb 0:8918a71cdbe9 783 else if(!mpiCompInt(d, 1))
Sergunb 0:8918a71cdbe9 784 {
Sergunb 0:8918a71cdbe9 785 //Set R = S
Sergunb 0:8918a71cdbe9 786 MPI_CHECK(mpiCopy(&r->x, &s->x));
Sergunb 0:8918a71cdbe9 787 MPI_CHECK(mpiCopy(&r->y, &s->y));
Sergunb 0:8918a71cdbe9 788 MPI_CHECK(mpiCopy(&r->z, &s->z));
Sergunb 0:8918a71cdbe9 789 }
Sergunb 0:8918a71cdbe9 790 //Check whether Sz == 0
Sergunb 0:8918a71cdbe9 791 else if(!mpiCompInt(&s->z, 0))
Sergunb 0:8918a71cdbe9 792 {
Sergunb 0:8918a71cdbe9 793 //Set R = (1, 1, 0)
Sergunb 0:8918a71cdbe9 794 MPI_CHECK(mpiSetValue(&r->x, 1));
Sergunb 0:8918a71cdbe9 795 MPI_CHECK(mpiSetValue(&r->y, 1));
Sergunb 0:8918a71cdbe9 796 MPI_CHECK(mpiSetValue(&r->z, 0));
Sergunb 0:8918a71cdbe9 797 }
Sergunb 0:8918a71cdbe9 798 else
Sergunb 0:8918a71cdbe9 799 {
Sergunb 0:8918a71cdbe9 800 //Check whether Sz != 1
Sergunb 0:8918a71cdbe9 801 if(mpiCompInt(&s->z, 1))
Sergunb 0:8918a71cdbe9 802 {
Sergunb 0:8918a71cdbe9 803 //Normalize S
Sergunb 0:8918a71cdbe9 804 EC_CHECK(ecAffinify(params, r, s));
Sergunb 0:8918a71cdbe9 805 EC_CHECK(ecProjectify(params, r, r));
Sergunb 0:8918a71cdbe9 806 }
Sergunb 0:8918a71cdbe9 807 else
Sergunb 0:8918a71cdbe9 808 {
Sergunb 0:8918a71cdbe9 809 //Set R = S
Sergunb 0:8918a71cdbe9 810 MPI_CHECK(mpiCopy(&r->x, &s->x));
Sergunb 0:8918a71cdbe9 811 MPI_CHECK(mpiCopy(&r->y, &s->y));
Sergunb 0:8918a71cdbe9 812 MPI_CHECK(mpiCopy(&r->z, &s->z));
Sergunb 0:8918a71cdbe9 813 }
Sergunb 0:8918a71cdbe9 814
Sergunb 0:8918a71cdbe9 815 //Left-to-right binary method
Sergunb 0:8918a71cdbe9 816 #if 0
Sergunb 0:8918a71cdbe9 817 for(i = mpiGetBitLength(d) - 1; i >= 1; i--)
Sergunb 0:8918a71cdbe9 818 {
Sergunb 0:8918a71cdbe9 819 //Point doubling
Sergunb 0:8918a71cdbe9 820 EC_CHECK(ecDouble(params, r, r));
Sergunb 0:8918a71cdbe9 821
Sergunb 0:8918a71cdbe9 822 if(mpiGetBitValue(d, i - 1))
Sergunb 0:8918a71cdbe9 823 {
Sergunb 0:8918a71cdbe9 824 //Compute R = R + S
Sergunb 0:8918a71cdbe9 825 EC_CHECK(ecFullAdd(params, r, r, s));
Sergunb 0:8918a71cdbe9 826 }
Sergunb 0:8918a71cdbe9 827 }
Sergunb 0:8918a71cdbe9 828 //Fast left-to-right binary method
Sergunb 0:8918a71cdbe9 829 #else
Sergunb 0:8918a71cdbe9 830 //Precompute h = 3 * d
Sergunb 0:8918a71cdbe9 831 MPI_CHECK(mpiAdd(&h, d, d));
Sergunb 0:8918a71cdbe9 832 MPI_CHECK(mpiAdd(&h, &h, d));
Sergunb 0:8918a71cdbe9 833
Sergunb 0:8918a71cdbe9 834 //Scalar multiplication
Sergunb 0:8918a71cdbe9 835 for(i = mpiGetBitLength(&h) - 2; i >= 1; i--)
Sergunb 0:8918a71cdbe9 836 {
Sergunb 0:8918a71cdbe9 837 //Point doubling
Sergunb 0:8918a71cdbe9 838 EC_CHECK(ecDouble(params, r, r));
Sergunb 0:8918a71cdbe9 839
Sergunb 0:8918a71cdbe9 840 //Check whether h(i) == 1 and k(i) == 0
Sergunb 0:8918a71cdbe9 841 if(mpiGetBitValue(&h, i) && !mpiGetBitValue(d, i))
Sergunb 0:8918a71cdbe9 842 {
Sergunb 0:8918a71cdbe9 843 //Compute R = R + S
Sergunb 0:8918a71cdbe9 844 EC_CHECK(ecFullAdd(params, r, r, s));
Sergunb 0:8918a71cdbe9 845 }
Sergunb 0:8918a71cdbe9 846 //Check whether h(i) == 0 and k(i) == 1
Sergunb 0:8918a71cdbe9 847 else if(!mpiGetBitValue(&h, i) && mpiGetBitValue(d, i))
Sergunb 0:8918a71cdbe9 848 {
Sergunb 0:8918a71cdbe9 849 //Compute R = R - S
Sergunb 0:8918a71cdbe9 850 EC_CHECK(ecFullSub(params, r, r, s));
Sergunb 0:8918a71cdbe9 851 }
Sergunb 0:8918a71cdbe9 852 }
Sergunb 0:8918a71cdbe9 853 #endif
Sergunb 0:8918a71cdbe9 854 }
Sergunb 0:8918a71cdbe9 855
Sergunb 0:8918a71cdbe9 856 end:
Sergunb 0:8918a71cdbe9 857 //Release multiple precision integer
Sergunb 0:8918a71cdbe9 858 mpiFree(&h);
Sergunb 0:8918a71cdbe9 859
Sergunb 0:8918a71cdbe9 860 //Return status code
Sergunb 0:8918a71cdbe9 861 return error;
Sergunb 0:8918a71cdbe9 862 }
Sergunb 0:8918a71cdbe9 863
Sergunb 0:8918a71cdbe9 864
Sergunb 0:8918a71cdbe9 865 /**
Sergunb 0:8918a71cdbe9 866 * @brief An auxiliary function for the twin multiplication
Sergunb 0:8918a71cdbe9 867 * @param[in] t An integer T such as 0 <= T <= 31
Sergunb 0:8918a71cdbe9 868 * @return Output value
Sergunb 0:8918a71cdbe9 869 **/
Sergunb 0:8918a71cdbe9 870
Sergunb 0:8918a71cdbe9 871 uint_t ecTwinMultF(uint_t t)
Sergunb 0:8918a71cdbe9 872 {
Sergunb 0:8918a71cdbe9 873 if(18 <= t && t < 22)
Sergunb 0:8918a71cdbe9 874 return 9;
Sergunb 0:8918a71cdbe9 875 else if(14 <= t && t < 18)
Sergunb 0:8918a71cdbe9 876 return 10;
Sergunb 0:8918a71cdbe9 877 else if(22 <= t && t < 24)
Sergunb 0:8918a71cdbe9 878 return 11;
Sergunb 0:8918a71cdbe9 879 else if(4 <= t && t < 12)
Sergunb 0:8918a71cdbe9 880 return 14;
Sergunb 0:8918a71cdbe9 881 else
Sergunb 0:8918a71cdbe9 882 return 12;
Sergunb 0:8918a71cdbe9 883 }
Sergunb 0:8918a71cdbe9 884
Sergunb 0:8918a71cdbe9 885
Sergunb 0:8918a71cdbe9 886 /**
Sergunb 0:8918a71cdbe9 887 * @brief Twin multiplication
Sergunb 0:8918a71cdbe9 888 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 889 * @param[out] r Resulting point R = d0.S + d1.T
Sergunb 0:8918a71cdbe9 890 * @param[in] d0 An integer d such as 0 <= d0 < p
Sergunb 0:8918a71cdbe9 891 * @param[in] s EC point
Sergunb 0:8918a71cdbe9 892 * @param[in] d1 An integer d such as 0 <= d1 < p
Sergunb 0:8918a71cdbe9 893 * @param[in] t EC point
Sergunb 0:8918a71cdbe9 894 * @return Error code
Sergunb 0:8918a71cdbe9 895 **/
Sergunb 0:8918a71cdbe9 896
Sergunb 0:8918a71cdbe9 897 error_t ecTwinMult(const EcDomainParameters *params, EcPoint *r,
Sergunb 0:8918a71cdbe9 898 const Mpi *d0, const EcPoint *s, const Mpi *d1, const EcPoint *t)
Sergunb 0:8918a71cdbe9 899 {
Sergunb 0:8918a71cdbe9 900 error_t error;
Sergunb 0:8918a71cdbe9 901 int_t k;
Sergunb 0:8918a71cdbe9 902 uint_t m;
Sergunb 0:8918a71cdbe9 903 uint_t m0;
Sergunb 0:8918a71cdbe9 904 uint_t m1;
Sergunb 0:8918a71cdbe9 905 uint_t c0;
Sergunb 0:8918a71cdbe9 906 uint_t c1;
Sergunb 0:8918a71cdbe9 907 uint_t h0;
Sergunb 0:8918a71cdbe9 908 uint_t h1;
Sergunb 0:8918a71cdbe9 909 int_t u0;
Sergunb 0:8918a71cdbe9 910 int_t u1;
Sergunb 0:8918a71cdbe9 911 EcPoint spt;
Sergunb 0:8918a71cdbe9 912 EcPoint smt;
Sergunb 0:8918a71cdbe9 913
Sergunb 0:8918a71cdbe9 914 //Initialize EC points
Sergunb 0:8918a71cdbe9 915 ecInit(&spt);
Sergunb 0:8918a71cdbe9 916 ecInit(&smt);
Sergunb 0:8918a71cdbe9 917
Sergunb 0:8918a71cdbe9 918 //Precompute SpT = S + T
Sergunb 0:8918a71cdbe9 919 EC_CHECK(ecFullAdd(params, &spt, s, t));
Sergunb 0:8918a71cdbe9 920 //Precompute SmT = S - T
Sergunb 0:8918a71cdbe9 921 EC_CHECK(ecFullSub(params, &smt, s, t));
Sergunb 0:8918a71cdbe9 922
Sergunb 0:8918a71cdbe9 923 //Let m0 be the bit length of d0
Sergunb 0:8918a71cdbe9 924 m0 = mpiGetBitLength(d0);
Sergunb 0:8918a71cdbe9 925 //Let m1 be the bit length of d1
Sergunb 0:8918a71cdbe9 926 m1 = mpiGetBitLength(d1);
Sergunb 0:8918a71cdbe9 927 //Let m = MAX(m0, m1)
Sergunb 0:8918a71cdbe9 928 m = MAX(m0, m1);
Sergunb 0:8918a71cdbe9 929
Sergunb 0:8918a71cdbe9 930 //Let c be a 2 x 6 binary matrix
Sergunb 0:8918a71cdbe9 931 c0 = mpiGetBitValue(d0, m - 4);
Sergunb 0:8918a71cdbe9 932 c0 |= mpiGetBitValue(d0, m - 3) << 1;
Sergunb 0:8918a71cdbe9 933 c0 |= mpiGetBitValue(d0, m - 2) << 2;
Sergunb 0:8918a71cdbe9 934 c0 |= mpiGetBitValue(d0, m - 1) << 3;
Sergunb 0:8918a71cdbe9 935 c1 = mpiGetBitValue(d1, m - 4);
Sergunb 0:8918a71cdbe9 936 c1 |= mpiGetBitValue(d1, m - 3) << 1;
Sergunb 0:8918a71cdbe9 937 c1 |= mpiGetBitValue(d1, m - 2) << 2;
Sergunb 0:8918a71cdbe9 938 c1 |= mpiGetBitValue(d1, m - 1) << 3;
Sergunb 0:8918a71cdbe9 939
Sergunb 0:8918a71cdbe9 940 //Set R = (1, 1, 0)
Sergunb 0:8918a71cdbe9 941 MPI_CHECK(mpiSetValue(&r->x, 1));
Sergunb 0:8918a71cdbe9 942 MPI_CHECK(mpiSetValue(&r->y, 1));
Sergunb 0:8918a71cdbe9 943 MPI_CHECK(mpiSetValue(&r->z, 0));
Sergunb 0:8918a71cdbe9 944
Sergunb 0:8918a71cdbe9 945 //Calculate both multiplications at the same time
Sergunb 0:8918a71cdbe9 946 for(k = m; k >= 0; k--)
Sergunb 0:8918a71cdbe9 947 {
Sergunb 0:8918a71cdbe9 948 //Compute h(0) = 16 * c(0,1) + 8 * c(0,2) + 4 * c(0,3) + 2 * c(0,4) + c(0,5)
Sergunb 0:8918a71cdbe9 949 h0 = c0 & 0x1F;
Sergunb 0:8918a71cdbe9 950 //Check whether c(0,0) == 1
Sergunb 0:8918a71cdbe9 951 if(c0 & 0x20)
Sergunb 0:8918a71cdbe9 952 h0 = 31 - h0;
Sergunb 0:8918a71cdbe9 953
Sergunb 0:8918a71cdbe9 954 //Compute h(1) = 16 * c(1,1) + 8 * c(1,2) + 4 * c(1,3) + 2 * c(1,4) + c(1,5)
Sergunb 0:8918a71cdbe9 955 h1 = c1 & 0x1F;
Sergunb 0:8918a71cdbe9 956 //Check whether c(1,0) == 1
Sergunb 0:8918a71cdbe9 957 if(c1 & 0x20)
Sergunb 0:8918a71cdbe9 958 h1 = 31 - h1;
Sergunb 0:8918a71cdbe9 959
Sergunb 0:8918a71cdbe9 960 //Compute u(0)
Sergunb 0:8918a71cdbe9 961 if(h0 < ecTwinMultF(h1))
Sergunb 0:8918a71cdbe9 962 u0 = 0;
Sergunb 0:8918a71cdbe9 963 else if(c0 & 0x20)
Sergunb 0:8918a71cdbe9 964 u0 = -1;
Sergunb 0:8918a71cdbe9 965 else
Sergunb 0:8918a71cdbe9 966 u0 = 1;
Sergunb 0:8918a71cdbe9 967
Sergunb 0:8918a71cdbe9 968 //Compute u(1)
Sergunb 0:8918a71cdbe9 969 if(h1 < ecTwinMultF(h0))
Sergunb 0:8918a71cdbe9 970 u1 = 0;
Sergunb 0:8918a71cdbe9 971 else if(c1 & 0x20)
Sergunb 0:8918a71cdbe9 972 u1 = -1;
Sergunb 0:8918a71cdbe9 973 else
Sergunb 0:8918a71cdbe9 974 u1 = 1;
Sergunb 0:8918a71cdbe9 975
Sergunb 0:8918a71cdbe9 976 //Update c matrix
Sergunb 0:8918a71cdbe9 977 c0 <<= 1;
Sergunb 0:8918a71cdbe9 978 c0 |= mpiGetBitValue(d0, k - 5);
Sergunb 0:8918a71cdbe9 979 c0 ^= u0 ? 0x20 : 0x00;
Sergunb 0:8918a71cdbe9 980 c1 <<= 1;
Sergunb 0:8918a71cdbe9 981 c1 |= mpiGetBitValue(d1, k - 5);
Sergunb 0:8918a71cdbe9 982 c1 ^= u1 ? 0x20 : 0x00;
Sergunb 0:8918a71cdbe9 983
Sergunb 0:8918a71cdbe9 984 //Point doubling
Sergunb 0:8918a71cdbe9 985 EC_CHECK(ecDouble(params, r, r));
Sergunb 0:8918a71cdbe9 986
Sergunb 0:8918a71cdbe9 987 //Check u(0) and u(1)
Sergunb 0:8918a71cdbe9 988 if(u0 == -1 && u1 == -1)
Sergunb 0:8918a71cdbe9 989 {
Sergunb 0:8918a71cdbe9 990 //Compute R = R - SpT
Sergunb 0:8918a71cdbe9 991 EC_CHECK(ecFullSub(params, r, r, &spt));
Sergunb 0:8918a71cdbe9 992 }
Sergunb 0:8918a71cdbe9 993 else if(u0 == -1 && u1 == 0)
Sergunb 0:8918a71cdbe9 994 {
Sergunb 0:8918a71cdbe9 995 //Compute R = R - S
Sergunb 0:8918a71cdbe9 996 EC_CHECK(ecFullSub(params, r, r, s));
Sergunb 0:8918a71cdbe9 997 }
Sergunb 0:8918a71cdbe9 998 else if(u0 == -1 && u1 == 1)
Sergunb 0:8918a71cdbe9 999 {
Sergunb 0:8918a71cdbe9 1000 //Compute R = R - SmT
Sergunb 0:8918a71cdbe9 1001 EC_CHECK(ecFullSub(params, r, r, &smt));
Sergunb 0:8918a71cdbe9 1002 }
Sergunb 0:8918a71cdbe9 1003 else if(u0 == 0 && u1 == -1)
Sergunb 0:8918a71cdbe9 1004 {
Sergunb 0:8918a71cdbe9 1005 //Compute R = R - T
Sergunb 0:8918a71cdbe9 1006 EC_CHECK(ecFullSub(params, r, r, t));
Sergunb 0:8918a71cdbe9 1007 }
Sergunb 0:8918a71cdbe9 1008 else if(u0 == 0 && u1 == 1)
Sergunb 0:8918a71cdbe9 1009 {
Sergunb 0:8918a71cdbe9 1010 //Compute R = R + T
Sergunb 0:8918a71cdbe9 1011 EC_CHECK(ecFullAdd(params, r, r, t));
Sergunb 0:8918a71cdbe9 1012 }
Sergunb 0:8918a71cdbe9 1013 else if(u0 == 1 && u1 == -1)
Sergunb 0:8918a71cdbe9 1014 {
Sergunb 0:8918a71cdbe9 1015 //Compute R = R + SmT
Sergunb 0:8918a71cdbe9 1016 EC_CHECK(ecFullAdd(params, r, r, &smt));
Sergunb 0:8918a71cdbe9 1017 }
Sergunb 0:8918a71cdbe9 1018 else if(u0 == 1 && u1 == 0)
Sergunb 0:8918a71cdbe9 1019 {
Sergunb 0:8918a71cdbe9 1020 //Compute R = R + S
Sergunb 0:8918a71cdbe9 1021 EC_CHECK(ecFullAdd(params, r, r, s));
Sergunb 0:8918a71cdbe9 1022 }
Sergunb 0:8918a71cdbe9 1023 else if(u0 == 1 && u1 == 1)
Sergunb 0:8918a71cdbe9 1024 {
Sergunb 0:8918a71cdbe9 1025 //Compute R = R + SpT
Sergunb 0:8918a71cdbe9 1026 EC_CHECK(ecFullAdd(params, r, r, &spt));
Sergunb 0:8918a71cdbe9 1027 }
Sergunb 0:8918a71cdbe9 1028 }
Sergunb 0:8918a71cdbe9 1029
Sergunb 0:8918a71cdbe9 1030 end:
Sergunb 0:8918a71cdbe9 1031 //Release EC points
Sergunb 0:8918a71cdbe9 1032 ecFree(&spt);
Sergunb 0:8918a71cdbe9 1033 ecFree(&smt);
Sergunb 0:8918a71cdbe9 1034
Sergunb 0:8918a71cdbe9 1035 //Return status code
Sergunb 0:8918a71cdbe9 1036 return error;
Sergunb 0:8918a71cdbe9 1037 }
Sergunb 0:8918a71cdbe9 1038
Sergunb 0:8918a71cdbe9 1039
Sergunb 0:8918a71cdbe9 1040 /**
Sergunb 0:8918a71cdbe9 1041 * @brief Fast modular addition
Sergunb 0:8918a71cdbe9 1042 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 1043 * @param[out] r Resulting integer R = (A + B) mod p
Sergunb 0:8918a71cdbe9 1044 * @param[in] a An integer such as 0 <= A < p
Sergunb 0:8918a71cdbe9 1045 * @param[in] b An integer such as 0 <= B < p
Sergunb 0:8918a71cdbe9 1046 * @return Error code
Sergunb 0:8918a71cdbe9 1047 **/
Sergunb 0:8918a71cdbe9 1048
Sergunb 0:8918a71cdbe9 1049 error_t ecAddMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Sergunb 0:8918a71cdbe9 1050 {
Sergunb 0:8918a71cdbe9 1051 error_t error;
Sergunb 0:8918a71cdbe9 1052
Sergunb 0:8918a71cdbe9 1053 //Compute R = A + B
Sergunb 0:8918a71cdbe9 1054 MPI_CHECK(mpiAdd(r, a, b));
Sergunb 0:8918a71cdbe9 1055
Sergunb 0:8918a71cdbe9 1056 //Compute R = (A + B) mod p
Sergunb 0:8918a71cdbe9 1057 if(mpiComp(r, &params->p) >= 0)
Sergunb 0:8918a71cdbe9 1058 {
Sergunb 0:8918a71cdbe9 1059 MPI_CHECK(mpiSub(r, r, &params->p));
Sergunb 0:8918a71cdbe9 1060 }
Sergunb 0:8918a71cdbe9 1061
Sergunb 0:8918a71cdbe9 1062 end:
Sergunb 0:8918a71cdbe9 1063 //Return status code
Sergunb 0:8918a71cdbe9 1064 return error;
Sergunb 0:8918a71cdbe9 1065 }
Sergunb 0:8918a71cdbe9 1066
Sergunb 0:8918a71cdbe9 1067
Sergunb 0:8918a71cdbe9 1068 /**
Sergunb 0:8918a71cdbe9 1069 * @brief Fast modular subtraction
Sergunb 0:8918a71cdbe9 1070 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 1071 * @param[out] r Resulting integer R = (A - B) mod p
Sergunb 0:8918a71cdbe9 1072 * @param[in] a An integer such as 0 <= A < p
Sergunb 0:8918a71cdbe9 1073 * @param[in] b An integer such as 0 <= B < p
Sergunb 0:8918a71cdbe9 1074 * @return Error code
Sergunb 0:8918a71cdbe9 1075 **/
Sergunb 0:8918a71cdbe9 1076
Sergunb 0:8918a71cdbe9 1077 error_t ecSubMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Sergunb 0:8918a71cdbe9 1078 {
Sergunb 0:8918a71cdbe9 1079 error_t error;
Sergunb 0:8918a71cdbe9 1080
Sergunb 0:8918a71cdbe9 1081 //Compute R = A - B
Sergunb 0:8918a71cdbe9 1082 MPI_CHECK(mpiSub(r, a, b));
Sergunb 0:8918a71cdbe9 1083
Sergunb 0:8918a71cdbe9 1084 //Compute R = (A - B) mod p
Sergunb 0:8918a71cdbe9 1085 if(mpiCompInt(r, 0) < 0)
Sergunb 0:8918a71cdbe9 1086 {
Sergunb 0:8918a71cdbe9 1087 MPI_CHECK(mpiAdd(r, r, &params->p));
Sergunb 0:8918a71cdbe9 1088 }
Sergunb 0:8918a71cdbe9 1089
Sergunb 0:8918a71cdbe9 1090 end:
Sergunb 0:8918a71cdbe9 1091 //Return status code
Sergunb 0:8918a71cdbe9 1092 return error;
Sergunb 0:8918a71cdbe9 1093 }
Sergunb 0:8918a71cdbe9 1094
Sergunb 0:8918a71cdbe9 1095
Sergunb 0:8918a71cdbe9 1096 /**
Sergunb 0:8918a71cdbe9 1097 * @brief Fast modular multiplication
Sergunb 0:8918a71cdbe9 1098 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 1099 * @param[out] r Resulting integer R = (A * B) mod p
Sergunb 0:8918a71cdbe9 1100 * @param[in] a An integer such as 0 <= A < p
Sergunb 0:8918a71cdbe9 1101 * @param[in] b An integer such as 0 <= B < p
Sergunb 0:8918a71cdbe9 1102 * @return Error code
Sergunb 0:8918a71cdbe9 1103 **/
Sergunb 0:8918a71cdbe9 1104
Sergunb 0:8918a71cdbe9 1105 error_t ecMulMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Sergunb 0:8918a71cdbe9 1106 {
Sergunb 0:8918a71cdbe9 1107 error_t error;
Sergunb 0:8918a71cdbe9 1108
Sergunb 0:8918a71cdbe9 1109 //Compute R = A * B
Sergunb 0:8918a71cdbe9 1110 MPI_CHECK(mpiMul(r, a, b));
Sergunb 0:8918a71cdbe9 1111
Sergunb 0:8918a71cdbe9 1112 //Compute R = (A * B) mod p
Sergunb 0:8918a71cdbe9 1113 if(params->mod != NULL)
Sergunb 0:8918a71cdbe9 1114 {
Sergunb 0:8918a71cdbe9 1115 MPI_CHECK(params->mod(r, &params->p));
Sergunb 0:8918a71cdbe9 1116 }
Sergunb 0:8918a71cdbe9 1117 else
Sergunb 0:8918a71cdbe9 1118 {
Sergunb 0:8918a71cdbe9 1119 MPI_CHECK(mpiMod(r, r, &params->p));
Sergunb 0:8918a71cdbe9 1120 }
Sergunb 0:8918a71cdbe9 1121
Sergunb 0:8918a71cdbe9 1122 end:
Sergunb 0:8918a71cdbe9 1123 //Return status code
Sergunb 0:8918a71cdbe9 1124 return error;
Sergunb 0:8918a71cdbe9 1125 }
Sergunb 0:8918a71cdbe9 1126
Sergunb 0:8918a71cdbe9 1127
Sergunb 0:8918a71cdbe9 1128 /**
Sergunb 0:8918a71cdbe9 1129 * @brief Fast modular squaring
Sergunb 0:8918a71cdbe9 1130 * @param[in] params EC domain parameters
Sergunb 0:8918a71cdbe9 1131 * @param[out] r Resulting integer R = (A ^ 2) mod p
Sergunb 0:8918a71cdbe9 1132 * @param[in] a An integer such as 0 <= A < p
Sergunb 0:8918a71cdbe9 1133 * @return Error code
Sergunb 0:8918a71cdbe9 1134 **/
Sergunb 0:8918a71cdbe9 1135
Sergunb 0:8918a71cdbe9 1136 error_t ecSqrMod(const EcDomainParameters *params, Mpi *r, const Mpi *a)
Sergunb 0:8918a71cdbe9 1137 {
Sergunb 0:8918a71cdbe9 1138 error_t error;
Sergunb 0:8918a71cdbe9 1139
Sergunb 0:8918a71cdbe9 1140 //Compute R = A ^ 2
Sergunb 0:8918a71cdbe9 1141 MPI_CHECK(mpiMul(r, a, a));
Sergunb 0:8918a71cdbe9 1142
Sergunb 0:8918a71cdbe9 1143 //Compute R = (A ^ 2) mod p
Sergunb 0:8918a71cdbe9 1144 if(params->mod != NULL)
Sergunb 0:8918a71cdbe9 1145 {
Sergunb 0:8918a71cdbe9 1146 MPI_CHECK(params->mod(r, &params->p));
Sergunb 0:8918a71cdbe9 1147 }
Sergunb 0:8918a71cdbe9 1148 else
Sergunb 0:8918a71cdbe9 1149 {
Sergunb 0:8918a71cdbe9 1150 MPI_CHECK(mpiMod(r, r, &params->p));
Sergunb 0:8918a71cdbe9 1151 }
Sergunb 0:8918a71cdbe9 1152
Sergunb 0:8918a71cdbe9 1153 end:
Sergunb 0:8918a71cdbe9 1154 //Return status code
Sergunb 0:8918a71cdbe9 1155 return error;
Sergunb 0:8918a71cdbe9 1156 }
Sergunb 0:8918a71cdbe9 1157
Sergunb 0:8918a71cdbe9 1158 #endif
Sergunb 0:8918a71cdbe9 1159