ssh lib
Embed:
(wiki syntax)
Show/hide line numbers
ge_low_mem.c
00001 /* ge_low_mem.c 00002 * 00003 * Copyright (C) 2006-2017 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 /* Based from Daniel Beer's public domain work. */ 00024 00025 #ifdef HAVE_CONFIG_H 00026 #include <config.h> 00027 #endif 00028 00029 #include <wolfcrypt/settings.h> 00030 00031 #ifdef HAVE_ED25519 00032 #ifdef ED25519_SMALL /* use slower code that takes less memory */ 00033 00034 #include <wolfcrypt/ge_operations.h> 00035 #include <wolfcrypt/error-crypt.h> 00036 #ifdef NO_INLINE 00037 #include <wolfcrypt/misc.h> 00038 #else 00039 #define WOLFSSL_MISC_INCLUDED 00040 #include <wolfcrypt/src/misc.c> 00041 #endif 00042 00043 void ed25519_smult(ge_p3 *r, const ge_p3 *a, const byte *e); 00044 void ed25519_add(ge_p3 *r, const ge_p3 *a, const ge_p3 *b); 00045 void ed25519_double(ge_p3 *r, const ge_p3 *a); 00046 00047 00048 static const byte ed25519_order[F25519_SIZE] = { 00049 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 00050 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 00051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00052 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 00053 }; 00054 00055 /*Arithmetic modulo the group order m = 2^252 + 00056 27742317777372353535851937790883648493 = 00057 7237005577332262213973186563042994240857116359379907606001950938285454250989 */ 00058 00059 static const word32 m[32] = { 00060 0xED,0xD3,0xF5,0x5C,0x1A,0x63,0x12,0x58,0xD6,0x9C,0xF7,0xA2,0xDE,0xF9, 00061 0xDE,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 00062 0x00,0x00,0x00,0x10 00063 }; 00064 00065 static const word32 mu[33] = { 00066 0x1B,0x13,0x2C,0x0A,0xA3,0xE5,0x9C,0xED,0xA7,0x29,0x63,0x08,0x5D,0x21, 00067 0x06,0x21,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 00068 0xFF,0xFF,0xFF,0xFF,0x0F 00069 }; 00070 00071 00072 int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, 00073 word32 keySz) 00074 { 00075 byte tmp[F25519_SIZE]; 00076 byte parity; 00077 byte pt[32]; 00078 int i; 00079 00080 lm_copy(tmp, xIn); 00081 parity = (tmp[0] & 1) << 7; 00082 00083 lm_copy(pt, yIn); 00084 pt[31] |= parity; 00085 00086 for(i = 0; i < 32; i++) { 00087 out[32-i-1] = pt[i]; 00088 } 00089 (void)keySz; 00090 return 0; 00091 } 00092 00093 00094 static word32 lt(word32 a,word32 b) /* 16-bit inputs */ 00095 { 00096 unsigned int x = a; 00097 x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ 00098 x >>= 31; /* 0: no; 1: yes */ 00099 return x; 00100 } 00101 00102 00103 /* Reduce coefficients of r before calling reduce_add_sub */ 00104 static void reduce_add_sub(word32 *r) 00105 { 00106 word32 pb = 0; 00107 word32 b; 00108 word32 mask; 00109 int i; 00110 unsigned char t[32]; 00111 00112 for(i=0;i<32;i++) 00113 { 00114 pb += m[i]; 00115 b = lt(r[i],pb); 00116 t[i] = r[i]-pb+(b<<8); 00117 pb = b; 00118 } 00119 mask = b - 1; 00120 for(i=0;i<32;i++) 00121 r[i] ^= mask & (r[i] ^ t[i]); 00122 } 00123 00124 00125 /* Reduce coefficients of x before calling barrett_reduce */ 00126 static void barrett_reduce(word32* r, word32 x[64]) 00127 { 00128 /* See HAC, Alg. 14.42 */ 00129 int i,j; 00130 word32 q2[66]; 00131 word32 *q3 = q2 + 33; 00132 word32 r1[33]; 00133 word32 r2[33]; 00134 word32 carry; 00135 word32 pb = 0; 00136 word32 b; 00137 00138 for (i = 0;i < 66;++i) q2[i] = 0; 00139 for (i = 0;i < 33;++i) r2[i] = 0; 00140 00141 for(i=0;i<33;i++) 00142 for(j=0;j<33;j++) 00143 if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; 00144 carry = q2[31] >> 8; 00145 q2[32] += carry; 00146 carry = q2[32] >> 8; 00147 q2[33] += carry; 00148 00149 for(i=0;i<33;i++)r1[i] = x[i]; 00150 for(i=0;i<32;i++) 00151 for(j=0;j<33;j++) 00152 if(i+j < 33) r2[i+j] += m[i]*q3[j]; 00153 00154 for(i=0;i<32;i++) 00155 { 00156 carry = r2[i] >> 8; 00157 r2[i+1] += carry; 00158 r2[i] &= 0xff; 00159 } 00160 00161 for(i=0;i<32;i++) 00162 { 00163 pb += r2[i]; 00164 b = lt(r1[i],pb); 00165 r[i] = r1[i]-pb+(b<<8); 00166 pb = b; 00167 } 00168 00169 /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 00170 * r is an unsigned type. 00171 * If so: Handle it here! 00172 */ 00173 00174 reduce_add_sub(r); 00175 reduce_add_sub(r); 00176 } 00177 00178 00179 void sc_reduce(unsigned char x[64]) 00180 { 00181 int i; 00182 word32 t[64]; 00183 word32 r[32]; 00184 for(i=0;i<64;i++) t[i] = x[i]; 00185 barrett_reduce(r, t); 00186 for(i=0;i<32;i++) x[i] = (r[i] & 0xFF); 00187 } 00188 00189 00190 void sc_muladd(byte* out, const byte* a, const byte* b, const byte* c) 00191 { 00192 00193 byte s[32]; 00194 byte e[64]; 00195 00196 XMEMSET(e, 0, sizeof(e)); 00197 XMEMCPY(e, b, 32); 00198 00199 /* Obtain e */ 00200 sc_reduce(e); 00201 00202 /* Compute s = ze + k */ 00203 fprime_mul(s, a, e, ed25519_order); 00204 fprime_add(s, c, ed25519_order); 00205 00206 XMEMCPY(out, s, 32); 00207 } 00208 00209 00210 /* Base point is (numbers wrapped): 00211 * 00212 * x = 151122213495354007725011514095885315114 00213 * 54012693041857206046113283949847762202 00214 * y = 463168356949264781694283940034751631413 00215 * 07993866256225615783033603165251855960 00216 * 00217 * y is derived by transforming the original Montgomery base (u=9). x 00218 * is the corresponding positive coordinate for the new curve equation. 00219 * t is x*y. 00220 */ 00221 const ge_p3 ed25519_base = { 00222 { 00223 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 00224 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 00225 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 00226 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 00227 }, 00228 { 00229 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 00230 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 00231 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 00232 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 00233 }, 00234 {1, 0}, 00235 { 00236 0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, 00237 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, 00238 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, 00239 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67 00240 }, 00241 00242 }; 00243 00244 00245 const ge_p3 ed25519_neutral = { 00246 {0}, 00247 {1, 0}, 00248 {1, 0}, 00249 {0}, 00250 00251 }; 00252 00253 00254 static const byte ed25519_d[F25519_SIZE] = { 00255 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, 00256 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, 00257 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, 00258 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52 00259 }; 00260 00261 00262 /* k = 2d */ 00263 static const byte ed25519_k[F25519_SIZE] = { 00264 0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb, 00265 0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00, 00266 0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19, 00267 0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24 00268 }; 00269 00270 00271 void ed25519_add(ge_p3 *r, 00272 const ge_p3 *p1, const ge_p3 *p2) 00273 { 00274 /* Explicit formulas database: add-2008-hwcd-3 00275 * 00276 * source 2008 Hisil--Wong--Carter--Dawson, 00277 * http://eprint.iacr.org/2008/522, Section 3.1 00278 * appliesto extended-1 00279 * parameter k 00280 * assume k = 2 d 00281 * compute A = (Y1-X1)(Y2-X2) 00282 * compute B = (Y1+X1)(Y2+X2) 00283 * compute C = T1 k T2 00284 * compute D = Z1 2 Z2 00285 * compute E = B - A 00286 * compute F = D - C 00287 * compute G = D + C 00288 * compute H = B + A 00289 * compute X3 = E F 00290 * compute Y3 = G H 00291 * compute T3 = E H 00292 * compute Z3 = F G 00293 */ 00294 byte a[F25519_SIZE]; 00295 byte b[F25519_SIZE]; 00296 byte c[F25519_SIZE]; 00297 byte d[F25519_SIZE]; 00298 byte e[F25519_SIZE]; 00299 byte f[F25519_SIZE]; 00300 byte g[F25519_SIZE]; 00301 byte h[F25519_SIZE]; 00302 00303 /* A = (Y1-X1)(Y2-X2) */ 00304 lm_sub(c, p1->Y, p1->X); 00305 lm_sub(d, p2->Y, p2->X); 00306 fe_mul__distinct(a, c, d); 00307 00308 /* B = (Y1+X1)(Y2+X2) */ 00309 lm_add(c, p1->Y, p1->X); 00310 lm_add(d, p2->Y, p2->X); 00311 fe_mul__distinct(b, c, d); 00312 00313 /* C = T1 k T2 */ 00314 fe_mul__distinct(d, p1->T, p2->T); 00315 fe_mul__distinct(c, d, ed25519_k); 00316 00317 /* D = Z1 2 Z2 */ 00318 fe_mul__distinct(d, p1->Z, p2->Z); 00319 lm_add(d, d, d); 00320 00321 /* E = B - A */ 00322 lm_sub(e, b, a); 00323 00324 /* F = D - C */ 00325 lm_sub(f, d, c); 00326 00327 /* G = D + C */ 00328 lm_add(g, d, c); 00329 00330 /* H = B + A */ 00331 lm_add(h, b, a); 00332 00333 /* X3 = E F */ 00334 fe_mul__distinct(r->X, e, f); 00335 00336 /* Y3 = G H */ 00337 fe_mul__distinct(r->Y, g, h); 00338 00339 /* T3 = E H */ 00340 fe_mul__distinct(r->T, e, h); 00341 00342 /* Z3 = F G */ 00343 fe_mul__distinct(r->Z, f, g); 00344 } 00345 00346 00347 void ed25519_double(ge_p3 *r, const ge_p3 *p) 00348 { 00349 /* Explicit formulas database: dbl-2008-hwcd 00350 * 00351 * source 2008 Hisil--Wong--Carter--Dawson, 00352 * http://eprint.iacr.org/2008/522, Section 3.3 00353 * compute A = X1^2 00354 * compute B = Y1^2 00355 * compute C = 2 Z1^2 00356 * compute D = a A 00357 * compute E = (X1+Y1)^2-A-B 00358 * compute G = D + B 00359 * compute F = G - C 00360 * compute H = D - B 00361 * compute X3 = E F 00362 * compute Y3 = G H 00363 * compute T3 = E H 00364 * compute Z3 = F G 00365 */ 00366 byte a[F25519_SIZE]; 00367 byte b[F25519_SIZE]; 00368 byte c[F25519_SIZE]; 00369 byte e[F25519_SIZE]; 00370 byte f[F25519_SIZE]; 00371 byte g[F25519_SIZE]; 00372 byte h[F25519_SIZE]; 00373 00374 /* A = X1^2 */ 00375 fe_mul__distinct(a, p->X, p->X); 00376 00377 /* B = Y1^2 */ 00378 fe_mul__distinct(b, p->Y, p->Y); 00379 00380 /* C = 2 Z1^2 */ 00381 fe_mul__distinct(c, p->Z, p->Z); 00382 lm_add(c, c, c); 00383 00384 /* D = a A (alter sign) */ 00385 /* E = (X1+Y1)^2-A-B */ 00386 lm_add(f, p->X, p->Y); 00387 fe_mul__distinct(e, f, f); 00388 lm_sub(e, e, a); 00389 lm_sub(e, e, b); 00390 00391 /* G = D + B */ 00392 lm_sub(g, b, a); 00393 00394 /* F = G - C */ 00395 lm_sub(f, g, c); 00396 00397 /* H = D - B */ 00398 lm_neg(h, b); 00399 lm_sub(h, h, a); 00400 00401 /* X3 = E F */ 00402 fe_mul__distinct(r->X, e, f); 00403 00404 /* Y3 = G H */ 00405 fe_mul__distinct(r->Y, g, h); 00406 00407 /* T3 = E H */ 00408 fe_mul__distinct(r->T, e, h); 00409 00410 /* Z3 = F G */ 00411 fe_mul__distinct(r->Z, f, g); 00412 } 00413 00414 00415 void ed25519_smult(ge_p3 *r_out, const ge_p3 *p, const byte *e) 00416 { 00417 ge_p3 r; 00418 int i; 00419 00420 XMEMCPY(&r, &ed25519_neutral, sizeof(r)); 00421 00422 for (i = 255; i >= 0; i--) { 00423 const byte bit = (e[i >> 3] >> (i & 7)) & 1; 00424 ge_p3 s; 00425 00426 ed25519_double(&r, &r); 00427 ed25519_add(&s, &r, p); 00428 00429 fe_select(r.X, r.X, s.X, bit); 00430 fe_select(r.Y, r.Y, s.Y, bit); 00431 fe_select(r.Z, r.Z, s.Z, bit); 00432 fe_select(r.T, r.T, s.T, bit); 00433 } 00434 XMEMCPY(r_out, &r, sizeof(r)); 00435 } 00436 00437 00438 void ge_scalarmult_base(ge_p3 *R,const unsigned char *nonce) 00439 { 00440 ed25519_smult(R, &ed25519_base, nonce); 00441 } 00442 00443 00444 /* pack the point h into array s */ 00445 void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) 00446 { 00447 byte x[F25519_SIZE]; 00448 byte y[F25519_SIZE]; 00449 byte z1[F25519_SIZE]; 00450 byte parity; 00451 00452 fe_inv__distinct(z1, h->Z); 00453 fe_mul__distinct(x, h->X, z1); 00454 fe_mul__distinct(y, h->Y, z1); 00455 00456 fe_normalize(x); 00457 fe_normalize(y); 00458 00459 parity = (x[0] & 1) << 7; 00460 lm_copy(s, y); 00461 fe_normalize(s); 00462 s[31] |= parity; 00463 } 00464 00465 00466 /* pack the point h into array s */ 00467 void ge_tobytes(unsigned char *s,const ge_p2 *h) 00468 { 00469 byte x[F25519_SIZE]; 00470 byte y[F25519_SIZE]; 00471 byte z1[F25519_SIZE]; 00472 byte parity; 00473 00474 fe_inv__distinct(z1, h->Z); 00475 fe_mul__distinct(x, h->X, z1); 00476 fe_mul__distinct(y, h->Y, z1); 00477 00478 fe_normalize(x); 00479 fe_normalize(y); 00480 00481 parity = (x[0] & 1) << 7; 00482 lm_copy(s, y); 00483 fe_normalize(s); 00484 s[31] |= parity; 00485 } 00486 00487 00488 /* 00489 Test if the public key can be uncompressed and negate it (-X,Y,Z,-T) 00490 return 0 on success 00491 */ 00492 int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s) 00493 { 00494 00495 byte parity; 00496 byte x[F25519_SIZE]; 00497 byte y[F25519_SIZE]; 00498 byte a[F25519_SIZE]; 00499 byte b[F25519_SIZE]; 00500 byte c[F25519_SIZE]; 00501 int ret = 0; 00502 00503 /* unpack the key s */ 00504 parity = s[31] >> 7; 00505 lm_copy(y, s); 00506 y[31] &= 127; 00507 00508 fe_mul__distinct(c, y, y); 00509 fe_mul__distinct(b, c, ed25519_d); 00510 lm_add(a, b, f25519_one); 00511 fe_inv__distinct(b, a); 00512 lm_sub(a, c, f25519_one); 00513 fe_mul__distinct(c, a, b); 00514 fe_sqrt(a, c); 00515 lm_neg(b, a); 00516 fe_select(x, a, b, (a[0] ^ parity) & 1); 00517 00518 /* test that x^2 is equal to c */ 00519 fe_mul__distinct(a, x, x); 00520 fe_normalize(a); 00521 fe_normalize(c); 00522 ret |= ConstantCompare(a, c, F25519_SIZE); 00523 00524 /* project the key s onto p */ 00525 lm_copy(p->X, x); 00526 lm_copy(p->Y, y); 00527 fe_load(p->Z, 1); 00528 fe_mul__distinct(p->T, x, y); 00529 00530 /* negate, the point becomes (-X,Y,Z,-T) */ 00531 lm_neg(p->X,p->X); 00532 lm_neg(p->T,p->T); 00533 00534 return ret; 00535 } 00536 00537 00538 int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h, 00539 const ge_p3 *inA,const unsigned char *sig) 00540 { 00541 ge_p3 p, A; 00542 int ret = 0; 00543 00544 XMEMCPY(&A, inA, sizeof(ge_p3)); 00545 00546 /* find SB */ 00547 ed25519_smult(&p, &ed25519_base, sig); 00548 00549 /* find H(R,A,M) * -A */ 00550 ed25519_smult(&A, &A, h); 00551 00552 /* SB + -H(R,A,M)A */ 00553 ed25519_add(&A, &p, &A); 00554 00555 lm_copy(R->X, A.X); 00556 lm_copy(R->Y, A.Y); 00557 lm_copy(R->Z, A.Z); 00558 00559 return ret; 00560 } 00561 00562 #endif /* ED25519_SMALL */ 00563 #endif /* HAVE_ED25519 */ 00564
Generated on Tue Jul 12 2022 16:58:06 by 1.7.2