1 /*
2 * Copyright 2019 Google LLC.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "private_join_and_compute/crypto/ec_point.h"
17
18 #include <string>
19 #include <utility>
20 #include <vector>
21
22 #include "absl/strings/str_cat.h"
23 #include "private_join_and_compute/crypto/big_num.h"
24 #include "private_join_and_compute/crypto/context.h"
25 #include "private_join_and_compute/crypto/openssl.inc"
26 #include "private_join_and_compute/util/status.inc"
27
28 namespace private_join_and_compute {
29
ECPoint(const EC_GROUP * group,BN_CTX * bn_ctx)30 ECPoint::ECPoint(const EC_GROUP* group, BN_CTX* bn_ctx)
31 : bn_ctx_(bn_ctx), group_(group) {
32 point_ = ECPointPtr(EC_POINT_new(group_));
33 }
34
ECPoint(const EC_GROUP * group,BN_CTX * bn_ctx,const BigNum & x,const BigNum & y)35 ECPoint::ECPoint(const EC_GROUP* group, BN_CTX* bn_ctx, const BigNum& x,
36 const BigNum& y)
37 : ECPoint::ECPoint(group, bn_ctx) {
38 CRYPTO_CHECK(1 == EC_POINT_set_affine_coordinates_GFp(
39 group_, point_.get(), x.GetConstBignumPtr(),
40 y.GetConstBignumPtr(), bn_ctx_));
41 }
42
ECPoint(const EC_GROUP * group,BN_CTX * bn_ctx,ECPointPtr point)43 ECPoint::ECPoint(const EC_GROUP* group, BN_CTX* bn_ctx, ECPointPtr point)
44 : ECPoint::ECPoint(group, bn_ctx) {
45 point_ = std::move(point);
46 }
47
ToBytesCompressed() const48 StatusOr<std::string> ECPoint::ToBytesCompressed() const {
49 int length = EC_POINT_point2oct(
50 group_, point_.get(), POINT_CONVERSION_COMPRESSED, nullptr, 0, bn_ctx_);
51 std::vector<unsigned char> bytes(length);
52 if (0 == EC_POINT_point2oct(group_, point_.get(), POINT_CONVERSION_COMPRESSED,
53 bytes.data(), length, bn_ctx_)) {
54 return InternalError(
55 absl::StrCat("EC_POINT_point2oct failed:", OpenSSLErrorString()));
56 }
57 return std::string(reinterpret_cast<char*>(bytes.data()), bytes.size());
58 }
59
ToBytesUnCompressed() const60 StatusOr<std::string> ECPoint::ToBytesUnCompressed() const {
61 int length = EC_POINT_point2oct(
62 group_, point_.get(), POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, bn_ctx_);
63 std::vector<unsigned char> bytes(length);
64 if (0 == EC_POINT_point2oct(group_, point_.get(),
65 POINT_CONVERSION_UNCOMPRESSED, bytes.data(),
66 length, bn_ctx_)) {
67 return InternalError(
68 absl::StrCat("EC_POINT_point2oct failed:", OpenSSLErrorString()));
69 }
70 return std::string(reinterpret_cast<char*>(bytes.data()), bytes.size());
71 }
72
Mul(const BigNum & scalar) const73 StatusOr<ECPoint> ECPoint::Mul(const BigNum& scalar) const {
74 ECPoint r = ECPoint(group_, bn_ctx_);
75 if (1 != EC_POINT_mul(group_, r.point_.get(), nullptr, point_.get(),
76 scalar.GetConstBignumPtr(), bn_ctx_)) {
77 return InternalError(
78 absl::StrCat("EC_POINT_mul failed:", OpenSSLErrorString()));
79 }
80 return std::move(r);
81 }
82
Add(const ECPoint & point) const83 StatusOr<ECPoint> ECPoint::Add(const ECPoint& point) const {
84 ECPoint r = ECPoint(group_, bn_ctx_);
85 if (1 != EC_POINT_add(group_, r.point_.get(), point_.get(),
86 point.point_.get(), bn_ctx_)) {
87 return InternalError(
88 absl::StrCat("EC_POINT_add failed:", OpenSSLErrorString()));
89 }
90 return std::move(r);
91 }
92
Clone() const93 StatusOr<ECPoint> ECPoint::Clone() const {
94 ECPoint r = ECPoint(group_, bn_ctx_);
95 if (1 != EC_POINT_copy(r.point_.get(), point_.get())) {
96 return InternalError(
97 absl::StrCat("EC_POINT_copy failed:", OpenSSLErrorString()));
98 }
99 return std::move(r);
100 }
101
Inverse() const102 StatusOr<ECPoint> ECPoint::Inverse() const {
103 // Create a copy of this.
104 ASSIGN_OR_RETURN(ECPoint inv, Clone());
105 // Invert the copy in-place.
106 if (1 != EC_POINT_invert(group_, inv.point_.get(), bn_ctx_)) {
107 return InternalError(
108 absl::StrCat("EC_POINT_invert failed:", OpenSSLErrorString()));
109 }
110 return std::move(inv);
111 }
112
IsPointAtInfinity() const113 bool ECPoint::IsPointAtInfinity() const {
114 return EC_POINT_is_at_infinity(group_, point_.get());
115 }
116
CompareTo(const ECPoint & point) const117 bool ECPoint::CompareTo(const ECPoint& point) const {
118 return 0 == EC_POINT_cmp(group_, point_.get(), point.point_.get(), bn_ctx_);
119 }
120
121 } // namespace private_join_and_compute
122