Path: blob/main/contrib/bearssl/src/ec/ecdsa_i15_vrfy_raw.c
39488 views
/*1* Copyright (c) 2017 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 I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)27#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))2829/* see bearssl_ec.h */30uint32_t31br_ecdsa_i15_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;42uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], t1[I15_LEN], t2[I15_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;47uint16_t n0i;48uint32_t res;4950/*51* If the curve is not supported, then report an error.52*/53if (((impl->supported_curves >> pk->curve) & 1) == 0) {54return 0;55}5657/*58* Get the curve parameters (generator and order).59*/60switch (pk->curve) {61case BR_EC_secp256r1:62cd = &br_secp256r1;63break;64case BR_EC_secp384r1:65cd = &br_secp384r1;66break;67case BR_EC_secp521r1:68cd = &br_secp521r1;69break;70default:71return 0;72}7374/*75* Signature length must be even.76*/77if (sig_len & 1) {78return 0;79}80rlen = sig_len >> 1;8182/*83* Public key point must have the proper size for this curve.84*/85if (pk->qlen != cd->generator_len) {86return 0;87}8889/*90* Get modulus; then decode the r and s values. They must be91* lower than the modulus, and s must not be null.92*/93nlen = cd->order_len;94br_i15_decode(n, cd->order, nlen);95n0i = br_i15_ninv15(n[1]);96if (!br_i15_decode_mod(r, sig, rlen, n)) {97return 0;98}99if (!br_i15_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {100return 0;101}102if (br_i15_iszero(s)) {103return 0;104}105106/*107* Invert s. We do that with a modular exponentiation; we use108* the fact that for all the curves we support, the least109* significant byte is not 0 or 1, so we can subtract 2 without110* any carry to process.111* We also want 1/s in Montgomery representation, which can be112* done by converting _from_ Montgomery representation before113* the inversion (because (1/s)*R = 1/(s/R)).114*/115br_i15_from_monty(s, n, n0i);116memcpy(tx, cd->order, nlen);117tx[nlen - 1] -= 2;118br_i15_modpow(s, tx, nlen, n, n0i, t1, t2);119120/*121* Truncate the hash to the modulus length (in bits) and reduce122* it modulo the curve order. The modular reduction can be done123* with a subtraction since the truncation already reduced the124* value to the modulus bit length.125*/126br_ecdsa_i15_bits2int(t1, hash, hash_len, n[0]);127br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);128129/*130* Multiply the (truncated, reduced) hash value with 1/s, result in131* t2, encoded in ty.132*/133br_i15_montymul(t2, t1, s, n, n0i);134br_i15_encode(ty, nlen, t2);135136/*137* Multiply r with 1/s, result in t1, encoded in tx.138*/139br_i15_montymul(t1, r, s, n, n0i);140br_i15_encode(tx, nlen, t1);141142/*143* Compute the point x*Q + y*G.144*/145ulen = cd->generator_len;146memcpy(eU, pk->q, ulen);147res = impl->muladd(eU, NULL, ulen,148tx, nlen, ty, nlen, cd->curve);149150/*151* Get the X coordinate, reduce modulo the curve order, and152* compare with the 'r' value.153*154* The modular reduction can be done with subtractions because155* we work with curves of prime order, so the curve order is156* close to the field order (Hasse's theorem).157*/158br_i15_zero(t1, n[0]);159br_i15_decode(t1, &eU[1], ulen >> 1);160t1[0] = n[0];161br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);162res &= ~br_i15_sub(t1, r, 1);163res &= br_i15_iszero(t1);164return res;165}166167168