Files
GmSSL/engines/sm_standard/sm9/sm9_standard.h
2017-07-10 14:51:03 +08:00

483 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ====================================================================
* 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