Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7200ee0d authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

GD SMP ECC improvements part 1

* make curve parameters into constants
* separate multipoint from BT specific ECC curve

Test: SmpEccValidationTest
Bug: 126463795
Change-Id: If6401c3038b340926310eafb40c2b7c5dc40dba9
parent 7afea26f
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
filegroup {
    name: "BluetoothSmpSources",
    srcs: [
        "ecc/p_256_curvepara.cc",
        "ecc/p_256_multprecision.cc",
        "ecc/multprecision.cc",
        "ecc/p_256_ecc_pp.cc",
    ]
}
+23 −29
Original line number Diff line number Diff line
@@ -22,23 +22,26 @@
 *
 ******************************************************************************/

#include "smp/ecc/p_256_multprecision.h"
#include "smp/ecc/multprecision.h"
#include <string.h>
#include "smp/ecc/p_256_ecc_pp.h"

namespace bluetooth {
namespace smp {
namespace ecc {

#define DWORD_BITS 32
#define DWORD_BYTES 4
#define DWORD_BITS_SHIFT 5

void multiprecision_init(uint32_t* c) {
  for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) c[i] = 0;
}

void multiprecision_copy(uint32_t* c, uint32_t* a) {
void multiprecision_copy(uint32_t* c, const uint32_t* a) {
  for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++) c[i] = a[i];
}

int multiprecision_compare(uint32_t* a, uint32_t* b) {
int multiprecision_compare(const uint32_t* a, const uint32_t* b) {
  for (int i = KEY_LENGTH_DWORDS_P256 - 1; i >= 0; i--) {
    if (a[i] > b[i]) return 1;
    if (a[i] < b[i]) return -1;
@@ -46,7 +49,7 @@ int multiprecision_compare(uint32_t* a, uint32_t* b) {
  return 0;
}

int multiprecision_iszero(uint32_t* a) {
int multiprecision_iszero(const uint32_t* a) {
  for (uint32_t i = 0; i < KEY_LENGTH_DWORDS_P256; i++)
    if (a[i]) return 0;

@@ -77,7 +80,7 @@ uint32_t multiprecision_most_signbits(uint32_t* a) {
  return (((aMostSignDWORDs - 1) << DWORD_BITS_SHIFT) + multiprecision_dword_bits(a[aMostSignDWORDs - 1]));
}

uint32_t multiprecision_add(uint32_t* c, uint32_t* a, uint32_t* b) {
uint32_t multiprecision_add(uint32_t* c, const uint32_t* a, const uint32_t* b) {
  uint32_t carrier;
  uint32_t temp;

@@ -94,7 +97,7 @@ uint32_t multiprecision_add(uint32_t* c, uint32_t* a, uint32_t* b) {
}

// c=a-b
uint32_t multiprecision_sub(uint32_t* c, uint32_t* a, uint32_t* b) {
uint32_t multiprecision_sub(uint32_t* c, const uint32_t* a, const uint32_t* b) {
  uint32_t borrow;
  uint32_t temp;

@@ -110,11 +113,8 @@ uint32_t multiprecision_sub(uint32_t* c, uint32_t* a, uint32_t* b) {
}

// c = a << 1
void multiprecision_lshift_mod(uint32_t* c, uint32_t* a) {
  uint32_t carrier;
  uint32_t* modp = curve_p256.p;

  carrier = multiprecision_lshift(c, a);
void multiprecision_lshift_mod(uint32_t* c, uint32_t* a, const uint32_t* modp) {
  uint32_t carrier = multiprecision_lshift(c, a);
  if (carrier) {
    multiprecision_sub(c, c, modp);
  } else if (multiprecision_compare(c, modp) >= 0) {
@@ -140,24 +140,21 @@ void multiprecision_rshift(uint32_t* c, uint32_t* a) {

// Curve specific optimization when p is a pseudo-Mersenns prime,
// p=2^(KEY_LENGTH_BITS)-omega
void multiprecision_mersenns_mult_mod(uint32_t* c, uint32_t* a, uint32_t* b) {
void multiprecision_mersenns_mult_mod(uint32_t* c, uint32_t* a, uint32_t* b, const uint32_t* modp) {
  uint32_t cc[2 * KEY_LENGTH_DWORDS_P256];

  multiprecision_mult(cc, a, b);
  multiprecision_fast_mod_P256(c, cc);
  multiprecision_fast_mod_P256(c, cc, modp);
}

// Curve specific optimization when p is a pseudo-Mersenns prime
void multiprecision_mersenns_squa_mod(uint32_t* c, uint32_t* a) {
  multiprecision_mersenns_mult_mod(c, a, a);
void multiprecision_mersenns_squa_mod(uint32_t* c, uint32_t* a, const uint32_t* modp) {
  multiprecision_mersenns_mult_mod(c, a, a, modp);
}

// c=(a+b) mod p, b<p, a<p
void multiprecision_add_mod(uint32_t* c, uint32_t* a, uint32_t* b) {
  uint32_t carrier;
  uint32_t* modp = curve_p256.p;

  carrier = multiprecision_add(c, a, b);
void multiprecision_add_mod(uint32_t* c, const uint32_t* a, const uint32_t* b, const uint32_t* modp) {
  uint32_t carrier = multiprecision_add(c, a, b);
  if (carrier) {
    multiprecision_sub(c, c, modp);
  } else if (multiprecision_compare(c, modp) >= 0) {
@@ -166,9 +163,8 @@ void multiprecision_add_mod(uint32_t* c, uint32_t* a, uint32_t* b) {
}

// c=(a-b) mod p, a<p, b<p
void multiprecision_sub_mod(uint32_t* c, uint32_t* a, uint32_t* b) {
void multiprecision_sub_mod(uint32_t* c, uint32_t* a, uint32_t* b, const uint32_t* modp) {
  uint32_t borrow;
  uint32_t* modp = curve_p256.p;

  borrow = multiprecision_sub(c, a, b);
  if (borrow) multiprecision_add(c, c, modp);
@@ -220,7 +216,7 @@ void multiprecision_mult(uint32_t* c, uint32_t* a, uint32_t* b) {
  }
}

void multiprecision_fast_mod_P256(uint32_t* c, uint32_t* a) {
void multiprecision_fast_mod_P256(uint32_t* c, uint32_t* a, const uint32_t* modp) {
  uint32_t A;
  uint32_t B;
  uint32_t C;
@@ -236,7 +232,6 @@ void multiprecision_fast_mod_P256(uint32_t* c, uint32_t* a) {
  uint8_t UF;
  uint8_t UG;
  uint32_t U;
  uint32_t* modp = curve_p256.p;

  // C = a[13] + a[14] + a[15];
  C = a[13];
@@ -453,11 +448,10 @@ void multiprecision_fast_mod_P256(uint32_t* c, uint32_t* a) {
  if (multiprecision_compare(c, modp) >= 0) multiprecision_sub(c, c, modp);
}

void multiprecision_inv_mod(uint32_t* aminus, uint32_t* u) {
void multiprecision_inv_mod(uint32_t* aminus, uint32_t* u, const uint32_t* modp) {
  uint32_t v[KEY_LENGTH_DWORDS_P256];
  uint32_t A[KEY_LENGTH_DWORDS_P256 + 1];
  uint32_t C[KEY_LENGTH_DWORDS_P256 + 1];
  uint32_t* modp = curve_p256.p;

  multiprecision_copy(v, modp);
  multiprecision_init(A);
@@ -492,10 +486,10 @@ void multiprecision_inv_mod(uint32_t* aminus, uint32_t* u) {

    if (multiprecision_compare(u, v) >= 0) {
      multiprecision_sub(u, u, v);
      multiprecision_sub_mod(A, A, C);
      multiprecision_sub_mod(A, A, C, modp);
    } else {
      multiprecision_sub(v, v, u);
      multiprecision_sub_mod(C, C, A);
      multiprecision_sub_mod(C, C, A, modp);
    }
  }

+14 −21
Original line number Diff line number Diff line
@@ -29,37 +29,30 @@ namespace bluetooth {
namespace smp {
namespace ecc {

#define DWORD_BITS 32
#define DWORD_BYTES 4
#define DWORD_BITS_SHIFT 5

#define KEY_LENGTH_DWORDS_P256 8
/* Arithmetic Operations*/

int multiprecision_compare(uint32_t* a, uint32_t* b);
int multiprecision_iszero(uint32_t* a);
int multiprecision_compare(const uint32_t* a, const uint32_t* b);
int multiprecision_iszero(const uint32_t* a);
void multiprecision_init(uint32_t* c);
void multiprecision_copy(uint32_t* c, uint32_t* a);
void multiprecision_copy(uint32_t* c, const uint32_t* a);
uint32_t multiprecision_dword_bits(uint32_t a);
uint32_t multiprecision_most_signdwords(uint32_t* a);
uint32_t multiprecision_most_signbits(uint32_t* a);
void multiprecision_inv_mod(uint32_t* aminus, uint32_t* a);
uint32_t multiprecision_add(uint32_t* c, uint32_t* a, uint32_t* b);  // c=a+b
void multiprecision_add_mod(uint32_t* c, uint32_t* a, uint32_t* b);
uint32_t multiprecision_sub(uint32_t* c, uint32_t* a, uint32_t* b);  // c=a-b
void multiprecision_sub_mod(uint32_t* c, uint32_t* a, uint32_t* b);
void multiprecision_inv_mod(uint32_t* aminus, uint32_t* a, const uint32_t* modp);
uint32_t multiprecision_add(uint32_t* c, const uint32_t* a, const uint32_t* b);  // c=a+b
void multiprecision_add_mod(uint32_t* c, const uint32_t* a, const uint32_t* b, const uint32_t* modp);
uint32_t multiprecision_sub(uint32_t* c, const uint32_t* a, const uint32_t* b);  // c=a-b
void multiprecision_sub_mod(uint32_t* c, uint32_t* a, uint32_t* b, const uint32_t* modp);
void multiprecision_rshift(uint32_t* c, uint32_t* a);                            // c=a>>1, return carrier
void multiprecision_lshift_mod(uint32_t* c,
                               uint32_t* a);  // c=a<<b, return carrier
void multiprecision_lshift_mod(uint32_t* c, uint32_t* a, const uint32_t* modp);  // c=a<<b, return carrier
uint32_t multiprecision_lshift(uint32_t* c,
                               uint32_t* a);                      // c=a<<b, return carrier
void multiprecision_mult(uint32_t* c, uint32_t* a, uint32_t* b);  // c=a*b
void multiprecision_mersenns_mult_mod(uint32_t* c, uint32_t* a, uint32_t* b);
void multiprecision_mersenns_squa_mod(uint32_t* c, uint32_t* a);
void multiprecision_mersenns_mult_mod(uint32_t* c, uint32_t* a, uint32_t* b, const uint32_t* modp);
void multiprecision_mersenns_squa_mod(uint32_t* c, uint32_t* a, const uint32_t* modp);
uint32_t multiprecision_lshift(uint32_t* c, uint32_t* a);
void multiprecision_mult(uint32_t* c, uint32_t* a, uint32_t* b);
void multiprecision_fast_mod(uint32_t* c, uint32_t* a);
void multiprecision_fast_mod_P256(uint32_t* c, uint32_t* a);
void multiprecision_fast_mod_P256(uint32_t* c, uint32_t* a, const uint32_t* modp);

}  // namespace ecc
}  // namespace smp
+0 −82
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2006-2015 Broadcom Corporation
 *
 *  Licensed 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.
 *
 ******************************************************************************/

/*******************************************************************************
 *
 *  This file contains simple pairing algorithms
 *
 ******************************************************************************/

#include <string.h>

#include "smp/ecc/p_256_ecc_pp.h"

namespace bluetooth {
namespace smp {
namespace ecc {

void p_256_init_curve() {
  elliptic_curve_t* ec = &curve_p256;

  ec->p[7] = 0xFFFFFFFF;
  ec->p[6] = 0x00000001;
  ec->p[5] = 0x0;
  ec->p[4] = 0x0;
  ec->p[3] = 0x0;
  ec->p[2] = 0xFFFFFFFF;
  ec->p[1] = 0xFFFFFFFF;
  ec->p[0] = 0xFFFFFFFF;

  memset(ec->omega, 0, KEY_LENGTH_DWORDS_P256);
  memset(ec->a, 0, KEY_LENGTH_DWORDS_P256);

  ec->a_minus3 = true;

  // b
  ec->b[7] = 0x5ac635d8;
  ec->b[6] = 0xaa3a93e7;
  ec->b[5] = 0xb3ebbd55;
  ec->b[4] = 0x769886bc;
  ec->b[3] = 0x651d06b0;
  ec->b[2] = 0xcc53b0f6;
  ec->b[1] = 0x3bce3c3e;
  ec->b[0] = 0x27d2604b;

  // base point
  ec->G.x[7] = 0x6b17d1f2;
  ec->G.x[6] = 0xe12c4247;
  ec->G.x[5] = 0xf8bce6e5;
  ec->G.x[4] = 0x63a440f2;
  ec->G.x[3] = 0x77037d81;
  ec->G.x[2] = 0x2deb33a0;
  ec->G.x[1] = 0xf4a13945;
  ec->G.x[0] = 0xd898c296;

  ec->G.y[7] = 0x4fe342e2;
  ec->G.y[6] = 0xfe1a7f9b;
  ec->G.y[5] = 0x8ee7eb4a;
  ec->G.y[4] = 0x7c0f9e16;
  ec->G.y[3] = 0x2bce3357;
  ec->G.y[2] = 0x6b315ece;
  ec->G.y[1] = 0xcbb64068;
  ec->G.y[0] = 0x37bf51f5;
}

}  // namespace ecc
}  // namespace smp
}  // namespace bluetooth
 No newline at end of file
+53 −59
Original line number Diff line number Diff line
@@ -26,14 +26,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "smp/ecc/p_256_multprecision.h"
#include "smp/ecc/multprecision.h"

namespace bluetooth {
namespace smp {
namespace ecc {

elliptic_curve_t curve;
elliptic_curve_t curve_p256;
const uint32_t* modp = curve_p256.p;

static void p_256_init_point(Point* q) {
  memset(q, 0, sizeof(Point));
@@ -67,29 +66,29 @@ static void ECC_Double(Point* q, Point* p) {
  y3 = q->y;
  z3 = q->z;

  multiprecision_mersenns_squa_mod(t1, z1);      // t1=z1^2
  multiprecision_sub_mod(t2, x1, t1);            // t2=x1-t1
  multiprecision_add_mod(t1, x1, t1);            // t1=x1+t1
  multiprecision_mersenns_mult_mod(t2, t1, t2);  // t2=t2*t1
  multiprecision_lshift_mod(t3, t2);
  multiprecision_add_mod(t2, t3, t2);  // t2=3t2

  multiprecision_mersenns_mult_mod(z3, y1, z1);  // z3=y1*z1
  multiprecision_lshift_mod(z3, z3);

  multiprecision_mersenns_squa_mod(y3, y1);  // y3=y1^2
  multiprecision_lshift_mod(y3, y3);
  multiprecision_mersenns_mult_mod(t3, y3, x1);  // t3=y3*x1=x1*y1^2
  multiprecision_lshift_mod(t3, t3);
  multiprecision_mersenns_squa_mod(y3, y3);  // y3=y3^2=y1^4
  multiprecision_lshift_mod(y3, y3);

  multiprecision_mersenns_squa_mod(x3, t2);      // x3=t2^2
  multiprecision_lshift_mod(t1, t3);             // t1=2t3
  multiprecision_sub_mod(x3, x3, t1);            // x3=x3-t1
  multiprecision_sub_mod(t1, t3, x3);            // t1=t3-x3
  multiprecision_mersenns_mult_mod(t1, t1, t2);  // t1=t1*t2
  multiprecision_sub_mod(y3, t1, y3);            // y3=t1-y3
  multiprecision_mersenns_squa_mod(t1, z1, modp);      // t1=z1^2
  multiprecision_sub_mod(t2, x1, t1, modp);            // t2=x1-t1
  multiprecision_add_mod(t1, x1, t1, modp);            // t1=x1+t1
  multiprecision_mersenns_mult_mod(t2, t1, t2, modp);  // t2=t2*t1
  multiprecision_lshift_mod(t3, t2, modp);
  multiprecision_add_mod(t2, t3, t2, modp);  // t2=3t2

  multiprecision_mersenns_mult_mod(z3, y1, z1, modp);  // z3=y1*z1
  multiprecision_lshift_mod(z3, z3, modp);

  multiprecision_mersenns_squa_mod(y3, y1, modp);  // y3=y1^2
  multiprecision_lshift_mod(y3, y3, modp);
  multiprecision_mersenns_mult_mod(t3, y3, x1, modp);  // t3=y3*x1=x1*y1^2
  multiprecision_lshift_mod(t3, t3, modp);
  multiprecision_mersenns_squa_mod(y3, y3, modp);  // y3=y3^2=y1^4
  multiprecision_lshift_mod(y3, y3, modp);

  multiprecision_mersenns_squa_mod(x3, t2, modp);      // x3=t2^2
  multiprecision_lshift_mod(t1, t3, modp);             // t1=2t3
  multiprecision_sub_mod(x3, x3, t1, modp);            // x3=x3-t1
  multiprecision_sub_mod(t1, t3, x3, modp);            // t1=t3-x3
  multiprecision_mersenns_mult_mod(t1, t1, t2, modp);  // t1=t1*t2
  multiprecision_sub_mod(y3, t1, y3, modp);            // y3=t1-y3
}

// q=q+p,     zp must be 1
@@ -128,13 +127,13 @@ static void ECC_Add(Point* r, Point* p, Point* q) {
    return;
  }

  multiprecision_mersenns_squa_mod(t1, z1);      // t1=z1^2
  multiprecision_mersenns_mult_mod(t2, z1, t1);  // t2=t1*z1
  multiprecision_mersenns_mult_mod(t1, x2, t1);  // t1=t1*x2
  multiprecision_mersenns_mult_mod(t2, y2, t2);  // t2=t2*y2
  multiprecision_mersenns_squa_mod(t1, z1, modp);      // t1=z1^2
  multiprecision_mersenns_mult_mod(t2, z1, t1, modp);  // t2=t1*z1
  multiprecision_mersenns_mult_mod(t1, x2, t1, modp);  // t1=t1*x2
  multiprecision_mersenns_mult_mod(t2, y2, t2, modp);  // t2=t2*y2

  multiprecision_sub_mod(t1, t1, x1);  // t1=t1-x1
  multiprecision_sub_mod(t2, t2, y1);  // t2=t2-y1
  multiprecision_sub_mod(t1, t1, x1, modp);  // t1=t1-x1
  multiprecision_sub_mod(t2, t2, y1, modp);  // t2=t2-y1

  if (multiprecision_iszero(t1)) {
    if (multiprecision_iszero(t2)) {
@@ -146,18 +145,18 @@ static void ECC_Add(Point* r, Point* p, Point* q) {
    }
  }

  multiprecision_mersenns_mult_mod(z3, z1, t1);  // z3=z1*t1
  multiprecision_mersenns_squa_mod(y3, t1);      // t3=t1^2
  multiprecision_mersenns_mult_mod(z1, y3, t1);  // t4=t3*t1
  multiprecision_mersenns_mult_mod(y3, y3, x1);  // t3=t3*x1
  multiprecision_lshift_mod(t1, y3);             // t1=2*t3
  multiprecision_mersenns_squa_mod(x3, t2);      // x3=t2^2
  multiprecision_sub_mod(x3, x3, t1);            // x3=x3-t1
  multiprecision_sub_mod(x3, x3, z1);            // x3=x3-t4
  multiprecision_sub_mod(y3, y3, x3);            // t3=t3-x3
  multiprecision_mersenns_mult_mod(y3, y3, t2);  // t3=t3*t2
  multiprecision_mersenns_mult_mod(z1, z1, y1);  // t4=t4*t1
  multiprecision_sub_mod(y3, y3, z1);
  multiprecision_mersenns_mult_mod(z3, z1, t1, modp);  // z3=z1*t1
  multiprecision_mersenns_squa_mod(y3, t1, modp);      // t3=t1^2
  multiprecision_mersenns_mult_mod(z1, y3, t1, modp);  // t4=t3*t1
  multiprecision_mersenns_mult_mod(y3, y3, x1, modp);  // t3=t3*x1
  multiprecision_lshift_mod(t1, y3, modp);             // t1=2*t3
  multiprecision_mersenns_squa_mod(x3, t2, modp);      // x3=t2^2
  multiprecision_sub_mod(x3, x3, t1, modp);            // x3=x3-t1
  multiprecision_sub_mod(x3, x3, z1, modp);            // x3=x3-t4
  multiprecision_sub_mod(y3, y3, x3, modp);            // t3=t3-x3
  multiprecision_mersenns_mult_mod(y3, y3, t2, modp);  // t3=t3*t2
  multiprecision_mersenns_mult_mod(z1, z1, y1, modp);  // t4=t4*t1
  multiprecision_sub_mod(y3, y3, z1, modp);
}

// Computing the Non-Adjacent Form of a positive integer
@@ -203,9 +202,6 @@ void ECC_PointMult_Bin_NAF(Point* q, Point* p, uint32_t* n) {
  uint32_t NumNaf;
  Point minus_p;
  Point r;
  uint32_t* modp;

  modp = curve_p256.p;

  p_256_init_point(&r);
  multiprecision_init(p->z);
@@ -239,30 +235,28 @@ void ECC_PointMult_Bin_NAF(Point* q, Point* p, uint32_t* n) {
    }
  }

  multiprecision_inv_mod(minus_p.x, q->z);
  multiprecision_mersenns_squa_mod(q->z, minus_p.x);
  multiprecision_mersenns_mult_mod(q->x, q->x, q->z);
  multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x);
  multiprecision_mersenns_mult_mod(q->y, q->y, q->z);
  multiprecision_inv_mod(minus_p.x, q->z, modp);
  multiprecision_mersenns_squa_mod(q->z, minus_p.x, modp);
  multiprecision_mersenns_mult_mod(q->x, q->x, q->z, modp);
  multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, modp);
  multiprecision_mersenns_mult_mod(q->y, q->y, q->z, modp);
}

bool ECC_ValidatePoint(const Point& pt) {
  p_256_init_curve();

  // Ensure y^2 = x^3 + a*x + b (mod p); a = -3

  // y^2 mod p
  uint32_t y2_mod[KEY_LENGTH_DWORDS_P256] = {0};
  multiprecision_mersenns_squa_mod(y2_mod, (uint32_t*)pt.y);
  multiprecision_mersenns_squa_mod(y2_mod, (uint32_t*)pt.y, modp);

  // Right hand side calculation
  uint32_t rhs[KEY_LENGTH_DWORDS_P256] = {0};
  multiprecision_mersenns_squa_mod(rhs, (uint32_t*)pt.x);
  multiprecision_mersenns_squa_mod(rhs, (uint32_t*)pt.x, modp);
  uint32_t three[KEY_LENGTH_DWORDS_P256] = {0};
  three[0] = 3;
  multiprecision_sub_mod(rhs, rhs, three);
  multiprecision_mersenns_mult_mod(rhs, rhs, (uint32_t*)pt.x);
  multiprecision_add_mod(rhs, rhs, curve_p256.b);
  multiprecision_sub_mod(rhs, rhs, three, modp);
  multiprecision_mersenns_mult_mod(rhs, rhs, (uint32_t*)pt.x, modp);
  multiprecision_add_mod(rhs, rhs, curve_p256.b, modp);

  return multiprecision_compare(rhs, y2_mod) == 0;
}
Loading