update sm_standard

This commit is contained in:
[GGSuchao]
2017-07-10 10:33:46 +08:00
committed by GGSuchao
parent fe0bb34dd8
commit ac3cb97071
9 changed files with 3810 additions and 0 deletions

View File

@@ -0,0 +1,482 @@
/* ====================================================================
* Copyright (c) 2016 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#ifndef HEADER_SM9_STANDARD_H
#define HEADER_SM9_STANDARD_H
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#ifdef __cplusplus
extern "C"{
#endif
#include "miracl.h"
#include "r-ate.h"
#include "kdf_standard.h"
#define BNLEN 32 //BN curve with 256bit is used in SM9 algorithm
#define SM9_ASK_MEMORY_ERR 0x00000001 //ask for memory fail(申请内存失败)
#define SM9_MEMBER_ERR 0x00000002 //the order of group G error(群的阶错误)
#define SM9_MY_ECAP_12A_ERR 0x00000003 //R-ate pairing generated error(R-ate对计算出现错误)
#define SM9_NOT_VALID_G1 0x00000004 //not valid element of G1
#define SM9_G1BASEPOINT_SET_ERR 0x00000005 //base point of G1 seted error(G1基点设置错误)
#define SM9_G2BASEPOINT_SET_ERR 0x00000006 //base point of G2 seted error(G2基点设置错误)
#define SM9_GEPUB_ERR 0x00000007 //pubkey error(生成公钥错误)
#define SM9_GEPRI_ERR 0x00000008 //privare key error(生成私钥错误)
#define SM9_ERR_CMP_S1SB 0x00000009 //S1!=SB
#define SM9_ERR_CMP_S2SA 0x0000000A //S2!=SA
#define SM9_ERR_RA 0x0000000B //RA error
#define SM9_ERR_RB 0x0000000C //RB error
#define SM9_ERR_SA 0x0000000D //SA error
#define SM9_ERR_SB 0x0000000E //SB error
#define SM9_C1_NOT_VALID_G1 0x0000000F //C1不属于群G1
#define SM9_ENCRYPT_ERR 0x00000010 //加密错误
#define SM9_ERR_K1_ZERO 0x00000011 //K1 equals 0(K1全0)
#define SM9_C3_MEMCMP_ERR 0x00000012 //C3对比不一致
#define SM9_DECRYPT_ERR 0x00000013 //解密错误
#define SM9_ERR_Encap_C 0x00000014 //cipher error in key encapsulation
#define SM9_ERR_Encap_K 0x00000015 //key to be encapsulated
#define SM9_ERR_Decap_K 0x00000016 //key generated by decapsulation
#define SM9_H_OUTRANGE 0x00000017 //签名H不属于[1,N-1]
#define SM9_DATA_MEMCMP_ERR 0x00000018 //数据对比不一致
#define SM9_S_NOT_VALID_G1 0x00000019 //S不属于群G1
#define SM9_L_error 0x0000001A //参数L错误
#define SM9_SIGN_ERR 0x0000001B //签名错误
static unsigned char SM9_q[32] = {0xB6, 0x40, 0x00, 0x00, 0x02, 0xA3, 0xA6, 0xF1, 0xD6, 0x03, 0xAB, 0x4F, 0xF5, 0x8E, 0xC7, 0x45,
0x21, 0xF2, 0x93, 0x4B, 0x1A, 0x7A, 0xEE, 0xDB, 0xE5, 0x6F, 0x9B, 0x27, 0xE3, 0x51, 0x45, 0x7D};
static unsigned char SM9_N[32] = {0xB6, 0x40, 0x00, 0x00, 0x02, 0xA3, 0xA6, 0xF1, 0xD6, 0x03, 0xAB, 0x4F, 0xF5, 0x8E, 0xC7, 0x44,
0x49, 0xF2, 0x93, 0x4B, 0x18, 0xEA, 0x8B, 0xEE, 0xE5, 0x6E, 0xE1, 0x9C, 0xD6, 0x9E, 0xCF, 0x25};
static unsigned char SM9_P1x[32] = {0x93, 0xDE, 0x05, 0x1D, 0x62, 0xBF, 0x71, 0x8F, 0xF5, 0xED, 0x07, 0x04, 0x48, 0x7D, 0x01, 0xD6,
0xE1, 0xE4, 0x08, 0x69, 0x09, 0xDC, 0x32, 0x80, 0xE8, 0xC4, 0xE4, 0x81, 0x7C, 0x66, 0xDD, 0xDD};
static unsigned char SM9_P1y[32] = {0x21, 0xFE, 0x8D, 0xDA, 0x4F, 0x21, 0xE6, 0x07, 0x63, 0x10, 0x65, 0x12, 0x5C, 0x39, 0x5B, 0xBC,
0x1C, 0x1C, 0x00, 0xCB, 0xFA, 0x60, 0x24, 0x35, 0x0C, 0x46, 0x4C, 0xD7, 0x0A, 0x3E, 0xA6, 0x16};
static unsigned char SM9_P2[128] = {0x85, 0xAE, 0xF3, 0xD0, 0x78, 0x64, 0x0C, 0x98, 0x59, 0x7B, 0x60, 0x27, 0xB4, 0x41, 0xA0, 0x1F,
0xF1, 0xDD, 0x2C, 0x19, 0x0F, 0x5E, 0x93, 0xC4, 0x54, 0x80, 0x6C, 0x11, 0xD8, 0x80, 0x61, 0x41,
0x37, 0x22, 0x75, 0x52, 0x92, 0x13, 0x0B, 0x08, 0xD2, 0xAA, 0xB9, 0x7F, 0xD3, 0x4E, 0xC1, 0x20,
0xEE, 0x26, 0x59, 0x48, 0xD1, 0x9C, 0x17, 0xAB, 0xF9, 0xB7, 0x21, 0x3B, 0xAF, 0x82, 0xD6, 0x5B,
0x17, 0x50, 0x9B, 0x09, 0x2E, 0x84, 0x5C, 0x12, 0x66, 0xBA, 0x0D, 0x26, 0x2C, 0xBE, 0xE6, 0xED,
0x07, 0x36, 0xA9, 0x6F, 0xA3, 0x47, 0xC8, 0xBD, 0x85, 0x6D, 0xC7, 0x6B, 0x84, 0xEB, 0xEB, 0x96,
0xA7, 0xCF, 0x28, 0xD5, 0x19, 0xBE, 0x3D, 0xA6, 0x5F, 0x31, 0x70, 0x15, 0x3D, 0x27, 0x8F, 0xF2,
0x47, 0xEF, 0xBA, 0x98, 0xA7, 0x1A, 0x08, 0x11, 0x62, 0x15, 0xBB, 0xA5, 0xC9, 0x99, 0xA7, 0xC7};
static unsigned char SM9_t[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x58, 0xF9, 0x8A};
static unsigned char SM9_a[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static unsigned char SM9_b[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05};
epoint *P1;
ecn2 P2;
big N; //order of group, N(t)
big para_a, para_b, para_t, para_q;
static BOOL bytes128_to_ecn2(unsigned char Ppubs[], ecn2 *res);
static void zzn12_ElementPrint(zzn12 x);
static void ecn2_Bytes128_Print(ecn2 x);
static void LinkCharZzn12(unsigned char *message, int len, zzn12 w, unsigned char *Z, int Zlen);
static int Test_Point(epoint* point);
void SM4_standard_block_encrypt(unsigned char key[], unsigned char * message, int mlen, unsigned char *cipher, int * cipher_len);
void SM4_standard_block_decrypt(unsigned char key[], unsigned char *cipher, int len, unsigned char *plain, int *plain_len);
int SM9_standard_keyex_kdf(unsigned char *IDA, unsigned char *IDB, epoint *RA, epoint *RB, zzn12 g1, zzn12 g2, zzn12 g3, int klen, unsigned char K[]);
int SM9_standard_keyex_hash(unsigned char hashid[], unsigned char *IDA, unsigned char *IDB, epoint *RA, epoint *RB, zzn12 g1, zzn12 g2, zzn12 g3, unsigned char hash[]);
static int SM9_standard_h1(unsigned char Z[], int Zlen, big n, big h1);
int SM9_standard_enc_mac(unsigned char *K, int Klen, unsigned char *M, int Mlen, unsigned char C[]);
static int SM9_standard_init();
static int SM9_standard_generateencryptkey(unsigned char hid[], unsigned char *ID, int IDlen, big ke, unsigned char Ppubs[], unsigned char deB[]);
int SM9_standard_keyex_inita_i(unsigned char hid[], unsigned char *IDB, unsigned char randA[],
unsigned char Ppub[], unsigned char deA[], epoint *RA);
int SM9_standard_keyex_reb_i(unsigned char hid[], unsigned char *IDA, unsigned char *IDB, unsigned char randB[], unsigned char Ppub[], unsigned char deB[], epoint *RA, epoint *RB, unsigned char SB[], zzn12 *g1, zzn12 *g2, zzn12 *g3);
int SM9_standard_keyex_inita_ii(unsigned char *IDA, unsigned char *IDB, unsigned char randA[], unsigned char Ppub[], unsigned char deA[], epoint *RA, epoint *RB, unsigned char SB[], unsigned char SA[]);
int SM9_standard_keyex_reb_ii(unsigned char *IDA, unsigned char *IDB, zzn12 g1, zzn12 g2, zzn12 g3, epoint *RA, epoint *RB, unsigned char SA[]);
int SM9_standard_exch_selfcheck();
int SM9_standard_enc_selfcheck();
int SM9_standard_encrypt(unsigned char hid[], unsigned char *IDB, unsigned char *message, int mlen, unsigned char rand[],
int EncID, int k1_len, int k2_len, unsigned char Ppub[], unsigned char C[], int *C_len);
int SM9_standard_decrypt(unsigned char C[], int C_len, unsigned char deB[], unsigned char *IDB, int EncID,
int k1_len, int k2_len, unsigned char M[], int * Mlen);
int SM9_standard_key_encap(unsigned char hid[], unsigned char *IDB, unsigned char rand[], unsigned char Ppub[], unsigned char C[], unsigned char K[], int Klen);
int SM9_standard_key_decap(unsigned char *IDB, unsigned char deB[], unsigned char C[], int Klen, unsigned char K[]);
int SM9_standard_encap_selfcheck();
static int Test_Range(big x);
int SM9_standard_h2(unsigned char Z[], int Zlen, big n, big h2);
int SM9_standard_generatesignkey(unsigned char hid[], unsigned char *ID, int IDlen, big ks, unsigned char Ppubs[], unsigned char dsa[]);
int SM9_standard_sign(unsigned char hid[], unsigned char *IDA, unsigned char *message, int len, unsigned char rand[], unsigned char dsa[], unsigned char Ppub[], unsigned char H[], unsigned char S[]);
int SM9_standard_verify(unsigned char H[], unsigned char S[], unsigned char hid[], unsigned char *IDA, unsigned char *message, int len, unsigned char Ppub[]);
int SM9_standard_sv_selfcheck();
static BOOL bytes128_to_ecn2(unsigned char Ppubs[], ecn2 *res)
{
zzn2 x, y;
big a, b;
ecn2 r;
r.x.a = mirvar(0);
r.x.b = mirvar(0);
r.y.a = mirvar(0);
r.y.b = mirvar(0);
r.z.a = mirvar(0);
r.z.b = mirvar(0);
r.marker = MR_EPOINT_INFINITY;
x.a = mirvar(0);
x.b = mirvar(0);
y.a = mirvar(0);
y.b = mirvar(0);
a = mirvar(0);
b = mirvar(0);
bytes_to_big(BNLEN, Ppubs, b);
bytes_to_big(BNLEN, Ppubs + BNLEN, a);
zzn2_from_bigs(a, b, &x);
bytes_to_big(BNLEN, Ppubs + BNLEN * 2, b);
bytes_to_big(BNLEN, Ppubs + BNLEN * 3, a);
zzn2_from_bigs(a, b, &y);
return ecn2_set(&x, &y, res);
}
static void ecn2_Bytes128_Print(ecn2 x)
{
big tmp;
tmp = mirvar(0);
redc(x.x.b, tmp);
cotnum(tmp, stdout);
redc(x.x.a, tmp);
cotnum(tmp, stdout);
redc(x.y.b, tmp);
cotnum(tmp, stdout);
redc(x.y.a, tmp);
cotnum(tmp, stdout);
}
static void zzn12_ElementPrint(zzn12 x)
{
big tmp;
tmp = mirvar(0);
redc(x.c.b.b, tmp);
cotnum(tmp, stdout);
redc(x.c.b.a, tmp);
cotnum(tmp, stdout);
redc(x.c.a.b, tmp);
cotnum(tmp, stdout);
redc(x.c.a.a, tmp);
cotnum(tmp,stdout);
redc(x.b.b.b, tmp);
cotnum(tmp, stdout);
redc(x.b.b.a, tmp);
cotnum(tmp, stdout);
redc(x.b.a.b, tmp);
cotnum(tmp, stdout);
redc(x.b.a.a, tmp);
cotnum(tmp, stdout);
redc(x.a.b.b, tmp);
cotnum(tmp, stdout);
redc(x.a.b.a, tmp);
cotnum(tmp, stdout);
redc(x.a.a.b, tmp);
cotnum(tmp, stdout);
redc(x.a.a.a, tmp);
cotnum(tmp, stdout);
}
static void LinkCharZzn12(unsigned char *message, int len, zzn12 w, unsigned char *Z, int Zlen)
{
big tmp;
tmp = mirvar(0);
memcpy(Z, message, len);
redc(w.c.b.b, tmp);
big_to_bytes(BNLEN, tmp, Z + len, 1);
redc(w.c.b.a, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN, 1);
redc(w.c.a.b, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 2, 1);
redc(w.c.a.a, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 3, 1);
redc(w.b.b.b, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 4, 1);
redc(w.b.b.a, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 5, 1);
redc(w.b.a.b, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 6, 1);
redc(w.b.a.a, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 7, 1);
redc(w.a.b.b, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 8, 1);
redc(w.a.b.a, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 9, 1);
redc(w.a.a.b, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 10, 1);
redc(w.a.a.a, tmp);
big_to_bytes(BNLEN, tmp, Z + len + BNLEN * 11, 1);
}
static int Test_Point(epoint* point)
{
big x, y, x_3, tmp;
epoint *buf;
x = mirvar(0);
y = mirvar(0);
x_3 = mirvar(0);
tmp = mirvar(0);
buf = epoint_init();
//test if y^2=x^3+b
epoint_get(point, x, y);
power(x, 3, para_q, x_3); //x_3=x^3 mod p
multiply(x, para_a, x);
divide(x, para_q, tmp);
add(x_3, x, x); //x=x^3+ax+b
add(x, para_b, x);
divide(x, para_q, tmp); //x=x^3+ax+b mod p
power(y, 2, para_q, y); //y=y^2 mod p
if(mr_compare(x, y) != 0)
return 1;
//test infinity
ecurve_mult(N, point, buf);
if(point_at_infinity(buf) == FALSE)
return 1;
return 0;
}
static int SM9_standard_h1(unsigned char Z[], int Zlen, big n, big h1)
{
int hlen, i, ZHlen;
big hh, i256, tmp, n1;
unsigned char *ZH = NULL,*ha = NULL;
hh = mirvar(0);
i256 = mirvar(0);
tmp = mirvar(0);
n1 = mirvar(0);
convert(1, i256);
ZHlen = Zlen + 1;
hlen = (int)ceil((5.0 * logb2(n)) / 32.0);
decr(n, 1, n1);
ZH = (char *)malloc(sizeof(char)*(ZHlen + 1));
if(ZH == NULL)
return SM9_ASK_MEMORY_ERR;
memcpy(ZH + 1, Z, Zlen);
ZH[0] = 0x01;
ha = (char *)malloc(sizeof(char)*(hlen + 1));
if(ha == NULL)
return SM9_ASK_MEMORY_ERR;
SM3_kdf(ZH, ZHlen, hlen, ha);
for(i = hlen - 1; i >= 0; i--)//key[从大到小]
{
premult(i256, ha[i], tmp);
add(hh, tmp, hh);
premult(i256, 256, i256);
divide(i256, n1, tmp);
divide(hh, n1, tmp);
}
incr(hh, 1, h1);
free(ZH);
free(ha);
return 0;
}
static int SM9_standard_init()
{
big P1_x, P1_y;
para_q = mirvar(0);
N = mirvar(0);
P1_x = mirvar(0);
P1_y = mirvar(0);
para_a = mirvar(0);
para_b = mirvar(0);
para_t = mirvar(0);
X.a = mirvar(0);
X.b = mirvar(0);
P2.x.a = mirvar(0);
P2.x.b = mirvar(0);
P2.y.a = mirvar(0);
P2.y.b = mirvar(0);
P2.z.a = mirvar(0);
P2.z.b = mirvar(0);
P2.marker = MR_EPOINT_INFINITY;
P1 = epoint_init();
bytes_to_big(BNLEN, SM9_q, para_q);
bytes_to_big(BNLEN, SM9_P1x, P1_x);
bytes_to_big(BNLEN, SM9_P1y, P1_y);
bytes_to_big(BNLEN, SM9_a, para_a);
bytes_to_big(BNLEN, SM9_b, para_b);
bytes_to_big(BNLEN, SM9_N, N);
bytes_to_big(BNLEN, SM9_t, para_t);
mip->TWIST = MR_SEXTIC_M;
ecurve_init(para_a, para_b, para_q, MR_PROJECTIVE); //Initialises GF(q) elliptic curve
//MR_PROJECTIVE specifying projective coordinates
if(!epoint_set(P1_x, P1_y, 0, P1))
return SM9_G1BASEPOINT_SET_ERR;
if(!(bytes128_to_ecn2(SM9_P2, &P2)))
return SM9_G2BASEPOINT_SET_ERR;
set_frobenius_constant(&X);
return 0;
}
static int SM9_standard_generateencryptkey(unsigned char hid[], unsigned char *ID, int IDlen, big ke, unsigned char Ppubs[], unsigned char deB[])
{
big h1, t1, t2, rem, xPpub, yPpub, tmp;
unsigned char *Z = NULL;
int Zlen = IDlen + 1, buf;
ecn2 dEB;
epoint *Ppub;
h1 = mirvar(0);
t1 = mirvar(0);
t2 = mirvar(0);
rem = mirvar(0);
tmp = mirvar(0);
xPpub = mirvar(0);
yPpub = mirvar(0);
Ppub = epoint_init();
dEB.x.a = mirvar(0);
dEB.x.b = mirvar(0);
dEB.y.a = mirvar(0);
dEB.y.b = mirvar(0);
dEB.z.a = mirvar(0);
dEB.z.b = mirvar(0);
dEB.marker = MR_EPOINT_INFINITY;
Z = (char *)malloc(sizeof(char)*(Zlen + 1));
memcpy(Z, ID, IDlen);
memcpy(Z + IDlen, hid, 1);
buf = SM9_standard_h1(Z, Zlen, N, h1);
if(buf != 0)
return buf;
add(h1, ke, t1);//t1=H1(IDA||hid,N)+ks
xgcd(t1, N, t1, t1, t1);//t1=t1(-1)
multiply(ke, t1, t2);
divide(t2, N, rem);//t2=ks*t1(-1)
//Ppub=[ke]P2
ecurve_mult(ke, P1, Ppub);
//deB=[t2]P2
ecn2_copy(&P2, &dEB);
ecn2_mul(t2, &dEB);
printf("\n**************The private key deB = (xdeB, ydeB)*********************\n");
ecn2_Bytes128_Print(dEB);
printf("\n**********************PublicKey Ppubs=[ke]P1*************************\n");
epoint_get(Ppub, xPpub, yPpub);
cotnum(xPpub, stdout);
cotnum(yPpub, stdout);
epoint_get(Ppub, xPpub, yPpub);
big_to_bytes(BNLEN, xPpub, Ppubs, 1);
big_to_bytes(BNLEN, yPpub, Ppubs + BNLEN, 1);
redc(dEB.x.b, tmp);
big_to_bytes(BNLEN, tmp, deB, 1);
redc(dEB.x.a, tmp);
big_to_bytes(BNLEN, tmp, deB + BNLEN, 1);
redc(dEB.y.b, tmp);
big_to_bytes(BNLEN, tmp, deB + BNLEN * 2, 1);
redc(dEB.y.a, tmp);
big_to_bytes(BNLEN, tmp, deB + BNLEN * 3, 1);
free(Z);
return 0;
}
static int Test_Range(big x)
{
big one, decr_n;
one = mirvar(0);
decr_n = mirvar(0);
convert(1, one);
decr(N, 1, decr_n);
if((mr_compare(x, one) < 0) | (mr_compare(x, decr_n) > 0))
return 1;
return 0;
}
#ifdef __cplusplus
}
#endif
#endif