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 #ifndef PRIVATE_JOIN_AND_COMPUTE_CRYPTO_EC_GROUP_H_ 17 #define PRIVATE_JOIN_AND_COMPUTE_CRYPTO_EC_GROUP_H_ 18 19 #include <memory> 20 #include <string> 21 22 #include "absl/strings/string_view.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 30 class ECPoint; 31 32 // Wrapper class for openssl EC_GROUP. 33 class ECGroup { 34 public: 35 // Deletes a EC_GROUP. 36 class ECGroupDeleter { 37 public: operator()38 void operator()(EC_GROUP* group) { EC_GROUP_free(group); } 39 }; 40 typedef std::unique_ptr<EC_GROUP, ECGroupDeleter> ECGroupPtr; 41 42 // Constructs a new ECGroup object for the given named curve id. 43 // See openssl header obj_mac.h for the available built-in curves. 44 // Use a well-known prime curve such as NID_X9_62_prime256v1 recommended by 45 // NIST. Returns INTERNAL error code if there is a failure in crypto 46 // operations. Security: this function is secure only for prime order curves. 47 // (All supported curves in BoringSSL have prime order.) 48 static StatusOr<ECGroup> Create(int curve_id, Context* context); 49 50 // Generates a new private key. The private key is a cryptographically strong 51 // pseudo-random number in the range (0, order). 52 BigNum GeneratePrivateKey() const; 53 54 // Verifies that the random key is a valid number in the range (0, order). 55 // Returns Status::OK if the key is valid, otherwise returns INVALID_ARGUMENT. 56 Status CheckPrivateKey(const BigNum& priv_key) const; 57 58 // Hashes m to a point on the elliptic curve y^2 = x^3 + ax + b over a 59 // prime field using SHA256 with "try-and-increment" method. 60 // See https://crypto.stanford.edu/~dabo/papers/bfibe.pdf, Section 5.2. 61 // Returns an INVALID_ARGUMENT error code if an error occurs. 62 // 63 // Security: The number of operations required to hash a string depends on the 64 // string, which could lead to a timing attack. 65 // Security: This function is only secure for curves of prime order. 66 StatusOr<ECPoint> GetPointByHashingToCurveSha256(absl::string_view m) const; 67 StatusOr<ECPoint> GetPointByHashingToCurveSha384(absl::string_view m) const; 68 StatusOr<ECPoint> GetPointByHashingToCurveSha512(absl::string_view m) const; 69 StatusOr<ECPoint> GetPointByHashingToCurveSswuRo(absl::string_view m, 70 absl::string_view dst) const; 71 72 // Returns y^2 for the given x. The returned value is computed as x^3 + ax + b 73 // mod p, where a and b are the parameters of the curve. 74 BigNum ComputeYSquare(const BigNum& x) const; 75 76 // Returns a fixed generator for this group. 77 // Returns an INTERNAL error code if it fails. 78 StatusOr<ECPoint> GetFixedGenerator() const; 79 80 // Returns a random generator for this group. 81 // Returns an INTERNAL error code if it fails. 82 StatusOr<ECPoint> GetRandomGenerator() const; 83 84 // Creates an ECPoint from the given string. 85 // Returns an INTERNAL error code if creating the point fails. 86 // Returns an INVALID_ARGUMENT error code if the created point is not in this 87 // group or if it is the point at infinity. 88 StatusOr<ECPoint> CreateECPoint(absl::string_view bytes) const; 89 90 // The parameters describing an elliptic curve given by the equation 91 // y^2 = x^3 + a * x + b over a prime field Fp. 92 struct CurveParams { 93 BigNum p; 94 BigNum a; 95 BigNum b; 96 }; 97 98 // Returns the order. GetOrder()99 const BigNum& GetOrder() const { return order_; } 100 101 // Returns the cofactor. GetCofactor()102 const BigNum& GetCofactor() const { return cofactor_; } 103 104 // Returns the curve id. GetCurveId()105 int GetCurveId() const { return EC_GROUP_get_curve_name(group_.get()); } 106 107 // Creates an ECPoint which is the identity. 108 StatusOr<ECPoint> GetPointAtInfinity() const; 109 110 private: 111 ECGroup(Context* context, ECGroupPtr group, BigNum order, BigNum cofactor, 112 CurveParams curve_params, BigNum p_minus_one_over_two); 113 114 // Creates an ECPoint object with the given x, y affine coordinates. 115 // Returns an INVALID_ARGUMENT error code if the point (x, y) is not in this 116 // group or if it is the point at infinity. 117 StatusOr<ECPoint> CreateECPoint(const BigNum& x, const BigNum& y) const; 118 119 // Returns true if q is a quadratic residue modulo curve_params_.p_. 120 bool IsSquare(const BigNum& q) const; 121 122 // Checks if the given point is valid. Returns false if the point is not in 123 // the group or if it is the point is at infinity. 124 bool IsValid(const ECPoint& point) const; 125 126 // Returns true if the given point is in the group. 127 bool IsOnCurve(const ECPoint& point) const; 128 129 // Returns true if the given point is at infinity. 130 bool IsAtInfinity(const ECPoint& point) const; 131 132 Context* context_; 133 ECGroupPtr group_; 134 // The order of this group. 135 BigNum order_; 136 // The cofactor of this group. 137 BigNum cofactor_; 138 // The parameters of the curve. These values are used to hash a number to a 139 // point on the curve. 140 CurveParams curve_params_; 141 // Constant used to evaluate if a number is a quadratic residue. 142 BigNum p_minus_one_over_two_; 143 144 StatusOr<ECPoint> GetPointByHashingToCurveInternal(const BigNum& x) const; 145 }; 146 147 } // namespace private_join_and_compute 148 149 #endif // PRIVATE_JOIN_AND_COMPUTE_CRYPTO_EC_GROUP_H_ 150