Webserver+3d print
cyclone_crypto/ec.c@0:8918a71cdbe9, 2017-02-04 (annotated)
- Committer:
- Sergunb
- Date:
- Sat Feb 04 18:15:49 2017 +0000
- Revision:
- 0:8918a71cdbe9
nothing else
Who changed what in which revision?
User | Revision | Line number | New 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(¶ms->p); |
Sergunb | 0:8918a71cdbe9 | 58 | mpiInit(¶ms->a); |
Sergunb | 0:8918a71cdbe9 | 59 | mpiInit(¶ms->b); |
Sergunb | 0:8918a71cdbe9 | 60 | ecInit(¶ms->g); |
Sergunb | 0:8918a71cdbe9 | 61 | mpiInit(¶ms->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(¶ms->p); |
Sergunb | 0:8918a71cdbe9 | 74 | mpiFree(¶ms->a); |
Sergunb | 0:8918a71cdbe9 | 75 | mpiFree(¶ms->b); |
Sergunb | 0:8918a71cdbe9 | 76 | ecFree(¶ms->g); |
Sergunb | 0:8918a71cdbe9 | 77 | mpiFree(¶ms->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(¶ms->p, curveInfo->p, curveInfo->pLen)); |
Sergunb | 0:8918a71cdbe9 | 100 | //Import parameter a |
Sergunb | 0:8918a71cdbe9 | 101 | MPI_CHECK(mpiReadRaw(¶ms->a, curveInfo->a, curveInfo->aLen)); |
Sergunb | 0:8918a71cdbe9 | 102 | //Import parameter b |
Sergunb | 0:8918a71cdbe9 | 103 | MPI_CHECK(mpiReadRaw(¶ms->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(¶ms->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(¶ms->g.y, curveInfo->gy, curveInfo->gyLen)); |
Sergunb | 0:8918a71cdbe9 | 108 | //Import base point order q |
Sergunb | 0:8918a71cdbe9 | 109 | MPI_CHECK(mpiReadRaw(¶ms->q, curveInfo->q, curveInfo->qLen)); |
Sergunb | 0:8918a71cdbe9 | 110 | |
Sergunb | 0:8918a71cdbe9 | 111 | //Normalize base point G |
Sergunb | 0:8918a71cdbe9 | 112 | MPI_CHECK(mpiSetValue(¶ms->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(" ", ¶ms->p); |
Sergunb | 0:8918a71cdbe9 | 120 | TRACE_DEBUG(" a:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 121 | TRACE_DEBUG_MPI(" ", ¶ms->a); |
Sergunb | 0:8918a71cdbe9 | 122 | TRACE_DEBUG(" b:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 123 | TRACE_DEBUG_MPI(" ", ¶ms->b); |
Sergunb | 0:8918a71cdbe9 | 124 | TRACE_DEBUG(" Gx:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 125 | TRACE_DEBUG_MPI(" ", ¶ms->g.x); |
Sergunb | 0:8918a71cdbe9 | 126 | TRACE_DEBUG(" Gy:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 127 | TRACE_DEBUG_MPI(" ", ¶ms->g.y); |
Sergunb | 0:8918a71cdbe9 | 128 | TRACE_DEBUG(" q:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 129 | TRACE_DEBUG_MPI(" ", ¶ms->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(¶ms->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(¶ms->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, ¶ms->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, ¶ms->a, &s->x)); |
Sergunb | 0:8918a71cdbe9 | 364 | EC_CHECK(ecAddMod(params, &t1, &t1, &t2)); |
Sergunb | 0:8918a71cdbe9 | 365 | EC_CHECK(ecAddMod(params, &t1, &t1, ¶ms->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, ¶ms->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, ¶ms->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, ¶ms->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, ¶ms->p) >= 0) |
Sergunb | 0:8918a71cdbe9 | 1058 | { |
Sergunb | 0:8918a71cdbe9 | 1059 | MPI_CHECK(mpiSub(r, r, ¶ms->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, ¶ms->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, ¶ms->p)); |
Sergunb | 0:8918a71cdbe9 | 1116 | } |
Sergunb | 0:8918a71cdbe9 | 1117 | else |
Sergunb | 0:8918a71cdbe9 | 1118 | { |
Sergunb | 0:8918a71cdbe9 | 1119 | MPI_CHECK(mpiMod(r, r, ¶ms->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, ¶ms->p)); |
Sergunb | 0:8918a71cdbe9 | 1147 | } |
Sergunb | 0:8918a71cdbe9 | 1148 | else |
Sergunb | 0:8918a71cdbe9 | 1149 | { |
Sergunb | 0:8918a71cdbe9 | 1150 | MPI_CHECK(mpiMod(r, r, ¶ms->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 |