blob: 21dd661e0a042790dd7f921962ec7bb2c76bfa25 [file] [log] [blame]
/**
* @file wcc_ZZZ.c
* @author Mike Scott
* @author Kealan McCusker
* @date 28th April 2016
* @brief AMCL Wang / Chow Choo (WCC) definitions
*
* LICENSE
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "wcc_ZZZ.h"
/* Perform sha256 of EC Points and Id. Map to an integer modulo the curve order. */
void WCC_ZZZ_Hq(int sha, octet *A,octet *B,octet *C,octet *D,octet *h)
{
BIG_XXX q,hs;
// hv has to store two points in G1, One in G2 and the Id length
char hv[2000];
octet HV= {0,sizeof(hv),hv};
char ht[WCC_PFS_ZZZ];
octet HT= {0,sizeof(ht),ht};
BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
#ifdef DEBUG
printf("WCC_ZZZ_Hq: A: ");
OCT_output(A);
printf("\n");
printf("WCC_ZZZ_Hq: B: ");
OCT_output(B);
printf("\n");
printf("WCC_ZZZ_Hq: C: ");
OCT_output(C);
printf("\n");
printf("WCC_ZZZ_Hq: D: ");
OCT_output(D);
printf("\n");
#endif
OCT_joctet(&HV,A);
OCT_joctet(&HV,B);
OCT_joctet(&HV,C);
OCT_joctet(&HV,D);
mhashit(sha,0,&HV,&HT);
BIG_XXX_fromBytes(hs,HT.val);
BIG_XXX_mod(hs,q);
OCT_clear(&HT);
BIG_XXX_toBytes(h->val,hs);
h->len=WCC_PGS_ZZZ;
}
/* Calculate a value in G1. VG1 = s*H1(ID) where ID is the identity */
int WCC_ZZZ_GET_G1_MULTIPLE(octet *S,octet *HID,octet *VG1)
{
BIG_XXX s;
ECP_ZZZ P;
ECP_ZZZ_mapit(&P,HID);
BIG_XXX_fromBytes(s,S->val);
PAIR_ZZZ_G1mul(&P,s);
ECP_ZZZ_toOctet(VG1,&P,false);
return 0;
}
/* Calculate a value in G2. VG2 = s*H2(ID) where ID is the identity */
int WCC_ZZZ_GET_G2_MULTIPLE(octet *S,octet *HID,octet *VG2)
{
BIG_XXX s;
ECP2_ZZZ P;
ECP2_ZZZ_mapit(&P,HID);
BIG_XXX_fromBytes(s,S->val);
PAIR_ZZZ_G2mul(&P,s);
ECP2_ZZZ_toOctet(VG2,&P);
return 0;
}
/* Calculate the sender AES Key */
int WCC_ZZZ_SENDER_KEY(int sha, octet *xOct, octet *piaOct, octet *pibOct, octet *PbG2Oct, octet *PgG1Oct, octet *AKeyG1Oct, octet *IdBOct, octet *AESKeyOct)
{
ECP_ZZZ sAG1,PgG1;
ECP2_ZZZ BG2,PbG2;
char hv1[WCC_PFS_ZZZ];
octet HV1= {0,sizeof(hv1),hv1};
// Pairing outputs
FP12_YYY g;
FP4_YYY c;
BIG_XXX t,x,z,pia,pib;
char xpgg1[2*WCC_PFS_ZZZ+1];
octet xPgG1Oct= {0,sizeof(xpgg1), xpgg1};
char hv[6*WCC_PFS_ZZZ+1];
octet HV= {0,sizeof(hv),hv};
char ht[AESKEY_ZZZ];
octet HT= {0,sizeof(ht),ht};
BIG_XXX_fromBytes(x,xOct->val);
BIG_XXX_fromBytes(pia,piaOct->val);
BIG_XXX_fromBytes(pib,pibOct->val);
if (!ECP2_ZZZ_fromOctet(&PbG2,PbG2Oct))
{
#ifdef DEBUG
printf("PbG2Oct Invalid Point: ");
OCT_output(PbG2Oct);
printf("\n");
#endif
return WCC_INVALID_POINT;
}
if (!ECP_ZZZ_fromOctet(&PgG1,PgG1Oct))
{
#ifdef DEBUG
printf("PgG1Oct Invalid Point: ");
OCT_output(PgG1Oct);
printf("\n");
#endif
return WCC_INVALID_POINT;
}
mhashit(sha,0,IdBOct,&HV1);
ECP2_ZZZ_mapit(&BG2,&HV1);
if (!ECP_ZZZ_fromOctet(&sAG1,AKeyG1Oct))
{
#ifdef DEBUG
printf("AKeyG1Oct Invalid Point: ");
OCT_output(AKeyG1Oct);
printf("\n");
#endif
return WCC_INVALID_POINT;
}
// z = x + pia
BIG_XXX_add(z,x,pia);
// (x+pia).AKeyG1
PAIR_ZZZ_G1mul(&sAG1,z);
// pib.BG2
PAIR_ZZZ_G2mul(&BG2,pib);
// pib.BG2+PbG2
ECP2_ZZZ_add(&BG2, &PbG2);
ECP2_ZZZ_affine(&BG2);
ECP_ZZZ_affine(&sAG1);
PAIR_ZZZ_ate(&g,&BG2,&sAG1);
PAIR_ZZZ_fexp(&g);
// printf("WCC_ZZZ_SENDER_KEY e(sAG1,BG2) = ");FP12_YYY_output(&g); printf("\n");
// x.PgG1
PAIR_ZZZ_G1mul(&PgG1,x);
ECP_ZZZ_toOctet(&xPgG1Oct,&PgG1,false);
// Generate AES Key : K=H(k,x.PgG1)
FP12_YYY_trace(&c,&g);
HV.len = 4*WCC_PFS_ZZZ;
FP_YYY_redc(t,&(c.a.a));
BIG_XXX_toBytes(&(HV.val[0]),t);
FP_YYY_redc(t,&(c.a.b));
BIG_XXX_toBytes(&(HV.val[WCC_PFS_ZZZ]),t);
FP_YYY_redc(t,&(c.b.a));
BIG_XXX_toBytes(&(HV.val[WCC_PFS_ZZZ*2]),t);
FP_YYY_redc(t,&(c.b.b));
BIG_XXX_toBytes(&(HV.val[WCC_PFS_ZZZ*3]),t);
// Set HV.len to correct value
OCT_joctet(&HV,&xPgG1Oct);
mhashit(sha,0,&HV,&HT);
OCT_empty(AESKeyOct);
OCT_jbytes(AESKeyOct,HT.val,AESKEY_ZZZ);
return 0;
}
/* Calculate the receiver AES key */
int WCC_ZZZ_RECEIVER_KEY(int sha, octet *yOct, octet *wOct, octet *piaOct, octet *pibOct, octet *PaG1Oct, octet *PgG1Oct, octet *BKeyG2Oct, octet *IdAOct, octet *AESKeyOct)
{
ECP_ZZZ AG1,PgG1,PaG1;
ECP2_ZZZ sBG2;
char hv1[WCC_PFS_ZZZ];
octet HV1= {0,sizeof(hv1),hv1};
// Pairing outputs
FP12_YYY g;
FP4_YYY c;
BIG_XXX t,w,y,pia,pib;;
char wpag1[2*WCC_PFS_ZZZ+1];
octet wPaG1Oct= {0,sizeof(wpag1), wpag1};
char hv[6*WCC_PFS_ZZZ+1];
octet HV= {0,sizeof(hv),hv};
char ht[AESKEY_ZZZ];
octet HT= {0,sizeof(ht),ht};
BIG_XXX_fromBytes(y,yOct->val);
BIG_XXX_fromBytes(w,wOct->val);
BIG_XXX_fromBytes(pia,piaOct->val);
BIG_XXX_fromBytes(pib,pibOct->val);
if (!ECP_ZZZ_fromOctet(&PaG1,PaG1Oct))
return WCC_INVALID_POINT;
if (!ECP_ZZZ_fromOctet(&PgG1,PgG1Oct))
return WCC_INVALID_POINT;
mhashit(sha,0,IdAOct,&HV1);
ECP_ZZZ_mapit(&AG1,&HV1);
if (!ECP2_ZZZ_fromOctet(&sBG2,BKeyG2Oct))
return WCC_INVALID_POINT;
// y = y + pib
BIG_XXX_add(y,y,pib);
// (y+pib).BKeyG2
PAIR_ZZZ_G2mul(&sBG2,y);
// pia.AG1
PAIR_ZZZ_G1mul(&AG1,pia);
// pia.AG1+PaG1
ECP_ZZZ_add(&AG1, &PaG1);
ECP2_ZZZ_affine(&sBG2);
ECP_ZZZ_affine(&AG1);
PAIR_ZZZ_ate(&g,&sBG2,&AG1);
PAIR_ZZZ_fexp(&g);
// printf("WCC_ZZZ_RECEIVER_KEY e(AG1,sBG2) = ");FP12_YYY_output(&g); printf("\n");
// w.PaG1
PAIR_ZZZ_G1mul(&PaG1,w);
ECP_ZZZ_toOctet(&wPaG1Oct,&PaG1,false);
// Generate AES Key: K=H(k,w.PaG1)
FP12_YYY_trace(&c,&g);
HV.len = 4*WCC_PFS_ZZZ;
FP_YYY_redc(t,&(c.a.a));
BIG_XXX_toBytes(&(HV.val[0]),t);
FP_YYY_redc(t,&(c.a.b));
BIG_XXX_toBytes(&(HV.val[WCC_PFS_ZZZ]),t);
FP_YYY_redc(t,&(c.b.a));
BIG_XXX_toBytes(&(HV.val[WCC_PFS_ZZZ*2]),t);
FP_YYY_redc(t,&(c.b.b));
BIG_XXX_toBytes(&(HV.val[WCC_PFS_ZZZ*3]),t);
// Set HV.len to correct value
OCT_joctet(&HV,&wPaG1Oct);
mhashit(sha,0,&HV,&HT);
OCT_empty(AESKeyOct);
OCT_jbytes(AESKeyOct,HT.val,AESKEY_ZZZ);
return 0;
}
/* Generate a random number modulus the group order */
int WCC_ZZZ_RANDOM_GENERATE(csprng *RNG,octet* S)
{
BIG_XXX r,s;
BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
BIG_XXX_randomnum(s,r,RNG);
BIG_XXX_toBytes(S->val,s);
S->len=WCC_PGS_ZZZ;
return 0;
}
/* Add two members from the group G1 */
int WCC_ZZZ_RECOMBINE_G1(octet *R1,octet *R2,octet *R)
{
ECP_ZZZ P,T;
int res=0;
if (!ECP_ZZZ_fromOctet(&P,R1)) res=WCC_INVALID_POINT;
if (!ECP_ZZZ_fromOctet(&T,R2)) res=WCC_INVALID_POINT;
if (res==0)
{
ECP_ZZZ_add(&P,&T);
ECP_ZZZ_toOctet(R,&P,false);
}
return res;
}
/* Add two members from the group G2 */
int WCC_ZZZ_RECOMBINE_G2(octet *W1,octet *W2,octet *W)
{
ECP2_ZZZ Q,T;
int res=0;
if (!ECP2_ZZZ_fromOctet(&Q,W1)) res=WCC_INVALID_POINT;
if (!ECP2_ZZZ_fromOctet(&T,W2)) res=WCC_INVALID_POINT;
if (res==0)
{
ECP2_ZZZ_add(&Q,&T);
ECP2_ZZZ_toOctet(W,&Q);
}
return res;
}