1 /* 2 * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include "inner.h" 26 27 /* see bearssl_ec.h */ 28 size_t 29 br_ec_keygen(const br_prng_class **rng_ctx, 30 const br_ec_impl *impl, br_ec_private_key *sk, 31 void *kbuf, int curve) 32 { 33 const unsigned char *order; 34 unsigned char *buf; 35 size_t len; 36 unsigned mask; 37 38 if (curve < 0 || curve >= 32 39 || ((impl->supported_curves >> curve) & 1) == 0) 40 { 41 return 0; 42 } 43 order = impl->order(curve, &len); 44 while (len > 0 && *order == 0) { 45 order ++; 46 len --; 47 } 48 if (kbuf == NULL || len == 0) { 49 return len; 50 } 51 mask = order[0]; 52 mask |= (mask >> 1); 53 mask |= (mask >> 2); 54 mask |= (mask >> 4); 55 56 /* 57 * We generate sequences of random bits of the right size, until 58 * the value is strictly lower than the curve order (we also 59 * check for all-zero values, which are invalid). 60 */ 61 buf = kbuf; 62 for (;;) { 63 size_t u; 64 unsigned cc, zz; 65 66 (*rng_ctx)->generate(rng_ctx, buf, len); 67 buf[0] &= mask; 68 cc = 0; 69 u = len; 70 zz = 0; 71 while (u -- > 0) { 72 cc = ((unsigned)(buf[u] - order[u] - cc) >> 8) & 1; 73 zz |= buf[u]; 74 } 75 if (cc != 0 && zz != 0) { 76 break; 77 } 78 } 79 80 if (sk != NULL) { 81 sk->curve = curve; 82 sk->x = buf; 83 sk->xlen = len; 84 } 85 return len; 86 } 87