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 poly1305.c
Sergunb 0:8918a71cdbe9 3 * @brief Poly1305 message-authentication code
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 <string.h>
Sergunb 0:8918a71cdbe9 34 #include "crypto.h"
Sergunb 0:8918a71cdbe9 35 #include "poly1305.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 (POLY1305_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 40
Sergunb 0:8918a71cdbe9 41
Sergunb 0:8918a71cdbe9 42 /**
Sergunb 0:8918a71cdbe9 43 * @brief Initialize Poly1305 message-authentication code computation
Sergunb 0:8918a71cdbe9 44 * @param[in] context Pointer to the Poly1305 context to initialize
Sergunb 0:8918a71cdbe9 45 * @param[in] key Pointer to the 256-bit key
Sergunb 0:8918a71cdbe9 46 **/
Sergunb 0:8918a71cdbe9 47
Sergunb 0:8918a71cdbe9 48 void poly1305Init(Poly1305Context *context, const uint8_t *key)
Sergunb 0:8918a71cdbe9 49 {
Sergunb 0:8918a71cdbe9 50 //The 256-bit key is partitioned into two parts, called r and s
Sergunb 0:8918a71cdbe9 51 context->r[0] = LOAD32LE(key);
Sergunb 0:8918a71cdbe9 52 context->r[1] = LOAD32LE(key + 4);
Sergunb 0:8918a71cdbe9 53 context->r[2] = LOAD32LE(key + 8);
Sergunb 0:8918a71cdbe9 54 context->r[3] = LOAD32LE(key + 12);
Sergunb 0:8918a71cdbe9 55 context->s[0] = LOAD32LE(key + 16);
Sergunb 0:8918a71cdbe9 56 context->s[1] = LOAD32LE(key + 20);
Sergunb 0:8918a71cdbe9 57 context->s[2] = LOAD32LE(key + 24);
Sergunb 0:8918a71cdbe9 58 context->s[3] = LOAD32LE(key + 28);
Sergunb 0:8918a71cdbe9 59
Sergunb 0:8918a71cdbe9 60 //Certain bits of r are required to be 0
Sergunb 0:8918a71cdbe9 61 context->r[0] &= 0x0FFFFFFF;
Sergunb 0:8918a71cdbe9 62 context->r[1] &= 0x0FFFFFFC;
Sergunb 0:8918a71cdbe9 63 context->r[2] &= 0x0FFFFFFC;
Sergunb 0:8918a71cdbe9 64 context->r[3] &= 0x0FFFFFFC;
Sergunb 0:8918a71cdbe9 65
Sergunb 0:8918a71cdbe9 66 //The accumulator is set to zero
Sergunb 0:8918a71cdbe9 67 context->a[0] = 0;
Sergunb 0:8918a71cdbe9 68 context->a[1] = 0;
Sergunb 0:8918a71cdbe9 69 context->a[2] = 0;
Sergunb 0:8918a71cdbe9 70 context->a[3] = 0;
Sergunb 0:8918a71cdbe9 71 context->a[4] = 0;
Sergunb 0:8918a71cdbe9 72 context->a[5] = 0;
Sergunb 0:8918a71cdbe9 73 context->a[6] = 0;
Sergunb 0:8918a71cdbe9 74 context->a[7] = 0;
Sergunb 0:8918a71cdbe9 75
Sergunb 0:8918a71cdbe9 76 //Number of bytes in the buffer
Sergunb 0:8918a71cdbe9 77 context->size = 0;
Sergunb 0:8918a71cdbe9 78 }
Sergunb 0:8918a71cdbe9 79
Sergunb 0:8918a71cdbe9 80
Sergunb 0:8918a71cdbe9 81 /**
Sergunb 0:8918a71cdbe9 82 * @brief Update Poly1305 message-authentication code computation
Sergunb 0:8918a71cdbe9 83 * @param[in] context Pointer to the Poly1305 context
Sergunb 0:8918a71cdbe9 84 * @param[in] data Pointer to the input message
Sergunb 0:8918a71cdbe9 85 * @param[in] length Length of the input message
Sergunb 0:8918a71cdbe9 86 **/
Sergunb 0:8918a71cdbe9 87
Sergunb 0:8918a71cdbe9 88 void poly1305Update(Poly1305Context *context, const void *data, size_t length)
Sergunb 0:8918a71cdbe9 89 {
Sergunb 0:8918a71cdbe9 90 size_t n;
Sergunb 0:8918a71cdbe9 91
Sergunb 0:8918a71cdbe9 92 //Process the incoming data
Sergunb 0:8918a71cdbe9 93 while(length > 0)
Sergunb 0:8918a71cdbe9 94 {
Sergunb 0:8918a71cdbe9 95 //The buffer can hold at most 16 bytes
Sergunb 0:8918a71cdbe9 96 n = MIN(length, 16 - context->size);
Sergunb 0:8918a71cdbe9 97
Sergunb 0:8918a71cdbe9 98 //Copy the data to the buffer
Sergunb 0:8918a71cdbe9 99 memcpy(context->buffer + context->size, data, n);
Sergunb 0:8918a71cdbe9 100
Sergunb 0:8918a71cdbe9 101 //Update the Poly1305 context
Sergunb 0:8918a71cdbe9 102 context->size += n;
Sergunb 0:8918a71cdbe9 103 //Advance the data pointer
Sergunb 0:8918a71cdbe9 104 data = (uint8_t *) data + n;
Sergunb 0:8918a71cdbe9 105 //Remaining bytes to process
Sergunb 0:8918a71cdbe9 106 length -= n;
Sergunb 0:8918a71cdbe9 107
Sergunb 0:8918a71cdbe9 108 //Process message in 16-byte blocks
Sergunb 0:8918a71cdbe9 109 if(context->size == 16)
Sergunb 0:8918a71cdbe9 110 {
Sergunb 0:8918a71cdbe9 111 //Transform the 16-byte block
Sergunb 0:8918a71cdbe9 112 poly1305ProcessBlock(context);
Sergunb 0:8918a71cdbe9 113 //Empty the buffer
Sergunb 0:8918a71cdbe9 114 context->size = 0;
Sergunb 0:8918a71cdbe9 115 }
Sergunb 0:8918a71cdbe9 116 }
Sergunb 0:8918a71cdbe9 117 }
Sergunb 0:8918a71cdbe9 118
Sergunb 0:8918a71cdbe9 119
Sergunb 0:8918a71cdbe9 120 /**
Sergunb 0:8918a71cdbe9 121 * @brief Finalize Poly1305 message-authentication code computation
Sergunb 0:8918a71cdbe9 122 * @param[in] context Pointer to the Poly1305 context
Sergunb 0:8918a71cdbe9 123 * @param[out] tag Calculated message-authentication code
Sergunb 0:8918a71cdbe9 124 **/
Sergunb 0:8918a71cdbe9 125
Sergunb 0:8918a71cdbe9 126 void poly1305Final(Poly1305Context *context, uint8_t *tag)
Sergunb 0:8918a71cdbe9 127 {
Sergunb 0:8918a71cdbe9 128 uint32_t mask;
Sergunb 0:8918a71cdbe9 129 uint32_t b[4];
Sergunb 0:8918a71cdbe9 130
Sergunb 0:8918a71cdbe9 131 //Process the last block
Sergunb 0:8918a71cdbe9 132 if(context->size != 0)
Sergunb 0:8918a71cdbe9 133 poly1305ProcessBlock(context);
Sergunb 0:8918a71cdbe9 134
Sergunb 0:8918a71cdbe9 135 //Save the accumulator
Sergunb 0:8918a71cdbe9 136 b[0] = context->a[0] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 137 b[1] = context->a[1] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 138 b[2] = context->a[2] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 139 b[3] = context->a[3] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 140
Sergunb 0:8918a71cdbe9 141 //Compute a + 5
Sergunb 0:8918a71cdbe9 142 context->a[0] += 5;
Sergunb 0:8918a71cdbe9 143
Sergunb 0:8918a71cdbe9 144 //Propagate the carry
Sergunb 0:8918a71cdbe9 145 context->a[1] += context->a[0] >> 32;
Sergunb 0:8918a71cdbe9 146 context->a[2] += context->a[1] >> 32;
Sergunb 0:8918a71cdbe9 147 context->a[3] += context->a[2] >> 32;
Sergunb 0:8918a71cdbe9 148 context->a[4] += context->a[3] >> 32;
Sergunb 0:8918a71cdbe9 149
Sergunb 0:8918a71cdbe9 150 //If (a + 5) >= 2^130, form a mask with the value 0x00000000. Else, form
Sergunb 0:8918a71cdbe9 151 //a mask with the value 0xffffffff
Sergunb 0:8918a71cdbe9 152 mask = ((context->a[4] & 0x04) >> 2) - 1;
Sergunb 0:8918a71cdbe9 153
Sergunb 0:8918a71cdbe9 154 //Select between ((a - (2^130 - 5)) % 2^128) and (a % 2^128)
Sergunb 0:8918a71cdbe9 155 context->a[0] = (context->a[0] & ~mask) | (b[0] & mask);
Sergunb 0:8918a71cdbe9 156 context->a[1] = (context->a[1] & ~mask) | (b[1] & mask);
Sergunb 0:8918a71cdbe9 157 context->a[2] = (context->a[2] & ~mask) | (b[2] & mask);
Sergunb 0:8918a71cdbe9 158 context->a[3] = (context->a[3] & ~mask) | (b[3] & mask);
Sergunb 0:8918a71cdbe9 159
Sergunb 0:8918a71cdbe9 160 //Finally, the value of the secret key s is added to the accumulator
Sergunb 0:8918a71cdbe9 161 context->a[0] += context->s[0];
Sergunb 0:8918a71cdbe9 162 context->a[1] += context->s[1];
Sergunb 0:8918a71cdbe9 163 context->a[2] += context->s[2];
Sergunb 0:8918a71cdbe9 164 context->a[3] += context->s[3];
Sergunb 0:8918a71cdbe9 165
Sergunb 0:8918a71cdbe9 166 //Propagate the carry
Sergunb 0:8918a71cdbe9 167 context->a[1] += context->a[0] >> 32;
Sergunb 0:8918a71cdbe9 168 context->a[2] += context->a[1] >> 32;
Sergunb 0:8918a71cdbe9 169 context->a[3] += context->a[2] >> 32;
Sergunb 0:8918a71cdbe9 170 context->a[4] += context->a[3] >> 32;
Sergunb 0:8918a71cdbe9 171
Sergunb 0:8918a71cdbe9 172 //We only consider the least significant bits
Sergunb 0:8918a71cdbe9 173 b[0] = context->a[0] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 174 b[1] = context->a[1] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 175 b[2] = context->a[2] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 176 b[3] = context->a[3] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 177
Sergunb 0:8918a71cdbe9 178 //The result is serialized as a little-endian number, producing
Sergunb 0:8918a71cdbe9 179 //the 16 byte tag
Sergunb 0:8918a71cdbe9 180 STORE32LE(b[0], tag);
Sergunb 0:8918a71cdbe9 181 STORE32LE(b[1], tag + 4);
Sergunb 0:8918a71cdbe9 182 STORE32LE(b[2], tag + 8);
Sergunb 0:8918a71cdbe9 183 STORE32LE(b[3], tag + 12);
Sergunb 0:8918a71cdbe9 184
Sergunb 0:8918a71cdbe9 185 //Clear the accumulator
Sergunb 0:8918a71cdbe9 186 context->a[0] = 0;
Sergunb 0:8918a71cdbe9 187 context->a[1] = 0;
Sergunb 0:8918a71cdbe9 188 context->a[2] = 0;
Sergunb 0:8918a71cdbe9 189 context->a[3] = 0;
Sergunb 0:8918a71cdbe9 190 context->a[4] = 0;
Sergunb 0:8918a71cdbe9 191 context->a[5] = 0;
Sergunb 0:8918a71cdbe9 192 context->a[6] = 0;
Sergunb 0:8918a71cdbe9 193 context->a[7] = 0;
Sergunb 0:8918a71cdbe9 194
Sergunb 0:8918a71cdbe9 195 //Clear r and s
Sergunb 0:8918a71cdbe9 196 context->r[0] = 0;
Sergunb 0:8918a71cdbe9 197 context->r[1] = 0;
Sergunb 0:8918a71cdbe9 198 context->r[2] = 0;
Sergunb 0:8918a71cdbe9 199 context->r[3] = 0;
Sergunb 0:8918a71cdbe9 200 context->s[0] = 0;
Sergunb 0:8918a71cdbe9 201 context->s[1] = 0;
Sergunb 0:8918a71cdbe9 202 context->s[2] = 0;
Sergunb 0:8918a71cdbe9 203 context->s[3] = 0;
Sergunb 0:8918a71cdbe9 204 }
Sergunb 0:8918a71cdbe9 205
Sergunb 0:8918a71cdbe9 206
Sergunb 0:8918a71cdbe9 207 /**
Sergunb 0:8918a71cdbe9 208 * @brief Process message in 16-byte blocks
Sergunb 0:8918a71cdbe9 209 * @param[in] context Pointer to the Poly1305 context
Sergunb 0:8918a71cdbe9 210 **/
Sergunb 0:8918a71cdbe9 211
Sergunb 0:8918a71cdbe9 212 void poly1305ProcessBlock(Poly1305Context *context)
Sergunb 0:8918a71cdbe9 213 {
Sergunb 0:8918a71cdbe9 214 uint32_t a[8];
Sergunb 0:8918a71cdbe9 215 uint32_t r[4];
Sergunb 0:8918a71cdbe9 216 uint_t n;
Sergunb 0:8918a71cdbe9 217
Sergunb 0:8918a71cdbe9 218 //Retrieve the length of the last block
Sergunb 0:8918a71cdbe9 219 n = context->size;
Sergunb 0:8918a71cdbe9 220
Sergunb 0:8918a71cdbe9 221 //Add one bit beyond the number of octets. For a 16-byte block,
Sergunb 0:8918a71cdbe9 222 //this is equivalent to adding 2^128 to the number. For the shorter
Sergunb 0:8918a71cdbe9 223 //block, it can be 2^120, 2^112, or any power of two that is evenly
Sergunb 0:8918a71cdbe9 224 //divisible by 8, all the way down to 2^8
Sergunb 0:8918a71cdbe9 225 context->buffer[n++] = 0x01;
Sergunb 0:8918a71cdbe9 226
Sergunb 0:8918a71cdbe9 227 //If the resulting block is not 17 bytes long (the last block),
Sergunb 0:8918a71cdbe9 228 //pad it with zeros
Sergunb 0:8918a71cdbe9 229 while(n < 17)
Sergunb 0:8918a71cdbe9 230 context->buffer[n++] = 0x00;
Sergunb 0:8918a71cdbe9 231
Sergunb 0:8918a71cdbe9 232 //Read the block as a little-endian number
Sergunb 0:8918a71cdbe9 233 a[0] = LOAD32LE(context->buffer);
Sergunb 0:8918a71cdbe9 234 a[1] = LOAD32LE(context->buffer + 4);
Sergunb 0:8918a71cdbe9 235 a[2] = LOAD32LE(context->buffer + 8);
Sergunb 0:8918a71cdbe9 236 a[3] = LOAD32LE(context->buffer + 12);
Sergunb 0:8918a71cdbe9 237 a[4] = context->buffer[16];
Sergunb 0:8918a71cdbe9 238
Sergunb 0:8918a71cdbe9 239 //Add this number to the accumulator
Sergunb 0:8918a71cdbe9 240 context->a[0] += a[0];
Sergunb 0:8918a71cdbe9 241 context->a[1] += a[1];
Sergunb 0:8918a71cdbe9 242 context->a[2] += a[2];
Sergunb 0:8918a71cdbe9 243 context->a[3] += a[3];
Sergunb 0:8918a71cdbe9 244 context->a[4] += a[4];
Sergunb 0:8918a71cdbe9 245
Sergunb 0:8918a71cdbe9 246 //Propagate the carry
Sergunb 0:8918a71cdbe9 247 context->a[1] += context->a[0] >> 32;
Sergunb 0:8918a71cdbe9 248 context->a[2] += context->a[1] >> 32;
Sergunb 0:8918a71cdbe9 249 context->a[3] += context->a[2] >> 32;
Sergunb 0:8918a71cdbe9 250 context->a[4] += context->a[3] >> 32;
Sergunb 0:8918a71cdbe9 251
Sergunb 0:8918a71cdbe9 252 //We only consider the least significant bits
Sergunb 0:8918a71cdbe9 253 a[0] = context->a[0] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 254 a[1] = context->a[1] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 255 a[2] = context->a[2] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 256 a[3] = context->a[3] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 257 a[4] = context->a[4] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 258
Sergunb 0:8918a71cdbe9 259 //Copy r
Sergunb 0:8918a71cdbe9 260 r[0] = context->r[0];
Sergunb 0:8918a71cdbe9 261 r[1] = context->r[1];
Sergunb 0:8918a71cdbe9 262 r[2] = context->r[2];
Sergunb 0:8918a71cdbe9 263 r[3] = context->r[3];
Sergunb 0:8918a71cdbe9 264
Sergunb 0:8918a71cdbe9 265 //Multiply the accumulator by r
Sergunb 0:8918a71cdbe9 266 context->a[0] = (uint64_t) a[0] * r[0];
Sergunb 0:8918a71cdbe9 267 context->a[1] = (uint64_t) a[0] * r[1] + (uint64_t) a[1] * r[0];
Sergunb 0:8918a71cdbe9 268 context->a[2] = (uint64_t) a[0] * r[2] + (uint64_t) a[1] * r[1] + (uint64_t) a[2] * r[0];
Sergunb 0:8918a71cdbe9 269 context->a[3] = (uint64_t) a[0] * r[3] + (uint64_t) a[1] * r[2] + (uint64_t) a[2] * r[1] + (uint64_t) a[3] * r[0];
Sergunb 0:8918a71cdbe9 270 context->a[4] = (uint64_t) a[1] * r[3] + (uint64_t) a[2] * r[2] + (uint64_t) a[3] * r[1] + (uint64_t) a[4] * r[0];
Sergunb 0:8918a71cdbe9 271 context->a[5] = (uint64_t) a[2] * r[3] + (uint64_t) a[3] * r[2] + (uint64_t) a[4] * r[1];
Sergunb 0:8918a71cdbe9 272 context->a[6] = (uint64_t) a[3] * r[3] + (uint64_t) a[4] * r[2];
Sergunb 0:8918a71cdbe9 273 context->a[7] = (uint64_t) a[4] * r[3];
Sergunb 0:8918a71cdbe9 274
Sergunb 0:8918a71cdbe9 275 //Propagate the carry
Sergunb 0:8918a71cdbe9 276 context->a[1] += context->a[0] >> 32;
Sergunb 0:8918a71cdbe9 277 context->a[2] += context->a[1] >> 32;
Sergunb 0:8918a71cdbe9 278 context->a[3] += context->a[2] >> 32;
Sergunb 0:8918a71cdbe9 279 context->a[4] += context->a[3] >> 32;
Sergunb 0:8918a71cdbe9 280 context->a[5] += context->a[4] >> 32;
Sergunb 0:8918a71cdbe9 281 context->a[6] += context->a[5] >> 32;
Sergunb 0:8918a71cdbe9 282 context->a[7] += context->a[6] >> 32;
Sergunb 0:8918a71cdbe9 283
Sergunb 0:8918a71cdbe9 284 //Save the high part of the accumulator
Sergunb 0:8918a71cdbe9 285 a[0] = context->a[4] & 0xFFFFFFFC;
Sergunb 0:8918a71cdbe9 286 a[1] = context->a[5] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 287 a[2] = context->a[6] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 288 a[3] = context->a[7] & 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 289
Sergunb 0:8918a71cdbe9 290 //We only consider the least significant bits
Sergunb 0:8918a71cdbe9 291 context->a[0] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 292 context->a[1] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 293 context->a[2] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 294 context->a[3] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 295 context->a[4] &= 0x00000003;
Sergunb 0:8918a71cdbe9 296
Sergunb 0:8918a71cdbe9 297 //Perform fast modular reduction (first pass)
Sergunb 0:8918a71cdbe9 298 context->a[0] += a[0];
Sergunb 0:8918a71cdbe9 299 context->a[0] += (a[0] >> 2) | (a[1] << 30);
Sergunb 0:8918a71cdbe9 300 context->a[1] += a[1];
Sergunb 0:8918a71cdbe9 301 context->a[1] += (a[1] >> 2) | (a[2] << 30);
Sergunb 0:8918a71cdbe9 302 context->a[2] += a[2];
Sergunb 0:8918a71cdbe9 303 context->a[2] += (a[2] >> 2) | (a[3] << 30);
Sergunb 0:8918a71cdbe9 304 context->a[3] += a[3];
Sergunb 0:8918a71cdbe9 305 context->a[3] += (a[3] >> 2);
Sergunb 0:8918a71cdbe9 306
Sergunb 0:8918a71cdbe9 307 //Propagate the carry
Sergunb 0:8918a71cdbe9 308 context->a[1] += context->a[0] >> 32;
Sergunb 0:8918a71cdbe9 309 context->a[2] += context->a[1] >> 32;
Sergunb 0:8918a71cdbe9 310 context->a[3] += context->a[2] >> 32;
Sergunb 0:8918a71cdbe9 311 context->a[4] += context->a[3] >> 32;
Sergunb 0:8918a71cdbe9 312
Sergunb 0:8918a71cdbe9 313 //Save the high part of the accumulator
Sergunb 0:8918a71cdbe9 314 a[0] = context->a[4] & 0xFFFFFFFC;
Sergunb 0:8918a71cdbe9 315
Sergunb 0:8918a71cdbe9 316 //We only consider the least significant bits
Sergunb 0:8918a71cdbe9 317 context->a[0] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 318 context->a[1] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 319 context->a[2] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 320 context->a[3] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 321 context->a[4] &= 0x00000003;
Sergunb 0:8918a71cdbe9 322
Sergunb 0:8918a71cdbe9 323 //Perform fast modular reduction (second pass)
Sergunb 0:8918a71cdbe9 324 context->a[0] += a[0];
Sergunb 0:8918a71cdbe9 325 context->a[0] += a[0] >> 2;
Sergunb 0:8918a71cdbe9 326
Sergunb 0:8918a71cdbe9 327 //Propagate the carry
Sergunb 0:8918a71cdbe9 328 context->a[1] += context->a[0] >> 32;
Sergunb 0:8918a71cdbe9 329 context->a[2] += context->a[1] >> 32;
Sergunb 0:8918a71cdbe9 330 context->a[3] += context->a[2] >> 32;
Sergunb 0:8918a71cdbe9 331 context->a[4] += context->a[3] >> 32;
Sergunb 0:8918a71cdbe9 332
Sergunb 0:8918a71cdbe9 333 //We only consider the least significant bits
Sergunb 0:8918a71cdbe9 334 context->a[0] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 335 context->a[1] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 336 context->a[2] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 337 context->a[3] &= 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 338 context->a[4] &= 0x00000003;
Sergunb 0:8918a71cdbe9 339 }
Sergunb 0:8918a71cdbe9 340
Sergunb 0:8918a71cdbe9 341 #endif
Sergunb 0:8918a71cdbe9 342