diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl index 29c0f9c..6909410 100644 --- a/crypto/bn/asm/x86_64-mont.pl +++ b/crypto/bn/asm/x86_64-mont.pl @@ -134,131 +134,139 @@ $code.=<<___; mov ($ap),%rax xor $i,$i # i=0 xor $j,$j # j=0 mov $n0,$m1 mulq $m0 # ap[0]*bp[0] mov %rax,$lo0 mov ($np),%rax imulq $lo0,$m1 # "tp[0]"*n0 mov %rdx,$hi0 mulq $m1 # np[0]*m1 add %rax,$lo0 # discarded mov 8($ap),%rax adc \$0,%rdx mov %rdx,$hi1 lea 1($j),$j # j++ + + cmp $num,$j + jz .L1st_over jmp .L1st_enter .align 16 .L1st: add %rax,$hi1 mov ($ap,$j,8),%rax adc \$0,%rdx add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] mov $lo0,$hi0 adc \$0,%rdx mov $hi1,-16(%rsp,$j,8) # tp[j-1] mov %rdx,$hi1 .L1st_enter: mulq $m0 # ap[j]*bp[0] add %rax,$hi0 mov ($np,$j,8),%rax adc \$0,%rdx lea 1($j),$j # j++ mov %rdx,$lo0 mulq $m1 # np[j]*m1 cmp $num,$j - jne .L1st + jb .L1st +.L1st_over: add %rax,$hi1 mov ($ap),%rax # ap[0] adc \$0,%rdx add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] adc \$0,%rdx mov $hi1,-16(%rsp,$j,8) # tp[j-1] mov %rdx,$hi1 mov $lo0,$hi0 xor %rdx,%rdx add $hi0,$hi1 adc \$0,%rdx mov $hi1,-8(%rsp,$num,8) mov %rdx,(%rsp,$num,8) # store upmost overflow bit lea 1($i),$i # i++ jmp .Louter .align 16 .Louter: mov ($bp,$i,8),$m0 # m0=bp[i] xor $j,$j # j=0 mov $n0,$m1 mov (%rsp),$lo0 mulq $m0 # ap[0]*bp[i] add %rax,$lo0 # ap[0]*bp[i]+tp[0] mov ($np),%rax adc \$0,%rdx imulq $lo0,$m1 # tp[0]*n0 mov %rdx,$hi0 mulq $m1 # np[0]*m1 add %rax,$lo0 # discarded mov 8($ap),%rax adc \$0,%rdx mov 8(%rsp),$lo0 # tp[1] mov %rdx,$hi1 lea 1($j),$j # j++ + + cmp $num,$j + jz .Linner_over jmp .Linner_enter .align 16 .Linner: add %rax,$hi1 mov ($ap,$j,8),%rax adc \$0,%rdx add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] mov (%rsp,$j,8),$lo0 adc \$0,%rdx mov $hi1,-16(%rsp,$j,8) # tp[j-1] mov %rdx,$hi1 .Linner_enter: mulq $m0 # ap[j]*bp[i] add %rax,$hi0 mov ($np,$j,8),%rax adc \$0,%rdx add $hi0,$lo0 # ap[j]*bp[i]+tp[j] mov %rdx,$hi0 adc \$0,$hi0 lea 1($j),$j # j++ mulq $m1 # np[j]*m1 cmp $num,$j - jne .Linner + jb .Linner +.Linner_over: add %rax,$hi1 mov ($ap),%rax # ap[0] adc \$0,%rdx add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] mov (%rsp,$j,8),$lo0 adc \$0,%rdx mov $hi1,-16(%rsp,$j,8) # tp[j-1] mov %rdx,$hi1 xor %rdx,%rdx add $hi0,$hi1 adc \$0,%rdx add $lo0,$hi1 # pull upmost overflow bit adc \$0,%rdx mov $hi1,-8(%rsp,$num,8) mov %rdx,(%rsp,$num,8) # store upmost overflow bit lea 1($i),$i # i++ cmp $num,$i jb .Louter diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl index 85386c1..384fe4e 100644 --- a/crypto/bn/asm/x86_64-mont5.pl +++ b/crypto/bn/asm/x86_64-mont5.pl @@ -167,65 +167,69 @@ $code.=<<___; movq `3*$STRIDE/4-96`($bp),%xmm3 pand %xmm6,%xmm2 por %xmm1,%xmm0 pand %xmm7,%xmm3 imulq $lo0,$m1 # "tp[0]"*n0 mov %rdx,$hi0 por %xmm2,%xmm0 lea $STRIDE($bp),$bp por %xmm3,%xmm0 mulq $m1 # np[0]*m1 add %rax,$lo0 # discarded mov 8($ap),%rax adc \$0,%rdx mov %rdx,$hi1 lea 1($j),$j # j++ + cmp $num,$j + jz .L1st_over + jmp .L1st_enter .align 16 .L1st: add %rax,$hi1 mov ($ap,$j,8),%rax adc \$0,%rdx add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] mov $lo0,$hi0 adc \$0,%rdx mov $hi1,-16(%rsp,$j,8) # tp[j-1] mov %rdx,$hi1 .L1st_enter: mulq $m0 # ap[j]*bp[0] add %rax,$hi0 mov ($np,$j,8),%rax adc \$0,%rdx lea 1($j),$j # j++ mov %rdx,$lo0 mulq $m1 # np[j]*m1 cmp $num,$j - jne .L1st + jb .L1st +.L1st_over: movq %xmm0,$m0 # bp[1] add %rax,$hi1 mov ($ap),%rax # ap[0] adc \$0,%rdx add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] adc \$0,%rdx mov $hi1,-16(%rsp,$j,8) # tp[j-1] mov %rdx,$hi1 mov $lo0,$hi0 xor %rdx,%rdx add $hi0,$hi1 adc \$0,%rdx mov $hi1,-8(%rsp,$num,8) mov %rdx,(%rsp,$num,8) # store upmost overflow bit lea 1($i),$i # i++ jmp .Louter .align 16 @@ -248,67 +252,71 @@ $code.=<<___; movq `3*$STRIDE/4-96`($bp),%xmm3 pand %xmm6,%xmm2 por %xmm1,%xmm0 pand %xmm7,%xmm3 imulq $lo0,$m1 # tp[0]*n0 mov %rdx,$hi0 por %xmm2,%xmm0 lea $STRIDE($bp),$bp por %xmm3,%xmm0 mulq $m1 # np[0]*m1 add %rax,$lo0 # discarded mov 8($ap),%rax adc \$0,%rdx mov 8(%rsp),$lo0 # tp[1] mov %rdx,$hi1 lea 1($j),$j # j++ + + cmp $num,$j + jz .Linner_over jmp .Linner_enter .align 16 .Linner: add %rax,$hi1 mov ($ap,$j,8),%rax adc \$0,%rdx add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] mov (%rsp,$j,8),$lo0 adc \$0,%rdx mov $hi1,-16(%rsp,$j,8) # tp[j-1] mov %rdx,$hi1 .Linner_enter: mulq $m0 # ap[j]*bp[i] add %rax,$hi0 mov ($np,$j,8),%rax adc \$0,%rdx add $hi0,$lo0 # ap[j]*bp[i]+tp[j] mov %rdx,$hi0 adc \$0,$hi0 lea 1($j),$j # j++ mulq $m1 # np[j]*m1 cmp $num,$j - jne .Linner + jb .Linner +.Linner_over: movq %xmm0,$m0 # bp[i+1] add %rax,$hi1 mov ($ap),%rax # ap[0] adc \$0,%rdx add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] mov (%rsp,$j,8),$lo0 adc \$0,%rdx mov $hi1,-16(%rsp,$j,8) # tp[j-1] mov %rdx,$hi1 xor %rdx,%rdx add $hi0,$hi1 adc \$0,%rdx add $lo0,$hi1 # pull upmost overflow bit adc \$0,%rdx mov $hi1,-8(%rsp,$num,8) mov %rdx,(%rsp,$num,8) # store upmost overflow bit lea 1($i),$i # i++ diff --git a/crypto/bn/bn_test.c b/crypto/bn/bn_test.c index 440e1b6..64b83ae 100644 --- a/crypto/bn/bn_test.c +++ b/crypto/bn/bn_test.c @@ -87,40 +87,41 @@ int test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_); int test_rshift1(BIO *bp); int test_rshift(BIO *bp, BN_CTX *ctx); int test_sqr(BIO *bp, BN_CTX *ctx); int test_mul(BIO *bp); int test_div(BIO *bp, BN_CTX *ctx); int rand_neg(void); int test_div_word(BIO *bp); int test_mont(BIO *bp, BN_CTX *ctx); int test_mod(BIO *bp, BN_CTX *ctx); int test_mod_mul(BIO *bp, BN_CTX *ctx); int test_mod_exp(BIO *bp, BN_CTX *ctx); int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx); int test_exp(BIO *bp, BN_CTX *ctx); int test_mod_sqrt(BIO *bp, BN_CTX *ctx); static int test_exp_mod_zero(); int test_small_prime(BIO *bp,BN_CTX *ctx); int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx); int test_sqrt(BIO *bp, BN_CTX *ctx); int test_bn2bin_padded(BIO *bp, BN_CTX *ctx); +int test_mod_exp_sizes(BIO *bp, BN_CTX *ctx); #if 0 int test_gf2m_add(BIO *bp); int test_gf2m_mod(BIO *bp); int test_gf2m_mod_mul(BIO *bp, BN_CTX *ctx); int test_gf2m_mod_sqr(BIO *bp, BN_CTX *ctx); int test_gf2m_mod_inv(BIO *bp, BN_CTX *ctx); int test_gf2m_mod_div(BIO *bp, BN_CTX *ctx); int test_gf2m_mod_exp(BIO *bp, BN_CTX *ctx); int test_gf2m_mod_sqrt(BIO *bp, BN_CTX *ctx); int test_gf2m_mod_solve_quad(BIO *bp, BN_CTX *ctx); #endif static int results = 0; static unsigned char lst[] = "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9" "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0"; static void ERR_print_errors_fp(FILE *out) { } @@ -265,40 +266,45 @@ int main(int argc, char *argv[]) { message(out, "BN_mod_sqrt"); if (!test_mod_sqrt(out, ctx)) goto err; (void)BIO_flush(out); message(out, "Small prime generation"); if (!test_small_prime(out, ctx)) goto err; (void)BIO_flush(out); message(out, "BN_sqrt"); if (!test_sqrt(out, ctx)) goto err; (void)BIO_flush(out); message(out, "BN_bn2bin_padded"); if (!test_bn2bin_padded(out, ctx)) goto err; (void)BIO_flush(out); + message(out, "Modexp with different sizes"); + if (!test_mod_exp_sizes(out, ctx)) + goto err; + (void)BIO_flush(out); + BN_CTX_free(ctx); BIO_free(out); printf("PASS\n"); return 0; err: BIO_puts(out, "1\n"); /* make sure the Perl script fed by bc notices * the failure, see test_bn in test/Makefile.ssl*/ (void)BIO_flush(out); return 1; } int test_add(BIO *bp) { BIGNUM a, b, c; int i; BN_init(&a); BN_init(&b); @@ -1389,20 +1395,68 @@ int test_bn2bin_padded(BIO *bp, BN_CTX *ctx) { } /* Pad up one byte extra. */ if (!BN_bn2bin_padded(out, bytes + 1, n) || memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) { fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); return 0; } /* Pad up to 256. */ if (!BN_bn2bin_padded(out, sizeof(out), n) || memcmp(out + sizeof(out) - bytes, reference, bytes) || memcmp(out, zeros, sizeof(out) - bytes)) { fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n"); return 0; } } BN_free(n); return 1; } + +int test_mod_exp_sizes(BIO *bp, BN_CTX *ctx) { + BN_CTX_start(ctx); + BIGNUM *p = BN_CTX_get(ctx); + BIGNUM *x = BN_CTX_get(ctx); + BIGNUM *y = BN_CTX_get(ctx); + BIGNUM *r = BN_CTX_get(ctx); + BIGNUM *r2 = BN_CTX_get(ctx); + BN_MONT_CTX *mont_ctx = BN_MONT_CTX_new(); + int size; + int ok = 0; + + if (r2 == NULL || mont_ctx == NULL) { + goto err; + } + + if (!BN_generate_prime_ex(p, 32, 0, NULL, NULL, NULL) || + !BN_MONT_CTX_set(mont_ctx, p, ctx)) { + goto err; + } + + for (size = 32; size < 1024; size += 8) { + if (!BN_rand(x, size, -1, 0) || + !BN_rand(y, size, -1, 0) || + !BN_mod_exp_mont_consttime(r, x, y, p, ctx, mont_ctx) || + !BN_mod_exp(r2, x, y, p, ctx)) { + goto err; + } + + if (BN_cmp(r, r2) != 0) { + char *r_str = BN_bn2hex(r); + char *r2_str = BN_bn2hex(r2); + printf("Incorrect answer at size %d: %s vs %s\n", size, r_str, r2_str); + free(r_str); + free(r2_str); + goto err; + } + } + + ok = 1; + +err: + if (mont_ctx) { + BN_MONT_CTX_free(mont_ctx); + } + BN_CTX_end(ctx); + return ok; +}