/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright The Mbed TLS Contributors │ │ │ │ Licensed under the Apache License, Version 2.0 (the "License"); │ │ you may not use this file except in compliance with the License. │ │ You may obtain a copy of the License at │ │ │ │ http://www.apache.org/licenses/LICENSE-2.0 │ │ │ │ Unless required by applicable law or agreed to in writing, software │ │ distributed under the License is distributed on an "AS IS" BASIS, │ │ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "third_party/mbedtls/ecp.h" #include "third_party/mbedtls/math.h" /* clang-format off */ static void mbedtls_mpi_shift_l_mod_p256( const mbedtls_ecp_group *G, mbedtls_mpi *X ) { bool c; MBEDTLS_ASSERT( G->P.n == 4 ); MBEDTLS_ASSERT( mbedtls_mpi_bitlen( X ) <= 256 ); MBEDTLS_ASSERT( mbedtls_mpi_bitlen( &G->P ) <= 256 ); X->p[4] = X->p[3] >> 63; X->p[3] = X->p[3] << 1 | X->p[2] >> 63; X->p[2] = X->p[2] << 1 | X->p[1] >> 63; X->p[1] = X->p[1] << 1 | X->p[0] >> 63; X->p[0] = X->p[0] << 1; if( (X->p[4] || X->p[3] > G->P.p[3] || (X->p[3] == G->P.p[3] && X->p[2] > G->P.p[2] || (X->p[2] == G->P.p[2] && X->p[0] > G->P.p[0] || (X->p[0] == G->P.p[0])))) ) { SBB(X->p[0], X->p[0], G->P.p[0], 0, c); SBB(X->p[1], X->p[1], G->P.p[1], c, c); SBB(X->p[2], X->p[2], G->P.p[2], c, c); SBB(X->p[3], X->p[3], G->P.p[3], c, c); SBB(X->p[4], X->p[4], 0, c, c); } } static void mbedtls_mpi_shift_l_mod_p384( const mbedtls_ecp_group *G, mbedtls_mpi *X ) { bool c; MBEDTLS_ASSERT( G->P.n == 6 ); MBEDTLS_ASSERT( mbedtls_mpi_bitlen( X ) <= 384 ); MBEDTLS_ASSERT( mbedtls_mpi_bitlen( &G->P ) <= 384 ); X->p[6] = X->p[5] >> 63; X->p[5] = X->p[5] << 1 | X->p[4] >> 63; X->p[4] = X->p[4] << 1 | X->p[3] >> 63; X->p[3] = X->p[3] << 1 | X->p[2] >> 63; X->p[2] = X->p[2] << 1 | X->p[1] >> 63; X->p[1] = X->p[1] << 1 | X->p[0] >> 63; X->p[0] = X->p[0] << 1; if( (X->p[6] || X->p[5] > G->P.p[5] || (X->p[5] == G->P.p[5] && X->p[4] > G->P.p[4] || (X->p[4] == G->P.p[4] && X->p[3] > G->P.p[3] || (X->p[3] == G->P.p[3] && X->p[2] > G->P.p[2] || (X->p[2] == G->P.p[2] && X->p[0] > G->P.p[0] || (X->p[0] == G->P.p[0])))))) ) { SBB(X->p[0], X->p[0], G->P.p[0], 0, c); SBB(X->p[1], X->p[1], G->P.p[1], c, c); SBB(X->p[2], X->p[2], G->P.p[2], c, c); SBB(X->p[3], X->p[3], G->P.p[3], c, c); SBB(X->p[4], X->p[4], G->P.p[4], c, c); SBB(X->p[5], X->p[5], G->P.p[5], c, c); SBB(X->p[6], X->p[6], 0, c, c); } } int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *G, mbedtls_mpi *X ) { int ret = 0; MBEDTLS_ASSERT( mbedtls_mpi_cmp_int( X, 0 ) >= 0 ); MBEDTLS_ASSERT( mbedtls_mpi_cmp_mpi( X, &G->P ) < 0 ); if( X->n == 8 ) mbedtls_mpi_shift_l_mod_p256( G, X ); else if( X->n == 12 ) mbedtls_mpi_shift_l_mod_p384( G, X ); else { MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, 1 ) ); if( mbedtls_mpi_cmp_mpi( X, &G->P ) >= 0 ) MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, X, &G->P ) ); } MBEDTLS_ASSERT( mbedtls_mpi_cmp_mpi( X, &G->P ) < 0 ); MBEDTLS_ASSERT( mbedtls_mpi_cmp_int( X, 0 ) >= 0 ); cleanup: return( ret ); }