608 lines
22 KiB
C
608 lines
22 KiB
C
/* Cryptic -- Cryptographic tools and protocols
|
|
* Copyright (C) 2010 Mikaël Ates <mates@entrouvert.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <glib.h>
|
|
#include <glib-object.h>
|
|
#include <openssl/bn.h>
|
|
|
|
#include "../errors.h"
|
|
#include "../utils.h"
|
|
|
|
#include "decompose_integer.h"
|
|
|
|
/*****************************************************************************/
|
|
/* private methods */
|
|
/*****************************************************************************/
|
|
|
|
static GObjectClass *parent_class = NULL;
|
|
|
|
/*****************************************************************************/
|
|
/* overridden parent class methods */
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
dispose(GObject *object)
|
|
{
|
|
CrypticDecomposeInteger *di = CRYPTIC_DECOMPOSEINTEGER(object);
|
|
|
|
cryptic_release_bn(di->ONE);
|
|
cryptic_release_bn(di->TWO);
|
|
cryptic_release_bn(di->THREE);
|
|
cryptic_release_bn(di->FOUR);
|
|
cryptic_release_bn(di->FIVE);
|
|
cryptic_release_bn(di->SEVEN);
|
|
cryptic_release_bn(di->EIGHT);
|
|
cryptic_release_bn(di->a);
|
|
cryptic_release_bn(di->b);
|
|
cryptic_release_bn(di->c);
|
|
cryptic_release_bn(di->d);
|
|
|
|
G_OBJECT_CLASS(parent_class)->dispose(G_OBJECT(di));
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* instance and class init functions */
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
instance_init(CrypticDecomposeInteger *di)
|
|
{
|
|
di->ONE = NULL;
|
|
di->TWO = NULL;
|
|
di->THREE = NULL;
|
|
di->FOUR = NULL;
|
|
di->FIVE = NULL;
|
|
di->SEVEN = NULL;
|
|
di->EIGHT = NULL;
|
|
di->a = NULL;
|
|
di->b = NULL;
|
|
di->c = NULL;
|
|
di->d = NULL;
|
|
}
|
|
|
|
static void
|
|
class_init(CrypticDecomposeIntegerClass *klass)
|
|
{
|
|
parent_class = g_type_class_peek_parent(klass);
|
|
|
|
G_OBJECT_CLASS(klass)->dispose = dispose;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* public methods */
|
|
/*****************************************************************************/
|
|
|
|
GType
|
|
cryptic_decompose_integer_get_type()
|
|
{
|
|
static GType this_type = 0;
|
|
|
|
if (!this_type) {
|
|
static const GTypeInfo this_info = {
|
|
sizeof (CrypticDecomposeIntegerClass),
|
|
NULL,
|
|
NULL,
|
|
(GClassInitFunc) class_init,
|
|
NULL,
|
|
NULL,
|
|
sizeof(CrypticDecomposeInteger),
|
|
0,
|
|
(GInstanceInitFunc) instance_init,
|
|
NULL
|
|
};
|
|
|
|
this_type = g_type_register_static(G_TYPE_OBJECT,
|
|
"CrypticDecomposeInteger", &this_info, 0);
|
|
}
|
|
return this_type;
|
|
}
|
|
|
|
/**
|
|
* cryptic_decompose_integer_new
|
|
* @numToDecompose: interger to decompose in four squares.
|
|
*
|
|
* Creates a new #CrypticDecomposeInteger.
|
|
* Perform the decomposition
|
|
*
|
|
* Return value: a newly created #CrypticDecomposeInteger object if decimposition is successful; or NULL if an error
|
|
* occured or the decomposition failed.
|
|
**/
|
|
CrypticDecomposeInteger*
|
|
cryptic_decompose_integer_new(BIGNUM *numToDecompose)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
CrypticDecomposeInteger *di;
|
|
di = g_object_new(CRYPTIC_TYPE_DECOMPOSEINTEGER, NULL);
|
|
|
|
BIGNUM *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL;
|
|
BIGNUM *approxSquareRoot = NULL, *z = NULL, *svg_num = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
|
|
if(BN_is_zero(numToDecompose)){
|
|
rc = CRYPTIC_NO_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp1 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp2 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp3 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp4 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(approxSquareRoot = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(z = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(svg_num = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
|
|
cryptic_release_bn(di->ONE);
|
|
cryptic_release_bn(di->TWO);
|
|
cryptic_release_bn(di->THREE);
|
|
cryptic_release_bn(di->FOUR);
|
|
cryptic_release_bn(di->FIVE);
|
|
cryptic_release_bn(di->SEVEN);
|
|
cryptic_release_bn(di->EIGHT);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->ONE = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->ONE,1) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->TWO = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->TWO,2) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->THREE = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->THREE,3) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->FOUR = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->FOUR,4) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->FIVE = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->FIVE,5) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->SEVEN = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->SEVEN,7) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->EIGHT = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->EIGHT,8) == 1);
|
|
|
|
cryptic_release_bn(di->a);
|
|
cryptic_release_bn(di->b);
|
|
cryptic_release_bn(di->c);
|
|
cryptic_release_bn(di->d);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->a = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->a,0) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->b = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->b,0) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->c = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->c,0) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(di->d = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->d,0) == 1);
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(svg_num, numToDecompose));
|
|
|
|
int specialCaseRS[17][4] = {
|
|
2, 1, 1, 0,
|
|
3, 1, 1, 1,
|
|
10, 3, 1, 0,
|
|
34, 3, 3, 4,
|
|
58, 3, 7, 0,
|
|
85, 6, 7, 0,
|
|
130, 3, 11, 0,
|
|
214, 3, 6, 13,
|
|
226, 8, 9, 9,
|
|
370, 8, 9, 15,
|
|
526, 6, 7, 21,
|
|
706, 15, 15, 16,
|
|
730, 1, 27, 0,
|
|
1414, 6, 17, 33,
|
|
1906, 13, 21, 36,
|
|
2986, 21, 32, 39,
|
|
9634, 56, 57, 57};
|
|
|
|
BIGNUM *specialCaseRSBN[17][5];
|
|
int i,j;
|
|
for(i=0;i<17;i++){
|
|
for(j=0;j<5;j++){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(specialCaseRSBN[i][j] = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(specialCaseRSBN[i][j], specialCaseRS[i][j]) == 1);
|
|
}
|
|
}
|
|
|
|
/********************************************
|
|
*** Reduction: mod 4 of NTD
|
|
*********************************************/
|
|
int red = 0;
|
|
while(1){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod(tmp1, numToDecompose, di->FOUR, ctx) == 1);
|
|
if(!BN_is_zero(tmp1))break;
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_div(tmp1,tmp2,numToDecompose, di->FOUR,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(numToDecompose,tmp1));
|
|
red++;
|
|
}
|
|
|
|
/********************************************
|
|
*** Special decomposition
|
|
*********************************************/
|
|
int found=-1;
|
|
for(i=0;i<17;i++){
|
|
if(!BN_cmp(specialCaseRSBN[i][0],numToDecompose)){
|
|
found=i;i=17;
|
|
}
|
|
}
|
|
if(found>-1){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->a,specialCaseRSBN[found][1]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->b,specialCaseRSBN[found][2]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->c,specialCaseRSBN[found][3]));
|
|
cryptic_check_good_rc(cryptic_decompose_integer_back_reduction(di,red));
|
|
goto finalize;
|
|
}
|
|
|
|
/********************************************
|
|
*** Approximative square root of NTDmod4
|
|
*********************************************/
|
|
cryptic_check_good_rc(cryptic_decompose_integer_square_root(di, numToDecompose, approxSquareRoot));
|
|
|
|
/********************************************
|
|
*** cleanup if the NTDmod4 is a square root
|
|
*********************************************/
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp2,approxSquareRoot,di->TWO,ctx));
|
|
if(!BN_cmp(numToDecompose,tmp2)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->a,approxSquareRoot));
|
|
cryptic_check_good_rc(cryptic_decompose_integer_back_reduction(di,red));
|
|
goto finalize;
|
|
}
|
|
|
|
/********************************************
|
|
*** We work with 4n+1:
|
|
*** Primes writable 4n+1 (8k+1 & 8k+5) may be a square
|
|
*** (All primes can be written 4n+1 or 4n-1)
|
|
*********************************************/
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod(tmp1,numToDecompose,di->FOUR,ctx) == 1);
|
|
if(BN_is_one(tmp1) && BN_is_prime_ex(numToDecompose,BN_prime_checks,ctx,NULL)){
|
|
cryptic_check_good_rc(cryptic_decompose_integer_sum_two_squares(di,numToDecompose));
|
|
if(!BN_is_zero(di->a)){
|
|
cryptic_check_good_rc(cryptic_decompose_integer_back_reduction(di,red));
|
|
goto finalize;
|
|
}
|
|
}
|
|
|
|
/********************************************
|
|
*** The only case where d is set (to 1) is
|
|
*** when NDTmod4 = 4n-1 with n odd (8k+7).
|
|
*** NDTmod4 = 8k+6+1
|
|
*********************************************/
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod(tmp1,numToDecompose,di->EIGHT,ctx) == 1);
|
|
if(BN_cmp(tmp1,di->SEVEN) == 0){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->d,1) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(numToDecompose,numToDecompose,di->ONE) == 1);
|
|
}
|
|
|
|
/********************************************
|
|
*** if x==8k+1, 8k+2, 8k+5, 8k+6: three squares and x==z^2+(4k+1)
|
|
*********************************************/
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod(tmp1,numToDecompose,di->FOUR,ctx) == 1);
|
|
if(!BN_cmp(tmp1,di->ONE) || !BN_cmp(tmp1,di->TWO)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(z, approxSquareRoot));
|
|
while(!BN_is_zero(z)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp1,z,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(tmp1,numToDecompose,tmp1) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod(tmp2,tmp1,di->FOUR,ctx) == 1);
|
|
if(BN_is_one(tmp2) && BN_is_prime_ex(tmp1,BN_prime_checks,ctx,NULL)){
|
|
cryptic_check_good_rc(cryptic_decompose_integer_sum_two_squares(di,tmp1));
|
|
if(!BN_is_zero(di->a)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->c,z));
|
|
cryptic_check_good_rc(cryptic_decompose_integer_back_reduction(di,red));
|
|
goto finalize;
|
|
}
|
|
}
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(z,z,di->ONE) == 1);
|
|
}
|
|
}
|
|
|
|
/********************************************
|
|
*** if x==8k+3: three squares and x==z^2+(2*(4k+1))
|
|
*********************************************/
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod(tmp1,numToDecompose,di->EIGHT,ctx) == 1);
|
|
if(BN_cmp(tmp1,di->THREE) == 0){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(z, approxSquareRoot));
|
|
while(!BN_is_zero(z)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp1,z,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(tmp1,numToDecompose,tmp1) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod(tmp2,tmp1,di->EIGHT,ctx) == 1);
|
|
if(BN_cmp(tmp2,di->TWO)>1){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(z,z,di->ONE) == 1);
|
|
}
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_div(tmp1,tmp2,tmp1,di->TWO,ctx) == 1);
|
|
if(BN_is_prime_ex(tmp1,BN_prime_checks,ctx,NULL)){
|
|
cryptic_check_good_rc(cryptic_decompose_integer_sum_two_squares(di,tmp1));
|
|
if(!BN_is_zero(di->a)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(di->b,di->a,di->b) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(tmp1,di->a,di->TWO,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(di->a,di->b,tmp1) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->c,z));
|
|
cryptic_check_good_rc(cryptic_decompose_integer_back_reduction(di,red));
|
|
goto finalize;
|
|
}
|
|
}
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(z,z,di->ONE) == 1);
|
|
}
|
|
}
|
|
|
|
finalize:
|
|
/* Correction if necessary
|
|
* To avoid this correction, catch before why d is not set to one.*/
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp1,di->a,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp2,di->b,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp3,di->c,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp4,di->d,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(tmp1,tmp1,tmp2) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(tmp1,tmp1,tmp3) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(tmp1,tmp1,tmp4) == 1);
|
|
if(BN_cmp(svg_num,tmp1) > 0) {
|
|
if(BN_is_zero(di->d)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(tmp1,svg_num,tmp1) == 1);
|
|
cryptic_check_good_rc(cryptic_decompose_integer_square_root(di, tmp1, tmp2));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp3,tmp2,di->TWO,ctx));
|
|
if(!BN_cmp(tmp1,tmp3)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->d,tmp2));
|
|
}else{
|
|
cryptic_critical("Decomposition failed - 2");
|
|
rc = CRYPTIC_MATHS_DECOMPOSITION_4_SQUARES_FAILED;
|
|
goto cleanup;
|
|
}
|
|
}else{
|
|
cryptic_critical("Decomposition failed - 1");
|
|
rc = CRYPTIC_MATHS_DECOMPOSITION_4_SQUARES_FAILED;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if(red>0){
|
|
for (i=0;i<red;i++){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(numToDecompose,numToDecompose,di->FOUR,ctx) == 1);
|
|
}
|
|
}
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_bn(tmp1);
|
|
cryptic_release_bn(tmp2);
|
|
cryptic_release_bn(tmp3);
|
|
cryptic_release_bn(tmp4);
|
|
cryptic_release_bn(approxSquareRoot);
|
|
cryptic_release_bn(z);
|
|
cryptic_release_bn(svg_num);
|
|
for(i=0;i<17;i++){
|
|
for(j=0;j<5;j++){
|
|
cryptic_release_bn(specialCaseRSBN[i][j]);
|
|
}
|
|
}
|
|
if(rc == CRYPTIC_NO_ERROR) {return di;}
|
|
else{
|
|
cryptic_release_gobject(di);
|
|
return (CrypticDecomposeInteger*) rc;
|
|
}
|
|
}
|
|
|
|
int
|
|
cryptic_decompose_integer_sum_two_squares(CrypticDecomposeInteger *di, BIGNUM *numToDecompose)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
int i=1;
|
|
BIGNUM *tmp1 = NULL, *tmp2 = NULL, *h = NULL, *root = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp1 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp2 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(h = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(root = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod(tmp1, numToDecompose, di->FOUR, ctx) == 1);
|
|
if(!BN_is_one(tmp1)){
|
|
goto cleanup;
|
|
}
|
|
|
|
if(BN_is_one(numToDecompose)){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->a,di->ONE));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->b,0) == 1);
|
|
rc = CRYPTIC_NO_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
do{
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(di->a,i) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp1,di->a,di->TWO,ctx));
|
|
if(BN_cmp(numToDecompose,tmp1)<=0){
|
|
goto cleanup;
|
|
}
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(tmp2,numToDecompose,tmp1) == 1);
|
|
cryptic_check_good_rc(cryptic_decompose_integer_square_root(di, tmp2, root));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp2,root,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(tmp1,tmp1,tmp2) == 1);
|
|
i++;
|
|
}while(BN_cmp(tmp1,numToDecompose));
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(di->b, root));
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_bn(tmp1);
|
|
cryptic_release_bn(tmp2);
|
|
cryptic_release_bn(h);
|
|
cryptic_release_bn(root);
|
|
return rc;
|
|
}
|
|
|
|
//result in root
|
|
int
|
|
cryptic_decompose_integer_newton_iteration(CrypticDecomposeInteger *di, BIGNUM *square, BIGNUM *root)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
BIGNUM *tmp1 = NULL, *tmp2 = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp1 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp2 = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_div(tmp1,tmp2,square,root,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(root,root,tmp1) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_div(root,square,root,di->TWO,ctx) == 1);
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_bn(tmp1);
|
|
cryptic_release_bn(tmp2);
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
cryptic_decompose_integer_square_root(CrypticDecomposeInteger *di, BIGNUM *square, BIGNUM *root)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
BIGNUM *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL, *oldroot = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp1 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp2 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp3 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(oldroot = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(root,di->ONE));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(oldroot,di->ONE));
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tmp3,square));
|
|
cryptic_check_good_rc(cryptic_decompose_integer_newton_iteration(di,tmp3,root));
|
|
|
|
while(1){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(tmp1,root,oldroot) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp2,root,di->TWO,ctx));
|
|
if((BN_is_zero(tmp1) || BN_is_one(tmp1)) || !BN_cmp(tmp2,square))break;
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(oldroot,root));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tmp3,square));
|
|
cryptic_check_good_rc(cryptic_decompose_integer_newton_iteration(di,tmp3,root));
|
|
}
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_bn(tmp1);
|
|
cryptic_release_bn(tmp2);
|
|
cryptic_release_bn(tmp3);
|
|
cryptic_release_bn(oldroot);
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
cryptic_decompose_integer_back_reduction(CrypticDecomposeInteger *di, int reduction)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
BIGNUM *tmp = NULL, *redBN = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(redBN = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_set_word(redBN,reduction) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp,di->TWO,redBN, ctx) == 1);
|
|
|
|
if (di->a) goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(di->a,di->a,tmp,ctx) == 1);
|
|
if (di->b) goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(di->b,di->b,tmp,ctx) == 1);
|
|
if (di->c) goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(di->c,di->c,tmp,ctx) == 1);
|
|
if (di->d) goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(di->d,di->d,tmp,ctx) == 1);
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_bn(tmp);
|
|
cryptic_release_bn(redBN);
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
cryptic_decompose_integer_verify_decomposition(CrypticDecomposeInteger *di,BIGNUM *numToDecompose)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
BIGNUM *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp1 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp2 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp3 = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp4 = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp1,di->a,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp2,di->b,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp3,di->c,di->TWO,ctx));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_exp(tmp4,di->d,di->TWO,ctx));
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(tmp1,tmp1,tmp2) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(tmp1,tmp1,tmp3) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(tmp1,tmp1,tmp4) == 1);
|
|
|
|
if(BN_cmp(tmp1,numToDecompose) == 0) {
|
|
rc = 1;
|
|
} else {
|
|
rc = CRYPTIC_NO_ERROR;
|
|
}
|
|
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_bn(tmp1);
|
|
cryptic_release_bn(tmp2);
|
|
cryptic_release_bn(tmp3);
|
|
cryptic_release_bn(tmp4);
|
|
return rc;
|
|
}
|
|
|
|
BIGNUM*
|
|
cryptic_getSqrRoot1(CrypticDecomposeInteger *di)
|
|
{
|
|
cryptic_return_null_if_fail(di->a);
|
|
return di->a;
|
|
}
|
|
|
|
BIGNUM*
|
|
cryptic_getSqrRoot2(CrypticDecomposeInteger *di)
|
|
{
|
|
cryptic_return_null_if_fail(di->b);
|
|
return di->b;
|
|
}
|
|
|
|
BIGNUM*
|
|
cryptic_getSqrRoot3(CrypticDecomposeInteger *di)
|
|
{
|
|
cryptic_return_null_if_fail(di->c);
|
|
return di->c;
|
|
}
|
|
|
|
BIGNUM*
|
|
cryptic_getSqrRoot4(CrypticDecomposeInteger *di)
|
|
{
|
|
cryptic_return_null_if_fail(di->d);
|
|
return di->d;
|
|
}
|