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

Commit 087b1ecd authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by android-build-merger
Browse files

Merge "Eliptic Curve Cryptography for GD"

am: 7afea26f

Change-Id: I80ae2e38c782c96b37cc9603cd5eb7f4da71a239
parents 60a22150 7afea26f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ cc_library {
        ":BluetoothHalSources",
        ":BluetoothHciSources",
        ":BluetoothPacketSources",
        ":BluetoothSmpSources",
    ],
    generated_headers: [
        "BluetoothGeneratedPackets_h",
@@ -245,6 +246,7 @@ cc_test {
        ":BluetoothHciTestSources",
        ":BluetoothL2capTestSources",
        ":BluetoothPacketTestSources",
        ":BluetoothSmpTestSources",
    ],
    generated_headers : [
        "BluetoothGeneratedPackets_h",
+15 −0
Original line number Diff line number Diff line
filegroup {
    name: "BluetoothSmpSources",
    srcs: [
        "ecc/p_256_curvepara.cc",
        "ecc/p_256_multprecision.cc",
        "ecc/p_256_ecc_pp.cc",
    ]
}

filegroup {
    name: "BluetoothSmpTestSources",
    srcs: [
        "ecc/multipoint_test.cc",
    ]
}
 No newline at end of file
+112 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *
 *  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.
 *
 ******************************************************************************/

#include <gtest/gtest.h>

#include "smp/ecc/p_256_ecc_pp.h"

namespace bluetooth {
namespace smp {
namespace ecc {

// Test ECC point validation
TEST(SmpEccValidationTest, test_valid_points) {
  Point p;

  // Test data from Bluetooth Core Specification
  // Version 5.0 | Vol 2, Part G | 7.1.2

  // Sample 1
  p.x[7] = 0x20b003d2;
  p.x[6] = 0xf297be2c;
  p.x[5] = 0x5e2c83a7;
  p.x[4] = 0xe9f9a5b9;
  p.x[3] = 0xeff49111;
  p.x[2] = 0xacf4fddb;
  p.x[1] = 0xcc030148;
  p.x[0] = 0x0e359de6;

  p.y[7] = 0xdc809c49;
  p.y[6] = 0x652aeb6d;
  p.y[5] = 0x63329abf;
  p.y[4] = 0x5a52155c;
  p.y[3] = 0x766345c2;
  p.y[2] = 0x8fed3024;
  p.y[1] = 0x741c8ed0;
  p.y[0] = 0x1589d28b;

  EXPECT_TRUE(ECC_ValidatePoint(p));

  // Sample 2
  p.x[7] = 0x2c31a47b;
  p.x[6] = 0x5779809e;
  p.x[5] = 0xf44cb5ea;
  p.x[4] = 0xaf5c3e43;
  p.x[3] = 0xd5f8faad;
  p.x[2] = 0x4a8794cb;
  p.x[1] = 0x987e9b03;
  p.x[0] = 0x745c78dd;

  p.y[7] = 0x91951218;
  p.y[6] = 0x3898dfbe;
  p.y[5] = 0xcd52e240;
  p.y[4] = 0x8e43871f;
  p.y[3] = 0xd0211091;
  p.y[2] = 0x17bd3ed4;
  p.y[1] = 0xeaf84377;
  p.y[0] = 0x43715d4f;

  EXPECT_TRUE(ECC_ValidatePoint(p));
}

TEST(SmpEccValidationTest, test_invalid_points) {
  Point p;
  multiprecision_init(p.x);
  multiprecision_init(p.y);

  EXPECT_FALSE(ECC_ValidatePoint(p));

  // Sample 1
  p.x[7] = 0x20b003d2;
  p.x[6] = 0xf297be2c;
  p.x[5] = 0x5e2c83a7;
  p.x[4] = 0xe9f9a5b9;
  p.x[3] = 0xeff49111;
  p.x[2] = 0xacf4fddb;
  p.x[1] = 0xcc030148;
  p.x[0] = 0x0e359de6;

  EXPECT_FALSE(ECC_ValidatePoint(p));

  p.y[7] = 0xdc809c49;
  p.y[6] = 0x652aeb6d;
  p.y[5] = 0x63329abf;
  p.y[4] = 0x5a52155c;
  p.y[3] = 0x766345c2;
  p.y[2] = 0x8fed3024;
  p.y[1] = 0x741c8ed0;
  p.y[0] = 0x1589d28b;

  p.y[0]--;

  EXPECT_FALSE(ECC_ValidatePoint(p));
}

}  // namespace ecc
}  // namespace smp
}  // namespace bluetooth
+82 −0
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
+272 −0
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 using Elliptic Curve
 *  Cryptography for private public key
 *
 ******************************************************************************/
#include "smp/ecc/p_256_ecc_pp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "smp/ecc/p_256_multprecision.h"

namespace bluetooth {
namespace smp {
namespace ecc {

elliptic_curve_t curve;
elliptic_curve_t curve_p256;

static void p_256_init_point(Point* q) {
  memset(q, 0, sizeof(Point));
}

static void p_256_copy_point(Point* q, Point* p) {
  memcpy(q, p, sizeof(Point));
}

// q=2q
static void ECC_Double(Point* q, Point* p) {
  uint32_t t1[KEY_LENGTH_DWORDS_P256];
  uint32_t t2[KEY_LENGTH_DWORDS_P256];
  uint32_t t3[KEY_LENGTH_DWORDS_P256];
  uint32_t* x1;
  uint32_t* x3;
  uint32_t* y1;
  uint32_t* y3;
  uint32_t* z1;
  uint32_t* z3;

  if (multiprecision_iszero(p->z)) {
    multiprecision_init(q->z);
    return;  // return infinity
  }

  x1 = p->x;
  y1 = p->y;
  z1 = p->z;
  x3 = q->x;
  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
}

// q=q+p,     zp must be 1
static void ECC_Add(Point* r, Point* p, Point* q) {
  uint32_t t1[KEY_LENGTH_DWORDS_P256];
  uint32_t t2[KEY_LENGTH_DWORDS_P256];
  uint32_t* x1;
  uint32_t* x2;
  uint32_t* x3;
  uint32_t* y1;
  uint32_t* y2;
  uint32_t* y3;
  uint32_t* z1;
  uint32_t* z2;
  uint32_t* z3;

  x1 = p->x;
  y1 = p->y;
  z1 = p->z;
  x2 = q->x;
  y2 = q->y;
  z2 = q->z;
  x3 = r->x;
  y3 = r->y;
  z3 = r->z;

  // if Q=infinity, return p
  if (multiprecision_iszero(z2)) {
    p_256_copy_point(r, p);
    return;
  }

  // if P=infinity, return q
  if (multiprecision_iszero(z1)) {
    p_256_copy_point(r, 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_sub_mod(t1, t1, x1);  // t1=t1-x1
  multiprecision_sub_mod(t2, t2, y1);  // t2=t2-y1

  if (multiprecision_iszero(t1)) {
    if (multiprecision_iszero(t2)) {
      ECC_Double(r, q);
      return;
    } else {
      multiprecision_init(z3);
      return;  // return infinity
    }
  }

  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);
}

// Computing the Non-Adjacent Form of a positive integer
static void ECC_NAF(uint8_t* naf, uint32_t* NumNAF, uint32_t* k) {
  uint32_t sign;
  int i = 0;
  int j;
  uint32_t var;

  while ((var = multiprecision_most_signbits(k)) >= 1) {
    if (k[0] & 0x01)  // k is odd
    {
      sign = (k[0] & 0x03);  // 1 or 3

      // k = k-naf[i]
      if (sign == 1)
        k[0] = k[0] & 0xFFFFFFFE;
      else {
        k[0] = k[0] + 1;
        if (k[0] == 0)  // overflow
        {
          j = 1;
          do {
            k[j]++;
          } while (k[j++] == 0);  // overflow
        }
      }
    } else
      sign = 0;

    multiprecision_rshift(k, k);
    naf[i / 4] |= (sign) << ((i % 4) * 2);
    i++;
  }

  *NumNAF = i;
}

// Binary Non-Adjacent Form for point multiplication
void ECC_PointMult_Bin_NAF(Point* q, Point* p, uint32_t* n) {
  uint32_t sign;
  uint8_t naf[256 / 4 + 1];
  uint32_t NumNaf;
  Point minus_p;
  Point r;
  uint32_t* modp;

  modp = curve_p256.p;

  p_256_init_point(&r);
  multiprecision_init(p->z);
  p->z[0] = 1;

  // initialization
  p_256_init_point(q);

  // -p
  multiprecision_copy(minus_p.x, p->x);
  multiprecision_sub(minus_p.y, modp, p->y);

  multiprecision_init(minus_p.z);
  minus_p.z[0] = 1;

  // NAF
  memset(naf, 0, sizeof(naf));
  ECC_NAF(naf, &NumNaf, n);

  for (int i = NumNaf - 1; i >= 0; i--) {
    p_256_copy_point(&r, q);
    ECC_Double(q, &r);
    sign = (naf[i / 4] >> ((i % 4) * 2)) & 0x03;

    if (sign == 1) {
      p_256_copy_point(&r, q);
      ECC_Add(q, &r, p);
    } else if (sign == 3) {
      p_256_copy_point(&r, q);
      ECC_Add(q, &r, &minus_p);
    }
  }

  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);
}

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);

  // Right hand side calculation
  uint32_t rhs[KEY_LENGTH_DWORDS_P256] = {0};
  multiprecision_mersenns_squa_mod(rhs, (uint32_t*)pt.x);
  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);

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

}  // namespace ecc
}  // namespace smp
}  // namespace bluetooth
 No newline at end of file
Loading