Exemple #1
0
def point_add(curve: Curve, point1, point2):
    op_sum = _point_new(curve.ec_group)
    with tmp_bn_ctx() as bn_ctx:
        res = BACKEND_LIB.EC_POINT_add(curve.ec_group, op_sum, point1, point2,
                                       bn_ctx)
        backend.openssl_assert(res == 1)
    return op_sum
Exemple #2
0
    def gen_rand(cls, curve: ec.EllipticCurve = None):
        """
        Returns a BigNum object with a cryptographically secure BigNum based
        on the given curve.
        """
        curve = curve if curve is not None else default_curve()
        curve_nid = backend._elliptic_curve_to_nid(curve)

        group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid)
        backend.openssl_assert(group != backend._ffi.NULL)

        order = backend._lib.BN_new()
        backend.openssl_assert(order != backend._ffi.NULL)
        order = backend._ffi.gc(order, backend._lib.BN_clear_free)

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx)
            backend.openssl_assert(res == 1)

        new_rand_bn = backend._lib.BN_new()
        backend.openssl_assert(new_rand_bn != backend._ffi.NULL)
        new_rand_bn = backend._ffi.gc(new_rand_bn, backend._lib.BN_clear_free)

        rand_res = backend._lib.BN_rand_range(new_rand_bn, order)
        backend.openssl_assert(rand_res == 1)

        return cls(new_rand_bn, curve_nid, group, order)
Exemple #3
0
def point_mul_bn(curve: Curve, point, bn):
    prod = _point_new(curve.ec_group)
    with tmp_bn_ctx() as bn_ctx:
        res = BACKEND_LIB.EC_POINT_mul(curve.ec_group, prod, BACKEND_FFI.NULL,
                                       point, bn, bn_ctx)
        backend.openssl_assert(res == 1)
    return prod
Exemple #4
0
def BN_MOD_INVERSE(priv_a) -> _EllipticCurvePrivateKey:
    """
    Performs an OpenSSL BN_mod_inverse on an EllipticCurvePrivateKey and
    returns the result in an EllipticCurvePrivateKey.
    """
    group = backend._lib.EC_KEY_get0_group(priv_a._ec_key)
    backend.openssl_assert(group != backend._ffi.NULL)

    prv_a = backend._lib.EC_KEY_get0_private_key(priv_a._ec_key)
    backend.openssl_assert(prv_a != backend._ffi.NULL)

    order = backend._lib.BN_new()
    backend.openssl_assert(order != backend._ffi.NULL)
    order = backend._ffi.gc(order, backend._lib.BN_free)

    with backend._tmp_bn_ctx() as bn_ctx:
        res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx)
        backend.openssl_assert(res == 1)

        inv = backend._lib.BN_mod_inverse(backend._ffi.NULL, prv_a, order,
                                          bn_ctx)
        backend.openssl_assert(inv != backend._ffi.NULL)
        inv = backend._ffi.gc(inv, backend._lib.BN_free)

    return _bignum_to_private_key(backend, group, inv)
Exemple #5
0
def point_eq(curve: Curve, point1, point2):
    with tmp_bn_ctx() as bn_ctx:
        is_equal = BACKEND_LIB.EC_POINT_cmp(curve.ec_group, point1, point2,
                                            bn_ctx)
        backend.openssl_assert(is_equal != -1)

    # 1 is not-equal, 0 is equal, -1 is error
    return is_equal == 0
Exemple #6
0
 def _get_ec_group_by_curve_nid(nid: int):
     """
     Returns the group of a given curve via its OpenSSL nid. This must be freed
     after each use otherwise it leaks memory.
     """
     group = BACKEND_LIB.EC_GROUP_new_by_curve_name(nid)
     backend.openssl_assert(group != BACKEND_FFI.NULL)
     return group
Exemple #7
0
def _get_ec_group_by_curve_nid(curve_nid: int):
    """
    Returns the group of a given curve via its OpenSSL nid.
    """
    group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid)
    backend.openssl_assert(group != backend._ffi.NULL)

    return group
Exemple #8
0
def _get_ec_order_by_group(ec_group):
    """
    Returns the order of a given curve via its OpenSSL EC_GROUP.
    """
    ec_order = _get_new_BN()
    with backend._tmp_bn_ctx() as bn_ctx:
        res = backend._lib.EC_GROUP_get_order(ec_group, ec_order, bn_ctx)
        backend.openssl_assert(res == 1)
    return ec_order
Exemple #9
0
def _get_ec_generator_by_group(ec_group):
    """
    Returns the generator point of a given curve via its OpenSSL EC_GROUP.
    """
    generator = backend._lib.EC_GROUP_get0_generator(ec_group)
    backend.openssl_assert(generator != backend._ffi.NULL)
    generator = backend._ffi.gc(generator, backend._lib.EC_POINT_clear_free)

    return generator
Exemple #10
0
def point_neg(curve: Curve, point):
    inv = BACKEND_LIB.EC_POINT_dup(point, curve.ec_group)
    backend.openssl_assert(inv != BACKEND_FFI.NULL)
    inv = BACKEND_FFI.gc(inv, BACKEND_LIB.EC_POINT_clear_free)

    with tmp_bn_ctx() as bn_ctx:
        res = BACKEND_LIB.EC_POINT_invert(curve.ec_group, inv, bn_ctx)
        backend.openssl_assert(res == 1)

    return inv
Exemple #11
0
def _point_new(ec_group):
    """
    Returns a new and initialized OpenSSL EC_POINT given the group of a curve.
    If __curve_nid is provided, it retrieves the group from the curve provided.
    """
    new_point = BACKEND_LIB.EC_POINT_new(ec_group)
    backend.openssl_assert(new_point != BACKEND_FFI.NULL)
    new_point = BACKEND_FFI.gc(new_point, BACKEND_LIB.EC_POINT_clear_free)

    return new_point
Exemple #12
0
def _get_ec_generator_by_curve_nid(curve_nid: int):
    """
    Returns the generator point of a given curve via its OpenSSL nid.
    """
    ec_group = _get_ec_group_by_curve_nid(curve_nid)

    generator = backend._lib.EC_GROUP_get0_generator(ec_group)
    backend.openssl_assert(generator != backend._ffi.NULL)

    return generator
Exemple #13
0
 def __add__(self, other):
     """
     Performs an EC_POINT_add on two EC_POINTS.
     """
     op_sum = openssl._get_new_EC_POINT(ec_group=self.group)
     with backend._tmp_bn_ctx() as bn_ctx:
         res = backend._lib.EC_POINT_add(self.group, op_sum, self.ec_point,
                                         other.ec_point, bn_ctx)
         backend.openssl_assert(res == 1)
     return Point(op_sum, self.curve_nid, self.group)
Exemple #14
0
def _bytes_to_bn(bytes_seq: bytes, set_consttime_flag=True):
    """
    Converts the given byte sequence to an OpenSSL BIGNUM. 
    If set_consttime_flag is set to True, OpenSSL will use constant time
    operations when using this BIGNUM.
    """
    bn = _get_new_BN(set_consttime_flag)
    backend._lib.BN_bin2bn(bytes_seq, len(bytes_seq), bn)
    backend.openssl_assert(bn != backend._ffi.NULL)    
    return bn
Exemple #15
0
def _get_new_EC_POINT(curve: 'Curve'):
    """
    Returns a new and initialized OpenSSL EC_POINT given the group of a curve.
    If __curve_nid is provided, it retrieves the group from the curve provided.
    """
    new_point = backend._lib.EC_POINT_new(curve.ec_group)
    backend.openssl_assert(new_point != backend._ffi.NULL)
    new_point = backend._ffi.gc(new_point, backend._lib.EC_POINT_clear_free)

    return new_point
Exemple #16
0
    def __sub__(self, other):
        """
        Performs a BN_mod_sub on two BIGNUMS.
        """
        diff = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_mod_sub(diff, self.bignum, other.bignum,
                                          self.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(diff, self.curve_nid, self.group, self.order)
Exemple #17
0
    def __invert__(self):
        """
        Performs a BN_mod_inverse.
        """
        with backend._tmp_bn_ctx() as bn_ctx:
            inv = backend._lib.BN_mod_inverse(backend._ffi.NULL, self.bignum,
                                              self.order, bn_ctx)
            backend.openssl_assert(inv != backend._ffi.NULL)
            inv = backend._ffi.gc(inv, backend._lib.BN_clear_free)

        return BigNum(inv, self.curve_nid, self.group, self.order)
Exemple #18
0
def _bn_new():
    """
    Returns a new and initialized OpenSSL BIGNUM.
    """
    new_bn = BACKEND_LIB.BN_new()
    backend.openssl_assert(new_bn != BACKEND_FFI.NULL)
    new_bn = BACKEND_FFI.gc(new_bn, BACKEND_LIB.BN_clear_free)

    # Always use constant time operations.
    BACKEND_LIB.BN_set_flags(new_bn, BACKEND_LIB.BN_FLG_CONSTTIME)
    return new_bn
Exemple #19
0
    def __eq__(self, other):
        """
        Compares two EC_POINTS for equality.
        """
        with backend._tmp_bn_ctx() as bn_ctx:
            is_equal = backend._lib.EC_POINT_cmp(self.group, self.ec_point,
                                                 other.ec_point, bn_ctx)
            backend.openssl_assert(is_equal != -1)

        # 1 is not-equal, 0 is equal, -1 is error
        return not bool(is_equal)
Exemple #20
0
    def __add__(self, other) -> 'CurveBN':
        """
        Performs a BN_mod_add on two BIGNUMs.
        """
        op_sum = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_mod_add(op_sum, self.bignum, other.bignum,
                                          self.curve.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(op_sum, self.curve)
Exemple #21
0
def _get_EC_POINT_via_affine(affine_x, affine_y, curve: 'Curve'):
    """
    Returns an EC_POINT given the group of a curve and the affine coordinates
    provided.
    """
    new_point = _get_new_EC_POINT(curve)
    with backend._tmp_bn_ctx() as bn_ctx:
        res = backend._lib.EC_POINT_set_affine_coordinates_GFp(
            curve.ec_group, new_point, affine_x, affine_y, bn_ctx)
        backend.openssl_assert(res == 1)
    return new_point
Exemple #22
0
    def __mul__(self, other):
        """
        Performs an EC_POINT_mul on an EC_POINT and a BIGNUM.
        """
        prod = openssl._get_new_EC_POINT(ec_group=self.group)
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_POINT_mul(
                self.group, prod, backend._ffi.NULL, self.ec_point, other.bignum, bn_ctx
            )
            backend.openssl_assert(res == 1)

        return Point(prod, self.curve_nid, self.group)
Exemple #23
0
def _get_affine_coords_via_EC_POINT(ec_point, curve: 'Curve'):
    """
    Returns the affine coordinates of a given point on the provided ec_group.
    """
    affine_x = _get_new_BN()
    affine_y = _get_new_BN()

    with backend._tmp_bn_ctx() as bn_ctx:
        res = backend._lib.EC_POINT_get_affine_coordinates_GFp(
            curve.ec_group, ec_point, affine_x, affine_y, bn_ctx)
        backend.openssl_assert(res == 1)
    return (affine_x, affine_y)
Exemple #24
0
    def __invert__(self):
        """
        Performs an EC_POINT_invert on itself.
        """
        inv = backend._lib.EC_POINT_dup(self.ec_point, self.group)
        backend.openssl_assert(inv != backend._ffi.NULL)
        inv = backend._ffi.gc(inv, backend._lib.EC_POINT_clear_free)

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_POINT_invert(self.group, inv, bn_ctx)
            backend.openssl_assert(res == 1)
        return Point(inv, self.curve_nid, self.group)
Exemple #25
0
    def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'Point':
        """
        Returns a Point object from the given byte data on the curve provided.
        """
        curve = curve if curve is not None else default_curve()

        point = openssl._get_new_EC_POINT(curve)
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_POINT_oct2point(curve.ec_group, point, data,
                                                  len(data), bn_ctx)
            backend.openssl_assert(res == 1)

        return cls(point, curve)
Exemple #26
0
def point_to_bytes_compressed(curve: Curve, point):
    point_conversion_form = BACKEND_LIB.POINT_CONVERSION_COMPRESSED

    size = curve.field_element_size + 1  # compressed point size

    bin_ptr = BACKEND_FFI.new("unsigned char[]", size)
    with tmp_bn_ctx() as bn_ctx:
        bin_len = BACKEND_LIB.EC_POINT_point2oct(curve.ec_group, point,
                                                 point_conversion_form,
                                                 bin_ptr, size, bn_ctx)
        backend.openssl_assert(bin_len != 0)

    return bytes(BACKEND_FFI.buffer(bin_ptr, bin_len)[:])
Exemple #27
0
    def __mul__(self, other) -> 'Point':
        """
        Performs an EC_POINT_mul on an EC_POINT and a BIGNUM.
        """
        # TODO: Check that both points use the same curve.
        prod = openssl._get_new_EC_POINT(self.curve)
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_POINT_mul(self.curve.ec_group, prod,
                                            backend._ffi.NULL, self.ec_point,
                                            other.bignum, bn_ctx)
            backend.openssl_assert(res == 1)

        return Point(prod, self.curve)
Exemple #28
0
    def __mul__(self, other) -> 'CurveBN':
        """
        Performs a BN_mod_mul between two BIGNUMS.
        """
        if type(other) != CurveBN:
            return NotImplemented

        product = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_mod_mul(product, self.bignum, other.bignum,
                                          self.curve.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(product, self.curve)
Exemple #29
0
def _get_new_BN(set_consttime_flag=True):
    """
    Returns a new and initialized OpenSSL BIGNUM.
    The set_consttime_flag is set to True by default. When this instance of a
    CurveBN object has BN_FLG_CONSTTIME set, OpenSSL will use constant time
    operations whenever this CurveBN is passed.
    """
    new_bn = backend._lib.BN_new()
    backend.openssl_assert(new_bn != backend._ffi.NULL)
    new_bn = backend._ffi.gc(new_bn, backend._lib.BN_clear_free)

    if set_consttime_flag:
        backend._lib.BN_set_flags(new_bn, backend._lib.BN_FLG_CONSTTIME)
    return new_bn
Exemple #30
0
    def __invert__(self) -> 'CurveBN':
        """
        Performs a BN_mod_inverse.

        WARNING: Only in constant time if BN_FLG_CONSTTIME is set on the BN.

        """
        with backend._tmp_bn_ctx() as bn_ctx:
            inv = backend._lib.BN_mod_inverse(backend._ffi.NULL, self.bignum,
                                              self.curve.order, bn_ctx)
            backend.openssl_assert(inv != backend._ffi.NULL)
            inv = backend._ffi.gc(inv, backend._lib.BN_clear_free)

        return CurveBN(inv, self.curve)