Commit f599df12 authored by Bradley Beddoes's avatar Bradley Beddoes
Browse files

Add ability to get affine coordinates from EcPoint

The initial usecase here is creating JWK representations as defined
within RFC 7517 from an EcKey created via a PEM source.
parent 51471c7c
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -1714,7 +1714,11 @@ extern "C" {
    pub fn EC_KEY_generate_key(key: *mut EC_KEY) -> c_int;
    pub fn EC_KEY_check_key(key: *const EC_KEY) -> c_int;
    pub fn EC_KEY_free(key: *mut EC_KEY);
    pub fn EC_KEY_set_public_key_affine_coordinates(key: *mut EC_KEY, x: *mut BIGNUM, y: *mut BIGNUM) -> c_int;
    pub fn EC_KEY_set_public_key_affine_coordinates(
        key: *mut EC_KEY,
        x: *mut BIGNUM,
        y: *mut BIGNUM,
    ) -> c_int;

    #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))]
    pub fn EC_GF2m_simple_method() -> *const EC_METHOD;
@@ -1798,6 +1802,21 @@ extern "C" {
        ctx: *mut BN_CTX,
    ) -> c_int;
    pub fn EC_POINT_free(point: *mut EC_POINT);
    pub fn EC_POINT_get_affine_coordinates_GFp(
        group: *const EC_GROUP,
        p: *const EC_POINT,
        x: *mut BIGNUM,
        y: *mut BIGNUM,
        ctx: *mut BN_CTX,
    ) -> c_int;
    #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))]
    pub fn EC_POINT_get_affine_coordinates_GF2m(
        group: *const EC_GROUP,
        p: *const EC_POINT,
        x: *mut BIGNUM,
        y: *mut BIGNUM,
        ctx: *mut BN_CTX,
    ) -> c_int;

    pub fn ERR_peek_last_error() -> c_ulong;
    pub fn ERR_get_error() -> c_ulong;
@@ -2643,10 +2662,7 @@ extern "C" {
        flags: c_uint,
    ) -> c_int;
    #[cfg(not(libressl))]
    pub fn SMIME_read_CMS(
        bio: *mut BIO,
        bcont: *mut *mut BIO,
    ) -> *mut CMS_ContentInfo;
    pub fn SMIME_read_CMS(bio: *mut BIO, bcont: *mut *mut BIO) -> *mut CMS_ContentInfo;
    #[cfg(not(libressl))]
    pub fn CMS_ContentInfo_free(cms: *mut CMS_ContentInfo);
}
+93 −21
Original line number Diff line number Diff line
@@ -271,6 +271,45 @@ impl EcPointRef {
            Ok(res == 0)
        }
    }

    /// Place affine coordinates of a curve over a prime field in the provided x and y BigNum's
    pub fn get_affine_coordinates_gfp(
        &self,
        group: &EcGroupRef,
        x: &mut BigNumRef,
        y: &mut BigNumRef,
        ctx: &mut BigNumContextRef,
    ) -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::EC_POINT_get_affine_coordinates_GFp(
                group.as_ptr(),
                self.as_ptr(),
                x.as_ptr(),
                y.as_ptr(),
                ctx.as_ptr(),
            )).map(|_| ())
        }
    }

    /// Place affine coordinates of a curve over a binary field in the provided x and y BigNum's
    #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))]
    pub fn get_affine_coordinates_gf2m(
        &self,
        group: &EcGroupRef,
        x: &mut BigNumRef,
        y: &mut BigNumRef,
        ctx: &mut BigNumContextRef,
    ) -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::EC_POINT_get_affine_coordinates_GF2m(
                group.as_ptr(),
                self.as_ptr(),
                x.as_ptr(),
                y.as_ptr(),
                ctx.as_ptr(),
            )).map(|_| ())
        }
    }
}

impl EcPoint {
@@ -461,25 +500,23 @@ impl EcKeyBuilderRef {
    }

    /// Sets the public key based on affine coordinates.
    pub fn set_public_key_affine_coordinates(&mut self,
    pub fn set_public_key_affine_coordinates(
        &mut self,
        x: &BigNumRef,
                                             y: &BigNumRef)
                                             -> Result<&mut EcKeyBuilderRef, ErrorStack> {
        y: &BigNumRef,
    ) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
        unsafe {
            cvt(ffi::EC_KEY_set_public_key_affine_coordinates(self.as_ptr(), 
            cvt(ffi::EC_KEY_set_public_key_affine_coordinates(
                self.as_ptr(),
                x.as_ptr(),
							      y.as_ptr())
	    ).map(|_| self)
                y.as_ptr(),
            )).map(|_| self)
        }
    }

    /// Sets the private key.
    pub fn set_private_key(&mut self,
			   key: &BigNumRef)
			   -> Result<&mut EcKeyBuilderRef, ErrorStack> {
        unsafe {
            cvt(ffi::EC_KEY_set_private_key(self.as_ptr(), key.as_ptr())).map(|_| self)
        }
    pub fn set_private_key(&mut self, key: &BigNumRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
        unsafe { cvt(ffi::EC_KEY_set_private_key(self.as_ptr(), key.as_ptr())).map(|_| self) }
    }
}

@@ -566,17 +603,21 @@ mod test {
    #[test]
    fn key_from_affine_coordinates() {
        let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap();
        let x = data_encoding::base64url::decode_nopad("MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4".as_bytes())
            .unwrap();
        let y = data_encoding::base64url::decode_nopad("4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM".as_bytes())
            .unwrap();
        let x = data_encoding::base64url::decode_nopad(
            "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4".as_bytes(),
        ).unwrap();
        let y = data_encoding::base64url::decode_nopad(
            "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM".as_bytes(),
        ).unwrap();

        let xbn = BigNum::from_slice(&x).unwrap();
        let ybn = BigNum::from_slice(&y).unwrap();

        let mut builder = EcKeyBuilder::new().unwrap();
        builder.set_group(&group).unwrap();
        builder.set_public_key_affine_coordinates(&xbn, &ybn).unwrap();
        builder
            .set_public_key_affine_coordinates(&xbn, &ybn)
            .unwrap();

        let ec_key = builder.build();
        assert!(ec_key.check_key().is_ok());
@@ -586,8 +627,9 @@ mod test {
    #[test]
    fn set_private_key() {
        let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap();
        let d = data_encoding::base64url::decode_nopad("870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE".as_bytes())
            .unwrap();
        let d = data_encoding::base64url::decode_nopad(
            "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE".as_bytes(),
        ).unwrap();

        let dbn = BigNum::from_slice(&d).unwrap();

@@ -598,4 +640,34 @@ mod test {
        let ec_key = builder.build();
        assert!(ec_key.private_key().is_some());
    }

    #[test]
    fn get_affine_coordinates() {
        let raw_x = "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4";
        let raw_y = "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM";
        let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap();
        let x = data_encoding::base64url::decode_nopad(raw_x.as_bytes()).unwrap();
        let y = data_encoding::base64url::decode_nopad(raw_y.as_bytes()).unwrap();

        let xbn = BigNum::from_slice(&x).unwrap();
        let ybn = BigNum::from_slice(&y).unwrap();

        let mut builder = EcKeyBuilder::new().unwrap();
        builder.set_group(&group).unwrap();
        builder
            .set_public_key_affine_coordinates(&xbn, &ybn)
            .unwrap();

        let ec_key = builder.build();

        let mut xbn2 = BigNum::new().unwrap();
        let mut ybn2 = BigNum::new().unwrap();
        let mut ctx = BigNumContext::new().unwrap();
        let ec_key_pk = ec_key.public_key().unwrap();
        ec_key_pk
            .get_affine_coordinates_gfp(&group, &mut xbn2, &mut ybn2, &mut ctx)
            .unwrap();
        assert_eq!(xbn2, xbn);
        assert_eq!(ybn2, ybn);
    }
}