/**
 * @brief Finds the Gibbs free energy for a stacking structure element.
 *
 * <PRE>
 * 5') [i] [i+1] ...
 *      |    |
 * 3') [j] [j-1] ...
 * </PRE>
 *
 *
 * @param arg_pair Pair containing nucleotides i and j indicating their positions in the sequence, where i < j.
 *
 * @todo 3 is hardcoded? << should be used from thermodynamics?
 */
float GibbsFreeEnergy::get_stacking_pair_element(Pair &arg_pair)
{
	Nucleotide n1 = this->sequence[arg_pair.first];
	Nucleotide n2 = this->sequence[arg_pair.second];
	
	Pairing p = Pairing(n1, n2);
	
	float energy;
	
	if(((arg_pair.second - arg_pair.first - 1) < 3) || !p.is_canonical())///@todo figure out why 3 is not implemented as a constant ? shoudl be this->settings->min_hairpin_length?
	
	{
		energy = N_INFINITY;
	}
	else
	{
		Nucleotide n1p = this->sequence[arg_pair.first + 1];
		Nucleotide n2p = this->sequence[arg_pair.second - 1];
		
		Pairing p2 = Pairing(n1p, n2p);
		
		energy = this->get_stack(p, p2);///@todo figure out why in the original code this penalty was extended with eparam[0] which seemed to be a stack specific penalty of 0
	}
	
	return energy;
}
/**
 * @brief Energy function for Bulge Loop
 *
 * @section DESCRIPTION
 * This function returns the amount of energy for a bulge loop element. The
 * parameters must be: i<ip<jp<j where in particular:
 *
 * (ip-i == 1) || (j-jp == 1)
 *
 * There are two types of bulge loops:
 *
 * - Casus "5 prime bulge":
 * <PRE>
 * 5': ... i , ... , ip ...
 * 3': ... j    ,    jp ...
 * </PRE>
 *
 * - Casus "3 prime bulge":
 * <PRE>
 * 5': ... i    ,    ip ...
 * 3': ... j , ... , jp ...
 * </PRE>
 *
 * The corresponding energy is found in additional tables.
 *
 *
 * @param i Nucleotide position of the sequence, paired to j, where i < i' (ip) < j' (jp) < j
 * @param j Nucleotide position of the sequence, paired to i, where i < i' (ip) < j' (jp) < j
 * @param ip (i') Nucleotide position of the sequence, paired to j', where i < i' (ip) < j' (jp) < j
 * @param jp (j') Nucleotide position of the sequence, paired to i', where i < i' (ip) < j' (jp) < j
 *
 * @return Amount of corresponding Gibbs free energy if there is an bulge loop betweein (i,j) and (i',j'); infinity otherwise.
 *
 * @todo check: why check the size of only one size? -> does the algorithm ensure one side is always == 0?
 */
float GibbsFreeEnergy::get_bulge_loop_element(Region &r)
{
	float energy;
	
	unsigned int n_unpaired_left = r.pair2.first - r.pair1.first;
	unsigned n_unpaired_right = r.pair1.second - r.pair2.second;
	
	unsigned int n_unpaired = std::max(n_unpaired_left, n_unpaired_right) - 1;
	
	if(r.pair2.second - r.pair2.first - 1 <=  this->thermodynamics.minimal_hairpin_length)
	{
		energy = N_INFINITY;
	}
#if DEBUG
	else if(n_unpaired < 1)
	{
		throw std::invalid_argument("GibbsFreeEnergy::get_bulge_loop_element({" + std::to_string(r.pair1.first) + "," + std::to_string(r.pair1.second) + "},{" + std::to_string(r.pair2.first) + "," + std::to_string(r.pair2.second) + "}): unnecessary invocation because of loop size");
		energy = N_INFINITY;
	}
#endif // DEBUG
	else
	{
		energy = this->get_loop_bulge(n_unpaired);
		
		Nucleotide n11 = this->sequence[r.pair1.first];
		Nucleotide n12 = this->sequence[r.pair1.second];
		Nucleotide n21 = this->sequence[r.pair2.first];
		Nucleotide n22 = this->sequence[r.pair2.second];
		
		Pairing pairing1 = Pairing(n11, n12);///@todo don't you get this penalty already when you calculate the hairpin?
		Pairing pairing2 = Pairing(n21, n22);
		
		if(n_unpaired == 1)
		{
			energy += this->get_stack(pairing1, pairing2);///@todo should the v matrix not be filled with the stack instead...? : return N_infinity?
		}
		else
		{
			energy += this->get_AU_penalty(pairing1);///@todo don't you get this penalty already when you calculate the hairpin?
			energy += this->get_AU_penalty(pairing2);
			
			///http://unafold.math.rpi.edu/lectures/old_RNAfold/node2.html
			// "Because free energies are assigned to loops, and not to helices, there is no a priori way of knowing whether or not a stacked pair will be terminal or not. For this reason, the terminal AU penalty is built into the TSTACKH and TSTACKI tables. For bulge, multi-branch and exterior loops, the penalty is applied explicitly. In all of these cases, the penalty is formally assigned to the adjacent loop, although it really belongs to the helix"
		}
	}
	
	return energy;
}
Exemplo n.º 3
0
static EpidStatus DoPrecomputation(VerifierCtx* ctx) {
  EpidStatus result = kEpidErr;
  FfElement* e12 = NULL;
  FfElement* e22 = NULL;
  FfElement* e2w = NULL;
  FfElement* eg12 = NULL;
  Epid2Params_* params = NULL;
  GroupPubKey_* pub_key = NULL;
  PairingState* ps_ctx = NULL;
  if (!ctx) {
    return kEpidBadArgErr;
  }
  if (!ctx->epid2_params || !ctx->epid2_params->GT ||
      !ctx->epid2_params->pairing_state || !ctx->pub_key || !ctx->e12 ||
      !ctx->e22 || !ctx->e2w || !ctx->eg12) {
    return kEpidBadArgErr;
  }
  pub_key = ctx->pub_key;
  params = ctx->epid2_params;
  e12 = ctx->e12;
  e22 = ctx->e22;
  e2w = ctx->e2w;
  eg12 = ctx->eg12;
  ps_ctx = params->pairing_state;
  // do precomputation
  // 1. The verifier computes e12 = pairing(h1, g2).
  result = Pairing(ps_ctx, e12, pub_key->h1, params->g2);
  if (kEpidNoErr != result) {
    return result;
  }
  // 2. The verifier computes e22 = pairing(h2, g2).
  result = Pairing(ps_ctx, e22, pub_key->h2, params->g2);
  if (kEpidNoErr != result) {
    return result;
  }
  // 3. The verifier computes e2w = pairing(h2, w).
  result = Pairing(ps_ctx, e2w, pub_key->h2, pub_key->w);
  if (kEpidNoErr != result) {
    return result;
  }
  // 4. The verifier computes eg12 = pairing(g1, g2).
  result = Pairing(ps_ctx, eg12, params->g1, params->g2);
  if (kEpidNoErr != result) {
    return result;
  }
  return kEpidNoErr;
}
/**
 * @brief Finds the Gibbs free energy for a hairpin loop structure element.
 *
 * @section DESCRIPTION
 * The hairpinloops Gibbs free energy levels are from a fixed table upto
 * a length of 30 unpaired nucleotides. Extrapoliation is applied for a
 * number of unpaired nucleotides which >= 30.
 *
 * <PRE>
 * 5') [i] [i+1] ...
 * 3') [j] [j-1] ...
 * </PRE>
 *
 *
 * @param arg_pair Pair containing nucleotides i and j indicating their positions in the sequence, where i < j.
 *
 * @return Amount of Gibbs free energy if (i,j) enclose a hairpin loop.
 */
float GibbsFreeEnergy::get_hairpin_loop_element(Pair &arg_pair)
{
	unsigned int n_unpaired = arg_pair.second - arg_pair.first - 1;		// The number of unpaired nucleotides between i and j: if i = j+1, unPaired = 0
	float energy;
	
	if(n_unpaired < this->thermodynamics.minimal_hairpin_length)		// Too small loop
	{
		energy = N_INFINITY;///@todo this should never happen and should be taken care of in the loops
	}
	else
	{
		// Loop size + Terminal mismatch(i',j')
		//energy = this->get_loop_hairpin(n_unpaired);
		
		Nucleotide i = this->sequence[arg_pair.first];
		Nucleotide j = this->sequence[arg_pair.second];
		
		Pairing pairing = Pairing(i, j);
		
		energy = this->get_loop_hairpin(n_unpaired) +
				 this->get_tstackh(pairing.type, this->sequence[arg_pair.first + 1], this->sequence[arg_pair.second - 1]);
				 
		// Loop-sequence specific penalty
		switch(n_unpaired)
		{
			case 3:
				{
					Sequence sub_sequence = this->sequence.subseq(arg_pair.first, arg_pair.second);
					///@todo AU penalty?
					energy += this->get_triloop(sub_sequence);
					break;
				}
			case 4:
				{
					Sequence sub_sequence = this->sequence.subseq(arg_pair.first, arg_pair.second);
					energy += this->get_tloop(sub_sequence);
					break;
				}
		}
		
		energy += this->get_poly_C_loop_penalty(arg_pair, n_unpaired);
		energy += this->get_GGG_U_loop_penalty(arg_pair);
	}
	
	return energy;
}
Exemplo n.º 5
0
EpidStatus EpidSignBasic(MemberCtx const* ctx, void const* msg, size_t msg_len,
                         void const* basename, size_t basename_len,
                         BasicSignature* sig, BigNumStr* rnd_bsn) {
  EpidStatus sts = kEpidErr;

  EcPoint* B = NULL;
  EcPoint* t = NULL;  // temp value in G1
  EcPoint* k = NULL;
  EcPoint* e = NULL;
  FfElement* R2 = NULL;
  FfElement* p2y = NULL;
  FfElement* t1 = NULL;
  FfElement* t2 = NULL;

  FfElement* a = NULL;
  FfElement* b = NULL;
  FfElement* rx = NULL;
  FfElement* ra = NULL;
  FfElement* rb = NULL;

  struct p2x_t {
    uint32_t i;
    uint8_t bsn[1];
  }* p2x = NULL;

  FfElement* t3 = NULL;  // temporary for multiplication
  FfElement* c = NULL;
  uint8_t* digest = NULL;

  PreComputedSignature curr_presig = {0};

  if (!ctx || !sig) {
    return kEpidBadArgErr;
  }
  if (!msg && (0 != msg_len)) {
    // if message is non-empty it must have both length and content
    return kEpidBadArgErr;
  }
  if (!basename && (0 != basename_len)) {
    // if basename is non-empty it must have both length and content
    return kEpidBadArgErr;
  }
  if (!ctx->epid2_params) {
    return kEpidBadArgErr;
  }

  do {
    FiniteField* Fp = ctx->epid2_params->Fp;
    SignCommitOutput commit_out = {0};
    FpElemStr c_str = {0};
    EcGroup* G1 = ctx->epid2_params->G1;
    FiniteField* GT = ctx->epid2_params->GT;

    FiniteField* Fq = ctx->epid2_params->Fq;
    PairingState* ps_ctx = ctx->epid2_params->pairing_state;
    const BigNumStr kOne = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
    BigNumStr t1_str = {0};
    BigNumStr t2_str = {0};
    size_t digest_size = 0;
    uint16_t* rf_ctr = (uint16_t*)&ctx->rf_ctr;
    FfElement const* x = ctx->x;

    if (basename) {
      if (!IsBasenameAllowed(ctx->allowed_basenames, basename, basename_len)) {
        sts = kEpidBadArgErr;
        BREAK_ON_EPID_ERROR(sts);
      }
    }

    sts = NewEcPoint(G1, &B);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewEcPoint(G1, &k);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewEcPoint(G1, &t);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewEcPoint(G1, &e);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(GT, &R2);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fq, &p2y);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &t1);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &t2);
    BREAK_ON_EPID_ERROR(sts);
    p2x = (struct p2x_t*)SAFE_ALLOC(sizeof(struct p2x_t) + basename_len - 1);
    if (!p2x) {
      sts = kEpidMemAllocErr;
      break;
    }

    sts = NewFfElement(Fp, &a);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &b);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &rx);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &ra);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &rb);
    BREAK_ON_EPID_ERROR(sts);

    sts = MemberGetPreSig((MemberCtx*)ctx, &curr_presig);
    BREAK_ON_EPID_ERROR(sts);

    // 3.  If the pre-computed signature pre-sigma exists, the member
    //     loads (B, K, T, a, b, rx, rf, ra, rb, R1, R2) from
    //     pre-sigma. Refer to Section 4.4 for the computation of
    //     these values.
    sts = ReadFfElement(Fp, &curr_presig.a, sizeof(curr_presig.a), a);
    BREAK_ON_EPID_ERROR(sts);
    sts = ReadFfElement(Fp, &curr_presig.b, sizeof(curr_presig.b), b);
    BREAK_ON_EPID_ERROR(sts);
    sts = ReadFfElement(Fp, &curr_presig.rx, sizeof(curr_presig.rx), rx);
    BREAK_ON_EPID_ERROR(sts);
    sts = ReadFfElement(Fp, &curr_presig.ra, sizeof(curr_presig.ra), ra);
    BREAK_ON_EPID_ERROR(sts);
    sts = ReadFfElement(Fp, &curr_presig.rb, sizeof(curr_presig.rb), rb);
    BREAK_ON_EPID_ERROR(sts);

    // If the basename is provided, use it, otherwise use presig B
    if (basename) {
      // 3.a. The member computes (B, i2, y2) = G1.tpmHash(bsn).
      sts = EcHash(G1, basename, basename_len, ctx->hash_alg, B, &p2x->i);
      BREAK_ON_EPID_ERROR(sts);
      p2x->i = htonl(p2x->i);
      sts = WriteEcPoint(G1, B, &commit_out.B, sizeof(commit_out.B));
      BREAK_ON_EPID_ERROR(sts);
      sts = ReadFfElement(Fq, &commit_out.B.y, sizeof(commit_out.B.y), p2y);
      BREAK_ON_EPID_ERROR(sts);

      // b.i. (KTPM, LTPM, ETPM, counterTPM) = TPM2_Commit(P1=h1,(s2, y2) = (i2
      // || bsn, y2)).
      // b.ii.K = KTPM.
      if (0 !=
          memcpy_S((void*)p2x->bsn, basename_len, basename, basename_len)) {
        sts = kEpidBadArgErr;
        break;
      }
      sts =
          Tpm2Commit(ctx->tpm2_ctx, ctx->h1, p2x, sizeof(p2x->i) + basename_len,
                     p2y, k, t, e, (uint16_t*)&ctx->rf_ctr);
      BREAK_ON_EPID_ERROR(sts);
      sts = WriteEcPoint(G1, k, &commit_out.K, sizeof(commit_out.K));
      BREAK_ON_EPID_ERROR(sts);
      // c.i. The member computes R1 = LTPM.
      sts = WriteEcPoint(G1, t, &commit_out.R1, sizeof(commit_out.R1));
      BREAK_ON_EPID_ERROR(sts);
      // c.ii. e12rf = pairing(ETPM, g2)
      sts = Pairing(ps_ctx, e, ctx->epid2_params->g2, R2);
      BREAK_ON_EPID_ERROR(sts);
      // c.iii. R2 = GT.sscmMultiExp(ea2, t1, e12rf, 1, e22, t2, e2w,ra).
      // 4.i. The member computes t1 = (- rx) mod p.
      sts = FfNeg(Fp, rx, t1);
      BREAK_ON_EPID_ERROR(sts);
      // 4.j. The member computes t2 = (rb - a * rx) mod p.
      sts = FfMul(Fp, a, rx, t2);
      BREAK_ON_EPID_ERROR(sts);
      sts = FfNeg(Fp, t2, t2);
      BREAK_ON_EPID_ERROR(sts);
      sts = FfAdd(Fp, rb, t2, t2);
      BREAK_ON_EPID_ERROR(sts);

      sts = WriteFfElement(Fp, t1, &t1_str, sizeof(t1_str));
      BREAK_ON_EPID_ERROR(sts);
      sts = WriteFfElement(Fp, t2, &t2_str, sizeof(t2_str));
      BREAK_ON_EPID_ERROR(sts);
      {
        FfElement const* points[4];
        BigNumStr const* exponents[4];
        points[0] = ctx->ea2;
        points[1] = R2;
        points[2] = ctx->e22;
        points[3] = ctx->e2w;
        exponents[0] = &t1_str;
        exponents[1] = &kOne;
        exponents[2] = &t2_str;
        exponents[3] = (BigNumStr*)&curr_presig.ra;
        sts = FfMultiExp(GT, points, exponents, COUNT_OF(points), R2);
        BREAK_ON_EPID_ERROR(sts);
      }

      sts = WriteFfElement(GT, R2, &commit_out.R2, sizeof(commit_out.R2));
      BREAK_ON_EPID_ERROR(sts);
      // d. The member over-writes the counterTPM, B, K, R1 and R2 values.
    } else {
      if (!rnd_bsn) {
        sts = kEpidBadArgErr;
        break;
      }
      sts = ReadEcPoint(G1, &curr_presig.B, sizeof(curr_presig.B), B);
      BREAK_ON_EPID_ERROR(sts);
      commit_out.B = curr_presig.B;
      commit_out.K = curr_presig.K;
      commit_out.R1 = curr_presig.R1;
      ((MemberCtx*)ctx)->rf_ctr = curr_presig.rf_ctr;
      commit_out.R2 = curr_presig.R2;
      *rnd_bsn = curr_presig.rnd_bsn;
    }

    commit_out.T = curr_presig.T;

    sts = HashSignCommitment(Fp, ctx->hash_alg, &ctx->pub_key, &commit_out, msg,
                             msg_len, &c_str);
    BREAK_ON_EPID_ERROR(sts);

    digest_size = EpidGetHashSize(ctx->hash_alg);
    digest = (uint8_t*)SAFE_ALLOC(digest_size);
    if (!digest) {
      sts = kEpidNoMemErr;
      break;
    }
    memcpy_S(digest + digest_size - sizeof(c_str), sizeof(c_str), &c_str,
             sizeof(c_str));

    sts = NewFfElement(Fp, &t3);
    BREAK_ON_EPID_ERROR(sts);

    sts = NewFfElement(Fp, &c);
    BREAK_ON_EPID_ERROR(sts);

    sts = ReadFfElement(Fp, &c_str, sizeof(c_str), c);
    BREAK_ON_EPID_ERROR(sts);

    // 7.  The member computes sx = (rx + c * x) mod p.
    sts = FfMul(Fp, c, x, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = FfAdd(Fp, rx, t3, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, t3, &sig->sx, sizeof(sig->sx));
    BREAK_ON_EPID_ERROR(sts);

    // 8.  The member computes sf = (rf + c * f) mod p.
    sts = Tpm2Sign(ctx->tpm2_ctx, digest, digest_size, *rf_ctr, NULL, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, t3, &sig->sf, sizeof(sig->sf));
    BREAK_ON_EPID_ERROR(sts);

    // 9.  The member computes sa = (ra + c * a) mod p.
    sts = FfMul(Fp, c, a, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = FfAdd(Fp, ra, t3, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, t3, &sig->sa, sizeof(sig->sa));
    BREAK_ON_EPID_ERROR(sts);

    // 10. The member computes sb = (rb + c * b) mod p.
    sts = FfMul(Fp, c, b, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = FfAdd(Fp, rb, t3, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, t3, &sig->sb, sizeof(sig->sb));
    BREAK_ON_EPID_ERROR(sts);

    sig->B = commit_out.B;
    sig->K = commit_out.K;
    sig->T = commit_out.T;
    sig->c = c_str;

    sts = kEpidNoErr;
  } while (0);

  if (sts != kEpidNoErr) {
    (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, (uint16_t)ctx->rf_ctr);
    (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, curr_presig.rf_ctr);
  } else if (basename) {
    (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, curr_presig.rf_ctr);
  }

  EpidZeroMemory(&curr_presig, sizeof(curr_presig));

  DeleteEcPoint(&B);
  DeleteEcPoint(&k);
  DeleteEcPoint(&t);
  DeleteEcPoint(&e);
  DeleteFfElement(&R2);
  DeleteFfElement(&p2y);
  DeleteFfElement(&t1);
  DeleteFfElement(&t2);

  DeleteFfElement(&a);
  DeleteFfElement(&b);
  DeleteFfElement(&rx);
  DeleteFfElement(&ra);
  DeleteFfElement(&rb);

  SAFE_FREE(p2x);

  DeleteFfElement(&t3);
  DeleteFfElement(&c);
  SAFE_FREE(digest);

  return sts;
}
Exemplo n.º 6
0
// implements section 3.2.2 "Validation of Private Key" from
// Intel(R) EPID 2.0 Spec
bool EpidIsPrivKeyInGroup(GroupPubKey const* pub_key, PrivKey const* priv_key) {
  bool result;

  // Intel(R) EPID Parameters
  Epid2Params_* params = NULL;
  PairingState* ps = NULL;

  // private key
  EcPoint* a_pt = NULL;    // an element in G1
  FfElement* x_el = NULL;  // an integer between [1, p-1]
  FfElement* f_el = NULL;  // an integer between [1, p-1]

  // public key
  EcPoint* h1_pt = NULL;  // an element in G1
  EcPoint* h2_pt = NULL;  // an element in G1
  EcPoint* w_pt = NULL;   // an element in G2

  // local variables
  EcPoint* t1_pt = NULL;    // an element in G2
  EcPoint* t2_pt = NULL;    // an element in G1
  FfElement* t3_el = NULL;  // an element in GT
  FfElement* t4_el = NULL;  // an element in GT

  if (!pub_key || !priv_key) {
    return false;
  }

  do {
    EpidStatus sts;
    EcGroup* G1 = NULL;
    EcGroup* G2 = NULL;
    FiniteField* GT = NULL;
    FiniteField* Fp = NULL;
    BigNumStr t_str = {0};

    sts = CreateEpid2Params(&params);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    G1 = params->G1;
    G2 = params->G2;
    GT = params->GT;
    Fp = params->Fp;

    sts = WriteBigNum(params->t, sizeof(t_str), &t_str);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = NewPairingState(G1, G2, GT, &t_str, params->neg, &ps);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Load private key
    sts = NewEcPoint(G1, &a_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = ReadEcPoint(G1, &priv_key->A, sizeof(priv_key->A), a_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = NewFfElement(Fp, &x_el);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = ReadFfElement(Fp, &priv_key->x, sizeof(priv_key->x), x_el);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = NewFfElement(Fp, &f_el);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = ReadFfElement(Fp, &priv_key->f, sizeof(priv_key->f), f_el);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Load public key
    sts = NewEcPoint(G1, &h1_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = ReadEcPoint(G1, &pub_key->h1, sizeof(pub_key->h1), h1_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = NewEcPoint(G1, &h2_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = ReadEcPoint(G1, &pub_key->h2, sizeof(pub_key->h2), h2_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = NewEcPoint(G2, &w_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = ReadEcPoint(G2, &pub_key->w, sizeof(pub_key->w), w_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // local variables
    sts = NewEcPoint(G2, &t1_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = NewEcPoint(G1, &t2_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = NewFfElement(GT, &t3_el);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = NewFfElement(GT, &t4_el);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Step 1. The member verifies that the gid in the public key matches the
    //         gid in the private key.
    if (0 != memcmp(&pub_key->gid, &priv_key->gid, sizeof(priv_key->gid))) {
      result = false;
      break;
    }

    // Step 2. The member computes t1 = G2.sscmExp(g2, x).
    sts = EcSscmExp(G2, params->g2, (BigNumStr const*)&priv_key->x, t1_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Step 3. The member computes t1 = G2.mul(t1, w).
    sts = EcMul(G2, t1_pt, w_pt, t1_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Step 4. The member computes t3 = pairing(A, t1).
    sts = Pairing(ps, t3_el, a_pt, t1_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Step 5. The member computes t2 = G1.sscmExp(h1, f).
    sts = EcSscmExp(G1, h1_pt, (BigNumStr const*)&priv_key->f, t2_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Step 6. The member computes t2 = G1.mul(t2, g1).
    sts = EcMul(G1, t2_pt, params->g1, t2_pt);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Step 7. The member computes t4 = pairing(t2, g2).
    sts = WriteBigNum(params->t, sizeof(t_str), &t_str);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    sts = Pairing(ps, t4_el, t2_pt, params->g2);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }

    // Step 8. If GT.isEqual(t3, t4) = false, reports bad private key.
    sts = FfIsEqual(GT, t3_el, t4_el, &result);
    if (kEpidNoErr != sts) {
      result = false;
      break;
    }
  } while (0);

  // local variables
  DeleteFfElement(&t4_el);
  DeleteFfElement(&t3_el);
  DeleteEcPoint(&t2_pt);
  DeleteEcPoint(&t1_pt);

  // public key
  DeleteEcPoint(&w_pt);
  DeleteEcPoint(&h2_pt);
  DeleteEcPoint(&h1_pt);

  // private key
  DeleteFfElement(&f_el);
  DeleteFfElement(&x_el);
  DeleteEcPoint(&a_pt);

  // Intel(R) EPID Parameters
  DeletePairingState(&ps);
  DeleteEpid2Params(&params);

  return result;
}
/**
 * @brief Energy function for Interior Loop
 *
 * @section DESCRIPTION
 * <PRE>
 * 5': i ... i' ... : 3'
 * 3': j ... j' ... : 5'
 * </PRE>
 *
 * @todo Check code for:
 * - loop contains end or beginning of sequence
 * - loop internal loop < min hairpin loop?
 * - use switches
 *
 * @param arg_region as region with Nucleotides i (pair1.first), j (pair1.second), i') and j' as positions of the sequence, where i paired to j, i' to j' and where i < i' < j' < j
 *
 * @return Amount of corresponding Gibbs free energy if there is an internal/interior loop betweein (i,j) and (i',j'); infinity otherwise.
 */
float GibbsFreeEnergy::get_interior_loop_element(Region &arg_region)
{
	unsigned int n_unpaired;
	signed int n_asym;
	
	float energy = 0.0;
	
	unsigned int l1 = arg_region.pair2.first - arg_region.pair1.first;
	unsigned int l2 = arg_region.pair1.second - arg_region.pair2.second;
	
	//{i}{i'}..     -> l1 = 2 - 1 = 1
	//{j}{j'}..     -> l2 = 8 - 9 = 1
	//nup = 1 + 1 - 2 = 0 (correct)
	n_unpaired = l1 + l2 - 2;// saves one CPU operation
	
	///@todo the following conversion is WEIRD but seems to solve the error
	///Only the results should be converted, so max(l1,l2) , min(l1,l2) and make negative if l2 > l1
	n_asym = ((signed int) l1 - (signed int) l2); // saves two CPU operations
	
	// 5') [i] ... [...] [i'] ... (3'
	//      |             |
	// 3') [j] ... [...] [j'] ... (5'
	if(arg_region.pair2.second - arg_region.pair2.first - 1 <=  this->thermodynamics.minimal_hairpin_length)///@todo arg_region.pair2.size() + test
	{
		energy = N_INFINITY;
	}
	else if(n_unpaired > 4 || abs(n_asym) > 1)
	{
		Nucleotide ni = this->sequence[arg_region.pair1.first];
		Nucleotide nj = this->sequence[arg_region.pair1.second];
		
		Nucleotide nip = this->sequence[arg_region.pair2.first];
		Nucleotide njp = this->sequence[arg_region.pair2.second];
		
		Pairing pairing1 = Pairing(ni, nj);
		Pairing pairing2 = Pairing(njp, nip);							// I and J are switched because 5' and 3' rotate after a hairpin
		
		//@todo this would mean that 2,2 loops get an equal penalty as 1,3 and 3,1 ?
		energy += this->get_loop_interior(n_unpaired);
		
		// tstki example:
		//
		//         [x1]{R1}[y2]
		// 5') xxxG            Axxxh
		//        |            |    h
		// 3') xxxC            Uxxxh
		//         [x2]{R2}[y1]
		//
		// {h} and {x} are nucleotides that don't matter of which h represent the hairpin.
		//
		// G-C is the first pair (5' -> 3')
		// U-A is the second pair (5' -> 3')
		//
		// For this example you want to find the stacking panalties for forward: [G-C][x1][x2]
		// And the 'reverse' stack: [U-A][y1][y2]
		//
		// This is done in the following two lines:
		energy += this->get_tstacki(pairing1, this->sequence[arg_region.pair1.first + 1], this->sequence[arg_region.pair1.second - 1]);
		energy += this->get_tstacki(pairing2, this->sequence[arg_region.pair2.second + 1], this->sequence[arg_region.pair2.first - 1]); // watch out for 5' <-> 3' rotation: (jp + 1) and (ip - 1)
		
		// Asymetrical penalty
		energy += std::min(
					  this->get_miscloop(MISCLOOP_ASYMETRIC_INTENRAL_LOOP),
					  (
						  (float) abs(n_asym) * this->get_poppen(
							  std::min(
								  (unsigned int) this->thermodynamics.poppen_p.size(),
								  std::min(
									  l1,
									  l2
								  )
							  ) - 1
						  )
					  )
				  );
	}
	else
	{
		///@todo SWITCH(n_unpaired)
		
		
		// 5') [i] [i+1] [i']
		//      |         |
		// 3') [j] [j-1] [j']
		if(n_unpaired == 2 && n_asym == 0)
		{
			Nucleotide ni = this->sequence[arg_region.pair1.first];
			Nucleotide nj = this->sequence[arg_region.pair1.second];
			
			Nucleotide nip = this->sequence[arg_region.pair2.first];
			Nucleotide njp = this->sequence[arg_region.pair2.second];
			
			Pairing pairing1 = Pairing(ni, nj);
			Pairing pairing2 = Pairing(nip, njp);						///@todo double check this order in the .dat file
			
			
#if DEBUG
			if(pairing2.type == PairingType::None)
			{
				fprintf(stderr, "GibbsFreeEnergy::get_interior_loop_element - Requesting energy for interior loop enclosing with non canonical pairing [%i,%i].\n", arg_region.pair2.first, arg_region.pair2.second);
				energy += N_INFINITY;
			}
			else
			{
				energy += this->get_int11(pairing1.type, pairing2.type, this->sequence[arg_region.pair1.first + 1], this->sequence[arg_region.pair1.second - 1]);
			}
#else
			energy += this->get_int11(pairing1.type, pairing2.type, this->sequence[arg_region.pair1.first + 1], this->sequence[arg_region.pair1.second - 1]);
#endif //DEBUG
		}
		
		// 5') [i] [i+1]       [i']
		//      |               |
		// 3') [j] [j-1] [j-2] [j']
		else if(n_unpaired == 3 && n_asym == -1)
		{
			Nucleotide ni = this->sequence[arg_region.pair1.first];
			Nucleotide nj = this->sequence[arg_region.pair1.second];
			
			Nucleotide nip = this->sequence[arg_region.pair2.first];
			Nucleotide njp = this->sequence[arg_region.pair2.second];
			
			Pairing pairing1 = Pairing(ni, nj);
			Pairing pairing2 = Pairing(nip, njp);
			
			
			energy += this->get_int21(
						  pairing1.type,
						  pairing2.type,
						  this->sequence[arg_region.pair1.first + 1],
						  this->sequence[arg_region.pair1.second - 1],
						  this->sequence[arg_region.pair1.second - 2]);	// checked : correct
		}
		
		// The situation we encounter is:
		// 5') [i] [i+1] [i+2] [i'] ... (3'
		//      |               |
		// 3') [j] [j-1]       [j'] ... (5'
		//
		// If we rotate it 180 degrees, we get:
		//
		// 5') [j']       [j-1] [j] (3'
		//      |                |
		// 3') [i'] [i+2] [i+1] [i] (5'
		//
		// And we can make use of the same energy vector
		else if(n_unpaired == 3 && n_asym == 1)
		{
			Nucleotide ni = this->sequence[arg_region.pair1.first];
			Nucleotide nj = this->sequence[arg_region.pair1.second];
			
			Nucleotide nip = this->sequence[arg_region.pair2.first];
			Nucleotide njp = this->sequence[arg_region.pair2.second];
			
			Pairing pairing1 = Pairing(njp, nip);						// Rotated
			Pairing pairing2 = Pairing(nj,  ni);						// Rotated
			
			energy += this->thermodynamics.int21
					  [pairing1.type]
					  [pairing2.type]
					  [this->sequence[arg_region.pair2.second + 1]]
					  [this->sequence[arg_region.pair2.first - 1]]
					  [this->sequence[arg_region.pair2.first - 2]];
		}
		
		// 5') [i] [i+1] [i+2] [i'] (3'
		//      |               |
		// 3') [j] [j-1] [j-2] [j'] (5'
		else if(n_unpaired == 4 && n_asym == 0)//@todo figure out whether n_asym must be checked - if it would be 2, it would be a bulge loop and shouldn't reach this point. Also, the first if statement contains "|| abs(n_asym) > 1" which is always true if n_unpaired == 4 and n_asym != 0
		{
			Nucleotide ni = this->sequence[arg_region.pair1.first];
			Nucleotide nj = this->sequence[arg_region.pair1.second];
			
			Nucleotide nip = this->sequence[arg_region.pair2.first];
			Nucleotide njp = this->sequence[arg_region.pair2.second];
			
			Pairing pairing1 = Pairing(ni, nj);
			Pairing pairing2 = Pairing(nip, njp);
			
			energy += this->thermodynamics.int22
					  [pairing1.type]
					  [pairing2.type]
					  [this->sequence[arg_region.pair1.first + 1]]
					  [this->sequence[arg_region.pair1.second - 1]]
					  [this->sequence[arg_region.pair1.first + 2]]
					  [this->sequence[arg_region.pair1.second - 2]];
		}
		else//@todo figure out when this should happen - probably never << probably when very small loops are requested
		{
			energy = N_INFINITY;
		}
	}
	
	return energy;
}