Path: blob/main/contrib/bearssl/src/ec/ecdsa_i31_vrfy_raw.c
39507 views
/*1* Copyright (c) 2016 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#include "inner.h"2526#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)27#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))2829/* see bearssl_ec.h */30uint32_t31br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,32const void *hash, size_t hash_len,33const br_ec_public_key *pk,34const void *sig, size_t sig_len)35{36/*37* IMPORTANT: this code is fit only for curves with a prime38* order. This is needed so that modular reduction of the X39* coordinate of a point can be done with a simple subtraction.40*/41const br_ec_curve_def *cd;42uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], t1[I31_LEN], t2[I31_LEN];43unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];44unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];45unsigned char eU[POINT_LEN];46size_t nlen, rlen, ulen;47uint32_t n0i, res;4849/*50* If the curve is not supported, then report an error.51*/52if (((impl->supported_curves >> pk->curve) & 1) == 0) {53return 0;54}5556/*57* Get the curve parameters (generator and order).58*/59switch (pk->curve) {60case BR_EC_secp256r1:61cd = &br_secp256r1;62break;63case BR_EC_secp384r1:64cd = &br_secp384r1;65break;66case BR_EC_secp521r1:67cd = &br_secp521r1;68break;69default:70return 0;71}7273/*74* Signature length must be even.75*/76if (sig_len & 1) {77return 0;78}79rlen = sig_len >> 1;8081/*82* Public key point must have the proper size for this curve.83*/84if (pk->qlen != cd->generator_len) {85return 0;86}8788/*89* Get modulus; then decode the r and s values. They must be90* lower than the modulus, and s must not be null.91*/92nlen = cd->order_len;93br_i31_decode(n, cd->order, nlen);94n0i = br_i31_ninv31(n[1]);95if (!br_i31_decode_mod(r, sig, rlen, n)) {96return 0;97}98if (!br_i31_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {99return 0;100}101if (br_i31_iszero(s)) {102return 0;103}104105/*106* Invert s. We do that with a modular exponentiation; we use107* the fact that for all the curves we support, the least108* significant byte is not 0 or 1, so we can subtract 2 without109* any carry to process.110* We also want 1/s in Montgomery representation, which can be111* done by converting _from_ Montgomery representation before112* the inversion (because (1/s)*R = 1/(s/R)).113*/114br_i31_from_monty(s, n, n0i);115memcpy(tx, cd->order, nlen);116tx[nlen - 1] -= 2;117br_i31_modpow(s, tx, nlen, n, n0i, t1, t2);118119/*120* Truncate the hash to the modulus length (in bits) and reduce121* it modulo the curve order. The modular reduction can be done122* with a subtraction since the truncation already reduced the123* value to the modulus bit length.124*/125br_ecdsa_i31_bits2int(t1, hash, hash_len, n[0]);126br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);127128/*129* Multiply the (truncated, reduced) hash value with 1/s, result in130* t2, encoded in ty.131*/132br_i31_montymul(t2, t1, s, n, n0i);133br_i31_encode(ty, nlen, t2);134135/*136* Multiply r with 1/s, result in t1, encoded in tx.137*/138br_i31_montymul(t1, r, s, n, n0i);139br_i31_encode(tx, nlen, t1);140141/*142* Compute the point x*Q + y*G.143*/144ulen = cd->generator_len;145memcpy(eU, pk->q, ulen);146res = impl->muladd(eU, NULL, ulen,147tx, nlen, ty, nlen, cd->curve);148149/*150* Get the X coordinate, reduce modulo the curve order, and151* compare with the 'r' value.152*153* The modular reduction can be done with subtractions because154* we work with curves of prime order, so the curve order is155* close to the field order (Hasse's theorem).156*/157br_i31_zero(t1, n[0]);158br_i31_decode(t1, &eU[1], ulen >> 1);159t1[0] = n[0];160br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);161res &= ~br_i31_sub(t1, r, 1);162res &= br_i31_iszero(t1);163return res;164}165166167