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

Commit 7afea26f authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Gerrit Code Review
Browse files

Merge "Eliptic Curve Cryptography for GD"

parents e26a8166 2007edf7
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