This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
cryptic/cryptic/maths/decompose_integer.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;
}