Exemple #1
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 #2
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 #3
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 #4
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 #5
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 #6
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 #7
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 #8
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 #9
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 #10
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 #11
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 #12
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 #13
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 #14
0
    def __add__(self, other):
        """
        Performs an EC_POINT_add on two EC_POINTS.
        """
        sum = backend._lib.EC_POINT_new(self.group)
        backend.openssl_assert(sum != backend._ffi.NULL)
        sum = backend._ffi.gc(sum, backend._lib.EC_POINT_clear_free)

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_POINT_add(self.group, sum, self.ec_point,
                                            other.ec_point, bn_ctx)
            backend.openssl_assert(res == 1)

        return Point(sum, self.curve_nid, self.group)
Exemple #15
0
    def __neg__(self) -> 'Point':
        """
        Computes the additive inverse of a Point, by performing an 
        EC_POINT_invert on itself.
        """
        inv = backend._lib.EC_POINT_dup(self.ec_point, self.curve.ec_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.curve.ec_group, inv,
                                               bn_ctx)
            backend.openssl_assert(res == 1)
        return Point(inv, self.curve)
Exemple #16
0
    def __mod__(self, other):
        """
        Performs a BN_nnmod on two BIGNUMS.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, None, None, None)

        rem = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_nnmod(rem, self.bignum, other.bignum, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(rem, self.curve_nid, self.group, self.order)
Exemple #17
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)
Exemple #18
0
    def __sub__(self, other):
        """
        Performs a BN_mod_sub on two BIGNUMS.
        """
        diff = backend._lib.BN_new()
        backend.openssl_assert(diff != backend._ffi.NULL)
        diff = backend._ffi.gc(diff, backend._lib.BN_clear_free)

        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 BigNum(diff, self.curve_nid, self.group, self.order)
Exemple #19
0
    def __add__(self, other):
        """
        Performs a BN_mod_add on two BIGNUMs.
        """
        sum = backend._lib.BN_new()
        backend.openssl_assert(sum != backend._ffi.NULL)
        sum = backend._ffi.gc(sum, backend._lib.BN_clear_free)

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_mod_add(sum, self.bignum, other.bignum,
                                          self.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return BigNum(sum, self.curve_nid, self.group, self.order)
Exemple #20
0
    def __sub__(self, other: Union[int, 'CurveBN']) -> 'CurveBN':
        """
        Performs a BN_mod_sub on two BIGNUMS.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, self.curve)

        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.curve.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(diff, self.curve)
Exemple #21
0
    def __neg__(self) -> 'CurveBN':
        """
        Computes the modular opposite (i.e., additive inverse) of a BIGNUM

        """
        zero = backend._int_to_bn(0)
        zero = backend._ffi.gc(zero, backend._lib.BN_clear_free)

        the_opposite = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_mod_sub(the_opposite, zero, self.bignum,
                                          self.curve.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(the_opposite, self.curve)
Exemple #22
0
    def __mod__(self, other: Union[int, 'CurveBN']) -> 'CurveBN':
        """
        Performs a BN_nnmod on two BIGNUMS.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, self.curve)

        other = cast('CurveBN', other)  # This is just for mypy

        rem = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_nnmod(rem, self.bignum, other.bignum, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(rem, self.curve)
Exemple #23
0
    def __mul__(self, other):
        """
        Performs a BN_mod_mul between two BIGNUMS.
        """
        if type(other) != BigNum:
            return NotImplemented

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

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

        return BigNum(product, self.curve_nid, self.group, self.order)
Exemple #24
0
    def gen_rand(cls, curve: Optional[Curve] = None) -> 'Point':
        """
        Returns a Point object with a cryptographically secure EC_POINT based
        on the provided curve.
        """
        curve = curve if curve is not None else default_curve()

        rand_point = openssl._get_new_EC_POINT(curve)
        rand_bn = CurveBN.gen_rand(curve).bignum

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_POINT_mul(curve.ec_group, rand_point,
                                            backend._ffi.NULL, curve.generator,
                                            rand_bn, bn_ctx)
            backend.openssl_assert(res == 1)

        return cls(rand_point, curve)
Exemple #25
0
def _tmp_bn_mont_ctx(modulus):
    """
    Initializes and returns a BN_MONT_CTX for Montgomery ops.
    Requires a modulus to place in the Montgomery structure.
    """
    bn_mont_ctx = backend._lib.BN_MONT_CTX_new()
    backend.openssl_assert(bn_mont_ctx != backend._ffi.NULL)
    # Don't set the garbage collector. Only free it when the context is done
    # or else you'll get a null pointer error.

    try:
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_MONT_CTX_set(bn_mont_ctx, modulus, bn_ctx)
            backend.openssl_assert(res == 1)
            yield bn_mont_ctx
    finally:
        backend._lib.BN_MONT_CTX_free(bn_mont_ctx)
Exemple #26
0
    def __pow__(self, other):
        """
        Performs a BN_mod_exp on two BIGNUMS.

        WARNING: Only in constant time if BN_FLG_CONSTTIME is set on the BN.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, None, None, None)

        power = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx, openssl._tmp_bn_mont_ctx(self.order) as bn_mont_ctx:
            res = backend._lib.BN_mod_exp_mont(
                power, self.bignum, other.bignum, self.order, bn_ctx, bn_mont_ctx
            )
            backend.openssl_assert(res == 1)

        return CurveBN(power, self.curve_nid, self.group, self.order)
Exemple #27
0
    def to_affine(self):
        """
        Returns a tuple of Python ints in the format of (x, y) that represents
        the point in the curve.
        """
        affine_x = backend._lib.BN_new()
        backend.openssl_assert(affine_x != backend._ffi.NULL)
        affine_x = backend._ffi.gc(affine_x, backend._lib.BN_clear_free)

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

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.EC_POINT_get_affine_coordinates_GFp(
                self.group, self.ec_point, affine_x, affine_y, bn_ctx)
            backend.openssl_assert(res == 1)
        return (backend._bn_to_int(affine_x), backend._bn_to_int(affine_y))
Exemple #28
0
    def __truediv__(self, other):
        """
        Performs a BN_div on two BIGNUMs (modulo the order of the curve).

        WARNING: Only in constant time if BN_FLG_CONSTTIME is set on the BN.
        """
        product = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            inv_other = backend._lib.BN_mod_inverse(backend._ffi.NULL,
                                                    other.bignum, self.order,
                                                    bn_ctx)
            backend.openssl_assert(inv_other != backend._ffi.NULL)

            res = backend._lib.BN_mod_mul(product, self.bignum, inv_other,
                                          self.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(product, self.curve_nid, self.group, self.order)
Exemple #29
0
    def __mod__(self, other):
        """
        Performs a BN_nnmod on two BIGNUMS.
        """
        if type(other) == int:
            other = backend._int_to_bn(other)
            other = backend._ffi.gc(other, backend._lib.BN_clear_free)

            other = BigNum(other, None, None, None)

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

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_nnmod(rem, self.bignum, other.bignum, bn_ctx)
            backend.openssl_assert(res == 1)

        return BigNum(rem, self.curve_nid, self.group, self.order)
Exemple #30
0
    def hash(cls, *crypto_items, params=None):
        params = params if params is not None else default_params()

        curve_nid = backend._elliptic_curve_to_nid(params.curve)
        order = openssl._get_ec_order_by_curve_nid(curve_nid)
        group = openssl._get_ec_group_by_curve_nid(curve_nid)

        # TODO: Clean this in an upcoming cleanup of pyUmbral
        blake2b = hashes.Hash(hashes.BLAKE2b(64), backend=backend)
        for item in crypto_items:
            try:
                item_bytes = item.to_bytes()
            except AttributeError:
                if isinstance(item, bytes):
                    item_bytes = item
                else:
                    raise TypeError(
                        "{} is not acceptable type, received {}".format(
                            item, type(item)))
            blake2b.update(item_bytes)

        hash_digest = blake2b.finalize()
        hash_digest = int.from_bytes(hash_digest,
                                     byteorder='big',
                                     signed=False)
        hash_digest = openssl._int_to_bn(hash_digest)

        _1 = backend._lib.BN_value_one()

        order_minus_1 = openssl._get_new_BN()
        res = backend._lib.BN_sub(order_minus_1, order, _1)
        backend.openssl_assert(res == 1)

        bignum = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_mod(bignum, hash_digest, order_minus_1,
                                      bn_ctx)
            backend.openssl_assert(res == 1)

        res = backend._lib.BN_add(bignum, bignum, _1)
        backend.openssl_assert(res == 1)

        return cls(bignum, curve_nid, group, order)