Manuel Pégourié-Gonnard | 32b04c1 | 2013-12-02 15:49:09 +0100 | [diff] [blame^] | 1 | /* |
| 2 | * Elliptic curves over GF(p): curve-specific data and functions |
| 3 | * |
| 4 | * Copyright (C) 2006-2013, Brainspark B.V. |
| 5 | * |
| 6 | * This file is part of PolarSSL (http://www.polarssl.org) |
| 7 | * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> |
| 8 | * |
| 9 | * All rights reserved. |
| 10 | * |
| 11 | * This program is free software; you can redistribute it and/or modify |
| 12 | * it under the terms of the GNU General Public License as published by |
| 13 | * the Free Software Foundation; either version 2 of the License, or |
| 14 | * (at your option) any later version. |
| 15 | * |
| 16 | * This program is distributed in the hope that it will be useful, |
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 19 | * GNU General Public License for more details. |
| 20 | * |
| 21 | * You should have received a copy of the GNU General Public License along |
| 22 | * with this program; if not, write to the Free Software Foundation, Inc., |
| 23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 24 | */ |
| 25 | |
| 26 | #include "polarssl/config.h" |
| 27 | |
| 28 | #if defined(POLARSSL_ECP_C) |
| 29 | |
| 30 | #include "polarssl/ecp.h" |
| 31 | |
| 32 | /* |
| 33 | * Domain parameters for secp192r1 |
| 34 | */ |
| 35 | #define SECP192R1_P \ |
| 36 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF" |
| 37 | #define SECP192R1_B \ |
| 38 | "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1" |
| 39 | #define SECP192R1_GX \ |
| 40 | "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" |
| 41 | #define SECP192R1_GY \ |
| 42 | "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811" |
| 43 | #define SECP192R1_N \ |
| 44 | "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831" |
| 45 | |
| 46 | /* |
| 47 | * Domain parameters for secp224r1 |
| 48 | */ |
| 49 | #define SECP224R1_P \ |
| 50 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001" |
| 51 | #define SECP224R1_B \ |
| 52 | "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4" |
| 53 | #define SECP224R1_GX \ |
| 54 | "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" |
| 55 | #define SECP224R1_GY \ |
| 56 | "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34" |
| 57 | #define SECP224R1_N \ |
| 58 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D" |
| 59 | |
| 60 | /* |
| 61 | * Domain parameters for secp256r1 |
| 62 | */ |
| 63 | #define SECP256R1_P \ |
| 64 | "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF" |
| 65 | #define SECP256R1_B \ |
| 66 | "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B" |
| 67 | #define SECP256R1_GX \ |
| 68 | "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" |
| 69 | #define SECP256R1_GY \ |
| 70 | "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" |
| 71 | #define SECP256R1_N \ |
| 72 | "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551" |
| 73 | |
| 74 | /* |
| 75 | * Domain parameters for secp384r1 |
| 76 | */ |
| 77 | #define SECP384R1_P \ |
| 78 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ |
| 79 | "FFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF" |
| 80 | #define SECP384R1_B \ |
| 81 | "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE814112" \ |
| 82 | "0314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF" |
| 83 | #define SECP384R1_GX \ |
| 84 | "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B98" \ |
| 85 | "59F741E082542A385502F25DBF55296C3A545E3872760AB7" |
| 86 | #define SECP384R1_GY \ |
| 87 | "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147C" \ |
| 88 | "E9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F" |
| 89 | #define SECP384R1_N \ |
| 90 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ |
| 91 | "C7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973" |
| 92 | |
| 93 | /* |
| 94 | * Domain parameters for secp521r1 |
| 95 | */ |
| 96 | #define SECP521R1_P \ |
| 97 | "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ |
| 98 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ |
| 99 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" |
| 100 | #define SECP521R1_B \ |
| 101 | "00000051953EB9618E1C9A1F929A21A0B68540EEA2DA725B" \ |
| 102 | "99B315F3B8B489918EF109E156193951EC7E937B1652C0BD" \ |
| 103 | "3BB1BF073573DF883D2C34F1EF451FD46B503F00" |
| 104 | #define SECP521R1_GX \ |
| 105 | "000000C6858E06B70404E9CD9E3ECB662395B4429C648139" \ |
| 106 | "053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127" \ |
| 107 | "A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" |
| 108 | #define SECP521R1_GY \ |
| 109 | "0000011839296A789A3BC0045C8A5FB42C7D1BD998F54449" \ |
| 110 | "579B446817AFBD17273E662C97EE72995EF42640C550B901" \ |
| 111 | "3FAD0761353C7086A272C24088BE94769FD16650" |
| 112 | #define SECP521R1_N \ |
| 113 | "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ |
| 114 | "FFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148" \ |
| 115 | "F709A5D03BB5C9B8899C47AEBB6FB71E91386409" |
| 116 | |
| 117 | /* |
| 118 | * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) |
| 119 | */ |
| 120 | #define BP256R1_P \ |
| 121 | "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377" |
| 122 | #define BP256R1_A \ |
| 123 | "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9" |
| 124 | #define BP256R1_B \ |
| 125 | "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6" |
| 126 | #define BP256R1_GX \ |
| 127 | "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262" |
| 128 | #define BP256R1_GY \ |
| 129 | "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997" |
| 130 | #define BP256R1_N \ |
| 131 | "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7" |
| 132 | |
| 133 | /* |
| 134 | * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) |
| 135 | */ |
| 136 | #define BP384R1_P \ |
| 137 | "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB711" \ |
| 138 | "23ACD3A729901D1A71874700133107EC53" |
| 139 | #define BP384R1_A \ |
| 140 | "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F9" \ |
| 141 | "0F8AA5814A503AD4EB04A8C7DD22CE2826" |
| 142 | #define BP384R1_B \ |
| 143 | "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62" \ |
| 144 | "D57CB4390295DBC9943AB78696FA504C11" |
| 145 | #define BP384R1_GX \ |
| 146 | "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10" \ |
| 147 | "E8E826E03436D646AAEF87B2E247D4AF1E" |
| 148 | #define BP384R1_GY \ |
| 149 | "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129" \ |
| 150 | "280E4646217791811142820341263C5315" |
| 151 | #define BP384R1_N \ |
| 152 | "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425" \ |
| 153 | "A7CF3AB6AF6B7FC3103B883202E9046565" |
| 154 | |
| 155 | /* |
| 156 | * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) |
| 157 | */ |
| 158 | #define BP512R1_P \ |
| 159 | "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308" \ |
| 160 | "717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3" |
| 161 | #define BP512R1_A \ |
| 162 | "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863" \ |
| 163 | "BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA" |
| 164 | #define BP512R1_B \ |
| 165 | "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117" \ |
| 166 | "A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723" |
| 167 | #define BP512R1_GX \ |
| 168 | "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009" \ |
| 169 | "8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822" |
| 170 | #define BP512R1_GY \ |
| 171 | "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81" \ |
| 172 | "11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892" |
| 173 | #define BP512R1_N \ |
| 174 | "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308" \ |
| 175 | "70553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069" |
| 176 | |
| 177 | /* |
| 178 | * Import an ECP group from ASCII strings, general case (A used) |
| 179 | */ |
| 180 | static int ecp_group_read_string_gen( ecp_group *grp, int radix, |
| 181 | const char *p, const char *a, const char *b, |
| 182 | const char *gx, const char *gy, const char *n) |
| 183 | { |
| 184 | int ret; |
| 185 | |
| 186 | MPI_CHK( mpi_read_string( &grp->P, radix, p ) ); |
| 187 | MPI_CHK( mpi_read_string( &grp->A, radix, a ) ); |
| 188 | MPI_CHK( mpi_read_string( &grp->B, radix, b ) ); |
| 189 | MPI_CHK( ecp_point_read_string( &grp->G, radix, gx, gy ) ); |
| 190 | MPI_CHK( mpi_read_string( &grp->N, radix, n ) ); |
| 191 | |
| 192 | grp->pbits = mpi_msb( &grp->P ); |
| 193 | grp->nbits = mpi_msb( &grp->N ); |
| 194 | |
| 195 | cleanup: |
| 196 | if( ret != 0 ) |
| 197 | ecp_group_free( grp ); |
| 198 | |
| 199 | return( ret ); |
| 200 | } |
| 201 | |
| 202 | #if defined(POLARSSL_ECP_NIST_OPTIM) |
| 203 | /* Forward declarations */ |
| 204 | int ecp_mod_p192( mpi * ); |
| 205 | int ecp_mod_p224( mpi * ); |
| 206 | int ecp_mod_p256( mpi * ); |
| 207 | int ecp_mod_p384( mpi * ); |
| 208 | int ecp_mod_p521( mpi * ); |
| 209 | #endif |
| 210 | |
| 211 | /* |
| 212 | * Set a group using well-known domain parameters |
| 213 | */ |
| 214 | int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) |
| 215 | { |
| 216 | grp->id = id; |
| 217 | |
| 218 | switch( id ) |
| 219 | { |
| 220 | #if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) |
| 221 | case POLARSSL_ECP_DP_SECP192R1: |
| 222 | #if defined(POLARSSL_ECP_NIST_OPTIM) |
| 223 | grp->modp = ecp_mod_p192; |
| 224 | #endif |
| 225 | return( ecp_group_read_string( grp, 16, |
| 226 | SECP192R1_P, SECP192R1_B, |
| 227 | SECP192R1_GX, SECP192R1_GY, SECP192R1_N ) ); |
| 228 | #endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ |
| 229 | |
| 230 | #if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) |
| 231 | case POLARSSL_ECP_DP_SECP224R1: |
| 232 | #if defined(POLARSSL_ECP_NIST_OPTIM) |
| 233 | grp->modp = ecp_mod_p224; |
| 234 | #endif |
| 235 | return( ecp_group_read_string( grp, 16, |
| 236 | SECP224R1_P, SECP224R1_B, |
| 237 | SECP224R1_GX, SECP224R1_GY, SECP224R1_N ) ); |
| 238 | #endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ |
| 239 | |
| 240 | #if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) |
| 241 | case POLARSSL_ECP_DP_SECP256R1: |
| 242 | #if defined(POLARSSL_ECP_NIST_OPTIM) |
| 243 | grp->modp = ecp_mod_p256; |
| 244 | #endif |
| 245 | return( ecp_group_read_string( grp, 16, |
| 246 | SECP256R1_P, SECP256R1_B, |
| 247 | SECP256R1_GX, SECP256R1_GY, SECP256R1_N ) ); |
| 248 | #endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ |
| 249 | |
| 250 | #if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) |
| 251 | case POLARSSL_ECP_DP_SECP384R1: |
| 252 | #if defined(POLARSSL_ECP_NIST_OPTIM) |
| 253 | grp->modp = ecp_mod_p384; |
| 254 | #endif |
| 255 | return( ecp_group_read_string( grp, 16, |
| 256 | SECP384R1_P, SECP384R1_B, |
| 257 | SECP384R1_GX, SECP384R1_GY, SECP384R1_N ) ); |
| 258 | #endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ |
| 259 | |
| 260 | #if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) |
| 261 | case POLARSSL_ECP_DP_SECP521R1: |
| 262 | #if defined(POLARSSL_ECP_NIST_OPTIM) |
| 263 | grp->modp = ecp_mod_p521; |
| 264 | #endif |
| 265 | return( ecp_group_read_string( grp, 16, |
| 266 | SECP521R1_P, SECP521R1_B, |
| 267 | SECP521R1_GX, SECP521R1_GY, SECP521R1_N ) ); |
| 268 | #endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ |
| 269 | |
| 270 | #if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) |
| 271 | case POLARSSL_ECP_DP_BP256R1: |
| 272 | return( ecp_group_read_string_gen( grp, 16, |
| 273 | BP256R1_P, BP256R1_A, BP256R1_B, |
| 274 | BP256R1_GX, BP256R1_GY, BP256R1_N ) ); |
| 275 | #endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */ |
| 276 | |
| 277 | #if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) |
| 278 | case POLARSSL_ECP_DP_BP384R1: |
| 279 | return( ecp_group_read_string_gen( grp, 16, |
| 280 | BP384R1_P, BP384R1_A, BP384R1_B, |
| 281 | BP384R1_GX, BP384R1_GY, BP384R1_N ) ); |
| 282 | #endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */ |
| 283 | |
| 284 | #if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) |
| 285 | case POLARSSL_ECP_DP_BP512R1: |
| 286 | return( ecp_group_read_string_gen( grp, 16, |
| 287 | BP512R1_P, BP512R1_A, BP512R1_B, |
| 288 | BP512R1_GX, BP512R1_GY, BP512R1_N ) ); |
| 289 | #endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */ |
| 290 | |
| 291 | default: |
| 292 | ecp_group_free( grp ); |
| 293 | return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | #if defined(POLARSSL_ECP_NIST_OPTIM) |
| 298 | /* |
| 299 | * Fast reduction modulo the primes used by the NIST curves. |
| 300 | * |
| 301 | * These functions are critical for speed, but not needed for correct |
| 302 | * operations. So, we make the choice to heavily rely on the internals of our |
| 303 | * bignum library, which creates a tight coupling between these functions and |
| 304 | * our MPI implementation. However, the coupling between the ECP module and |
| 305 | * MPI remains loose, since these functions can be deactivated at will. |
| 306 | */ |
| 307 | |
| 308 | #if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) |
| 309 | /* |
| 310 | * Compared to the way things are presented in FIPS 186-3 D.2, |
| 311 | * we proceed in columns, from right (least significant chunk) to left, |
| 312 | * adding chunks to N in place, and keeping a carry for the next chunk. |
| 313 | * This avoids moving things around in memory, and uselessly adding zeros, |
| 314 | * compared to the more straightforward, line-oriented approach. |
| 315 | * |
| 316 | * For this prime we need to handle data in chunks of 64 bits. |
| 317 | * Since this is always a multiple of our basic t_uint, we can |
| 318 | * use a t_uint * to designate such a chunk, and small loops to handle it. |
| 319 | */ |
| 320 | |
| 321 | /* Add 64-bit chunks (dst += src) and update carry */ |
| 322 | static inline void add64( t_uint *dst, t_uint *src, t_uint *carry ) |
| 323 | { |
| 324 | unsigned char i; |
| 325 | t_uint c = 0; |
| 326 | for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ ) |
| 327 | { |
| 328 | *dst += c; c = ( *dst < c ); |
| 329 | *dst += *src; c += ( *dst < *src ); |
| 330 | } |
| 331 | *carry += c; |
| 332 | } |
| 333 | |
| 334 | /* Add carry to a 64-bit chunk and update carry */ |
| 335 | static inline void carry64( t_uint *dst, t_uint *carry ) |
| 336 | { |
| 337 | unsigned char i; |
| 338 | for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ ) |
| 339 | { |
| 340 | *dst += *carry; |
| 341 | *carry = ( *dst < *carry ); |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | #define WIDTH 8 / sizeof( t_uint ) |
| 346 | #define A( i ) N->p + i * WIDTH |
| 347 | #define ADD( i ) add64( p, A( i ), &c ) |
| 348 | #define NEXT p += WIDTH; carry64( p, &c ) |
| 349 | #define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 |
| 350 | |
| 351 | /* |
| 352 | * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) |
| 353 | */ |
| 354 | int ecp_mod_p192( mpi *N ) |
| 355 | { |
| 356 | int ret; |
| 357 | t_uint c = 0; |
| 358 | t_uint *p, *end; |
| 359 | |
| 360 | /* Make sure we have enough blocks so that A(5) is legal */ |
| 361 | MPI_CHK( mpi_grow( N, 6 * WIDTH ) ); |
| 362 | |
| 363 | p = N->p; |
| 364 | end = p + N->n; |
| 365 | |
| 366 | ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 |
| 367 | ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 |
| 368 | ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 |
| 369 | |
| 370 | cleanup: |
| 371 | return( ret ); |
| 372 | } |
| 373 | |
| 374 | #undef WIDTH |
| 375 | #undef A |
| 376 | #undef ADD |
| 377 | #undef NEXT |
| 378 | #undef LAST |
| 379 | #endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ |
| 380 | |
| 381 | #if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \ |
| 382 | defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \ |
| 383 | defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) |
| 384 | /* |
| 385 | * The reader is advised to first understand ecp_mod_p192() since the same |
| 386 | * general structure is used here, but with additional complications: |
| 387 | * (1) chunks of 32 bits, and (2) subtractions. |
| 388 | */ |
| 389 | |
| 390 | /* |
| 391 | * For these primes, we need to handle data in chunks of 32 bits. |
| 392 | * This makes it more complicated if we use 64 bits limbs in MPI, |
| 393 | * which prevents us from using a uniform access method as for p192. |
| 394 | * |
| 395 | * So, we define a mini abstraction layer to access 32 bit chunks, |
| 396 | * load them in 'cur' for work, and store them back from 'cur' when done. |
| 397 | * |
| 398 | * While at it, also define the size of N in terms of 32-bit chunks. |
| 399 | */ |
| 400 | #define LOAD32 cur = A( i ); |
| 401 | |
| 402 | #if defined(POLARSSL_HAVE_INT8) /* 8 bit */ |
| 403 | |
| 404 | #define MAX32 N->n / 4 |
| 405 | #define A( j ) (uint32_t)( N->p[4*j+0] ) | \ |
| 406 | ( N->p[4*j+1] << 8 ) | \ |
| 407 | ( N->p[4*j+2] << 16 ) | \ |
| 408 | ( N->p[4*j+3] << 24 ) |
| 409 | #define STORE32 N->p[4*i+0] = (t_uint)( cur ); \ |
| 410 | N->p[4*i+1] = (t_uint)( cur >> 8 ); \ |
| 411 | N->p[4*i+2] = (t_uint)( cur >> 16 ); \ |
| 412 | N->p[4*i+3] = (t_uint)( cur >> 24 ); |
| 413 | |
| 414 | #elif defined(POLARSSL_HAVE_INT16) /* 16 bit */ |
| 415 | |
| 416 | #define MAX32 N->n / 2 |
| 417 | #define A( j ) (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 ) |
| 418 | #define STORE32 N->p[2*i+0] = (t_uint)( cur ); \ |
| 419 | N->p[2*i+1] = (t_uint)( cur >> 16 ); |
| 420 | |
| 421 | #elif defined(POLARSSL_HAVE_INT32) /* 32 bit */ |
| 422 | |
| 423 | #define MAX32 N->n |
| 424 | #define A( j ) N->p[j] |
| 425 | #define STORE32 N->p[i] = cur; |
| 426 | |
| 427 | #else /* 64-bit */ |
| 428 | |
| 429 | #define MAX32 N->n * 2 |
| 430 | #define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] ) |
| 431 | #define STORE32 \ |
| 432 | if( i % 2 ) { \ |
| 433 | N->p[i/2] &= 0x00000000FFFFFFFF; \ |
| 434 | N->p[i/2] |= ((t_uint) cur) << 32; \ |
| 435 | } else { \ |
| 436 | N->p[i/2] &= 0xFFFFFFFF00000000; \ |
| 437 | N->p[i/2] |= (t_uint) cur; \ |
| 438 | } |
| 439 | |
| 440 | #endif /* sizeof( t_uint ) */ |
| 441 | |
| 442 | /* |
| 443 | * Helpers for addition and subtraction of chunks, with signed carry. |
| 444 | */ |
| 445 | static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) |
| 446 | { |
| 447 | *dst += src; |
| 448 | *carry += ( *dst < src ); |
| 449 | } |
| 450 | |
| 451 | static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) |
| 452 | { |
| 453 | *carry -= ( *dst < src ); |
| 454 | *dst -= src; |
| 455 | } |
| 456 | |
| 457 | #define ADD( j ) add32( &cur, A( j ), &c ); |
| 458 | #define SUB( j ) sub32( &cur, A( j ), &c ); |
| 459 | |
| 460 | /* |
| 461 | * Helpers for the main 'loop' |
| 462 | * (see fix_negative for the motivation of C) |
| 463 | */ |
| 464 | #define INIT( b ) \ |
| 465 | int ret; \ |
| 466 | signed char c = 0, cc; \ |
| 467 | uint32_t cur; \ |
| 468 | size_t i = 0, bits = b; \ |
| 469 | mpi C; \ |
| 470 | t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ]; \ |
| 471 | \ |
| 472 | C.s = 1; \ |
| 473 | C.n = b / 8 / sizeof( t_uint) + 1; \ |
| 474 | C.p = Cp; \ |
| 475 | memset( Cp, 0, C.n * sizeof( t_uint ) ); \ |
| 476 | \ |
| 477 | MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \ |
| 478 | LOAD32; |
| 479 | |
| 480 | #define NEXT \ |
| 481 | STORE32; i++; LOAD32; \ |
| 482 | cc = c; c = 0; \ |
| 483 | if( cc < 0 ) \ |
| 484 | sub32( &cur, -cc, &c ); \ |
| 485 | else \ |
| 486 | add32( &cur, cc, &c ); \ |
| 487 | |
| 488 | #define LAST \ |
| 489 | STORE32; i++; \ |
| 490 | cur = c > 0 ? c : 0; STORE32; \ |
| 491 | cur = 0; while( ++i < MAX32 ) { STORE32; } \ |
| 492 | if( c < 0 ) fix_negative( N, c, &C, bits ); |
| 493 | |
| 494 | /* |
| 495 | * If the result is negative, we get it in the form |
| 496 | * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' |
| 497 | */ |
| 498 | static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits ) |
| 499 | { |
| 500 | int ret; |
| 501 | |
| 502 | /* C = - c * 2^(bits + 32) */ |
| 503 | #if !defined(POLARSSL_HAVE_INT64) |
| 504 | ((void) bits); |
| 505 | #else |
| 506 | if( bits == 224 ) |
| 507 | C->p[ C->n - 1 ] = ((t_uint) -c) << 32; |
| 508 | else |
| 509 | #endif |
| 510 | C->p[ C->n - 1 ] = (t_uint) -c; |
| 511 | |
| 512 | /* N = - ( C - N ) */ |
| 513 | MPI_CHK( mpi_sub_abs( N, C, N ) ); |
| 514 | N->s = -1; |
| 515 | |
| 516 | cleanup: |
| 517 | |
| 518 | return( ret ); |
| 519 | } |
| 520 | |
| 521 | #if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) |
| 522 | /* |
| 523 | * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) |
| 524 | */ |
| 525 | int ecp_mod_p224( mpi *N ) |
| 526 | { |
| 527 | INIT( 224 ); |
| 528 | |
| 529 | SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 |
| 530 | SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 |
| 531 | SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 |
| 532 | SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 |
| 533 | SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 |
| 534 | SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 |
| 535 | SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 |
| 536 | |
| 537 | cleanup: |
| 538 | return( ret ); |
| 539 | } |
| 540 | #endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ |
| 541 | |
| 542 | #if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) |
| 543 | /* |
| 544 | * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) |
| 545 | */ |
| 546 | int ecp_mod_p256( mpi *N ) |
| 547 | { |
| 548 | INIT( 256 ); |
| 549 | |
| 550 | ADD( 8 ); ADD( 9 ); |
| 551 | SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 |
| 552 | |
| 553 | ADD( 9 ); ADD( 10 ); |
| 554 | SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 |
| 555 | |
| 556 | ADD( 10 ); ADD( 11 ); |
| 557 | SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 |
| 558 | |
| 559 | ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); |
| 560 | SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 |
| 561 | |
| 562 | ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); |
| 563 | SUB( 9 ); SUB( 10 ); NEXT; // A4 |
| 564 | |
| 565 | ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); |
| 566 | SUB( 10 ); SUB( 11 ); NEXT; // A5 |
| 567 | |
| 568 | ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); |
| 569 | SUB( 8 ); SUB( 9 ); NEXT; // A6 |
| 570 | |
| 571 | ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); |
| 572 | SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 |
| 573 | |
| 574 | cleanup: |
| 575 | return( ret ); |
| 576 | } |
| 577 | #endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ |
| 578 | |
| 579 | #if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) |
| 580 | /* |
| 581 | * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) |
| 582 | */ |
| 583 | int ecp_mod_p384( mpi *N ) |
| 584 | { |
| 585 | INIT( 384 ); |
| 586 | |
| 587 | ADD( 12 ); ADD( 21 ); ADD( 20 ); |
| 588 | SUB( 23 ); NEXT; // A0 |
| 589 | |
| 590 | ADD( 13 ); ADD( 22 ); ADD( 23 ); |
| 591 | SUB( 12 ); SUB( 20 ); NEXT; // A2 |
| 592 | |
| 593 | ADD( 14 ); ADD( 23 ); |
| 594 | SUB( 13 ); SUB( 21 ); NEXT; // A2 |
| 595 | |
| 596 | ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); |
| 597 | SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 |
| 598 | |
| 599 | ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); |
| 600 | SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 |
| 601 | |
| 602 | ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); |
| 603 | SUB( 16 ); NEXT; // A5 |
| 604 | |
| 605 | ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); |
| 606 | SUB( 17 ); NEXT; // A6 |
| 607 | |
| 608 | ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); |
| 609 | SUB( 18 ); NEXT; // A7 |
| 610 | |
| 611 | ADD( 20 ); ADD( 17 ); ADD( 16 ); |
| 612 | SUB( 19 ); NEXT; // A8 |
| 613 | |
| 614 | ADD( 21 ); ADD( 18 ); ADD( 17 ); |
| 615 | SUB( 20 ); NEXT; // A9 |
| 616 | |
| 617 | ADD( 22 ); ADD( 19 ); ADD( 18 ); |
| 618 | SUB( 21 ); NEXT; // A10 |
| 619 | |
| 620 | ADD( 23 ); ADD( 20 ); ADD( 19 ); |
| 621 | SUB( 22 ); LAST; // A11 |
| 622 | |
| 623 | cleanup: |
| 624 | return( ret ); |
| 625 | } |
| 626 | #endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ |
| 627 | |
| 628 | #undef A |
| 629 | #undef LOAD32 |
| 630 | #undef STORE32 |
| 631 | #undef MAX32 |
| 632 | #undef INIT |
| 633 | #undef NEXT |
| 634 | #undef LAST |
| 635 | |
| 636 | #endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED || |
| 637 | POLARSSL_ECP_DP_SECP256R1_ENABLED || |
| 638 | POLARSSL_ECP_DP_SECP384R1_ENABLED */ |
| 639 | |
| 640 | #if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) |
| 641 | /* |
| 642 | * Here we have an actual Mersenne prime, so things are more straightforward. |
| 643 | * However, chunks are aligned on a 'weird' boundary (521 bits). |
| 644 | */ |
| 645 | |
| 646 | /* Size of p521 in terms of t_uint */ |
| 647 | #define P521_WIDTH ( 521 / 8 / sizeof( t_uint ) + 1 ) |
| 648 | |
| 649 | /* Bits to keep in the most significant t_uint */ |
| 650 | #if defined(POLARSSL_HAVE_INT8) |
| 651 | #define P521_MASK 0x01 |
| 652 | #else |
| 653 | #define P521_MASK 0x01FF |
| 654 | #endif |
| 655 | |
| 656 | /* |
| 657 | * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) |
| 658 | * Write N as A1 + 2^521 A0, return A0 + A1 |
| 659 | */ |
| 660 | int ecp_mod_p521( mpi *N ) |
| 661 | { |
| 662 | int ret; |
| 663 | size_t i; |
| 664 | mpi M; |
| 665 | t_uint Mp[P521_WIDTH + 1]; |
| 666 | /* Worst case for the size of M is when t_uint is 16 bits: |
| 667 | * we need to hold bits 513 to 1056, which is 34 limbs, that is |
| 668 | * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ |
| 669 | |
| 670 | if( N->n < P521_WIDTH ) |
| 671 | return( 0 ); |
| 672 | |
| 673 | /* M = A1 */ |
| 674 | M.s = 1; |
| 675 | M.n = N->n - ( P521_WIDTH - 1 ); |
| 676 | if( M.n > P521_WIDTH + 1 ) |
| 677 | M.n = P521_WIDTH + 1; |
| 678 | M.p = Mp; |
| 679 | memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) ); |
| 680 | MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) ); |
| 681 | |
| 682 | /* N = A0 */ |
| 683 | N->p[P521_WIDTH - 1] &= P521_MASK; |
| 684 | for( i = P521_WIDTH; i < N->n; i++ ) |
| 685 | N->p[i] = 0; |
| 686 | |
| 687 | /* N = A0 + A1 */ |
| 688 | MPI_CHK( mpi_add_abs( N, N, &M ) ); |
| 689 | |
| 690 | cleanup: |
| 691 | return( ret ); |
| 692 | } |
| 693 | |
| 694 | #undef P521_WIDTH |
| 695 | #undef P521_MASK |
| 696 | #endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ |
| 697 | |
| 698 | #endif /* POLARSSL_ECP_NIST_OPTIM */ |
| 699 | |
| 700 | #endif |