Update OpenSSL 3 compatibility patches.
This replaces the parts of the original PR with official patches which landed in [ruby/openssl](https://github.com/ruby/openssl) repository and should reflect the state of OpenSSL 3 support in Ruby 3.1.
This commit is contained in:
		
							parent
							
								
									a0bcb33eaa
								
							
						
					
					
						commit
						2da7a540e7
					
				
							
								
								
									
										630
									
								
								ruby-3.1.0-Allocate-EVP_PKEY-on-initialize.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										630
									
								
								ruby-3.1.0-Allocate-EVP_PKEY-on-initialize.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,630 @@ | |||||||
|  | From 316cb2a41f154e4663d7e7fead60cfc0bfa86af9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Mon, 12 Apr 2021 13:55:10 +0900 | ||||||
|  | Subject: [PATCH 1/2] pkey: do not check NULL argument in ossl_pkey_new() | ||||||
|  | 
 | ||||||
|  | Passing NULL to ossl_pkey_new() makes no sense in the first place, and | ||||||
|  | in fact it is ensured not to be NULL in all cases. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_pkey.c | 6 +----- | ||||||
|  |  ext/openssl/ossl_pkey.h | 1 + | ||||||
|  |  2 files changed, 2 insertions(+), 5 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
 | ||||||
|  | index f9f5162e..820e4a2c 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.c
 | ||||||
|  | @@ -38,12 +38,8 @@ static VALUE
 | ||||||
|  |  pkey_new0(EVP_PKEY *pkey) | ||||||
|  |  { | ||||||
|  |      VALUE klass, obj; | ||||||
|  | -    int type;
 | ||||||
|  |   | ||||||
|  | -    if (!pkey || (type = EVP_PKEY_base_id(pkey)) == EVP_PKEY_NONE)
 | ||||||
|  | -	ossl_raise(rb_eRuntimeError, "pkey is empty");
 | ||||||
|  | -
 | ||||||
|  | -    switch (type) {
 | ||||||
|  | +    switch (EVP_PKEY_base_id(pkey)) {
 | ||||||
|  |  #if !defined(OPENSSL_NO_RSA) | ||||||
|  |        case EVP_PKEY_RSA: klass = cRSA; break; | ||||||
|  |  #endif | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
 | ||||||
|  | index 4beede22..f0476780 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.h
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.h
 | ||||||
|  | @@ -35,6 +35,7 @@ extern const rb_data_type_t ossl_evp_pkey_type;
 | ||||||
|  |      } \ | ||||||
|  |  } while (0) | ||||||
|  |   | ||||||
|  | +/* Takes ownership of the EVP_PKEY */
 | ||||||
|  |  VALUE ossl_pkey_new(EVP_PKEY *); | ||||||
|  |  void ossl_pkey_check_public_key(const EVP_PKEY *); | ||||||
|  |  EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE); | ||||||
|  | 
 | ||||||
|  | From 74f6c6175688502a5bf27ae35367616858630c0f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Mon, 12 Apr 2021 18:32:40 +0900 | ||||||
|  | Subject: [PATCH 2/2] pkey: allocate EVP_PKEY on #initialize | ||||||
|  | 
 | ||||||
|  | Allocate an EVP_PKEY when the content is ready: when #initialize | ||||||
|  | or #initialize_copy is called, rather than when a T_DATA is allocated. | ||||||
|  | This is more natural because the lower level API has been deprecated | ||||||
|  | and an EVP_PKEY is becoming the minimum unit of handling keys. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_pkey.c     | 15 ++---- | ||||||
|  |  ext/openssl/ossl_pkey.h     | 15 ++---- | ||||||
|  |  ext/openssl/ossl_pkey_dh.c  | 71 +++++++++++++++++++-------- | ||||||
|  |  ext/openssl/ossl_pkey_dsa.c | 93 ++++++++++++++++++++--------------- | ||||||
|  |  ext/openssl/ossl_pkey_ec.c  | 91 +++++++++++++++++++---------------- | ||||||
|  |  ext/openssl/ossl_pkey_rsa.c | 96 ++++++++++++++++++++++--------------- | ||||||
|  |  6 files changed, 218 insertions(+), 163 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
 | ||||||
|  | index 820e4a2c..ea75d63f 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.c
 | ||||||
|  | @@ -54,8 +54,8 @@ pkey_new0(EVP_PKEY *pkey)
 | ||||||
|  |  #endif | ||||||
|  |        default:           klass = cPKey; break; | ||||||
|  |      } | ||||||
|  | -    obj = NewPKey(klass);
 | ||||||
|  | -    SetPKey(obj, pkey);
 | ||||||
|  | +    obj = rb_obj_alloc(klass);
 | ||||||
|  | +    RTYPEDDATA_DATA(obj) = pkey;
 | ||||||
|  |      return obj; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -511,16 +511,7 @@ DupPKeyPtr(VALUE obj)
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_pkey_alloc(VALUE klass) | ||||||
|  |  { | ||||||
|  | -    EVP_PKEY *pkey;
 | ||||||
|  | -    VALUE obj;
 | ||||||
|  | -
 | ||||||
|  | -    obj = NewPKey(klass);
 | ||||||
|  | -    if (!(pkey = EVP_PKEY_new())) {
 | ||||||
|  | -	ossl_raise(ePKeyError, NULL);
 | ||||||
|  | -    }
 | ||||||
|  | -    SetPKey(obj, pkey);
 | ||||||
|  | -
 | ||||||
|  | -    return obj;
 | ||||||
|  | +    return TypedData_Wrap_Struct(klass, &ossl_evp_pkey_type, NULL);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
 | ||||||
|  | index f0476780..ed18bc69 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.h
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.h
 | ||||||
|  | @@ -15,19 +15,10 @@ extern VALUE cPKey;
 | ||||||
|  |  extern VALUE ePKeyError; | ||||||
|  |  extern const rb_data_type_t ossl_evp_pkey_type; | ||||||
|  |   | ||||||
|  | -#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
 | ||||||
|  | -#define OSSL_PKEY_SET_PUBLIC(obj)  rb_iv_set((obj), "private", Qfalse)
 | ||||||
|  | -#define OSSL_PKEY_IS_PRIVATE(obj)  (rb_iv_get((obj), "private") == Qtrue)
 | ||||||
|  | +/* For ENGINE */
 | ||||||
|  | +#define OSSL_PKEY_SET_PRIVATE(obj) rb_ivar_set((obj), rb_intern("private"), Qtrue)
 | ||||||
|  | +#define OSSL_PKEY_IS_PRIVATE(obj)  (rb_attr_get((obj), rb_intern("private")) == Qtrue)
 | ||||||
|  |   | ||||||
|  | -#define NewPKey(klass) \
 | ||||||
|  | -    TypedData_Wrap_Struct((klass), &ossl_evp_pkey_type, 0)
 | ||||||
|  | -#define SetPKey(obj, pkey) do { \
 | ||||||
|  | -    if (!(pkey)) { \
 | ||||||
|  | -	rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \
 | ||||||
|  | -    } \
 | ||||||
|  | -    RTYPEDDATA_DATA(obj) = (pkey); \
 | ||||||
|  | -    OSSL_PKEY_SET_PUBLIC(obj); \
 | ||||||
|  | -} while (0)
 | ||||||
|  |  #define GetPKey(obj, pkey) do {\ | ||||||
|  |      TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \ | ||||||
|  |      if (!(pkey)) { \ | ||||||
|  | diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
 | ||||||
|  | index ca782bbe..04c11b21 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey_dh.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey_dh.c
 | ||||||
|  | @@ -72,34 +72,57 @@ static VALUE
 | ||||||
|  |  ossl_dh_initialize(int argc, VALUE *argv, VALUE self) | ||||||
|  |  { | ||||||
|  |      EVP_PKEY *pkey; | ||||||
|  | +    int type;
 | ||||||
|  |      DH *dh; | ||||||
|  | -    BIO *in;
 | ||||||
|  | +    BIO *in = NULL;
 | ||||||
|  |      VALUE arg; | ||||||
|  |   | ||||||
|  | -    GetPKey(self, pkey);
 | ||||||
|  | +    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
 | ||||||
|  | +    if (pkey)
 | ||||||
|  | +        rb_raise(rb_eTypeError, "pkey already initialized");
 | ||||||
|  | +
 | ||||||
|  |      /* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */ | ||||||
|  |      if (rb_scan_args(argc, argv, "01", &arg) == 0) { | ||||||
|  |          dh = DH_new(); | ||||||
|  |          if (!dh) | ||||||
|  |              ossl_raise(eDHError, "DH_new"); | ||||||
|  | +        goto legacy;
 | ||||||
|  |      } | ||||||
|  | -    else {
 | ||||||
|  | -	arg = ossl_to_der_if_possible(arg);
 | ||||||
|  | -	in = ossl_obj2bio(&arg);
 | ||||||
|  | -	dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
 | ||||||
|  | -	if (!dh){
 | ||||||
|  | -	    OSSL_BIO_reset(in);
 | ||||||
|  | -	    dh = d2i_DHparams_bio(in, NULL);
 | ||||||
|  | -	}
 | ||||||
|  | -	BIO_free(in);
 | ||||||
|  | -	if (!dh) {
 | ||||||
|  | -	    ossl_raise(eDHError, NULL);
 | ||||||
|  | -	}
 | ||||||
|  | +
 | ||||||
|  | +    arg = ossl_to_der_if_possible(arg);
 | ||||||
|  | +    in = ossl_obj2bio(&arg);
 | ||||||
|  | +
 | ||||||
|  | +    /*
 | ||||||
|  | +     * On OpenSSL <= 1.1.1 and current versions of LibreSSL, the generic
 | ||||||
|  | +     * routine does not support DER-encoded parameters
 | ||||||
|  | +     */
 | ||||||
|  | +    dh = d2i_DHparams_bio(in, NULL);
 | ||||||
|  | +    if (dh)
 | ||||||
|  | +        goto legacy;
 | ||||||
|  | +    OSSL_BIO_reset(in);
 | ||||||
|  | +
 | ||||||
|  | +    pkey = ossl_pkey_read_generic(in, Qnil);
 | ||||||
|  | +    BIO_free(in);
 | ||||||
|  | +    if (!pkey)
 | ||||||
|  | +        ossl_raise(eDHError, "could not parse pkey");
 | ||||||
|  | +
 | ||||||
|  | +    type = EVP_PKEY_base_id(pkey);
 | ||||||
|  | +    if (type != EVP_PKEY_DH) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        rb_raise(eDHError, "incorrect pkey type: %s", OBJ_nid2sn(type));
 | ||||||
|  |      } | ||||||
|  | -    if (!EVP_PKEY_assign_DH(pkey, dh)) {
 | ||||||
|  | -	DH_free(dh);
 | ||||||
|  | -	ossl_raise(eDHError, NULL);
 | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  | +    return self;
 | ||||||
|  | +
 | ||||||
|  | +  legacy:
 | ||||||
|  | +    BIO_free(in);
 | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        DH_free(dh);
 | ||||||
|  | +        ossl_raise(eDHError, "EVP_PKEY_assign_DH");
 | ||||||
|  |      } | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -110,15 +133,14 @@ ossl_dh_initialize_copy(VALUE self, VALUE other)
 | ||||||
|  |      DH *dh, *dh_other; | ||||||
|  |      const BIGNUM *pub, *priv; | ||||||
|  |   | ||||||
|  | -    GetPKey(self, pkey);
 | ||||||
|  | -    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
 | ||||||
|  | -	ossl_raise(eDHError, "DH already initialized");
 | ||||||
|  | +    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
 | ||||||
|  | +    if (pkey)
 | ||||||
|  | +        rb_raise(rb_eTypeError, "pkey already initialized");
 | ||||||
|  |      GetDH(other, dh_other); | ||||||
|  |   | ||||||
|  |      dh = DHparams_dup(dh_other); | ||||||
|  |      if (!dh) | ||||||
|  |  	ossl_raise(eDHError, "DHparams_dup"); | ||||||
|  | -    EVP_PKEY_assign_DH(pkey, dh);
 | ||||||
|  |   | ||||||
|  |      DH_get0_key(dh_other, &pub, &priv); | ||||||
|  |      if (pub) { | ||||||
|  | @@ -133,6 +155,13 @@ ossl_dh_initialize_copy(VALUE self, VALUE other)
 | ||||||
|  |  	DH_set0_key(dh, pub2, priv2); | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        DH_free(dh);
 | ||||||
|  | +        ossl_raise(eDHError, "EVP_PKEY_assign_DH");
 | ||||||
|  | +    }
 | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
 | ||||||
|  | index 7af00eeb..15724548 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey_dsa.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey_dsa.c
 | ||||||
|  | @@ -83,50 +83,59 @@ VALUE eDSAError;
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) | ||||||
|  |  { | ||||||
|  | -    EVP_PKEY *pkey, *tmp;
 | ||||||
|  | -    DSA *dsa = NULL;
 | ||||||
|  | -    BIO *in;
 | ||||||
|  | +    EVP_PKEY *pkey;
 | ||||||
|  | +    DSA *dsa;
 | ||||||
|  | +    BIO *in = NULL;
 | ||||||
|  |      VALUE arg, pass; | ||||||
|  | +    int type;
 | ||||||
|  | +
 | ||||||
|  | +    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
 | ||||||
|  | +    if (pkey)
 | ||||||
|  | +        rb_raise(rb_eTypeError, "pkey already initialized");
 | ||||||
|  |   | ||||||
|  | -    GetPKey(self, pkey);
 | ||||||
|  |      /* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ | ||||||
|  |      rb_scan_args(argc, argv, "02", &arg, &pass); | ||||||
|  |      if (argc == 0) { | ||||||
|  |          dsa = DSA_new(); | ||||||
|  |          if (!dsa) | ||||||
|  |              ossl_raise(eDSAError, "DSA_new"); | ||||||
|  | +        goto legacy;
 | ||||||
|  |      } | ||||||
|  | -    else {
 | ||||||
|  | -	pass = ossl_pem_passwd_value(pass);
 | ||||||
|  | -	arg = ossl_to_der_if_possible(arg);
 | ||||||
|  | -	in = ossl_obj2bio(&arg);
 | ||||||
|  | -
 | ||||||
|  | -        tmp = ossl_pkey_read_generic(in, pass);
 | ||||||
|  | -        if (tmp) {
 | ||||||
|  | -            if (EVP_PKEY_base_id(tmp) != EVP_PKEY_DSA)
 | ||||||
|  | -                rb_raise(eDSAError, "incorrect pkey type: %s",
 | ||||||
|  | -                         OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
 | ||||||
|  | -            dsa = EVP_PKEY_get1_DSA(tmp);
 | ||||||
|  | -            EVP_PKEY_free(tmp);
 | ||||||
|  | -        }
 | ||||||
|  | -	if (!dsa) {
 | ||||||
|  | -	    OSSL_BIO_reset(in);
 | ||||||
|  | -#define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
 | ||||||
|  | -	(d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u))
 | ||||||
|  | -	    dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
 | ||||||
|  | -#undef PEM_read_bio_DSAPublicKey
 | ||||||
|  | -	}
 | ||||||
|  | -	BIO_free(in);
 | ||||||
|  | -	if (!dsa) {
 | ||||||
|  | -	    ossl_clear_error();
 | ||||||
|  | -	    ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
 | ||||||
|  | -	}
 | ||||||
|  | -    }
 | ||||||
|  | -    if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
 | ||||||
|  | -	DSA_free(dsa);
 | ||||||
|  | -	ossl_raise(eDSAError, NULL);
 | ||||||
|  | +
 | ||||||
|  | +    pass = ossl_pem_passwd_value(pass);
 | ||||||
|  | +    arg = ossl_to_der_if_possible(arg);
 | ||||||
|  | +    in = ossl_obj2bio(&arg);
 | ||||||
|  | +
 | ||||||
|  | +    /* DER-encoded DSAPublicKey format isn't supported by the generic routine */
 | ||||||
|  | +    dsa = (DSA *)PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAPublicKey,
 | ||||||
|  | +                                   PEM_STRING_DSA_PUBLIC,
 | ||||||
|  | +                                   in, NULL, NULL, NULL);
 | ||||||
|  | +    if (dsa)
 | ||||||
|  | +        goto legacy;
 | ||||||
|  | +    OSSL_BIO_reset(in);
 | ||||||
|  | +
 | ||||||
|  | +    pkey = ossl_pkey_read_generic(in, pass);
 | ||||||
|  | +    BIO_free(in);
 | ||||||
|  | +    if (!pkey)
 | ||||||
|  | +        ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
 | ||||||
|  | +
 | ||||||
|  | +    type = EVP_PKEY_base_id(pkey);
 | ||||||
|  | +    if (type != EVP_PKEY_DSA) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
 | ||||||
|  |      } | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  | +    return self;
 | ||||||
|  |   | ||||||
|  | +  legacy:
 | ||||||
|  | +    BIO_free(in);
 | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa) != 1) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        DSA_free(dsa);
 | ||||||
|  | +        ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
 | ||||||
|  | +    }
 | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -136,16 +145,24 @@ ossl_dsa_initialize_copy(VALUE self, VALUE other)
 | ||||||
|  |      EVP_PKEY *pkey; | ||||||
|  |      DSA *dsa, *dsa_new; | ||||||
|  |   | ||||||
|  | -    GetPKey(self, pkey);
 | ||||||
|  | -    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
 | ||||||
|  | -	ossl_raise(eDSAError, "DSA already initialized");
 | ||||||
|  | +    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
 | ||||||
|  | +    if (pkey)
 | ||||||
|  | +        rb_raise(rb_eTypeError, "pkey already initialized");
 | ||||||
|  |      GetDSA(other, dsa); | ||||||
|  |   | ||||||
|  | -    dsa_new = ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, (d2i_of_void *)d2i_DSAPrivateKey, (char *)dsa);
 | ||||||
|  | +    dsa_new = (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey,
 | ||||||
|  | +                              (d2i_of_void *)d2i_DSAPrivateKey,
 | ||||||
|  | +                              (char *)dsa);
 | ||||||
|  |      if (!dsa_new) | ||||||
|  |  	ossl_raise(eDSAError, "ASN1_dup"); | ||||||
|  |   | ||||||
|  | -    EVP_PKEY_assign_DSA(pkey, dsa_new);
 | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa_new) != 1) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        DSA_free(dsa_new);
 | ||||||
|  | +        ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
 | ||||||
|  | +    }
 | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  |   | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  | diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | index db80d112..71e63969 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | @@ -114,13 +114,16 @@ ossl_ec_key_s_generate(VALUE klass, VALUE arg)
 | ||||||
|  |      VALUE obj; | ||||||
|  |   | ||||||
|  |      obj = rb_obj_alloc(klass); | ||||||
|  | -    GetPKey(obj, pkey);
 | ||||||
|  |   | ||||||
|  |      ec = ec_key_new_from_group(arg); | ||||||
|  | -    if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
 | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  |          EC_KEY_free(ec); | ||||||
|  |          ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); | ||||||
|  |      } | ||||||
|  | +    RTYPEDDATA_DATA(obj) = pkey;
 | ||||||
|  | +
 | ||||||
|  |      if (!EC_KEY_generate_key(ec)) | ||||||
|  |  	ossl_raise(eECError, "EC_KEY_generate_key"); | ||||||
|  |   | ||||||
|  | @@ -141,51 +144,54 @@ ossl_ec_key_s_generate(VALUE klass, VALUE arg)
 | ||||||
|  |  static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) | ||||||
|  |  { | ||||||
|  |      EVP_PKEY *pkey; | ||||||
|  | -    EC_KEY *ec = NULL;
 | ||||||
|  | +    EC_KEY *ec;
 | ||||||
|  | +    BIO *in;
 | ||||||
|  |      VALUE arg, pass; | ||||||
|  | +    int type;
 | ||||||
|  |   | ||||||
|  | -    GetPKey(self, pkey);
 | ||||||
|  | -    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
 | ||||||
|  | -        ossl_raise(eECError, "EC_KEY already initialized");
 | ||||||
|  | +    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
 | ||||||
|  | +    if (pkey)
 | ||||||
|  | +        rb_raise(rb_eTypeError, "pkey already initialized");
 | ||||||
|  |   | ||||||
|  |      rb_scan_args(argc, argv, "02", &arg, &pass); | ||||||
|  | -
 | ||||||
|  |      if (NIL_P(arg)) { | ||||||
|  |          if (!(ec = EC_KEY_new())) | ||||||
|  | -	    ossl_raise(eECError, NULL);
 | ||||||
|  | -    } else if (rb_obj_is_kind_of(arg, cEC)) {
 | ||||||
|  | -	EC_KEY *other_ec = NULL;
 | ||||||
|  | +            ossl_raise(eECError, "EC_KEY_new");
 | ||||||
|  | +        goto legacy;
 | ||||||
|  | +    }
 | ||||||
|  | +    else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
 | ||||||
|  | +        ec = ec_key_new_from_group(arg);
 | ||||||
|  | +        goto legacy;
 | ||||||
|  | +    }
 | ||||||
|  |   | ||||||
|  | -	GetEC(arg, other_ec);
 | ||||||
|  | -	if (!(ec = EC_KEY_dup(other_ec)))
 | ||||||
|  | -	    ossl_raise(eECError, NULL);
 | ||||||
|  | -    } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
 | ||||||
|  | -	ec = ec_key_new_from_group(arg);
 | ||||||
|  | -    } else {
 | ||||||
|  | -        BIO *in = ossl_obj2bio(&arg);
 | ||||||
|  | -        EVP_PKEY *tmp;
 | ||||||
|  | -        pass = ossl_pem_passwd_value(pass);
 | ||||||
|  | -        tmp = ossl_pkey_read_generic(in, pass);
 | ||||||
|  | -        if (tmp) {
 | ||||||
|  | -            if (EVP_PKEY_base_id(tmp) != EVP_PKEY_EC)
 | ||||||
|  | -                rb_raise(eECError, "incorrect pkey type: %s",
 | ||||||
|  | -                         OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
 | ||||||
|  | -            ec = EVP_PKEY_get1_EC_KEY(tmp);
 | ||||||
|  | -            EVP_PKEY_free(tmp);
 | ||||||
|  | -        }
 | ||||||
|  | -	BIO_free(in);
 | ||||||
|  | +    pass = ossl_pem_passwd_value(pass);
 | ||||||
|  | +    arg = ossl_to_der_if_possible(arg);
 | ||||||
|  | +    in = ossl_obj2bio(&arg);
 | ||||||
|  |   | ||||||
|  | -	if (!ec) {
 | ||||||
|  | -	    ossl_clear_error();
 | ||||||
|  | -	    ec = ec_key_new_from_group(arg);
 | ||||||
|  | -	}
 | ||||||
|  | +    pkey = ossl_pkey_read_generic(in, pass);
 | ||||||
|  | +    BIO_free(in);
 | ||||||
|  | +    if (!pkey) {
 | ||||||
|  | +        ossl_clear_error();
 | ||||||
|  | +        ec = ec_key_new_from_group(arg);
 | ||||||
|  | +        goto legacy;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
 | ||||||
|  | -	EC_KEY_free(ec);
 | ||||||
|  | -	ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
 | ||||||
|  | +    type = EVP_PKEY_base_id(pkey);
 | ||||||
|  | +    if (type != EVP_PKEY_EC) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
 | ||||||
|  |      } | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  | +    return self;
 | ||||||
|  |   | ||||||
|  | +  legacy:
 | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        EC_KEY_free(ec);
 | ||||||
|  | +        ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
 | ||||||
|  | +    }
 | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -195,18 +201,21 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other)
 | ||||||
|  |      EVP_PKEY *pkey; | ||||||
|  |      EC_KEY *ec, *ec_new; | ||||||
|  |   | ||||||
|  | -    GetPKey(self, pkey);
 | ||||||
|  | -    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
 | ||||||
|  | -	ossl_raise(eECError, "EC already initialized");
 | ||||||
|  | +    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
 | ||||||
|  | +    if (pkey)
 | ||||||
|  | +        rb_raise(rb_eTypeError, "pkey already initialized");
 | ||||||
|  |      GetEC(other, ec); | ||||||
|  |   | ||||||
|  |      ec_new = EC_KEY_dup(ec); | ||||||
|  |      if (!ec_new) | ||||||
|  |  	ossl_raise(eECError, "EC_KEY_dup"); | ||||||
|  | -    if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) {
 | ||||||
|  | -	EC_KEY_free(ec_new);
 | ||||||
|  | -	ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
 | ||||||
|  | +
 | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec_new) != 1) {
 | ||||||
|  | +        EC_KEY_free(ec_new);
 | ||||||
|  | +        ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
 | ||||||
|  |      } | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  |   | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  | diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
 | ||||||
|  | index 8ebd3ec5..b8dbc0e1 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey_rsa.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey_rsa.c
 | ||||||
|  | @@ -76,51 +76,62 @@ VALUE eRSAError;
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) | ||||||
|  |  { | ||||||
|  | -    EVP_PKEY *pkey, *tmp;
 | ||||||
|  | -    RSA *rsa = NULL;
 | ||||||
|  | -    BIO *in;
 | ||||||
|  | +    EVP_PKEY *pkey;
 | ||||||
|  | +    RSA *rsa;
 | ||||||
|  | +    BIO *in = NULL;
 | ||||||
|  |      VALUE arg, pass; | ||||||
|  | +    int type;
 | ||||||
|  | +
 | ||||||
|  | +    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
 | ||||||
|  | +    if (pkey)
 | ||||||
|  | +        rb_raise(rb_eTypeError, "pkey already initialized");
 | ||||||
|  |   | ||||||
|  | -    GetPKey(self, pkey);
 | ||||||
|  |      /* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ | ||||||
|  |      rb_scan_args(argc, argv, "02", &arg, &pass); | ||||||
|  |      if (argc == 0) { | ||||||
|  |  	rsa = RSA_new(); | ||||||
|  |          if (!rsa) | ||||||
|  |              ossl_raise(eRSAError, "RSA_new"); | ||||||
|  | +        goto legacy;
 | ||||||
|  |      } | ||||||
|  | -    else {
 | ||||||
|  | -	pass = ossl_pem_passwd_value(pass);
 | ||||||
|  | -	arg = ossl_to_der_if_possible(arg);
 | ||||||
|  | -	in = ossl_obj2bio(&arg);
 | ||||||
|  | -
 | ||||||
|  | -        tmp = ossl_pkey_read_generic(in, pass);
 | ||||||
|  | -        if (tmp) {
 | ||||||
|  | -            if (EVP_PKEY_base_id(tmp) != EVP_PKEY_RSA)
 | ||||||
|  | -                rb_raise(eRSAError, "incorrect pkey type: %s",
 | ||||||
|  | -                         OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
 | ||||||
|  | -            rsa = EVP_PKEY_get1_RSA(tmp);
 | ||||||
|  | -            EVP_PKEY_free(tmp);
 | ||||||
|  | -        }
 | ||||||
|  | -	if (!rsa) {
 | ||||||
|  | -	    OSSL_BIO_reset(in);
 | ||||||
|  | -	    rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
 | ||||||
|  | -	}
 | ||||||
|  | -	if (!rsa) {
 | ||||||
|  | -	    OSSL_BIO_reset(in);
 | ||||||
|  | -	    rsa = d2i_RSAPublicKey_bio(in, NULL);
 | ||||||
|  | -	}
 | ||||||
|  | -	BIO_free(in);
 | ||||||
|  | -	if (!rsa) {
 | ||||||
|  | -            ossl_clear_error();
 | ||||||
|  | -	    ossl_raise(eRSAError, "Neither PUB key nor PRIV key");
 | ||||||
|  | -	}
 | ||||||
|  | -    }
 | ||||||
|  | -    if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
 | ||||||
|  | -	RSA_free(rsa);
 | ||||||
|  | -	ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
 | ||||||
|  | +
 | ||||||
|  | +    pass = ossl_pem_passwd_value(pass);
 | ||||||
|  | +    arg = ossl_to_der_if_possible(arg);
 | ||||||
|  | +    in = ossl_obj2bio(&arg);
 | ||||||
|  | +
 | ||||||
|  | +    /* First try RSAPublicKey format */
 | ||||||
|  | +    rsa = d2i_RSAPublicKey_bio(in, NULL);
 | ||||||
|  | +    if (rsa)
 | ||||||
|  | +        goto legacy;
 | ||||||
|  | +    OSSL_BIO_reset(in);
 | ||||||
|  | +    rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
 | ||||||
|  | +    if (rsa)
 | ||||||
|  | +        goto legacy;
 | ||||||
|  | +    OSSL_BIO_reset(in);
 | ||||||
|  | +
 | ||||||
|  | +    /* Use the generic routine */
 | ||||||
|  | +    pkey = ossl_pkey_read_generic(in, pass);
 | ||||||
|  | +    BIO_free(in);
 | ||||||
|  | +    if (!pkey)
 | ||||||
|  | +        ossl_raise(eRSAError, "Neither PUB key nor PRIV key");
 | ||||||
|  | +
 | ||||||
|  | +    type = EVP_PKEY_base_id(pkey);
 | ||||||
|  | +    if (type != EVP_PKEY_RSA) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        rb_raise(eRSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
 | ||||||
|  |      } | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  | +    return self;
 | ||||||
|  |   | ||||||
|  | +  legacy:
 | ||||||
|  | +    BIO_free(in);
 | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        RSA_free(rsa);
 | ||||||
|  | +        ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
 | ||||||
|  | +    }
 | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -130,16 +141,23 @@ ossl_rsa_initialize_copy(VALUE self, VALUE other)
 | ||||||
|  |      EVP_PKEY *pkey; | ||||||
|  |      RSA *rsa, *rsa_new; | ||||||
|  |   | ||||||
|  | -    GetPKey(self, pkey);
 | ||||||
|  | -    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
 | ||||||
|  | -	ossl_raise(eRSAError, "RSA already initialized");
 | ||||||
|  | +    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
 | ||||||
|  | +    if (pkey)
 | ||||||
|  | +        rb_raise(rb_eTypeError, "pkey already initialized");
 | ||||||
|  |      GetRSA(other, rsa); | ||||||
|  |   | ||||||
|  | -    rsa_new = ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, (d2i_of_void *)d2i_RSAPrivateKey, (char *)rsa);
 | ||||||
|  | +    rsa_new = (RSA *)ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey,
 | ||||||
|  | +                              (d2i_of_void *)d2i_RSAPrivateKey,
 | ||||||
|  | +                              (char *)rsa);
 | ||||||
|  |      if (!rsa_new) | ||||||
|  |  	ossl_raise(eRSAError, "ASN1_dup"); | ||||||
|  |   | ||||||
|  | -    EVP_PKEY_assign_RSA(pkey, rsa_new);
 | ||||||
|  | +    pkey = EVP_PKEY_new();
 | ||||||
|  | +    if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa_new) != 1) {
 | ||||||
|  | +        RSA_free(rsa_new);
 | ||||||
|  | +        ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
 | ||||||
|  | +    }
 | ||||||
|  | +    RTYPEDDATA_DATA(self) = pkey;
 | ||||||
|  |   | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  | 
 | ||||||
							
								
								
									
										719
									
								
								ruby-3.1.0-Deprecate-PKey-set_-and-PKey-DH-EC-generate_key.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										719
									
								
								ruby-3.1.0-Deprecate-PKey-set_-and-PKey-DH-EC-generate_key.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,719 @@ | |||||||
|  | From 46ca47060ca8ef3419ec36c2326a81b442d9b43b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Sun, 12 Dec 2021 01:25:20 +0900 | ||||||
|  | Subject: [PATCH 1/5] pkey/dh: avoid using DH#set_key in DH#compute_key | ||||||
|  | 
 | ||||||
|  | DH#set_key will not work on OpenSSL 3.0 because keys are immutable. | ||||||
|  | For now, let's reimplement DH#compute_key by manually constructing a | ||||||
|  | DER-encoded SubjectPublicKeyInfo structure and feeding it to | ||||||
|  | OpenSSL::PKey.read. | ||||||
|  | 
 | ||||||
|  | Eventually, we should implement a new method around EVP_PKEY_fromdata() | ||||||
|  | and use it instead. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/lib/openssl/pkey.rb | 16 +++++++++++++--- | ||||||
|  |  1 file changed, 13 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | index f6bf5892..5864faa9 100644
 | ||||||
|  | --- a/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | +++ b/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | @@ -47,9 +47,19 @@ def public_key
 | ||||||
|  |      # * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by | ||||||
|  |      #   DH#public_key as that contains the DH parameters only. | ||||||
|  |      def compute_key(pub_bn) | ||||||
|  | -      peer = dup
 | ||||||
|  | -      peer.set_key(pub_bn, nil)
 | ||||||
|  | -      derive(peer)
 | ||||||
|  | +      # FIXME: This is constructing an X.509 SubjectPublicKeyInfo and is very
 | ||||||
|  | +      # inefficient
 | ||||||
|  | +      obj = OpenSSL::ASN1.Sequence([
 | ||||||
|  | +        OpenSSL::ASN1.Sequence([
 | ||||||
|  | +          OpenSSL::ASN1.ObjectId("dhKeyAgreement"),
 | ||||||
|  | +          OpenSSL::ASN1.Sequence([
 | ||||||
|  | +            OpenSSL::ASN1.Integer(p),
 | ||||||
|  | +            OpenSSL::ASN1.Integer(g),
 | ||||||
|  | +          ]),
 | ||||||
|  | +        ]),
 | ||||||
|  | +        OpenSSL::ASN1.BitString(OpenSSL::ASN1.Integer(pub_bn).to_der),
 | ||||||
|  | +      ])
 | ||||||
|  | +      derive(OpenSSL::PKey.read(obj.to_der))
 | ||||||
|  |      end | ||||||
|  |   | ||||||
|  |      # :call-seq: | ||||||
|  | 
 | ||||||
|  | From fc9aabc18df3c189cc6a76a1470ca908c4f16480 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Fri, 17 Dec 2021 02:22:25 +0900 | ||||||
|  | Subject: [PATCH 2/5] pkey/ec: avoid using EC#public_key= in EC#dh_compute_key | ||||||
|  | 
 | ||||||
|  | Similarly to DH#compute_key, work around it by constructing a | ||||||
|  | SubjectPublicKeyInfo. This should be considered as a temporary | ||||||
|  | implementation. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/lib/openssl/pkey.rb | 11 ++++++++--- | ||||||
|  |  1 file changed, 8 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | index 5864faa9..ba04cf4b 100644
 | ||||||
|  | --- a/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | +++ b/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | @@ -259,9 +259,14 @@ def dsa_verify_asn1(data, sig)
 | ||||||
|  |      # This method is provided for backwards compatibility, and calls #derive | ||||||
|  |      # internally. | ||||||
|  |      def dh_compute_key(pubkey) | ||||||
|  | -      peer = OpenSSL::PKey::EC.new(group)
 | ||||||
|  | -      peer.public_key = pubkey
 | ||||||
|  | -      derive(peer)
 | ||||||
|  | +      obj = OpenSSL::ASN1.Sequence([
 | ||||||
|  | +        OpenSSL::ASN1.Sequence([
 | ||||||
|  | +          OpenSSL::ASN1.ObjectId("id-ecPublicKey"),
 | ||||||
|  | +          group.to_der,
 | ||||||
|  | +        ]),
 | ||||||
|  | +        OpenSSL::ASN1.BitString(pubkey.to_octet_string(:uncompressed)),
 | ||||||
|  | +      ])
 | ||||||
|  | +      derive(OpenSSL::PKey.read(obj.to_der))
 | ||||||
|  |      end | ||||||
|  |    end | ||||||
|  |   | ||||||
|  | 
 | ||||||
|  | From 8ee6a582c7e4614eec4f5ca5ab59898fbcb50d2a Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Fri, 22 Oct 2021 16:24:07 +0900 | ||||||
|  | Subject: [PATCH 3/5] pkey/dh: deprecate OpenSSL::PKey::DH#generate_key! | ||||||
|  | 
 | ||||||
|  | OpenSSL::PKey::DH#generate_key! will not work on OpenSSL 3.0 because | ||||||
|  | keys are made immutable. Users should use OpenSSL::PKey.generate_key | ||||||
|  | instead. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/lib/openssl/pkey.rb | 23 +++++++++++++++++++---- | ||||||
|  |  ext/openssl/ossl_pkey_dh.c      |  9 +++++---- | ||||||
|  |  test/openssl/test_pkey_dh.rb    | 18 ++++++++++-------- | ||||||
|  |  3 files changed, 34 insertions(+), 16 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | index ba04cf4b..c3e06290 100644
 | ||||||
|  | --- a/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | +++ b/ext/openssl/lib/openssl/pkey.rb
 | ||||||
|  | @@ -71,14 +71,29 @@ def compute_key(pub_bn)
 | ||||||
|  |      # called first in order to generate the per-session keys before performing | ||||||
|  |      # the actual key exchange. | ||||||
|  |      # | ||||||
|  | +    # <b>Deprecated in version 3.0</b>. This method is incompatible with
 | ||||||
|  | +    # OpenSSL 3.0.0 or later.
 | ||||||
|  | +    #
 | ||||||
|  |      # See also OpenSSL::PKey.generate_key. | ||||||
|  |      # | ||||||
|  |      # Example: | ||||||
|  | -    #   dh = OpenSSL::PKey::DH.new(2048)
 | ||||||
|  | -    #   public_key = dh.public_key #contains no private/public key yet
 | ||||||
|  | -    #   public_key.generate_key!
 | ||||||
|  | -    #   puts public_key.private? # => true
 | ||||||
|  | +    #   # DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later
 | ||||||
|  | +    #   dh0 = OpenSSL::PKey::DH.new(2048)
 | ||||||
|  | +    #   dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name)
 | ||||||
|  | +    #   dh.generate_key!
 | ||||||
|  | +    #   puts dh.private? # => true
 | ||||||
|  | +    #   puts dh0.pub_key == dh.pub_key #=> false
 | ||||||
|  | +    #
 | ||||||
|  | +    #   # With OpenSSL::PKey.generate_key
 | ||||||
|  | +    #   dh0 = OpenSSL::PKey::DH.new(2048)
 | ||||||
|  | +    #   dh = OpenSSL::PKey.generate_key(dh0)
 | ||||||
|  | +    #   puts dh0.pub_key == dh.pub_key #=> false
 | ||||||
|  |      def generate_key! | ||||||
|  | +      if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000
 | ||||||
|  | +        raise DHError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \
 | ||||||
|  | +        "use OpenSSL::PKey.generate_key instead"
 | ||||||
|  | +      end
 | ||||||
|  | +
 | ||||||
|  |        unless priv_key | ||||||
|  |          tmp = OpenSSL::PKey.generate_key(self) | ||||||
|  |          set_key(tmp.pub_key, tmp.priv_key) | ||||||
|  | diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
 | ||||||
|  | index 04c11b2157..e70d60ed19 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey_dh.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey_dh.c
 | ||||||
|  | @@ -58,15 +58,16 @@ VALUE eDHError;
 | ||||||
|  |   * | ||||||
|  |   * Examples: | ||||||
|  |   *   # Creating an instance from scratch | ||||||
|  | - *   dh = DH.new
 | ||||||
|  | + *   # Note that this is deprecated and will not work on OpenSSL 3.0 or later.
 | ||||||
|  | + *   dh = OpenSSL::PKey::DH.new
 | ||||||
|  |   *   dh.set_pqg(bn_p, nil, bn_g) | ||||||
|  |   * | ||||||
|  |   *   # Generating a parameters and a key pair | ||||||
|  | - *   dh = DH.new(2048) # An alias of DH.generate(2048)
 | ||||||
|  | + *   dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
 | ||||||
|  |   * | ||||||
|  |   *   # Reading DH parameters | ||||||
|  | - *   dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
 | ||||||
|  | - *   dh.generate_key! # -> dh with public and private key
 | ||||||
|  | + *   dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
 | ||||||
|  | + *   dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair
 | ||||||
|  |   */ | ||||||
|  |  static VALUE | ||||||
|  |  ossl_dh_initialize(int argc, VALUE *argv, VALUE self) | ||||||
|  | diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
 | ||||||
|  | index 757704ca..ac11af38 100644
 | ||||||
|  | --- a/test/openssl/test_pkey_dh.rb
 | ||||||
|  | +++ b/test/openssl/test_pkey_dh.rb
 | ||||||
|  | @@ -26,14 +26,19 @@ def test_new_break
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_derive_key | ||||||
|  | -    dh1 = Fixtures.pkey("dh1024").generate_key!
 | ||||||
|  | -    dh2 = Fixtures.pkey("dh1024").generate_key!
 | ||||||
|  | +    params = Fixtures.pkey("dh1024")
 | ||||||
|  | +    dh1 = OpenSSL::PKey.generate_key(params)
 | ||||||
|  | +    dh2 = OpenSSL::PKey.generate_key(params)
 | ||||||
|  |      dh1_pub = OpenSSL::PKey.read(dh1.public_to_der) | ||||||
|  |      dh2_pub = OpenSSL::PKey.read(dh2.public_to_der) | ||||||
|  | +
 | ||||||
|  |      z = dh1.g.mod_exp(dh1.priv_key, dh1.p).mod_exp(dh2.priv_key, dh1.p).to_s(2) | ||||||
|  |      assert_equal z, dh1.derive(dh2_pub) | ||||||
|  |      assert_equal z, dh2.derive(dh1_pub) | ||||||
|  |   | ||||||
|  | +    assert_raise(OpenSSL::PKey::PKeyError) { params.derive(dh1_pub) }
 | ||||||
|  | +    assert_raise(OpenSSL::PKey::PKeyError) { dh1_pub.derive(params) }
 | ||||||
|  | +
 | ||||||
|  |      assert_equal z, dh1.compute_key(dh2.pub_key) | ||||||
|  |      assert_equal z, dh2.compute_key(dh1.pub_key) | ||||||
|  |    end | ||||||
|  | @@ -74,19 +79,16 @@ def test_public_key
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_generate_key | ||||||
|  | -    dh = Fixtures.pkey("dh1024").public_key # creates a copy
 | ||||||
|  | +    # Deprecated in v3.0.0; incompatible with OpenSSL 3.0
 | ||||||
|  | +    dh = Fixtures.pkey("dh1024").public_key # creates a copy with params only
 | ||||||
|  |      assert_no_key(dh) | ||||||
|  |      dh.generate_key! | ||||||
|  |      assert_key(dh) | ||||||
|  | -  end
 | ||||||
|  |   | ||||||
|  | -  def test_key_exchange
 | ||||||
|  | -    dh = Fixtures.pkey("dh1024")
 | ||||||
|  |      dh2 = dh.public_key | ||||||
|  | -    dh.generate_key!
 | ||||||
|  |      dh2.generate_key! | ||||||
|  |      assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key)) | ||||||
|  | -  end
 | ||||||
|  | +  end if !openssl?(3, 0, 0)
 | ||||||
|  |   | ||||||
|  |    def test_params_ok? | ||||||
|  |      dh0 = Fixtures.pkey("dh1024") | ||||||
|  | 
 | ||||||
|  | From 5e2e66cce870ea86001dbb0eaa3092badfd37994 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Fri, 17 Dec 2021 02:21:42 +0900 | ||||||
|  | Subject: [PATCH 4/5] pkey/ec: deprecate OpenSSL::PKey::EC#generate_key! | ||||||
|  | 
 | ||||||
|  | OpenSSL::PKey::EC#generate_key! will not work on OpenSSL 3.0 because | ||||||
|  | keys are made immutable. Users should use OpenSSL::PKey.generate_key | ||||||
|  | instead. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_pkey_ec.c   |  4 ++++ | ||||||
|  |  test/openssl/test_pkey_ec.rb | 21 +++++++++++++-------- | ||||||
|  |  2 files changed, 17 insertions(+), 8 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | index db80d112..398a550a 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | @@ -442,6 +442,9 @@ ossl_ec_key_to_der(VALUE self)
 | ||||||
|  |   */ | ||||||
|  |  static VALUE ossl_ec_key_generate_key(VALUE self) | ||||||
|  |  { | ||||||
|  | +#if OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  | +    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
 | ||||||
|  | +#else
 | ||||||
|  |      EC_KEY *ec; | ||||||
|  |   | ||||||
|  |      GetEC(self, ec); | ||||||
|  | @@ -449,6 +452,7 @@ static VALUE ossl_ec_key_generate_key(VALUE self)
 | ||||||
|  |  	ossl_raise(eECError, "EC_KEY_generate_key"); | ||||||
|  |   | ||||||
|  |      return self; | ||||||
|  | +#endif
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
 | ||||||
|  | index 3f5958af..33f78a4c 100644
 | ||||||
|  | --- a/test/openssl/test_pkey_ec.rb
 | ||||||
|  | +++ b/test/openssl/test_pkey_ec.rb
 | ||||||
|  | @@ -13,15 +13,13 @@ def test_ec_key
 | ||||||
|  |        # FIPS-selftest failure on some environment, so skip for now. | ||||||
|  |        next if ["Oakley", "X25519"].any? { |n| curve_name.start_with?(n) } | ||||||
|  |   | ||||||
|  | -      key = OpenSSL::PKey::EC.new(curve_name)
 | ||||||
|  | -      key.generate_key!
 | ||||||
|  | -
 | ||||||
|  | +      key = OpenSSL::PKey::EC.generate(curve_name)
 | ||||||
|  |        assert_predicate key, :private? | ||||||
|  |        assert_predicate key, :public? | ||||||
|  |        assert_nothing_raised { key.check_key } | ||||||
|  |      end | ||||||
|  |   | ||||||
|  | -    key1 = OpenSSL::PKey::EC.new("prime256v1").generate_key!
 | ||||||
|  | +    key1 = OpenSSL::PKey::EC.generate("prime256v1")
 | ||||||
|  |   | ||||||
|  |      key2 = OpenSSL::PKey::EC.new | ||||||
|  |      key2.group = key1.group | ||||||
|  | @@ -52,6 +50,13 @@ def test_generate
 | ||||||
|  |      assert_equal(true, ec.private?) | ||||||
|  |    end | ||||||
|  |   | ||||||
|  | +  def test_generate_key
 | ||||||
|  | +    ec = OpenSSL::PKey::EC.new("prime256v1")
 | ||||||
|  | +    assert_equal false, ec.private?
 | ||||||
|  | +    ec.generate_key!
 | ||||||
|  | +    assert_equal true, ec.private?
 | ||||||
|  | +  end if !openssl?(3, 0, 0)
 | ||||||
|  | +
 | ||||||
|  |    def test_marshal | ||||||
|  |      key = Fixtures.pkey("p256") | ||||||
|  |      deserialized = Marshal.load(Marshal.dump(key)) | ||||||
|  | @@ -136,7 +141,7 @@ def test_sign_verify_raw
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_dsa_sign_asn1_FIPS186_3 | ||||||
|  | -    key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
 | ||||||
|  | +    key = OpenSSL::PKey::EC.generate("prime256v1")
 | ||||||
|  |      size = key.group.order.num_bits / 8 + 1 | ||||||
|  |      dgst = (1..size).to_a.pack('C*') | ||||||
|  |      sig = key.dsa_sign_asn1(dgst) | ||||||
|  | @@ -145,8 +150,8 @@ def test_dsa_sign_asn1_FIPS186_3
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_dh_compute_key | ||||||
|  | -    key_a = OpenSSL::PKey::EC.new("prime256v1").generate_key!
 | ||||||
|  | -    key_b = OpenSSL::PKey::EC.new(key_a.group).generate_key!
 | ||||||
|  | +    key_a = OpenSSL::PKey::EC.generate("prime256v1")
 | ||||||
|  | +    key_b = OpenSSL::PKey::EC.generate(key_a.group)
 | ||||||
|  |   | ||||||
|  |      pub_a = key_a.public_key | ||||||
|  |      pub_b = key_b.public_key | ||||||
|  | @@ -276,7 +281,7 @@ def test_ec_group
 | ||||||
|  |   | ||||||
|  |    def test_ec_point | ||||||
|  |      group = OpenSSL::PKey::EC::Group.new("prime256v1") | ||||||
|  | -    key = OpenSSL::PKey::EC.new(group).generate_key!
 | ||||||
|  | +    key = OpenSSL::PKey::EC.generate(group)
 | ||||||
|  |      point = key.public_key | ||||||
|  |   | ||||||
|  |      point2 = OpenSSL::PKey::EC::Point.new(group, point.to_bn) | ||||||
|  | 
 | ||||||
|  | From 6848d2d969d90e6a400d89848ecec21076b87888 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Tue, 21 Sep 2021 18:29:59 +0900 | ||||||
|  | Subject: [PATCH 5/5] pkey: deprecate PKey#set_* methods | ||||||
|  | 
 | ||||||
|  | OpenSSL 3.0 made EVP_PKEY immutable. This means we can only have a const | ||||||
|  | pointer of the low level struct and the following methods can no longer | ||||||
|  | be provided when linked against OpenSSL 3.0: | ||||||
|  | 
 | ||||||
|  |  - OpenSSL::PKey::RSA#set_key | ||||||
|  |  - OpenSSL::PKey::RSA#set_factors | ||||||
|  |  - OpenSSL::PKey::RSA#set_crt_params | ||||||
|  |  - OpenSSL::PKey::DSA#set_pqg | ||||||
|  |  - OpenSSL::PKey::DSA#set_key | ||||||
|  |  - OpenSSL::PKey::DH#set_pqg | ||||||
|  |  - OpenSSL::PKey::DH#set_key | ||||||
|  |  - OpenSSL::PKey::EC#group= | ||||||
|  |  - OpenSSL::PKey::EC#private_key= | ||||||
|  |  - OpenSSL::PKey::EC#public_key= | ||||||
|  | 
 | ||||||
|  | There is no direct replacement for this functionality at the moment. | ||||||
|  | I plan to introduce a wrapper around EVP_PKEY_fromdata(), which takes | ||||||
|  | all key components at once to construct an EVP_PKEY. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_pkey.h       | 16 +++++++ | ||||||
|  |  ext/openssl/ossl_pkey_ec.c    | 12 +++++ | ||||||
|  |  test/openssl/test_pkey_dh.rb  | 38 +++++++++++----- | ||||||
|  |  test/openssl/test_pkey_dsa.rb |  8 +++- | ||||||
|  |  test/openssl/test_pkey_ec.rb  | 58 ++++++++++++++---------- | ||||||
|  |  test/openssl/test_pkey_rsa.rb | 85 ++++++++++++++++++++++------------- | ||||||
|  |  6 files changed, 149 insertions(+), 68 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
 | ||||||
|  | index 4beede22..4536e58e 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.h
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.h
 | ||||||
|  | @@ -116,6 +116,7 @@ static VALUE ossl_##_keytype##_get_##_name(VALUE self)			\
 | ||||||
|  |  	OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2,			\ | ||||||
|  |  		_type##_get0_##_group(obj, NULL, &bn)) | ||||||
|  |   | ||||||
|  | +#if !OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  |  #define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3)	\ | ||||||
|  |  /*									\ | ||||||
|  |   *  call-seq:								\ | ||||||
|  | @@ -173,6 +174,21 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
 | ||||||
|  |  	}								\ | ||||||
|  |  	return self;							\ | ||||||
|  |  } | ||||||
|  | +#else
 | ||||||
|  | +#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3)	\
 | ||||||
|  | +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \
 | ||||||
|  | +{									\
 | ||||||
|  | +        rb_raise(ePKeyError,						\
 | ||||||
|  | +                 #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2)	\
 | ||||||
|  | +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
 | ||||||
|  | +{									\
 | ||||||
|  | +        rb_raise(ePKeyError,						\
 | ||||||
|  | +                 #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
 | ||||||
|  | +}
 | ||||||
|  | +#endif
 | ||||||
|  |   | ||||||
|  |  #define OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, _name)	\ | ||||||
|  |  /*									\ | ||||||
|  | diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | index 398a550a..7a6ed1c9 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey_ec.c
 | ||||||
|  | @@ -251,6 +251,9 @@ ossl_ec_key_get_group(VALUE self)
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_ec_key_set_group(VALUE self, VALUE group_v) | ||||||
|  |  { | ||||||
|  | +#if OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  | +    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
 | ||||||
|  | +#else
 | ||||||
|  |      EC_KEY *ec; | ||||||
|  |      EC_GROUP *group; | ||||||
|  |   | ||||||
|  | @@ -261,6 +264,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v)
 | ||||||
|  |          ossl_raise(eECError, "EC_KEY_set_group"); | ||||||
|  |   | ||||||
|  |      return group_v; | ||||||
|  | +#endif
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | @@ -289,6 +293,9 @@ static VALUE ossl_ec_key_get_private_key(VALUE self)
 | ||||||
|  |   */ | ||||||
|  |  static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key) | ||||||
|  |  { | ||||||
|  | +#if OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  | +    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
 | ||||||
|  | +#else
 | ||||||
|  |      EC_KEY *ec; | ||||||
|  |      BIGNUM *bn = NULL; | ||||||
|  |   | ||||||
|  | @@ -307,6 +314,7 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      return private_key; | ||||||
|  | +#endif
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | @@ -335,6 +343,9 @@ static VALUE ossl_ec_key_get_public_key(VALUE self)
 | ||||||
|  |   */ | ||||||
|  |  static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) | ||||||
|  |  { | ||||||
|  | +#if OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  | +    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
 | ||||||
|  | +#else
 | ||||||
|  |      EC_KEY *ec; | ||||||
|  |      EC_POINT *point = NULL; | ||||||
|  |   | ||||||
|  | @@ -353,6 +364,7 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      return public_key; | ||||||
|  | +#endif
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
 | ||||||
|  | index ac11af38..161af189 100644
 | ||||||
|  | --- a/test/openssl/test_pkey_dh.rb
 | ||||||
|  | +++ b/test/openssl/test_pkey_dh.rb
 | ||||||
|  | @@ -107,13 +107,32 @@ def test_params_ok?
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_dup | ||||||
|  | -    dh = Fixtures.pkey("dh1024")
 | ||||||
|  | -    dh2 = dh.dup
 | ||||||
|  | -    assert_equal dh.to_der, dh2.to_der # params
 | ||||||
|  | -    assert_equal_params dh, dh2 # keys
 | ||||||
|  | -    dh2.set_pqg(dh2.p + 1, nil, dh2.g)
 | ||||||
|  | -    assert_not_equal dh2.p, dh.p
 | ||||||
|  | -    assert_equal dh2.g, dh.g
 | ||||||
|  | +    # Parameters only
 | ||||||
|  | +    dh1 = Fixtures.pkey("dh1024")
 | ||||||
|  | +    dh2 = dh1.dup
 | ||||||
|  | +    assert_equal dh1.to_der, dh2.to_der
 | ||||||
|  | +    assert_not_equal nil, dh1.p
 | ||||||
|  | +    assert_not_equal nil, dh1.g
 | ||||||
|  | +    assert_equal [dh1.p, dh1.g], [dh2.p, dh2.g]
 | ||||||
|  | +    assert_equal nil, dh1.pub_key
 | ||||||
|  | +    assert_equal nil, dh1.priv_key
 | ||||||
|  | +    assert_equal [dh1.pub_key, dh1.priv_key], [dh2.pub_key, dh2.priv_key]
 | ||||||
|  | +
 | ||||||
|  | +    # PKey is immutable in OpenSSL >= 3.0
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      dh2.set_pqg(dh2.p + 1, nil, dh2.g)
 | ||||||
|  | +      assert_not_equal dh2.p, dh1.p
 | ||||||
|  | +    end
 | ||||||
|  | +
 | ||||||
|  | +    # With a key pair
 | ||||||
|  | +    dh3 = OpenSSL::PKey.generate_key(Fixtures.pkey("dh1024"))
 | ||||||
|  | +    dh4 = dh3.dup
 | ||||||
|  | +    assert_equal dh3.to_der, dh4.to_der
 | ||||||
|  | +    assert_equal dh1.to_der, dh4.to_der # encodes parameters only
 | ||||||
|  | +    assert_equal [dh1.p, dh1.g], [dh4.p, dh4.g]
 | ||||||
|  | +    assert_not_equal nil, dh3.pub_key
 | ||||||
|  | +    assert_not_equal nil, dh3.priv_key
 | ||||||
|  | +    assert_equal [dh3.pub_key, dh3.priv_key], [dh4.pub_key, dh4.priv_key]
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_marshal | ||||||
|  | @@ -125,11 +144,6 @@ def test_marshal
 | ||||||
|  |   | ||||||
|  |    private | ||||||
|  |   | ||||||
|  | -  def assert_equal_params(dh1, dh2)
 | ||||||
|  | -    assert_equal(dh1.g, dh2.g)
 | ||||||
|  | -    assert_equal(dh1.p, dh2.p)
 | ||||||
|  | -  end
 | ||||||
|  | -
 | ||||||
|  |    def assert_no_key(dh) | ||||||
|  |      assert_equal(false, dh.public?) | ||||||
|  |      assert_equal(false, dh.private?) | ||||||
|  | diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
 | ||||||
|  | index 0994607f..726b7dbf 100644
 | ||||||
|  | --- a/test/openssl/test_pkey_dsa.rb
 | ||||||
|  | +++ b/test/openssl/test_pkey_dsa.rb
 | ||||||
|  | @@ -208,8 +208,12 @@ def test_dup
 | ||||||
|  |      key = Fixtures.pkey("dsa1024") | ||||||
|  |      key2 = key.dup | ||||||
|  |      assert_equal key.params, key2.params | ||||||
|  | -    key2.set_pqg(key2.p + 1, key2.q, key2.g)
 | ||||||
|  | -    assert_not_equal key.params, key2.params
 | ||||||
|  | +
 | ||||||
|  | +    # PKey is immutable in OpenSSL >= 3.0
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      key2.set_pqg(key2.p + 1, key2.q, key2.g)
 | ||||||
|  | +      assert_not_equal key.params, key2.params
 | ||||||
|  | +    end
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_marshal | ||||||
|  | diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
 | ||||||
|  | index 33f78a4c..ffe5a94e 100644
 | ||||||
|  | --- a/test/openssl/test_pkey_ec.rb
 | ||||||
|  | +++ b/test/openssl/test_pkey_ec.rb
 | ||||||
|  | @@ -21,11 +21,15 @@ def test_ec_key
 | ||||||
|  |   | ||||||
|  |      key1 = OpenSSL::PKey::EC.generate("prime256v1") | ||||||
|  |   | ||||||
|  | -    key2 = OpenSSL::PKey::EC.new
 | ||||||
|  | -    key2.group = key1.group
 | ||||||
|  | -    key2.private_key = key1.private_key
 | ||||||
|  | -    key2.public_key = key1.public_key
 | ||||||
|  | -    assert_equal key1.to_der, key2.to_der
 | ||||||
|  | +    # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is
 | ||||||
|  | +    # deprecated
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      key2 = OpenSSL::PKey::EC.new
 | ||||||
|  | +      key2.group = key1.group
 | ||||||
|  | +      key2.private_key = key1.private_key
 | ||||||
|  | +      key2.public_key = key1.public_key
 | ||||||
|  | +      assert_equal key1.to_der, key2.to_der
 | ||||||
|  | +    end
 | ||||||
|  |   | ||||||
|  |      key3 = OpenSSL::PKey::EC.new(key1) | ||||||
|  |      assert_equal key1.to_der, key3.to_der | ||||||
|  | @@ -35,10 +39,14 @@ def test_ec_key
 | ||||||
|  |   | ||||||
|  |      key5 = key1.dup | ||||||
|  |      assert_equal key1.to_der, key5.to_der | ||||||
|  | -    key_tmp = OpenSSL::PKey::EC.new("prime256v1").generate_key!
 | ||||||
|  | -    key5.private_key = key_tmp.private_key
 | ||||||
|  | -    key5.public_key = key_tmp.public_key
 | ||||||
|  | -    assert_not_equal key1.to_der, key5.to_der
 | ||||||
|  | +
 | ||||||
|  | +    # PKey is immutable in OpenSSL >= 3.0; EC object should not be modified
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      key_tmp = OpenSSL::PKey::EC.generate("prime256v1")
 | ||||||
|  | +      key5.private_key = key_tmp.private_key
 | ||||||
|  | +      key5.public_key = key_tmp.public_key
 | ||||||
|  | +      assert_not_equal key1.to_der, key5.to_der
 | ||||||
|  | +    end
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_generate | ||||||
|  | @@ -65,22 +73,26 @@ def test_marshal
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_check_key | ||||||
|  | -    key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
 | ||||||
|  | -    assert_equal(true, key.check_key)
 | ||||||
|  | -    assert_equal(true, key.private?)
 | ||||||
|  | -    assert_equal(true, key.public?)
 | ||||||
|  | -    key2 = OpenSSL::PKey::EC.new(key.group)
 | ||||||
|  | -    assert_equal(false, key2.private?)
 | ||||||
|  | -    assert_equal(false, key2.public?)
 | ||||||
|  | -    key2.public_key = key.public_key
 | ||||||
|  | -    assert_equal(false, key2.private?)
 | ||||||
|  | -    assert_equal(true, key2.public?)
 | ||||||
|  | -    key2.private_key = key.private_key
 | ||||||
|  | +    key0 = Fixtures.pkey("p256")
 | ||||||
|  | +    assert_equal(true, key0.check_key)
 | ||||||
|  | +    assert_equal(true, key0.private?)
 | ||||||
|  | +    assert_equal(true, key0.public?)
 | ||||||
|  | +
 | ||||||
|  | +    key1 = OpenSSL::PKey.read(key0.public_to_der)
 | ||||||
|  | +    assert_equal(true, key1.check_key)
 | ||||||
|  | +    assert_equal(false, key1.private?)
 | ||||||
|  | +    assert_equal(true, key1.public?)
 | ||||||
|  | +
 | ||||||
|  | +    key2 = OpenSSL::PKey.read(key0.private_to_der)
 | ||||||
|  |      assert_equal(true, key2.private?) | ||||||
|  |      assert_equal(true, key2.public?) | ||||||
|  |      assert_equal(true, key2.check_key) | ||||||
|  | -    key2.private_key += 1
 | ||||||
|  | -    assert_raise(OpenSSL::PKey::ECError) { key2.check_key }
 | ||||||
|  | +
 | ||||||
|  | +    # EC#private_key= is deprecated in 3.0 and won't work on OpenSSL 3.0
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      key2.private_key += 1
 | ||||||
|  | +      assert_raise(OpenSSL::PKey::ECError) { key2.check_key }
 | ||||||
|  | +    end
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_sign_verify | ||||||
|  | @@ -112,7 +124,7 @@ def test_derive_key
 | ||||||
|  |      assert_equal [zIUT].pack("H*"), a.derive(b) | ||||||
|  |   | ||||||
|  |      assert_equal a.derive(b), a.dh_compute_key(b.public_key) | ||||||
|  | -  end
 | ||||||
|  | +  end if !openssl?(3, 0, 0) # TODO: Test it without using #private_key=
 | ||||||
|  |   | ||||||
|  |    def test_sign_verify_raw | ||||||
|  |      key = Fixtures.pkey("p256") | ||||||
|  | diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | index dbe87ba4..1c7f9ccf 100644
 | ||||||
|  | --- a/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | +++ b/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | @@ -31,15 +31,18 @@ def test_private
 | ||||||
|  |      assert(!key4.private?) | ||||||
|  |      rsa1024 = Fixtures.pkey("rsa1024") | ||||||
|  |   | ||||||
|  | -    # Generated by RSA#set_key
 | ||||||
|  | -    key5 = OpenSSL::PKey::RSA.new
 | ||||||
|  | -    key5.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
 | ||||||
|  | -    assert(key5.private?)
 | ||||||
|  | -
 | ||||||
|  | -    # Generated by RSA#set_key, without d
 | ||||||
|  | -    key6 = OpenSSL::PKey::RSA.new
 | ||||||
|  | -    key6.set_key(rsa1024.n, rsa1024.e, nil)
 | ||||||
|  | -    assert(!key6.private?)
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      key = OpenSSL::PKey::RSA.new
 | ||||||
|  | +      # Generated by RSA#set_key
 | ||||||
|  | +      key5 = OpenSSL::PKey::RSA.new
 | ||||||
|  | +      key5.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
 | ||||||
|  | +      assert(key5.private?)
 | ||||||
|  | +
 | ||||||
|  | +      # Generated by RSA#set_key, without d
 | ||||||
|  | +      key6 = OpenSSL::PKey::RSA.new
 | ||||||
|  | +      key6.set_key(rsa1024.n, rsa1024.e, nil)
 | ||||||
|  | +      assert(!key6.private?)
 | ||||||
|  | +    end
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_new | ||||||
|  | @@ -235,36 +238,52 @@ def test_encrypt_decrypt_legacy
 | ||||||
|  |   | ||||||
|  |    def test_export | ||||||
|  |      rsa1024 = Fixtures.pkey("rsa1024") | ||||||
|  | -    key = OpenSSL::PKey::RSA.new
 | ||||||
|  |   | ||||||
|  | -    # key has only n, e and d
 | ||||||
|  | -    key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
 | ||||||
|  | -    assert_equal rsa1024.public_key.export, key.export
 | ||||||
|  | +    pub = OpenSSL::PKey.read(rsa1024.public_to_der)
 | ||||||
|  | +    assert_not_equal rsa1024.export, pub.export
 | ||||||
|  | +    assert_equal rsa1024.public_to_pem, pub.export
 | ||||||
|  | +
 | ||||||
|  | +    # PKey is immutable in OpenSSL >= 3.0
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      key = OpenSSL::PKey::RSA.new
 | ||||||
|  |   | ||||||
|  | -    # key has only n, e, d, p and q
 | ||||||
|  | -    key.set_factors(rsa1024.p, rsa1024.q)
 | ||||||
|  | -    assert_equal rsa1024.public_key.export, key.export
 | ||||||
|  | +      # key has only n, e and d
 | ||||||
|  | +      key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
 | ||||||
|  | +      assert_equal rsa1024.public_key.export, key.export
 | ||||||
|  |   | ||||||
|  | -    # key has n, e, d, p, q, dmp1, dmq1 and iqmp
 | ||||||
|  | -    key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
 | ||||||
|  | -    assert_equal rsa1024.export, key.export
 | ||||||
|  | +      # key has only n, e, d, p and q
 | ||||||
|  | +      key.set_factors(rsa1024.p, rsa1024.q)
 | ||||||
|  | +      assert_equal rsa1024.public_key.export, key.export
 | ||||||
|  | +
 | ||||||
|  | +      # key has n, e, d, p, q, dmp1, dmq1 and iqmp
 | ||||||
|  | +      key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
 | ||||||
|  | +      assert_equal rsa1024.export, key.export
 | ||||||
|  | +    end
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_to_der | ||||||
|  |      rsa1024 = Fixtures.pkey("rsa1024") | ||||||
|  | -    key = OpenSSL::PKey::RSA.new
 | ||||||
|  |   | ||||||
|  | -    # key has only n, e and d
 | ||||||
|  | -    key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
 | ||||||
|  | -    assert_equal rsa1024.public_key.to_der, key.to_der
 | ||||||
|  | +    pub = OpenSSL::PKey.read(rsa1024.public_to_der)
 | ||||||
|  | +    assert_not_equal rsa1024.to_der, pub.to_der
 | ||||||
|  | +    assert_equal rsa1024.public_to_der, pub.to_der
 | ||||||
|  |   | ||||||
|  | -    # key has only n, e, d, p and q
 | ||||||
|  | -    key.set_factors(rsa1024.p, rsa1024.q)
 | ||||||
|  | -    assert_equal rsa1024.public_key.to_der, key.to_der
 | ||||||
|  | +    # PKey is immutable in OpenSSL >= 3.0
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      key = OpenSSL::PKey::RSA.new
 | ||||||
|  |   | ||||||
|  | -    # key has n, e, d, p, q, dmp1, dmq1 and iqmp
 | ||||||
|  | -    key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
 | ||||||
|  | -    assert_equal rsa1024.to_der, key.to_der
 | ||||||
|  | +      # key has only n, e and d
 | ||||||
|  | +      key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
 | ||||||
|  | +      assert_equal rsa1024.public_key.to_der, key.to_der
 | ||||||
|  | +
 | ||||||
|  | +      # key has only n, e, d, p and q
 | ||||||
|  | +      key.set_factors(rsa1024.p, rsa1024.q)
 | ||||||
|  | +      assert_equal rsa1024.public_key.to_der, key.to_der
 | ||||||
|  | +
 | ||||||
|  | +      # key has n, e, d, p, q, dmp1, dmq1 and iqmp
 | ||||||
|  | +      key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
 | ||||||
|  | +      assert_equal rsa1024.to_der, key.to_der
 | ||||||
|  | +    end
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_RSAPrivateKey | ||||||
|  | @@ -501,8 +520,12 @@ def test_dup
 | ||||||
|  |      key = Fixtures.pkey("rsa1024") | ||||||
|  |      key2 = key.dup | ||||||
|  |      assert_equal key.params, key2.params | ||||||
|  | -    key2.set_key(key2.n, 3, key2.d)
 | ||||||
|  | -    assert_not_equal key.params, key2.params
 | ||||||
|  | +
 | ||||||
|  | +    # PKey is immutable in OpenSSL >= 3.0
 | ||||||
|  | +    if !openssl?(3, 0, 0)
 | ||||||
|  | +      key2.set_key(key2.n, 3, key2.d)
 | ||||||
|  | +      assert_not_equal key.params, key2.params
 | ||||||
|  | +    end
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_marshal | ||||||
							
								
								
									
										27
									
								
								ruby-3.1.0-Disable-test_no_private_exp-on-OpenSSL-3.0.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								ruby-3.1.0-Disable-test_no_private_exp-on-OpenSSL-3.0.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | From 47975ece4096cdab16b3f200f93ea2377dfb41ac Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Mon, 31 May 2021 14:17:21 +0900 | ||||||
|  | Subject: [PATCH] test/openssl/test_pkey_rsa: disable test_no_private_exp on | ||||||
|  |  OpenSSL 3.0 | ||||||
|  | 
 | ||||||
|  | OpenSSL::PKey::RSA#set_key does not exist when built with OpenSSL 3.0, | ||||||
|  | so it is not possible to create an RSA object with incomplete state. | ||||||
|  | 
 | ||||||
|  | https://github.com/ruby/openssl/commit/ca03c9c070 | ||||||
|  | ---
 | ||||||
|  |  test/openssl/test_pkey_rsa.rb | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | index 4548bdb2cfa6..dbe87ba4c1b0 100644
 | ||||||
|  | --- a/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | +++ b/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | @@ -11,7 +11,7 @@ def test_no_private_exp
 | ||||||
|  |      key.set_factors(rsa.p, rsa.q) | ||||||
|  |      assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt("foo") } | ||||||
|  |      assert_raise(OpenSSL::PKey::RSAError){ key.private_decrypt("foo") } | ||||||
|  | -  end
 | ||||||
|  | +  end if !openssl?(3, 0, 0) # Impossible state in OpenSSL 3.0
 | ||||||
|  |   | ||||||
|  |    def test_private | ||||||
|  |      # Generated by key size and public exponent | ||||||
| @ -0,0 +1,523 @@ | |||||||
|  | From 8253d7c9cea16c2aa009b59db4f5d93afb74c6eb Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Tue, 30 Jun 2020 14:27:13 +0900 | ||||||
|  | Subject: [PATCH 1/2] hmac: add a test case for OpenSSL::HMAC singleton methods | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  test/openssl/test_hmac.rb | 9 +++++++++ | ||||||
|  |  1 file changed, 9 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb
 | ||||||
|  | index 9cb3c5a86..7202a5902 100644
 | ||||||
|  | --- a/test/openssl/test_hmac.rb
 | ||||||
|  | +++ b/test/openssl/test_hmac.rb
 | ||||||
|  | @@ -49,6 +49,15 @@ def test_eq
 | ||||||
|  |      refute_equal h1, h2.digest | ||||||
|  |      refute_equal h1, h3 | ||||||
|  |    end | ||||||
|  | +
 | ||||||
|  | +  def test_singleton_methods
 | ||||||
|  | +    # RFC 2202 2. Test Cases for HMAC-MD5
 | ||||||
|  | +    key = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*")
 | ||||||
|  | +    digest = OpenSSL::HMAC.digest("MD5", key, "Hi There")
 | ||||||
|  | +    assert_equal ["9294727a3638bb1c13f48ef8158bfc9d"].pack("H*"), digest
 | ||||||
|  | +    hexdigest = OpenSSL::HMAC.hexdigest("MD5", key, "Hi There")
 | ||||||
|  | +    assert_equal "9294727a3638bb1c13f48ef8158bfc9d", hexdigest
 | ||||||
|  | +  end
 | ||||||
|  |  end | ||||||
|  |   | ||||||
|  |  end | ||||||
|  | 
 | ||||||
|  | From 0317e2fc028be40a7d64d0e4337d3e21539613ce Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Mon, 18 May 2020 16:15:07 +0900 | ||||||
|  | Subject: [PATCH 2/2] hmac: migrate from the low-level HMAC API to the EVP API | ||||||
|  | 
 | ||||||
|  | Use the EVP API instead of the low-level HMAC API. Use of the HMAC API | ||||||
|  | has been discouraged and is being marked as deprecated starting from | ||||||
|  | OpenSSL 3.0.0. | ||||||
|  | 
 | ||||||
|  | The two singleton methods OpenSSL::HMAC, HMAC.digest and HMAC.hexdigest | ||||||
|  | are now in lib/openssl/hmac.rb. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/extconf.rb          |   3 +- | ||||||
|  |  ext/openssl/lib/openssl/hmac.rb |  40 +++++++ | ||||||
|  |  ext/openssl/openssl_missing.c   |  26 ----- | ||||||
|  |  ext/openssl/openssl_missing.h   |  10 +- | ||||||
|  |  ext/openssl/ossl.h              |   1 - | ||||||
|  |  ext/openssl/ossl_hmac.c         | 179 ++++++++------------------------ | ||||||
|  |  6 files changed, 89 insertions(+), 170 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
 | ||||||
|  | index 693e55cd9..063498a76 100644
 | ||||||
|  | --- a/ext/openssl/extconf.rb
 | ||||||
|  | +++ b/ext/openssl/extconf.rb
 | ||||||
|  | @@ -141,8 +141,7 @@ def find_openssl_library
 | ||||||
|  |  have_func("BN_GENCB_get_arg") | ||||||
|  |  have_func("EVP_MD_CTX_new") | ||||||
|  |  have_func("EVP_MD_CTX_free") | ||||||
|  | -have_func("HMAC_CTX_new")
 | ||||||
|  | -have_func("HMAC_CTX_free")
 | ||||||
|  | +have_func("EVP_MD_CTX_pkey_ctx")
 | ||||||
|  |  have_func("X509_STORE_get_ex_data") | ||||||
|  |  have_func("X509_STORE_set_ex_data") | ||||||
|  |  have_func("X509_STORE_get_ex_new_index") | ||||||
|  | diff --git a/ext/openssl/lib/openssl/hmac.rb b/ext/openssl/lib/openssl/hmac.rb
 | ||||||
|  | index 3d4427611d..9bc8bc8df3 100644
 | ||||||
|  | --- a/ext/openssl/lib/openssl/hmac.rb
 | ||||||
|  | +++ b/ext/openssl/lib/openssl/hmac.rb
 | ||||||
|  | @@ -9,5 +9,45 @@ def ==(other)
 | ||||||
|  |   | ||||||
|  |        OpenSSL.fixed_length_secure_compare(self.digest, other.digest) | ||||||
|  |      end | ||||||
|  | +
 | ||||||
|  | +    class << self
 | ||||||
|  | +      # :call-seq:
 | ||||||
|  | +      #    HMAC.digest(digest, key, data) -> aString
 | ||||||
|  | +      #
 | ||||||
|  | +      # Returns the authentication code as a binary string. The _digest_ parameter
 | ||||||
|  | +      # specifies the digest algorithm to use. This may be a String representing
 | ||||||
|  | +      # the algorithm name or an instance of OpenSSL::Digest.
 | ||||||
|  | +      #
 | ||||||
|  | +      # === Example
 | ||||||
|  | +      #  key = 'key'
 | ||||||
|  | +      #  data = 'The quick brown fox jumps over the lazy dog'
 | ||||||
|  | +      #
 | ||||||
|  | +      #  hmac = OpenSSL::HMAC.digest('SHA1', key, data)
 | ||||||
|  | +      #  #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
 | ||||||
|  | +      def digest(digest, key, data)
 | ||||||
|  | +        hmac = new(key, digest)
 | ||||||
|  | +        hmac << data
 | ||||||
|  | +        hmac.digest
 | ||||||
|  | +      end
 | ||||||
|  | +
 | ||||||
|  | +      # :call-seq:
 | ||||||
|  | +      #    HMAC.hexdigest(digest, key, data) -> aString
 | ||||||
|  | +      #
 | ||||||
|  | +      # Returns the authentication code as a hex-encoded string. The _digest_
 | ||||||
|  | +      # parameter specifies the digest algorithm to use. This may be a String
 | ||||||
|  | +      # representing the algorithm name or an instance of OpenSSL::Digest.
 | ||||||
|  | +      #
 | ||||||
|  | +      # === Example
 | ||||||
|  | +      #  key = 'key'
 | ||||||
|  | +      #  data = 'The quick brown fox jumps over the lazy dog'
 | ||||||
|  | +      #
 | ||||||
|  | +      #  hmac = OpenSSL::HMAC.hexdigest('SHA1', key, data)
 | ||||||
|  | +      #  #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
 | ||||||
|  | +      def hexdigest(digest, key, data)
 | ||||||
|  | +        hmac = new(key, digest)
 | ||||||
|  | +        hmac << data
 | ||||||
|  | +        hmac.hexdigest
 | ||||||
|  | +      end
 | ||||||
|  | +    end
 | ||||||
|  |    end | ||||||
|  |  end | ||||||
|  | diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
 | ||||||
|  | index b36ef0288..010c158dc 100644
 | ||||||
|  | --- a/ext/openssl/openssl_missing.c
 | ||||||
|  | +++ b/ext/openssl/openssl_missing.c
 | ||||||
|  | @@ -13,9 +13,6 @@
 | ||||||
|  |  #if !defined(OPENSSL_NO_ENGINE) | ||||||
|  |  # include <openssl/engine.h> | ||||||
|  |  #endif | ||||||
|  | -#if !defined(OPENSSL_NO_HMAC)
 | ||||||
|  | -# include <openssl/hmac.h>
 | ||||||
|  | -#endif
 | ||||||
|  |  #include <openssl/x509_vfy.h> | ||||||
|  |   | ||||||
|  |  #include "openssl_missing.h" | ||||||
|  | @@ -58,29 +55,6 @@ ossl_EC_curve_nist2nid(const char *name)
 | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  |  /*** added in 1.1.0 ***/ | ||||||
|  | -#if !defined(HAVE_HMAC_CTX_NEW)
 | ||||||
|  | -HMAC_CTX *
 | ||||||
|  | -ossl_HMAC_CTX_new(void)
 | ||||||
|  | -{
 | ||||||
|  | -    HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX));
 | ||||||
|  | -    if (!ctx)
 | ||||||
|  | -	return NULL;
 | ||||||
|  | -    HMAC_CTX_init(ctx);
 | ||||||
|  | -    return ctx;
 | ||||||
|  | -}
 | ||||||
|  | -#endif
 | ||||||
|  | -
 | ||||||
|  | -#if !defined(HAVE_HMAC_CTX_FREE)
 | ||||||
|  | -void
 | ||||||
|  | -ossl_HMAC_CTX_free(HMAC_CTX *ctx)
 | ||||||
|  | -{
 | ||||||
|  | -    if (ctx) {
 | ||||||
|  | -	HMAC_CTX_cleanup(ctx);
 | ||||||
|  | -	OPENSSL_free(ctx);
 | ||||||
|  | -    }
 | ||||||
|  | -}
 | ||||||
|  | -#endif
 | ||||||
|  | -
 | ||||||
|  |  #if !defined(HAVE_X509_CRL_GET0_SIGNATURE) | ||||||
|  |  void | ||||||
|  |  ossl_X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, | ||||||
|  | diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
 | ||||||
|  | index 7d218f86f..06d2a9082 100644
 | ||||||
|  | --- a/ext/openssl/openssl_missing.h
 | ||||||
|  | +++ b/ext/openssl/openssl_missing.h
 | ||||||
|  | @@ -54,14 +54,8 @@ int ossl_EC_curve_nist2nid(const char *);
 | ||||||
|  |  #  define EVP_MD_CTX_free EVP_MD_CTX_destroy | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | -#if !defined(HAVE_HMAC_CTX_NEW)
 | ||||||
|  | -HMAC_CTX *ossl_HMAC_CTX_new(void);
 | ||||||
|  | -#  define HMAC_CTX_new ossl_HMAC_CTX_new
 | ||||||
|  | -#endif
 | ||||||
|  | -
 | ||||||
|  | -#if !defined(HAVE_HMAC_CTX_FREE)
 | ||||||
|  | -void ossl_HMAC_CTX_free(HMAC_CTX *);
 | ||||||
|  | -#  define HMAC_CTX_free ossl_HMAC_CTX_free
 | ||||||
|  | +#if !defined(HAVE_EVP_MD_CTX_PKEY_CTX)
 | ||||||
|  | +#  define EVP_MD_CTX_pkey_ctx(x) (x)->pctx
 | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  |  #if !defined(HAVE_X509_STORE_GET_EX_DATA) | ||||||
|  | diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
 | ||||||
|  | index c20f506bd..577eb6d6b 100644
 | ||||||
|  | --- a/ext/openssl/ossl.h
 | ||||||
|  | +++ b/ext/openssl/ossl.h
 | ||||||
|  | @@ -24,7 +24,6 @@
 | ||||||
|  |  #include <openssl/ssl.h> | ||||||
|  |  #include <openssl/pkcs12.h> | ||||||
|  |  #include <openssl/pkcs7.h> | ||||||
|  | -#include <openssl/hmac.h>
 | ||||||
|  |  #include <openssl/rand.h> | ||||||
|  |  #include <openssl/conf.h> | ||||||
|  |  #ifndef OPENSSL_NO_TS | ||||||
|  | diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
 | ||||||
|  | index 70e9fb819..a21db6c48 100644
 | ||||||
|  | --- a/ext/openssl/ossl_hmac.c
 | ||||||
|  | +++ b/ext/openssl/ossl_hmac.c
 | ||||||
|  | @@ -7,14 +7,12 @@
 | ||||||
|  |   * This program is licensed under the same licence as Ruby. | ||||||
|  |   * (See the file 'LICENCE'.) | ||||||
|  |   */ | ||||||
|  | -#if !defined(OPENSSL_NO_HMAC)
 | ||||||
|  | -
 | ||||||
|  |  #include "ossl.h" | ||||||
|  |   | ||||||
|  |  #define NewHMAC(klass) \ | ||||||
|  |      TypedData_Wrap_Struct((klass), &ossl_hmac_type, 0) | ||||||
|  |  #define GetHMAC(obj, ctx) do { \ | ||||||
|  | -    TypedData_Get_Struct((obj), HMAC_CTX, &ossl_hmac_type, (ctx)); \
 | ||||||
|  | +    TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_hmac_type, (ctx)); \
 | ||||||
|  |      if (!(ctx)) { \ | ||||||
|  |  	ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \ | ||||||
|  |      } \ | ||||||
|  | @@ -36,7 +34,7 @@ VALUE eHMACError;
 | ||||||
|  |  static void | ||||||
|  |  ossl_hmac_free(void *ctx) | ||||||
|  |  { | ||||||
|  | -    HMAC_CTX_free(ctx);
 | ||||||
|  | +    EVP_MD_CTX_free(ctx);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static const rb_data_type_t ossl_hmac_type = { | ||||||
|  | @@ -51,12 +49,12 @@ static VALUE
 | ||||||
|  |  ossl_hmac_alloc(VALUE klass) | ||||||
|  |  { | ||||||
|  |      VALUE obj; | ||||||
|  | -    HMAC_CTX *ctx;
 | ||||||
|  | +    EVP_MD_CTX *ctx;
 | ||||||
|  |   | ||||||
|  |      obj = NewHMAC(klass); | ||||||
|  | -    ctx = HMAC_CTX_new();
 | ||||||
|  | +    ctx = EVP_MD_CTX_new();
 | ||||||
|  |      if (!ctx) | ||||||
|  | -	ossl_raise(eHMACError, NULL);
 | ||||||
|  | +        ossl_raise(eHMACError, "EVP_MD_CTX");
 | ||||||
|  |      RTYPEDDATA_DATA(obj) = ctx; | ||||||
|  |   | ||||||
|  |      return obj; | ||||||
|  | @@ -76,8 +74,7 @@ ossl_hmac_alloc(VALUE klass)
 | ||||||
|  |   * === Example | ||||||
|  |   * | ||||||
|  |   *	key = 'key' | ||||||
|  | - * 	digest = OpenSSL::Digest.new('sha1')
 | ||||||
|  | - * 	instance = OpenSSL::HMAC.new(key, digest)
 | ||||||
|  | + * 	instance = OpenSSL::HMAC.new(key, 'SHA1')
 | ||||||
|  |   * 	#=> f42bb0eeb018ebbd4597ae7213711ec60760843f | ||||||
|  |   * 	instance.class | ||||||
|  |   * 	#=> OpenSSL::HMAC | ||||||
|  | @@ -86,7 +83,7 @@ ossl_hmac_alloc(VALUE klass)
 | ||||||
|  |   * | ||||||
|  |   * Two instances can be securely compared with #== in constant time: | ||||||
|  |   * | ||||||
|  | - *	other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
 | ||||||
|  | + *	other_instance = OpenSSL::HMAC.new('key', 'SHA1')
 | ||||||
|  |   *  #=> f42bb0eeb018ebbd4597ae7213711ec60760843f | ||||||
|  |   *  instance == other_instance | ||||||
|  |   *  #=> true | ||||||
|  | @@ -95,12 +92,23 @@ ossl_hmac_alloc(VALUE klass)
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) | ||||||
|  |  { | ||||||
|  | -    HMAC_CTX *ctx;
 | ||||||
|  | +    EVP_MD_CTX *ctx;
 | ||||||
|  | +    EVP_PKEY *pkey;
 | ||||||
|  |   | ||||||
|  | -    StringValue(key);
 | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  | -    HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key),
 | ||||||
|  | -		 ossl_evp_get_digestbyname(digest), NULL);
 | ||||||
|  | +    StringValue(key);
 | ||||||
|  | +    pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
 | ||||||
|  | +                                (unsigned char *)RSTRING_PTR(key),
 | ||||||
|  | +                                RSTRING_LENINT(key));
 | ||||||
|  | +    if (!pkey)
 | ||||||
|  | +        ossl_raise(eHMACError, "EVP_PKEY_new_mac_key");
 | ||||||
|  | +    if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest),
 | ||||||
|  | +                           NULL, pkey) != 1) {
 | ||||||
|  | +        EVP_PKEY_free(pkey);
 | ||||||
|  | +        ossl_raise(eHMACError, "EVP_DigestSignInit");
 | ||||||
|  | +    }
 | ||||||
|  | +    /* Decrement reference counter; EVP_MD_CTX still keeps it */
 | ||||||
|  | +    EVP_PKEY_free(pkey);
 | ||||||
|  |   | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  | @@ -108,16 +116,15 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_hmac_copy(VALUE self, VALUE other) | ||||||
|  |  { | ||||||
|  | -    HMAC_CTX *ctx1, *ctx2;
 | ||||||
|  | +    EVP_MD_CTX *ctx1, *ctx2;
 | ||||||
|  |   | ||||||
|  |      rb_check_frozen(self); | ||||||
|  |      if (self == other) return self; | ||||||
|  |   | ||||||
|  |      GetHMAC(self, ctx1); | ||||||
|  |      GetHMAC(other, ctx2); | ||||||
|  | -
 | ||||||
|  | -    if (!HMAC_CTX_copy(ctx1, ctx2))
 | ||||||
|  | -	ossl_raise(eHMACError, "HMAC_CTX_copy");
 | ||||||
|  | +    if (EVP_MD_CTX_copy(ctx1, ctx2) != 1)
 | ||||||
|  | +        ossl_raise(eHMACError, "EVP_MD_CTX_copy");
 | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -142,33 +149,16 @@ ossl_hmac_copy(VALUE self, VALUE other)
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_hmac_update(VALUE self, VALUE data) | ||||||
|  |  { | ||||||
|  | -    HMAC_CTX *ctx;
 | ||||||
|  | +    EVP_MD_CTX *ctx;
 | ||||||
|  |   | ||||||
|  |      StringValue(data); | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  | -    HMAC_Update(ctx, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data));
 | ||||||
|  | +    if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
 | ||||||
|  | +        ossl_raise(eHMACError, "EVP_DigestSignUpdate");
 | ||||||
|  |   | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static void
 | ||||||
|  | -hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
 | ||||||
|  | -{
 | ||||||
|  | -    HMAC_CTX *final;
 | ||||||
|  | -
 | ||||||
|  | -    final = HMAC_CTX_new();
 | ||||||
|  | -    if (!final)
 | ||||||
|  | -	ossl_raise(eHMACError, "HMAC_CTX_new");
 | ||||||
|  | -
 | ||||||
|  | -    if (!HMAC_CTX_copy(final, ctx)) {
 | ||||||
|  | -	HMAC_CTX_free(final);
 | ||||||
|  | -	ossl_raise(eHMACError, "HMAC_CTX_copy");
 | ||||||
|  | -    }
 | ||||||
|  | -
 | ||||||
|  | -    HMAC_Final(final, buf, buf_len);
 | ||||||
|  | -    HMAC_CTX_free(final);
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  |  /* | ||||||
|  |   *  call-seq: | ||||||
|  |   *     hmac.digest -> string | ||||||
|  | @@ -176,7 +166,7 @@ hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
 | ||||||
|  |   * Returns the authentication code an instance represents as a binary string. | ||||||
|  |   * | ||||||
|  |   * === Example | ||||||
|  | - *  instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
 | ||||||
|  | + *  instance = OpenSSL::HMAC.new('key', 'SHA1')
 | ||||||
|  |   *  #=> f42bb0eeb018ebbd4597ae7213711ec60760843f | ||||||
|  |   *  instance.digest | ||||||
|  |   *  #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?" | ||||||
|  | @@ -184,15 +174,16 @@ hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_hmac_digest(VALUE self) | ||||||
|  |  { | ||||||
|  | -    HMAC_CTX *ctx;
 | ||||||
|  | -    unsigned int buf_len;
 | ||||||
|  | +    EVP_MD_CTX *ctx;
 | ||||||
|  | +    size_t buf_len;
 | ||||||
|  |      VALUE ret; | ||||||
|  |   | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  |      ret = rb_str_new(NULL, EVP_MAX_MD_SIZE); | ||||||
|  | -    hmac_final(ctx, (unsigned char *)RSTRING_PTR(ret), &buf_len);
 | ||||||
|  | -    assert(buf_len <= EVP_MAX_MD_SIZE);
 | ||||||
|  | -    rb_str_set_len(ret, buf_len);
 | ||||||
|  | +    if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(ret),
 | ||||||
|  | +                            &buf_len) != 1)
 | ||||||
|  | +        ossl_raise(eHMACError, "EVP_DigestSignFinal");
 | ||||||
|  | +    rb_str_set_len(ret, (long)buf_len);
 | ||||||
|  |   | ||||||
|  |      return ret; | ||||||
|  |  } | ||||||
|  | @@ -207,13 +198,14 @@ ossl_hmac_digest(VALUE self)
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_hmac_hexdigest(VALUE self) | ||||||
|  |  { | ||||||
|  | -    HMAC_CTX *ctx;
 | ||||||
|  | +    EVP_MD_CTX *ctx;
 | ||||||
|  |      unsigned char buf[EVP_MAX_MD_SIZE]; | ||||||
|  | -    unsigned int buf_len;
 | ||||||
|  | +    size_t buf_len;
 | ||||||
|  |      VALUE ret; | ||||||
|  |   | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  | -    hmac_final(ctx, buf, &buf_len);
 | ||||||
|  | +    if (EVP_DigestSignFinal(ctx, buf, &buf_len) != 1)
 | ||||||
|  | +        ossl_raise(eHMACError, "EVP_DigestSignFinal");
 | ||||||
|  |      ret = rb_str_new(NULL, buf_len * 2); | ||||||
|  |      ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len); | ||||||
|  |   | ||||||
|  | @@ -230,7 +222,7 @@ ossl_hmac_hexdigest(VALUE self)
 | ||||||
|  |   * === Example | ||||||
|  |   * | ||||||
|  |   *	data = "The quick brown fox jumps over the lazy dog" | ||||||
|  | - * 	instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
 | ||||||
|  | + * 	instance = OpenSSL::HMAC.new('key', 'SHA1')
 | ||||||
|  |   * 	#=> f42bb0eeb018ebbd4597ae7213711ec60760843f | ||||||
|  |   * | ||||||
|  |   * 	instance.update(data) | ||||||
|  | @@ -242,84 +234,17 @@ ossl_hmac_hexdigest(VALUE self)
 | ||||||
|  |  static VALUE | ||||||
|  |  ossl_hmac_reset(VALUE self) | ||||||
|  |  { | ||||||
|  | -    HMAC_CTX *ctx;
 | ||||||
|  | +    EVP_MD_CTX *ctx;
 | ||||||
|  | +    EVP_PKEY *pkey;
 | ||||||
|  |   | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  | -    HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
 | ||||||
|  | +    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
 | ||||||
|  | +    if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_md(ctx), NULL, pkey) != 1)
 | ||||||
|  | +        ossl_raise(eHMACError, "EVP_DigestSignInit");
 | ||||||
|  |   | ||||||
|  |      return self; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -/*
 | ||||||
|  | - *  call-seq:
 | ||||||
|  | - *     HMAC.digest(digest, key, data) -> aString
 | ||||||
|  | - *
 | ||||||
|  | - * Returns the authentication code as a binary string. The _digest_ parameter
 | ||||||
|  | - * specifies the digest algorithm to use. This may be a String representing
 | ||||||
|  | - * the algorithm name or an instance of OpenSSL::Digest.
 | ||||||
|  | - *
 | ||||||
|  | - * === Example
 | ||||||
|  | - *
 | ||||||
|  | - *	key = 'key'
 | ||||||
|  | - * 	data = 'The quick brown fox jumps over the lazy dog'
 | ||||||
|  | - *
 | ||||||
|  | - * 	hmac = OpenSSL::HMAC.digest('sha1', key, data)
 | ||||||
|  | - * 	#=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
 | ||||||
|  | - *
 | ||||||
|  | - */
 | ||||||
|  | -static VALUE
 | ||||||
|  | -ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
 | ||||||
|  | -{
 | ||||||
|  | -    unsigned char *buf;
 | ||||||
|  | -    unsigned int buf_len;
 | ||||||
|  | -
 | ||||||
|  | -    StringValue(key);
 | ||||||
|  | -    StringValue(data);
 | ||||||
|  | -    buf = HMAC(ossl_evp_get_digestbyname(digest), RSTRING_PTR(key),
 | ||||||
|  | -	       RSTRING_LENINT(key), (unsigned char *)RSTRING_PTR(data),
 | ||||||
|  | -	       RSTRING_LEN(data), NULL, &buf_len);
 | ||||||
|  | -
 | ||||||
|  | -    return rb_str_new((const char *)buf, buf_len);
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  | -/*
 | ||||||
|  | - *  call-seq:
 | ||||||
|  | - *     HMAC.hexdigest(digest, key, data) -> aString
 | ||||||
|  | - *
 | ||||||
|  | - * Returns the authentication code as a hex-encoded string. The _digest_
 | ||||||
|  | - * parameter specifies the digest algorithm to use. This may be a String
 | ||||||
|  | - * representing the algorithm name or an instance of OpenSSL::Digest.
 | ||||||
|  | - *
 | ||||||
|  | - * === Example
 | ||||||
|  | - *
 | ||||||
|  | - *	key = 'key'
 | ||||||
|  | - * 	data = 'The quick brown fox jumps over the lazy dog'
 | ||||||
|  | - *
 | ||||||
|  | - * 	hmac = OpenSSL::HMAC.hexdigest('sha1', key, data)
 | ||||||
|  | - * 	#=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
 | ||||||
|  | - *
 | ||||||
|  | - */
 | ||||||
|  | -static VALUE
 | ||||||
|  | -ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
 | ||||||
|  | -{
 | ||||||
|  | -    unsigned char buf[EVP_MAX_MD_SIZE];
 | ||||||
|  | -    unsigned int buf_len;
 | ||||||
|  | -    VALUE ret;
 | ||||||
|  | -
 | ||||||
|  | -    StringValue(key);
 | ||||||
|  | -    StringValue(data);
 | ||||||
|  | -
 | ||||||
|  | -    if (!HMAC(ossl_evp_get_digestbyname(digest), RSTRING_PTR(key),
 | ||||||
|  | -	      RSTRING_LENINT(key), (unsigned char *)RSTRING_PTR(data),
 | ||||||
|  | -	      RSTRING_LEN(data), buf, &buf_len))
 | ||||||
|  | -	ossl_raise(eHMACError, "HMAC");
 | ||||||
|  | -
 | ||||||
|  | -    ret = rb_str_new(NULL, buf_len * 2);
 | ||||||
|  | -    ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
 | ||||||
|  | -
 | ||||||
|  | -    return ret;
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  |  /* | ||||||
|  |   * INIT | ||||||
|  |   */ | ||||||
|  | @@ -353,8 +278,7 @@ Init_ossl_hmac(void)
 | ||||||
|  |       *   data1 = File.read("file1") | ||||||
|  |       *   data2 = File.read("file2") | ||||||
|  |       *   key = "key" | ||||||
|  | -     *   digest = OpenSSL::Digest.new('SHA256')
 | ||||||
|  | -     *   hmac = OpenSSL::HMAC.new(key, digest)
 | ||||||
|  | +     *   hmac = OpenSSL::HMAC.new(key, 'SHA256')
 | ||||||
|  |       *   hmac << data1 | ||||||
|  |       *   hmac << data2 | ||||||
|  |       *   mac = hmac.digest | ||||||
|  | @@ -364,8 +288,6 @@ Init_ossl_hmac(void)
 | ||||||
|  |      cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject); | ||||||
|  |   | ||||||
|  |      rb_define_alloc_func(cHMAC, ossl_hmac_alloc); | ||||||
|  | -    rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3);
 | ||||||
|  | -    rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3);
 | ||||||
|  |   | ||||||
|  |      rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2); | ||||||
|  |      rb_define_method(cHMAC, "initialize_copy", ossl_hmac_copy, 1); | ||||||
|  | @@ -378,12 +300,3 @@ Init_ossl_hmac(void)
 | ||||||
|  |      rb_define_alias(cHMAC, "inspect", "hexdigest"); | ||||||
|  |      rb_define_alias(cHMAC, "to_s", "hexdigest"); | ||||||
|  |  } | ||||||
|  | -
 | ||||||
|  | -#else /* NO_HMAC */
 | ||||||
|  | -#  warning >>> OpenSSL is compiled without HMAC support <<<
 | ||||||
|  | -void
 | ||||||
|  | -Init_ossl_hmac(void)
 | ||||||
|  | -{
 | ||||||
|  | -    rb_warning("HMAC is not available: OpenSSL is compiled without HMAC.");
 | ||||||
|  | -}
 | ||||||
|  | -#endif /* NO_HMAC */
 | ||||||
|  | -- 
 | ||||||
|  | 2.34.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,458 @@ | |||||||
|  | From 91d04f991f8b9910efea7bbe5aecb0fea2bbd5fa Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Sun, 24 Oct 2021 17:50:18 +0900 | ||||||
|  | Subject: [PATCH 1/8] cipher: update test_ciphers | ||||||
|  | 
 | ||||||
|  | Do not attempt to actually use all algorithms. Not all algorithms listed | ||||||
|  | in OpenSSL::Cipher.ciphers are always available. | ||||||
|  | ---
 | ||||||
|  |  test/openssl/test_cipher.rb | 13 +++++-------- | ||||||
|  |  1 file changed, 5 insertions(+), 8 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb
 | ||||||
|  | index 6d18c0c8..b5fdf0b3 100644
 | ||||||
|  | --- a/test/openssl/test_cipher.rb
 | ||||||
|  | +++ b/test/openssl/test_cipher.rb
 | ||||||
|  | @@ -135,14 +135,11 @@ def test_ctr_if_exists
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_ciphers | ||||||
|  | -    OpenSSL::Cipher.ciphers.each{|name|
 | ||||||
|  | -      next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name
 | ||||||
|  | -      begin
 | ||||||
|  | -        assert_kind_of(OpenSSL::Cipher, OpenSSL::Cipher.new(name))
 | ||||||
|  | -      rescue OpenSSL::Cipher::CipherError => e
 | ||||||
|  | -        raise unless /wrap/ =~ name and /wrap mode not allowed/ =~ e.message
 | ||||||
|  | -      end
 | ||||||
|  | -    }
 | ||||||
|  | +    ciphers = OpenSSL::Cipher.ciphers
 | ||||||
|  | +    assert_kind_of Array, ciphers
 | ||||||
|  | +    assert_include ciphers, "aes-128-cbc"
 | ||||||
|  | +    assert_include ciphers, "aes128" # alias of aes-128-cbc
 | ||||||
|  | +    assert_include ciphers, "aes-128-gcm"
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_AES | ||||||
|  | 
 | ||||||
|  | From 6a60c7b2e7b6afe8b8c98d864ef2740094d86e1d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Sat, 11 Dec 2021 16:27:42 +0900 | ||||||
|  | Subject: [PATCH 2/8] hmac: fix wrong usage of EVP_DigestSignFinal() | ||||||
|  | 
 | ||||||
|  | According to the manpage, the "siglen" parameter must be initialized | ||||||
|  | beforehand. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_hmac.c | 4 ++-- | ||||||
|  |  1 file changed, 2 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
 | ||||||
|  | index f89ff2f9..bfe3a74b 100644
 | ||||||
|  | --- a/ext/openssl/ossl_hmac.c
 | ||||||
|  | +++ b/ext/openssl/ossl_hmac.c
 | ||||||
|  | @@ -175,7 +175,7 @@ static VALUE
 | ||||||
|  |  ossl_hmac_digest(VALUE self) | ||||||
|  |  { | ||||||
|  |      EVP_MD_CTX *ctx; | ||||||
|  | -    size_t buf_len;
 | ||||||
|  | +    size_t buf_len = EVP_MAX_MD_SIZE;
 | ||||||
|  |      VALUE ret; | ||||||
|  |   | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  | @@ -200,7 +200,7 @@ ossl_hmac_hexdigest(VALUE self)
 | ||||||
|  |  { | ||||||
|  |      EVP_MD_CTX *ctx; | ||||||
|  |      unsigned char buf[EVP_MAX_MD_SIZE]; | ||||||
|  | -    size_t buf_len;
 | ||||||
|  | +    size_t buf_len = EVP_MAX_MD_SIZE;
 | ||||||
|  |      VALUE ret; | ||||||
|  |   | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  | 
 | ||||||
|  | From 46995816392a79d037df5550b2fb226652c06f42 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Sat, 11 Dec 2021 16:30:30 +0900 | ||||||
|  | Subject: [PATCH 3/8] hmac: skip test_dup on OpenSSL 3.0 for now | ||||||
|  | 
 | ||||||
|  | EVP_MD_CTX_copy() doesn't seem to work as intended on HMAC EVP_MD_CTX | ||||||
|  | on OpenSSL 3.0.0 and causes a double free. I haven't found the root | ||||||
|  | problem yet, but let's skip the test case for now. | ||||||
|  | ---
 | ||||||
|  |  test/openssl/test_hmac.rb | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb
 | ||||||
|  | index 2f53a813..47cb3718 100644
 | ||||||
|  | --- a/test/openssl/test_hmac.rb
 | ||||||
|  | +++ b/test/openssl/test_hmac.rb
 | ||||||
|  | @@ -19,6 +19,7 @@ def test_hmac
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_dup | ||||||
|  | +    pend "HMAC#initialize_copy is currently broken on OpenSSL 3.0.0" if openssl?(3, 0, 0)
 | ||||||
|  |      h1 = OpenSSL::HMAC.new("KEY", "MD5") | ||||||
|  |      h1.update("DATA") | ||||||
|  |      h = h1.dup | ||||||
|  | 
 | ||||||
|  | From 69a27d8de4bd291cb4eb21a4d715b197e7da5a06 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Thu, 15 Apr 2021 00:51:58 +0900 | ||||||
|  | Subject: [PATCH 4/8] engine: disable OpenSSL::Engine on OpenSSL 3.0 | ||||||
|  | 
 | ||||||
|  | The entire ENGINE API is deprecated in OpenSSL 3.0 in favor of the new | ||||||
|  | "Provider" concept. | ||||||
|  | 
 | ||||||
|  | OpenSSL::Engine will not be defined when compiled with OpenSSL 3.0. | ||||||
|  | We would need a way to interact with providers from Ruby programs, but | ||||||
|  | since the concept is completely different from the ENGINE API, it will | ||||||
|  | not be through the current OpenSSL::Engine interface. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/openssl_missing.c | 3 --- | ||||||
|  |  ext/openssl/ossl.h            | 8 +++++--- | ||||||
|  |  ext/openssl/ossl_engine.c     | 3 ++- | ||||||
|  |  ext/openssl/ossl_pkey.c       | 4 ++++ | ||||||
|  |  4 files changed, 11 insertions(+), 7 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
 | ||||||
|  | index 8b93cba6..4415703d 100644
 | ||||||
|  | --- a/ext/openssl/openssl_missing.c
 | ||||||
|  | +++ b/ext/openssl/openssl_missing.c
 | ||||||
|  | @@ -10,9 +10,6 @@
 | ||||||
|  |  #include RUBY_EXTCONF_H | ||||||
|  |   | ||||||
|  |  #include <string.h> /* memcpy() */ | ||||||
|  | -#if !defined(OPENSSL_NO_ENGINE)
 | ||||||
|  | -# include <openssl/engine.h>
 | ||||||
|  | -#endif
 | ||||||
|  |  #include <openssl/x509_vfy.h> | ||||||
|  |   | ||||||
|  |  #include "openssl_missing.h" | ||||||
|  | diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
 | ||||||
|  | index 3a0ab1e5..4b512689 100644
 | ||||||
|  | --- a/ext/openssl/ossl.h
 | ||||||
|  | +++ b/ext/openssl/ossl.h
 | ||||||
|  | @@ -18,6 +18,7 @@
 | ||||||
|  |  #include <ruby/io.h> | ||||||
|  |  #include <ruby/thread.h> | ||||||
|  |  #include <openssl/opensslv.h> | ||||||
|  | +
 | ||||||
|  |  #include <openssl/err.h> | ||||||
|  |  #include <openssl/asn1.h> | ||||||
|  |  #include <openssl/x509v3.h> | ||||||
|  | @@ -30,9 +31,6 @@
 | ||||||
|  |    #include <openssl/ts.h> | ||||||
|  |  #endif | ||||||
|  |  #include <openssl/crypto.h> | ||||||
|  | -#if !defined(OPENSSL_NO_ENGINE)
 | ||||||
|  | -#  include <openssl/engine.h>
 | ||||||
|  | -#endif
 | ||||||
|  |  #if !defined(OPENSSL_NO_OCSP) | ||||||
|  |  #  include <openssl/ocsp.h> | ||||||
|  |  #endif | ||||||
|  | @@ -54,6 +52,10 @@
 | ||||||
|  |        (LIBRESSL_VERSION_NUMBER >= (maj << 28) | (min << 20) | (pat << 12)) | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | +#if !defined(OPENSSL_NO_ENGINE) && !OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  | +# define OSSL_USE_ENGINE
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  /* | ||||||
|  |   * Common Module | ||||||
|  |   */ | ||||||
|  | diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
 | ||||||
|  | index 661a1368..1abde7f7 100644
 | ||||||
|  | --- a/ext/openssl/ossl_engine.c
 | ||||||
|  | +++ b/ext/openssl/ossl_engine.c
 | ||||||
|  | @@ -9,7 +9,8 @@
 | ||||||
|  |   */ | ||||||
|  |  #include "ossl.h" | ||||||
|  |   | ||||||
|  | -#if !defined(OPENSSL_NO_ENGINE)
 | ||||||
|  | +#ifdef OSSL_USE_ENGINE
 | ||||||
|  | +# include <openssl/engine.h>
 | ||||||
|  |   | ||||||
|  |  #define NewEngine(klass) \ | ||||||
|  |      TypedData_Wrap_Struct((klass), &ossl_engine_type, 0) | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
 | ||||||
|  | index 7030be3c..94760d32 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.c
 | ||||||
|  | @@ -9,6 +9,10 @@
 | ||||||
|  |   */ | ||||||
|  |  #include "ossl.h" | ||||||
|  |   | ||||||
|  | +#ifdef OSSL_USE_ENGINE
 | ||||||
|  | +# include <openssl/engine.h>
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  /* | ||||||
|  |   * Classes | ||||||
|  |   */ | ||||||
|  | 
 | ||||||
|  | From b1ee2f23b28c2d0b14fd9b4b9fef13e870370746 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Wed, 17 Nov 2021 11:39:06 +0900 | ||||||
|  | Subject: [PATCH 5/8] ssl: add constants for new SSL_OP_* flags | ||||||
|  | 
 | ||||||
|  | Add all SSL_OP_* constants defined in OpenSSL 3.0.0 which are not | ||||||
|  | specific to DTLS. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_ssl.c | 35 +++++++++++++++++++++++++++++------ | ||||||
|  |  1 file changed, 29 insertions(+), 6 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
 | ||||||
|  | index 3b425ca7..9a0682a7 100644
 | ||||||
|  | --- a/ext/openssl/ossl_ssl.c
 | ||||||
|  | +++ b/ext/openssl/ossl_ssl.c
 | ||||||
|  | @@ -2941,13 +2941,28 @@ Init_ossl_ssl(void)
 | ||||||
|  |      rb_define_const(mSSL, "VERIFY_CLIENT_ONCE", INT2NUM(SSL_VERIFY_CLIENT_ONCE)); | ||||||
|  |   | ||||||
|  |      rb_define_const(mSSL, "OP_ALL", ULONG2NUM(SSL_OP_ALL)); | ||||||
|  | +#ifdef SSL_OP_CLEANSE_PLAINTEXT /* OpenSSL 3.0 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_CLEANSE_PLAINTEXT", ULONG2NUM(SSL_OP_CLEANSE_PLAINTEXT));
 | ||||||
|  | +#endif
 | ||||||
|  |      rb_define_const(mSSL, "OP_LEGACY_SERVER_CONNECT", ULONG2NUM(SSL_OP_LEGACY_SERVER_CONNECT)); | ||||||
|  | +#ifdef SSL_OP_ENABLE_KTLS /* OpenSSL 3.0 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_ENABLE_KTLS", ULONG2NUM(SSL_OP_ENABLE_KTLS));
 | ||||||
|  | +#endif
 | ||||||
|  |  #ifdef SSL_OP_TLSEXT_PADDING /* OpenSSL 1.0.1h and OpenSSL 1.0.2 */ | ||||||
|  |      rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING)); | ||||||
|  |  #endif | ||||||
|  |  #ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG /* OpenSSL 1.0.1f and OpenSSL 1.0.2 */ | ||||||
|  |      rb_define_const(mSSL, "OP_SAFARI_ECDHE_ECDSA_BUG", ULONG2NUM(SSL_OP_SAFARI_ECDHE_ECDSA_BUG)); | ||||||
|  |  #endif | ||||||
|  | +#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF /* OpenSSL 3.0 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_IGNORE_UNEXPECTED_EOF", ULONG2NUM(SSL_OP_IGNORE_UNEXPECTED_EOF));
 | ||||||
|  | +#endif
 | ||||||
|  | +#ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION /* OpenSSL 3.0 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_ALLOW_CLIENT_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_CLIENT_RENEGOTIATION));
 | ||||||
|  | +#endif
 | ||||||
|  | +#ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES /* OpenSSL 3.0 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_DISABLE_TLSEXT_CA_NAMES", ULONG2NUM(SSL_OP_DISABLE_TLSEXT_CA_NAMES));
 | ||||||
|  | +#endif
 | ||||||
|  |  #ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1 */ | ||||||
|  |      rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX)); | ||||||
|  |  #endif | ||||||
|  | @@ -2959,13 +2974,15 @@ Init_ossl_ssl(void)
 | ||||||
|  |  #ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1 */ | ||||||
|  |      rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC)); | ||||||
|  |  #endif | ||||||
|  | -    rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
 | ||||||
|  | -    rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
 | ||||||
|  | -#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
 | ||||||
|  | -    rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
 | ||||||
|  | +#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT));
 | ||||||
|  | +#endif
 | ||||||
|  | +#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA));
 | ||||||
|  | +#endif
 | ||||||
|  | +#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY));
 | ||||||
|  |  #endif | ||||||
|  | -    rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
 | ||||||
|  | -
 | ||||||
|  |      rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3)); | ||||||
|  |      rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1)); | ||||||
|  |      rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1)); | ||||||
|  | @@ -2973,6 +2990,12 @@ Init_ossl_ssl(void)
 | ||||||
|  |  #ifdef SSL_OP_NO_TLSv1_3 /* OpenSSL 1.1.1 */ | ||||||
|  |      rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3)); | ||||||
|  |  #endif | ||||||
|  | +    rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
 | ||||||
|  | +    rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
 | ||||||
|  | +#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
 | ||||||
|  | +    rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
 | ||||||
|  | +#endif
 | ||||||
|  | +    rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
 | ||||||
|  |   | ||||||
|  |      /* SSL_OP_* flags for DTLS */ | ||||||
|  |  #if 0 | ||||||
|  | 
 | ||||||
|  | From e168df0f3570709bfb38e9a39838bd0a7e78164c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Sun, 12 Dec 2021 00:47:35 +0900 | ||||||
|  | Subject: [PATCH 6/8] ssl: update test_options_disable_versions | ||||||
|  | 
 | ||||||
|  | Use the combination of TLS 1.2 and TLS 1.3 instead of TLS 1.1 and TLS | ||||||
|  | 1.2 so that will the test case will be run on latest platforms. | ||||||
|  | ---
 | ||||||
|  |  test/openssl/test_ssl.rb | 75 +++++++++++++++++++++------------------- | ||||||
|  |  1 file changed, 40 insertions(+), 35 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
 | ||||||
|  | index 22691292..2abade06 100644
 | ||||||
|  | --- a/test/openssl/test_ssl.rb
 | ||||||
|  | +++ b/test/openssl/test_ssl.rb
 | ||||||
|  | @@ -1180,46 +1180,51 @@ def test_minmax_version
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_options_disable_versions | ||||||
|  | -    # Note: Use of these OP_* flags has been deprecated since OpenSSL 1.1.0.
 | ||||||
|  | +    # It's recommended to use SSLContext#{min,max}_version= instead in real
 | ||||||
|  | +    # applications. The purpose of this test case is to check that SSL options
 | ||||||
|  | +    # are properly propagated to OpenSSL library.
 | ||||||
|  |      supported = check_supported_protocol_versions | ||||||
|  | +    if !defined?(OpenSSL::SSL::TLS1_3_VERSION) ||
 | ||||||
|  | +        !supported.include?(OpenSSL::SSL::TLS1_2_VERSION) ||
 | ||||||
|  | +        !supported.include?(OpenSSL::SSL::TLS1_3_VERSION) ||
 | ||||||
|  | +        !defined?(OpenSSL::SSL::OP_NO_TLSv1_3) # LibreSSL < 3.4
 | ||||||
|  | +      pend "this test case requires both TLS 1.2 and TLS 1.3 to be supported " \
 | ||||||
|  | +        "and enabled by default"
 | ||||||
|  | +    end
 | ||||||
|  |   | ||||||
|  | -    if supported.include?(OpenSSL::SSL::TLS1_1_VERSION) &&
 | ||||||
|  | -        supported.include?(OpenSSL::SSL::TLS1_2_VERSION)
 | ||||||
|  | -      # Server disables ~ TLS 1.1
 | ||||||
|  | -      ctx_proc = proc { |ctx|
 | ||||||
|  | -        ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
 | ||||||
|  | -          OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1
 | ||||||
|  | -      }
 | ||||||
|  | -      start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
 | ||||||
|  | -        # Client only supports TLS 1.1
 | ||||||
|  | -        ctx1 = OpenSSL::SSL::SSLContext.new
 | ||||||
|  | -        ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_1_VERSION
 | ||||||
|  | -        assert_handshake_error { server_connect(port, ctx1) { } }
 | ||||||
|  | +    # Server disables TLS 1.2 and earlier
 | ||||||
|  | +    ctx_proc = proc { |ctx|
 | ||||||
|  | +      ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
 | ||||||
|  | +        OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1 |
 | ||||||
|  | +        OpenSSL::SSL::OP_NO_TLSv1_2
 | ||||||
|  | +    }
 | ||||||
|  | +    start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
 | ||||||
|  | +      # Client only supports TLS 1.2
 | ||||||
|  | +      ctx1 = OpenSSL::SSL::SSLContext.new
 | ||||||
|  | +      ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_2_VERSION
 | ||||||
|  | +      assert_handshake_error { server_connect(port, ctx1) { } }
 | ||||||
|  |   | ||||||
|  | -        # Client only supports TLS 1.2
 | ||||||
|  | -        ctx2 = OpenSSL::SSL::SSLContext.new
 | ||||||
|  | -        ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_2_VERSION
 | ||||||
|  | -        assert_nothing_raised { server_connect(port, ctx2) { } }
 | ||||||
|  | -      }
 | ||||||
|  | +      # Client only supports TLS 1.3
 | ||||||
|  | +      ctx2 = OpenSSL::SSL::SSLContext.new
 | ||||||
|  | +      ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_3_VERSION
 | ||||||
|  | +      assert_nothing_raised { server_connect(port, ctx2) { } }
 | ||||||
|  | +    }
 | ||||||
|  |   | ||||||
|  | -      # Server only supports TLS 1.1
 | ||||||
|  | -      ctx_proc = proc { |ctx|
 | ||||||
|  | -        ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
 | ||||||
|  | -      }
 | ||||||
|  | -      start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
 | ||||||
|  | -        # Client disables TLS 1.1
 | ||||||
|  | -        ctx1 = OpenSSL::SSL::SSLContext.new
 | ||||||
|  | -        ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_1
 | ||||||
|  | -        assert_handshake_error { server_connect(port, ctx1) { } }
 | ||||||
|  | +    # Server only supports TLS 1.2
 | ||||||
|  | +    ctx_proc = proc { |ctx|
 | ||||||
|  | +      ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
 | ||||||
|  | +    }
 | ||||||
|  | +    start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
 | ||||||
|  | +      # Client doesn't support TLS 1.2
 | ||||||
|  | +      ctx1 = OpenSSL::SSL::SSLContext.new
 | ||||||
|  | +      ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_2
 | ||||||
|  | +      assert_handshake_error { server_connect(port, ctx1) { } }
 | ||||||
|  |   | ||||||
|  | -        # Client disables TLS 1.2
 | ||||||
|  | -        ctx2 = OpenSSL::SSL::SSLContext.new
 | ||||||
|  | -        ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_2
 | ||||||
|  | -        assert_nothing_raised { server_connect(port, ctx2) { } }
 | ||||||
|  | -      }
 | ||||||
|  | -    else
 | ||||||
|  | -      pend "TLS 1.1 and TLS 1.2 must be supported; skipping"
 | ||||||
|  | -    end
 | ||||||
|  | +      # Client supports TLS 1.2 by default
 | ||||||
|  | +      ctx2 = OpenSSL::SSL::SSLContext.new
 | ||||||
|  | +      ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_3
 | ||||||
|  | +      assert_nothing_raised { server_connect(port, ctx2) { } }
 | ||||||
|  | +    }
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_ssl_methods_constant | ||||||
|  | 
 | ||||||
|  | From ccdb6f7bfa5f988a07beecedbf2b6205b6ab8492 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Sat, 20 Mar 2021 23:16:41 +0900 | ||||||
|  | Subject: [PATCH 7/8] pkey: assume a pkey always has public key components on | ||||||
|  |  OpenSSL 3.0 | ||||||
|  | 
 | ||||||
|  | OpenSSL 3.0's EVP_PKEY_get0() returns NULL for provider-backed pkeys. | ||||||
|  | This causes segfault because it was supposed to never return NULL | ||||||
|  | before. | ||||||
|  | 
 | ||||||
|  | We can't check the existence of public key components in this way on | ||||||
|  | OpenSSL 3.0. Let's just skip it for now. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_pkey.c | 11 +++++++++++ | ||||||
|  |  1 file changed, 11 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
 | ||||||
|  | index 94760d32..09d45d85 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.c
 | ||||||
|  | @@ -428,9 +428,19 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
 | ||||||
|  |      return pkey_generate(argc, argv, self, 0); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * TODO: There is no convenient way to check the presence of public key
 | ||||||
|  | + * components on OpenSSL 3.0. But since keys are immutable on 3.0, pkeys without
 | ||||||
|  | + * these should only be created by OpenSSL::PKey.generate_parameters or by
 | ||||||
|  | + * parsing DER-/PEM-encoded string. We would need another flag for that.
 | ||||||
|  | + */
 | ||||||
|  |  void | ||||||
|  |  ossl_pkey_check_public_key(const EVP_PKEY *pkey) | ||||||
|  |  { | ||||||
|  | +#if OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  | +    if (EVP_PKEY_missing_parameters(pkey))
 | ||||||
|  | +        ossl_raise(ePKeyError, "parameters missing");
 | ||||||
|  | +#else
 | ||||||
|  |      void *ptr; | ||||||
|  |      const BIGNUM *n, *e, *pubkey; | ||||||
|  |   | ||||||
|  | @@ -466,6 +476,7 @@ ossl_pkey_check_public_key(const EVP_PKEY *pkey)
 | ||||||
|  |  	return; | ||||||
|  |      } | ||||||
|  |      ossl_raise(ePKeyError, "public key missing"); | ||||||
|  | +#endif
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  EVP_PKEY * | ||||||
|  | 
 | ||||||
|  | From d6535d13d174cd87ae99f3e60e97f7a00e1474e5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Mon, 12 Apr 2021 10:43:46 +0900 | ||||||
|  | Subject: [PATCH 8/8] pkey: use EVP_PKEY_CTX_new_from_name() on OpenSSL 3.0 | ||||||
|  | 
 | ||||||
|  | Replace EVP_PKEY_CTX_new_id() with the new EVP_PKEY_CTX_new_from_name() | ||||||
|  | which takes the algorithm name in a string instead of in an NID. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_pkey.c | 6 ++++++ | ||||||
|  |  1 file changed, 6 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
 | ||||||
|  | index 09d45d85..2a4835a2 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.c
 | ||||||
|  | @@ -315,6 +315,11 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
 | ||||||
|  |              ossl_raise(ePKeyError, "EVP_PKEY_CTX_new"); | ||||||
|  |      } | ||||||
|  |      else { | ||||||
|  | +#if OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  | +        ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL);
 | ||||||
|  | +        if (!ctx)
 | ||||||
|  | +            ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name");
 | ||||||
|  | +#else
 | ||||||
|  |          const EVP_PKEY_ASN1_METHOD *ameth; | ||||||
|  |          ENGINE *tmpeng; | ||||||
|  |          int pkey_id; | ||||||
|  | @@ -333,6 +338,7 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
 | ||||||
|  |          ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL/* engine */); | ||||||
|  |          if (!ctx) | ||||||
|  |              ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_id"); | ||||||
|  | +#endif
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      if (genparam && EVP_PKEY_paramgen_init(ctx) <= 0) { | ||||||
| @ -1,7 +1,7 @@ | |||||||
| From 8f948ed68a4ed6c05ff66d822711e3b70ae4bb3f Mon Sep 17 00:00:00 2001 | From 8f948ed68a4ed6c05ff66d822711e3b70ae4bb3f Mon Sep 17 00:00:00 2001 | ||||||
| From: Kazuki Yamaguchi <k@rhe.jp> | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
| Date: Mon, 27 Sep 2021 13:32:03 +0900 | Date: Mon, 27 Sep 2021 13:32:03 +0900 | ||||||
| Subject: [PATCH 1/3] ext/openssl/ossl.h: add helper macros for | Subject: [PATCH 1/5] ext/openssl/ossl.h: add helper macros for | ||||||
|  OpenSSL/LibreSSL versions |  OpenSSL/LibreSSL versions | ||||||
| 
 | 
 | ||||||
| Add following convenient macros: | Add following convenient macros: | ||||||
| @ -17,7 +17,7 @@ diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h | |||||||
| index c20f506bda..a0cef29d74 100644
 | index c20f506bda..a0cef29d74 100644
 | ||||||
| --- a/ext/openssl/ossl.h
 | --- a/ext/openssl/ossl.h
 | ||||||
| +++ b/ext/openssl/ossl.h
 | +++ b/ext/openssl/ossl.h
 | ||||||
| @@ -43,6 +43,18 @@
 | @@ -42,6 +42,18 @@
 | ||||||
|  #include <openssl/evp.h> |  #include <openssl/evp.h> | ||||||
|  #include <openssl/dh.h> |  #include <openssl/dh.h> | ||||||
|   |   | ||||||
| @ -43,7 +43,7 @@ index c20f506bda..a0cef29d74 100644 | |||||||
| From bbf235091e49807ece8f3a3df95bbfcc9d3ab43d Mon Sep 17 00:00:00 2001 | From bbf235091e49807ece8f3a3df95bbfcc9d3ab43d Mon Sep 17 00:00:00 2001 | ||||||
| From: Kazuki Yamaguchi <k@rhe.jp> | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
| Date: Sat, 22 Feb 2020 05:37:01 +0900 | Date: Sat, 22 Feb 2020 05:37:01 +0900 | ||||||
| Subject: [PATCH 2/3] ts: use TS_VERIFY_CTX_set_certs instead of | Subject: [PATCH 2/5] ts: use TS_VERIFY_CTX_set_certs instead of | ||||||
|  TS_VERIFY_CTS_set_certs |  TS_VERIFY_CTS_set_certs | ||||||
| 
 | 
 | ||||||
| OpenSSL 3.0 fixed the typo in the function name and replaced the | OpenSSL 3.0 fixed the typo in the function name and replaced the | ||||||
| @ -58,7 +58,7 @@ diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb | |||||||
| index 17d93443fc..09cae05b72 100644
 | index 17d93443fc..09cae05b72 100644
 | ||||||
| --- a/ext/openssl/extconf.rb
 | --- a/ext/openssl/extconf.rb
 | ||||||
| +++ b/ext/openssl/extconf.rb
 | +++ b/ext/openssl/extconf.rb
 | ||||||
| @@ -166,7 +166,7 @@ def find_openssl_library
 | @@ -165,7 +165,7 @@ def find_openssl_library
 | ||||||
|  have_func("TS_STATUS_INFO_get0_status") |  have_func("TS_STATUS_INFO_get0_status") | ||||||
|  have_func("TS_STATUS_INFO_get0_text") |  have_func("TS_STATUS_INFO_get0_text") | ||||||
|  have_func("TS_STATUS_INFO_get0_failure_info") |  have_func("TS_STATUS_INFO_get0_failure_info") | ||||||
| @ -67,7 +67,7 @@ index 17d93443fc..09cae05b72 100644 | |||||||
|  have_func("TS_VERIFY_CTX_set_store") |  have_func("TS_VERIFY_CTX_set_store") | ||||||
|  have_func("TS_VERIFY_CTX_add_flags") |  have_func("TS_VERIFY_CTX_add_flags") | ||||||
|  have_func("TS_RESP_CTX_set_time_cb") |  have_func("TS_RESP_CTX_set_time_cb") | ||||||
| @@ -175,6 +175,9 @@ def find_openssl_library
 | @@ -174,6 +174,9 @@ def find_openssl_library
 | ||||||
|   |   | ||||||
|  # added in 1.1.1 |  # added in 1.1.1 | ||||||
|  have_func("EVP_PKEY_check") |  have_func("EVP_PKEY_check") | ||||||
| @ -81,7 +81,7 @@ diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h | |||||||
| index e575415f49..fe486bcfcf 100644
 | index e575415f49..fe486bcfcf 100644
 | ||||||
| --- a/ext/openssl/openssl_missing.h
 | --- a/ext/openssl/openssl_missing.h
 | ||||||
| +++ b/ext/openssl/openssl_missing.h
 | +++ b/ext/openssl/openssl_missing.h
 | ||||||
| @@ -242,4 +242,9 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
 | @@ -236,4 +236,9 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
 | ||||||
|      } while (0) |      } while (0) | ||||||
|  #endif |  #endif | ||||||
|   |   | ||||||
| @ -111,7 +111,7 @@ index 692c0d620f..f1da7c1947 100644 | |||||||
| From 5fba3bc1df93ab6abc3ea53be3393480f36ea259 Mon Sep 17 00:00:00 2001 | From 5fba3bc1df93ab6abc3ea53be3393480f36ea259 Mon Sep 17 00:00:00 2001 | ||||||
| From: Kazuki Yamaguchi <k@rhe.jp> | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
| Date: Fri, 19 Mar 2021 19:18:25 +0900 | Date: Fri, 19 Mar 2021 19:18:25 +0900 | ||||||
| Subject: [PATCH 3/3] ssl: use SSL_get_rbio() to check if SSL is started or not | Subject: [PATCH 3/5] ssl: use SSL_get_rbio() to check if SSL is started or not | ||||||
| 
 | 
 | ||||||
| Use SSL_get_rbio() instead of SSL_get_fd(). SSL_get_fd() internally | Use SSL_get_rbio() instead of SSL_get_fd(). SSL_get_fd() internally | ||||||
| calls SSL_get_rbio() and it's enough for our purpose. | calls SSL_get_rbio() and it's enough for our purpose. | ||||||
| @ -140,3 +140,165 @@ index 4b7efa39f5..ec430bfb0c 100644 | |||||||
| -- 
 | -- 
 | ||||||
| 2.32.0 | 2.32.0 | ||||||
| 
 | 
 | ||||||
|  | From 0a253027e6be47c0b7fd8b664f1048f24d7ca657 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Thu, 22 Apr 2021 13:57:47 +0900 | ||||||
|  | Subject: [PATCH 4/5] digest: use EVP_MD_CTX_get0_md() instead of | ||||||
|  |  EVP_MD_CTX_md() if exists | ||||||
|  | 
 | ||||||
|  | The function was renamed in OpenSSL 3.0 due to the change of the | ||||||
|  | lifetime of EVP_MD objects. They are no longer necessarily statically | ||||||
|  | allocated and can be reference-counted -- when an EVP_MD_CTX is free'd, | ||||||
|  | the associated EVP_MD can also become inaccessible. | ||||||
|  | 
 | ||||||
|  | Currently Ruby/OpenSSL only handles builtin algorithms, so no special | ||||||
|  | handling is needed except for adapting to the rename. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/extconf.rb        | 1 + | ||||||
|  |  ext/openssl/openssl_missing.h | 4 ++++ | ||||||
|  |  ext/openssl/ossl_digest.c     | 6 +++--- | ||||||
|  |  ext/openssl/ossl_hmac.c       | 2 +- | ||||||
|  |  4 files changed, 9 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
 | ||||||
|  | index 98f96afe..842b7f5b 100644
 | ||||||
|  | --- a/ext/openssl/extconf.rb
 | ||||||
|  | +++ b/ext/openssl/extconf.rb
 | ||||||
|  | @@ -177,6 +177,7 @@ def find_openssl_library
 | ||||||
|  |    | ||||||
|  |  # added in 3.0.0 | ||||||
|  |  have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") | ||||||
|  | +have_func("EVP_MD_CTX_get0_md")
 | ||||||
|  |   | ||||||
|  |  Logging::message "=== Checking done. ===\n" | ||||||
|  |   | ||||||
|  | diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
 | ||||||
|  | index 1b1a54a8..64212349 100644
 | ||||||
|  | --- a/ext/openssl/openssl_missing.h
 | ||||||
|  | +++ b/ext/openssl/openssl_missing.h
 | ||||||
|  | @@ -241,4 +241,8 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
 | ||||||
|  |  #  define TS_VERIFY_CTX_set_certs(ctx, crts) TS_VERIFY_CTS_set_certs(ctx, crts) | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | +#ifndef HAVE_EVP_MD_CTX_GET0_MD
 | ||||||
|  | +#  define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx)
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  #endif /* _OSSL_OPENSSL_MISSING_H_ */ | ||||||
|  | diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
 | ||||||
|  | index b2506de7..fc326ec1 100644
 | ||||||
|  | --- a/ext/openssl/ossl_digest.c
 | ||||||
|  | +++ b/ext/openssl/ossl_digest.c
 | ||||||
|  | @@ -63,7 +63,7 @@ ossl_evp_get_digestbyname(VALUE obj)
 | ||||||
|  |   | ||||||
|  |          GetDigest(obj, ctx); | ||||||
|  |   | ||||||
|  | -        md = EVP_MD_CTX_md(ctx);
 | ||||||
|  | +        md = EVP_MD_CTX_get0_md(ctx);
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      return md; | ||||||
|  | @@ -176,7 +176,7 @@ ossl_digest_reset(VALUE self)
 | ||||||
|  |      EVP_MD_CTX *ctx; | ||||||
|  |   | ||||||
|  |      GetDigest(self, ctx); | ||||||
|  | -    if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) {
 | ||||||
|  | +    if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) {
 | ||||||
|  |  	ossl_raise(eDigestError, "Digest initialization failed."); | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | @@ -259,7 +259,7 @@ ossl_digest_name(VALUE self)
 | ||||||
|  |   | ||||||
|  |      GetDigest(self, ctx); | ||||||
|  |   | ||||||
|  | -    return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
 | ||||||
|  | +    return rb_str_new_cstr(EVP_MD_name(EVP_MD_CTX_get0_md(ctx)));
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
 | ||||||
|  | index a21db6c4..2642728b 100644
 | ||||||
|  | --- a/ext/openssl/ossl_hmac.c
 | ||||||
|  | +++ b/ext/openssl/ossl_hmac.c
 | ||||||
|  | @@ -239,7 +239,7 @@ ossl_hmac_reset(VALUE self)
 | ||||||
|  |   | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  |      pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); | ||||||
|  | -    if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_md(ctx), NULL, pkey) != 1)
 | ||||||
|  | +    if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1)
 | ||||||
|  |          ossl_raise(eHMACError, "EVP_DigestSignInit"); | ||||||
|  |   | ||||||
|  |      return self; | ||||||
|  | 
 | ||||||
|  | From c106d888c62e44a11cdbba5e4d2d0cb837ec3e52 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Tue, 22 Jun 2021 18:50:17 +0900 | ||||||
|  | Subject: [PATCH 5/5] hmac: use EVP_MD_CTX_get_pkey_ctx() instead of | ||||||
|  |  EVP_MD_CTX_pkey_ctx() | ||||||
|  | 
 | ||||||
|  | OpenSSL 3.0 renamed EVP_MD_CTX_pkey_ctx() to include "get" in the | ||||||
|  | function name. Adjust compatibility macro so that we can use the new | ||||||
|  | function name for all OpenSSL 1.0.2-3.0. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/extconf.rb        |  1 + | ||||||
|  |  ext/openssl/openssl_missing.h | 16 ++++++++++++---- | ||||||
|  |  ext/openssl/ossl_hmac.c       |  2 +- | ||||||
|  |  3 files changed, 14 insertions(+), 5 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
 | ||||||
|  | index 842b7f5b..d9d34b7c 100644
 | ||||||
|  | --- a/ext/openssl/extconf.rb
 | ||||||
|  | +++ b/ext/openssl/extconf.rb
 | ||||||
|  | @@ -178,6 +178,7 @@ def find_openssl_library
 | ||||||
|  |  # added in 3.0.0 | ||||||
|  |  have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") | ||||||
|  |  have_func("EVP_MD_CTX_get0_md") | ||||||
|  | +have_func("EVP_MD_CTX_get_pkey_ctx")
 | ||||||
|  |   | ||||||
|  |  Logging::message "=== Checking done. ===\n" | ||||||
|  |   | ||||||
|  | diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
 | ||||||
|  | index 64212349..55c4f378 100644
 | ||||||
|  | --- a/ext/openssl/openssl_missing.h
 | ||||||
|  | +++ b/ext/openssl/openssl_missing.h
 | ||||||
|  | @@ -42,10 +42,6 @@ int ossl_EC_curve_nist2nid(const char *);
 | ||||||
|  |  #  define EVP_MD_CTX_free EVP_MD_CTX_destroy | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | -#if !defined(HAVE_EVP_MD_CTX_PKEY_CTX)
 | ||||||
|  | -#  define EVP_MD_CTX_pkey_ctx(x) (x)->pctx
 | ||||||
|  | -#endif
 | ||||||
|  | -
 | ||||||
|  |  #if !defined(HAVE_X509_STORE_GET_EX_DATA) | ||||||
|  |  #  define X509_STORE_get_ex_data(x, idx) \ | ||||||
|  |  	CRYPTO_get_ex_data(&(x)->ex_data, (idx)) | ||||||
|  | @@ -245,4 +241,16 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
 | ||||||
|  |  #  define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx) | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * OpenSSL 1.1.0 added EVP_MD_CTX_pkey_ctx(), and then it was renamed to
 | ||||||
|  | + * EVP_MD_CTX_get_pkey_ctx(x) in OpenSSL 3.0.
 | ||||||
|  | + */
 | ||||||
|  | +#ifndef HAVE_EVP_MD_CTX_GET_PKEY_CTX
 | ||||||
|  | +# ifdef HAVE_EVP_MD_CTX_PKEY_CTX
 | ||||||
|  | +#  define EVP_MD_CTX_get_pkey_ctx(x) EVP_MD_CTX_pkey_ctx(x)
 | ||||||
|  | +# else
 | ||||||
|  | +#  define EVP_MD_CTX_get_pkey_ctx(x) (x)->pctx
 | ||||||
|  | +# endif
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  #endif /* _OSSL_OPENSSL_MISSING_H_ */ | ||||||
|  | diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
 | ||||||
|  | index 2642728b..f89ff2f9 100644
 | ||||||
|  | --- a/ext/openssl/ossl_hmac.c
 | ||||||
|  | +++ b/ext/openssl/ossl_hmac.c
 | ||||||
|  | @@ -238,7 +238,7 @@ ossl_hmac_reset(VALUE self)
 | ||||||
|  |      EVP_PKEY *pkey; | ||||||
|  |   | ||||||
|  |      GetHMAC(self, ctx); | ||||||
|  | -    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
 | ||||||
|  | +    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
 | ||||||
|  |      if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1) | ||||||
|  |          ossl_raise(eHMACError, "EVP_DigestSignInit"); | ||||||
|  |   | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -698,7 +698,7 @@ diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb | |||||||
| index b3c6647faf..17d93443fc 100644
 | index b3c6647faf..17d93443fc 100644
 | ||||||
| --- a/ext/openssl/extconf.rb
 | --- a/ext/openssl/extconf.rb
 | ||||||
| +++ b/ext/openssl/extconf.rb
 | +++ b/ext/openssl/extconf.rb
 | ||||||
| @@ -173,6 +173,9 @@ def find_openssl_library
 | @@ -172,6 +172,9 @@ def find_openssl_library
 | ||||||
|  have_func("EVP_PBE_scrypt") |  have_func("EVP_PBE_scrypt") | ||||||
|  have_func("SSL_CTX_set_post_handshake_auth") |  have_func("SSL_CTX_set_post_handshake_auth") | ||||||
|   |   | ||||||
|  | |||||||
| @ -0,0 +1,114 @@ | |||||||
|  | From 8c185e0ae5e42bf5f3d76a1a0898946671116fa3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Wed, 3 Nov 2021 23:31:29 +0900 | ||||||
|  | Subject: [PATCH 1/2] pkey: test parsing concatenated PEM string | ||||||
|  | 
 | ||||||
|  | PEM-encoded private keys are sometimes stored together with irrelevant | ||||||
|  | PEM blocks, such as the corresponding X.509 certificate. | ||||||
|  | 
 | ||||||
|  | PEM_read_bio_*() family automatically skips unknown PEM blocks, but on | ||||||
|  | OpenSSL 3.0 we will be using the new OSSL_DECODER API instead due to | ||||||
|  | some breaking changes around the password callback. | ||||||
|  | 
 | ||||||
|  | Let's add a test case so that we won't break the current behavior. | ||||||
|  | ---
 | ||||||
|  |  test/openssl/test_pkey_rsa.rb | 6 ++++++ | ||||||
|  |  1 file changed, 6 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | index dbe87ba4..7510658d 100644
 | ||||||
|  | --- a/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | +++ b/test/openssl/test_pkey_rsa.rb
 | ||||||
|  | @@ -306,6 +306,12 @@ def test_RSAPrivateKey
 | ||||||
|  |   | ||||||
|  |      assert_equal asn1.to_der, rsa1024.to_der | ||||||
|  |      assert_equal pem, rsa1024.export | ||||||
|  | +
 | ||||||
|  | +    # Unknown PEM prepended
 | ||||||
|  | +    cert = issue_cert(OpenSSL::X509::Name.new([["CN", "nobody"]]), rsa1024, 1, [], nil, nil)
 | ||||||
|  | +    str = cert.to_text + cert.to_pem + rsa1024.to_pem
 | ||||||
|  | +    key = OpenSSL::PKey::RSA.new(str)
 | ||||||
|  | +    assert_same_rsa rsa1024, key
 | ||||||
|  |    end | ||||||
|  |   | ||||||
|  |    def test_RSAPrivateKey_encrypted | ||||||
|  | 
 | ||||||
|  | From a84ea531bbd080c3f58fe8d3dc9ffb1af2251f35 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Sat, 20 Mar 2021 23:16:16 +0900 | ||||||
|  | Subject: [PATCH 2/2] pkey: use OSSL_DECODER to load encrypted PEM on OpenSSL | ||||||
|  |  3.0 | ||||||
|  | 
 | ||||||
|  | OpenSSL 3.0 has rewritten routines to load pkeys (PEM_read_bio_* and | ||||||
|  | d2i_* functions) around the newly introduced OSSL_DECODER API. | ||||||
|  | 
 | ||||||
|  | This comes with a slight behavior change. They now decrypt and parse | ||||||
|  | each encountered PEM block, then check the kind of the block. This used | ||||||
|  | to be the reverse: they checked the PEM header to see the kind, and then | ||||||
|  | decrypted the content. This means that the password callback may now be | ||||||
|  | called repeatedly. | ||||||
|  | 
 | ||||||
|  | Let's use the OSSL_DECODER API directly on OpenSSL 3.0 so that the | ||||||
|  | return value from the password callback will be reused automatically. | ||||||
|  | ---
 | ||||||
|  |  ext/openssl/ossl_pkey.c | 40 ++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 40 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
 | ||||||
|  | index f9f5162e..b08168a5 100644
 | ||||||
|  | --- a/ext/openssl/ossl_pkey.c
 | ||||||
|  | +++ b/ext/openssl/ossl_pkey.c
 | ||||||
|  | @@ -78,6 +78,45 @@ ossl_pkey_new(EVP_PKEY *pkey)
 | ||||||
|  |      return obj; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +#if OSSL_OPENSSL_PREREQ(3, 0, 0)
 | ||||||
|  | +# include <openssl/decoder.h>
 | ||||||
|  | +
 | ||||||
|  | +EVP_PKEY *
 | ||||||
|  | +ossl_pkey_read_generic(BIO *bio, VALUE pass)
 | ||||||
|  | +{
 | ||||||
|  | +    void *ppass = (void *)pass;
 | ||||||
|  | +    OSSL_DECODER_CTX *dctx;
 | ||||||
|  | +    EVP_PKEY *pkey = NULL;
 | ||||||
|  | +    int pos = 0, pos2;
 | ||||||
|  | +
 | ||||||
|  | +    dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, NULL, 0, NULL, NULL);
 | ||||||
|  | +    if (!dctx)
 | ||||||
|  | +        goto out;
 | ||||||
|  | +    if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1)
 | ||||||
|  | +        goto out;
 | ||||||
|  | +
 | ||||||
|  | +    /* First check DER */
 | ||||||
|  | +    if (OSSL_DECODER_from_bio(dctx, bio) == 1)
 | ||||||
|  | +        goto out;
 | ||||||
|  | +
 | ||||||
|  | +    /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */
 | ||||||
|  | +    OSSL_BIO_reset(bio);
 | ||||||
|  | +    if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1)
 | ||||||
|  | +        goto out;
 | ||||||
|  | +    while (OSSL_DECODER_from_bio(dctx, bio) != 1) {
 | ||||||
|  | +        if (BIO_eof(bio))
 | ||||||
|  | +            goto out;
 | ||||||
|  | +        pos2 = BIO_tell(bio);
 | ||||||
|  | +        if (pos2 < 0 || pos2 <= pos)
 | ||||||
|  | +            goto out;
 | ||||||
|  | +        pos = pos2;
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +  out:
 | ||||||
|  | +    OSSL_DECODER_CTX_free(dctx);
 | ||||||
|  | +    return pkey;
 | ||||||
|  | +}
 | ||||||
|  | +#else
 | ||||||
|  |  EVP_PKEY * | ||||||
|  |  ossl_pkey_read_generic(BIO *bio, VALUE pass) | ||||||
|  |  { | ||||||
|  | @@ -106,6 +145,7 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
 | ||||||
|  |    out: | ||||||
|  |      return pkey; | ||||||
|  |  } | ||||||
|  | +#endif
 | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  |   *  call-seq: | ||||||
| @ -974,7 +974,7 @@ index 693e55cd97..b3c6647faf 100644 | |||||||
| -have_func("BN_GENCB_get_arg")
 | -have_func("BN_GENCB_get_arg")
 | ||||||
|  have_func("EVP_MD_CTX_new") |  have_func("EVP_MD_CTX_new") | ||||||
|  have_func("EVP_MD_CTX_free") |  have_func("EVP_MD_CTX_free") | ||||||
|  have_func("HMAC_CTX_new") |  have_func("EVP_MD_CTX_pkey_ctx") | ||||||
| diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
 | diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
 | ||||||
| index 7d218f86f5..e575415f49 100644
 | index 7d218f86f5..e575415f49 100644
 | ||||||
| --- a/ext/openssl/openssl_missing.h
 | --- a/ext/openssl/openssl_missing.h
 | ||||||
|  | |||||||
							
								
								
									
										71
									
								
								ruby.spec
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								ruby.spec
									
									
									
									
									
								
							| @ -22,7 +22,7 @@ | |||||||
| %endif | %endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| %global release 158 | %global release 159 | ||||||
| %{!?release_string:%define release_string %{?development_release:0.}%{release}%{?development_release:.%{development_release}}%{?dist}} | %{!?release_string:%define release_string %{?development_release:0.}%{release}%{?development_release:.%{development_release}}%{?dist}} | ||||||
| 
 | 
 | ||||||
| # The RubyGems library has to stay out of Ruby directory tree, since the | # The RubyGems library has to stay out of Ruby directory tree, since the | ||||||
| @ -173,6 +173,9 @@ Patch21: ruby-3.1.0-Properly-exclude-test-cases.patch | |||||||
| # https://bugzilla.redhat.com/show_bug.cgi?id=2027099 | # https://bugzilla.redhat.com/show_bug.cgi?id=2027099 | ||||||
| # https://github.com/rubygems/rubygems/pull/5154 | # https://github.com/rubygems/rubygems/pull/5154 | ||||||
| Patch22: rubygems-3.2.33-Fix-loading-operating_system-rb-customizations-too-late.patch | Patch22: rubygems-3.2.33-Fix-loading-operating_system-rb-customizations-too-late.patch | ||||||
|  | # Fix segfault in `TestArray#test_sample` on s390x. | ||||||
|  | # https://github.com/ruby/ruby/pull/5239 | ||||||
|  | Patch23: ruby-3.1.0-Fix-stack-buffer-overflow.patch | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # OpenSSL 3.0 compatibility patches | # OpenSSL 3.0 compatibility patches | ||||||
| @ -193,47 +196,63 @@ Patch40: ruby-3.1.0-Refactor-PEM-DER-serialization-code.patch | |||||||
| # Implement more 'generic' operations using the EVP API. | # Implement more 'generic' operations using the EVP API. | ||||||
| # https://github.com/ruby/openssl/pull/329 | # https://github.com/ruby/openssl/pull/329 | ||||||
| Patch41: ruby-3.1.0-Add-more-support-for-generic-pkey-types.patch | Patch41: ruby-3.1.0-Add-more-support-for-generic-pkey-types.patch | ||||||
|  | # Migrate from the low-level HMAC API to the EVP API. | ||||||
|  | # https://github.com/ruby/openssl/pull/371 | ||||||
|  | Patch42: ruby-3.1.0-Migrate-from-the-low-level-HMAC-API-to-the-EVP-API.patch | ||||||
| # Allow setting algorithm-specific options in #sign and #verify. | # Allow setting algorithm-specific options in #sign and #verify. | ||||||
| # https://github.com/ruby/openssl/pull/374 | # https://github.com/ruby/openssl/pull/374 | ||||||
| Patch42: ruby-3.1.0-Allow-setting-algorithm-specific-options-in-sign-and-verify.patch | Patch43: ruby-3.1.0-Allow-setting-algorithm-specific-options-in-sign-and-verify.patch | ||||||
| # Use high level EVP interface to generate parameters and keys. | # Use high level EVP interface to generate parameters and keys. | ||||||
| # https://github.com/ruby/openssl/pull/397 | # https://github.com/ruby/openssl/pull/397 | ||||||
| Patch43: ruby-3.1.0-Use-high-level-EVP-interface-to-generate-parameters-and-keys.patch | Patch44: ruby-3.1.0-Use-high-level-EVP-interface-to-generate-parameters-and-keys.patch | ||||||
| # Use EVP API in more places. | # Use EVP API in more places. | ||||||
| # https://github.com/ruby/openssl/pull/436 | # https://github.com/ruby/openssl/pull/436 | ||||||
| Patch44: ruby-3.1.0-Use-EVP-API-in-more-places.patch | Patch45: ruby-3.1.0-Use-EVP-API-in-more-places.patch | ||||||
| # Implement PKey#{encrypt,decrypt,sign_raw,verify_{raw,verify_recover}}. | # Implement PKey#{encrypt,decrypt,sign_raw,verify_{raw,verify_recover}}. | ||||||
| # https://github.com/ruby/openssl/pull/382 | # https://github.com/ruby/openssl/pull/382 | ||||||
| Patch45: ruby-3.1.0-Implement-PKey-encrypt-decrypt-sign_raw-verify_raw-and-verify_recover.patch | Patch46: ruby-3.1.0-Implement-PKey-encrypt-decrypt-sign_raw-verify_raw-and-verify_recover.patch | ||||||
| # Fix `OpenSSL::TestSSL#test_dup` test failure. | # Fix `OpenSSL::TestSSL#test_dup` test failure. | ||||||
| # https://github.com/ruby/openssl/commit/7b66eaa2dbabb6570dbbbdfac24c4dcdcc6793d7 | # https://github.com/ruby/openssl/commit/7b66eaa2dbabb6570dbbbdfac24c4dcdcc6793d7 | ||||||
| Patch46: ruby-3.1.0-test-openssl-utils-remove-dup_public-helper-method.patch | Patch47: ruby-3.1.0-test-openssl-utils-remove-dup_public-helper-method.patch | ||||||
| # Fix `OpenSSL::TestDigest#test_digest_constants` test case. | # Fix `OpenSSL::TestDigest#test_digest_constants` test case. | ||||||
| # https://github.com/ruby/openssl/commit/a3e59f4c2e200c76ef1d93945ff8737a05715e17 | # https://github.com/ruby/openssl/commit/a3e59f4c2e200c76ef1d93945ff8737a05715e17 | ||||||
| Patch47: ruby-3.1.0-test-openssl-test_digest-do-not-test-constants-for-l.patch | Patch48: ruby-3.1.0-test-openssl-test_digest-do-not-test-constants-for-l.patch | ||||||
| # Fix `OpenSSL::TestSSL#test_connect_certificate_verify_failed_exception_message` | # Fix `OpenSSL::TestSSL#test_connect_certificate_verify_failed_exception_message` | ||||||
| # test case. | # test case. | ||||||
| # https://github.com/ruby/openssl/commit/b5a0a198505452c7457b192da2e5cd5dda04f23d | # https://github.com/ruby/openssl/commit/b5a0a198505452c7457b192da2e5cd5dda04f23d | ||||||
| Patch48: ruby-3.1.0-test-openssl-test_ssl-relax-regex-to-match-OpenSSL-s.patch | Patch49: ruby-3.1.0-test-openssl-test_ssl-relax-regex-to-match-OpenSSL-s.patch | ||||||
| # Fix `OpenSSL::TestPKCS12#test_{new_with_no_keys,new_with_one_key_and_one_cert}` | # Fix `OpenSSL::TestPKCS12#test_{new_with_no_keys,new_with_one_key_and_one_cert}` | ||||||
| # test failures. | # test failures. | ||||||
| # https://github.com/ruby/openssl/commit/998406d18f2acf73090e9fd9d92a7b4227ac593b | # https://github.com/ruby/openssl/commit/998406d18f2acf73090e9fd9d92a7b4227ac593b | ||||||
| Patch49: ruby-3.1.0-test-openssl-test_pkcs12-fix-test-failures-with-Open.patch | Patch50: ruby-3.1.0-test-openssl-test_pkcs12-fix-test-failures-with-Open.patch | ||||||
| # Fix `OpenSSL::TestPKey#test_s_generate_key` test case. | # Fix `OpenSSL::TestPKey#test_s_generate_key` test case. | ||||||
| # https://github.com/ruby/openssl/commit/c732387ee5aaa8c5a9717e8b3ffebb3d7430e99a | # https://github.com/ruby/openssl/commit/c732387ee5aaa8c5a9717e8b3ffebb3d7430e99a | ||||||
| Patch50: ruby-3.1.0-test-openssl-test_pkey-use-EC-keys-for-PKey.generate.patch | Patch51: ruby-3.1.0-test-openssl-test_pkey-use-EC-keys-for-PKey.generate.patch | ||||||
| # Miscellaneous changes for OpenSSL 3.0 support. | # Miscellaneous changes for OpenSSL 3.0 support. | ||||||
| # https://github.com/ruby/openssl/pull/468 | # https://github.com/ruby/openssl/pull/468 | ||||||
| Patch51: ruby-3.1.0-Miscellaneous-changes-for-OpenSSL-3.0-support.patch | Patch52: ruby-3.1.0-Miscellaneous-changes-for-OpenSSL-3.0-support.patch | ||||||
| # Support OpenSSL 3.0. | # Use OSSL_DECODER to load encrypted PEM. | ||||||
| # https://github.com/ruby/openssl/pull/399 | # https://github.com/ruby/openssl/pull/479 | ||||||
| Patch52: ruby-3.1.0-Support-OpenSSL-3.0.patch | Patch53: ruby-3.1.0-Use-OSSL_DECODER-to-load-encrypted-PEM-on-OpenSSL-3.0.patch | ||||||
|  | # Allocate EVP_PKEY on #initialize. | ||||||
|  | # https://github.com/ruby/openssl/pull/478 | ||||||
|  | Patch54: ruby-3.1.0-Allocate-EVP_PKEY-on-initialize.patch | ||||||
|  | # Disable `OpenSSL::TestPKeyRSA#test_no_private_exp` test case which is not | ||||||
|  | # compatible with OpenSSL 3.0. | ||||||
|  | # https://github.com/ruby/ruby/commit/47975ece4096cdab16b3f200f93ea2377dfb41ac | ||||||
|  | Patch55: ruby-3.1.0-Disable-test_no_private_exp-on-OpenSSL-3.0.patch | ||||||
|  | # Deprecate PKey::*#set_* and PKey::{DH,EC}#generate_key! | ||||||
|  | # https://github.com/ruby/openssl/pull/480 | ||||||
|  | Patch56: ruby-3.1.0-Deprecate-PKey-set_-and-PKey-DH-EC-generate_key.patch | ||||||
|  | # Fix `OpenSSL::PKey::PKeyError: pkeys are immutable on OpenSSL 3.0` errors. | ||||||
|  | # https://github.com/rubygems/rubygems/pull/5196 | ||||||
|  | Patch57: rubygems-3.3.1-Fix-compatibility-with-OpenSSL3.0.patch | ||||||
|  | # Miscellaneous changes for OpenSSL 3.0 support. | ||||||
|  | # https://github.com/ruby/openssl/pull/481 | ||||||
|  | Patch58: ruby-3.1.0-Miscellaneous-changes-for-OpenSSL-3.0-support-part-2.patch | ||||||
| # Fix `TestPumaControlCli#test_control_ssl` testcase in Puma. | # Fix `TestPumaControlCli#test_control_ssl` testcase in Puma. | ||||||
| # https://github.com/ruby/openssl/pull/399#issuecomment-966239736 | # https://github.com/ruby/openssl/pull/399#issuecomment-966239736 | ||||||
| Patch53: ruby-3.1.0-SSL_read-EOF-handling.patch | Patch59: ruby-3.1.0-SSL_read-EOF-handling.patch | ||||||
| # Fix segfault in `TestArray#test_sample` on s390x. |  | ||||||
| # https://github.com/ruby/ruby/pull/5239 |  | ||||||
| Patch54: ruby-3.1.0-Fix-stack-buffer-overflow.patch |  | ||||||
| 
 | 
 | ||||||
| Requires: %{name}-libs%{?_isa} = %{version}-%{release} | Requires: %{name}-libs%{?_isa} = %{version}-%{release} | ||||||
| Suggests: rubypick | Suggests: rubypick | ||||||
| @ -685,6 +704,7 @@ rm -rf ext/fiddle/libffi* | |||||||
| %patch20 -p1 | %patch20 -p1 | ||||||
| %patch21 -p1 | %patch21 -p1 | ||||||
| %patch22 -p1 | %patch22 -p1 | ||||||
|  | %patch23 -p1 | ||||||
| %patch30 -p1 -R | %patch30 -p1 -R | ||||||
| %patch31 -p1 | %patch31 -p1 | ||||||
| %patch40 -p1 | %patch40 -p1 | ||||||
| @ -702,6 +722,11 @@ rm -rf ext/fiddle/libffi* | |||||||
| %patch52 -p1 | %patch52 -p1 | ||||||
| %patch53 -p1 | %patch53 -p1 | ||||||
| %patch54 -p1 | %patch54 -p1 | ||||||
|  | %patch55 -p1 | ||||||
|  | %patch56 -p1 | ||||||
|  | %patch57 -p1 | ||||||
|  | %patch58 -p1 | ||||||
|  | %patch59 -p1 | ||||||
| 
 | 
 | ||||||
| # Provide an example of usage of the tapset: | # Provide an example of usage of the tapset: | ||||||
| cp -a %{SOURCE3} . | cp -a %{SOURCE3} . | ||||||
| @ -980,13 +1005,6 @@ MSPECOPTS="" | |||||||
| # Avoid `hostname' dependency. | # Avoid `hostname' dependency. | ||||||
| %{!?with_hostname:MSPECOPTS="-P 'Socket.gethostname returns the host name'"} | %{!?with_hostname:MSPECOPTS="-P 'Socket.gethostname returns the host name'"} | ||||||
| 
 | 
 | ||||||
| # Some tests are failing upstream due to OpenSSL 3.x compatibility. |  | ||||||
| # https://github.com/ruby/openssl/pull/399/checks?check_run_id=3716152870 |  | ||||||
| DISABLE_TESTS="$DISABLE_TESTS -n !/OpenSSL::TestEC#test_check_key/" |  | ||||||
| DISABLE_TESTS="$DISABLE_TESTS -n !/OpenSSL::TestPKeyDH#test_derive_key/" |  | ||||||
| DISABLE_TESTS="$DISABLE_TESTS -n !/OpenSSL::TestPKeyDH#test_key_exchange/" |  | ||||||
| DISABLE_TESTS="$DISABLE_TESTS -n !/OpenSSL::TestCipher#test_ciphers/" |  | ||||||
| 
 |  | ||||||
| # Several test broken by libffi-3.4.2. There should be fix in libffi, once | # Several test broken by libffi-3.4.2. There should be fix in libffi, once | ||||||
| # other components are fixed. | # other components are fixed. | ||||||
| # https://bugzilla.redhat.com/show_bug.cgi?id=2040380 | # https://bugzilla.redhat.com/show_bug.cgi?id=2040380 | ||||||
| @ -1469,6 +1487,9 @@ mv test/fiddle/test_import.rb{,.disable} | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
|  | * Tue Jan 25 2022 Vít Ondruch <vondruch@redhat.com> - 3.0.3-158 | ||||||
|  | - Update OpenSSL 3 compatibility patches. | ||||||
|  | 
 | ||||||
| * Thu Jan 20 2022 Vít Ondruch <vondruch@redhat.com> - 3.0.3-158 | * Thu Jan 20 2022 Vít Ondruch <vondruch@redhat.com> - 3.0.3-158 | ||||||
| - Disable package notes to prevent rubygem- build breakage. | - Disable package notes to prevent rubygem- build breakage. | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -92,10 +92,9 @@ even fully sure it was the right thing to do when I added that, and it | |||||||
| was not the culprit of the end user issue that led to making that | was not the culprit of the end user issue that led to making that | ||||||
| change. | change. | ||||||
| ---
 | ---
 | ||||||
|  .github/workflows/install-rubygems.yml |  5 ---- |  lib/rubygems.rb                | 32 ++++++++++++++++---------------- | ||||||
|  lib/rubygems.rb                        | 32 +++++++++++++------------- |  test/rubygems/test_rubygems.rb | 23 +++++++++++++++++++++++ | ||||||
|  test/rubygems/test_rubygems.rb         | 23 ++++++++++++++++++ |  2 files changed, 39 insertions(+), 16 deletions(-) | ||||||
|  3 files changed, 39 insertions(+), 21 deletions(-) |  | ||||||
| 
 | 
 | ||||||
| diff --git a/lib/rubygems.rb b/lib/rubygems.rb
 | diff --git a/lib/rubygems.rb b/lib/rubygems.rb
 | ||||||
| index b8747409304..11474b6554c 100644
 | index b8747409304..11474b6554c 100644
 | ||||||
| @ -189,8 +188,8 @@ Otherwise first OS customizations load and activate that fiddle version, | |||||||
| but then when we change to `Gem.default_dir`, that fiddle version is no | but then when we change to `Gem.default_dir`, that fiddle version is no | ||||||
| longer there. | longer there. | ||||||
| ---
 | ---
 | ||||||
|  bundler/spec/commands/clean_spec.rb          | 2 +- |  spec/bundler/commands/clean_spec.rb          | 2 +- | ||||||
|  bundler/spec/install/gems/standalone_spec.rb | 2 +- |  spec/bundler/install/gems/standalone_spec.rb | 2 +- | ||||||
|  2 files changed, 2 insertions(+), 2 deletions(-) |  2 files changed, 2 insertions(+), 2 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/spec/bundler/commands/clean_spec.rb b/spec/bundler/commands/clean_spec.rb
 | diff --git a/spec/bundler/commands/clean_spec.rb b/spec/bundler/commands/clean_spec.rb
 | ||||||
|  | |||||||
							
								
								
									
										105
									
								
								rubygems-3.3.1-Fix-compatibility-with-OpenSSL3.0.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								rubygems-3.3.1-Fix-compatibility-with-OpenSSL3.0.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | |||||||
|  | From 558128594de16add5b453833fd5b043a24c1b7f5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Wed, 22 Dec 2021 01:38:47 +0900 | ||||||
|  | Subject: [PATCH 1/3] Use OpenSSL::PKey::EC.generate to generate ECC key pairs | ||||||
|  | 
 | ||||||
|  | When Ruby/OpenSSL is built against OpenSSL 3.0, OpenSSL::PKey::PKey | ||||||
|  | instances are immutable and OpenSSL::PKey::EC#generate_key cannot work | ||||||
|  | because it modifies the receiver. | ||||||
|  | 
 | ||||||
|  | OpenSSL::PKey::EC.generate is available on Ruby 2.4 (Ruby/OpenSSL 2.0) | ||||||
|  | or later. | ||||||
|  | ---
 | ||||||
|  |  lib/rubygems/security.rb | 10 +++++++--- | ||||||
|  |  1 file changed, 7 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
 | ||||||
|  | index 22759972070..2aa07381d69 100644
 | ||||||
|  | --- a/lib/rubygems/security.rb
 | ||||||
|  | +++ b/lib/rubygems/security.rb
 | ||||||
|  | @@ -490,9 +490,13 @@ def self.create_key(algorithm)
 | ||||||
|  |        when 'rsa' | ||||||
|  |          OpenSSL::PKey::RSA.new(RSA_DSA_KEY_LENGTH) | ||||||
|  |        when 'ec' | ||||||
|  | -        domain_key = OpenSSL::PKey::EC.new(EC_NAME)
 | ||||||
|  | -        domain_key.generate_key
 | ||||||
|  | -        domain_key
 | ||||||
|  | +        if RUBY_VERSION >= "2.4.0"
 | ||||||
|  | +          OpenSSL::PKey::EC.generate(EC_NAME)
 | ||||||
|  | +        else
 | ||||||
|  | +          domain_key = OpenSSL::PKey::EC.new(EC_NAME)
 | ||||||
|  | +          domain_key.generate_key
 | ||||||
|  | +          domain_key
 | ||||||
|  | +        end
 | ||||||
|  |        else | ||||||
|  |          raise Gem::Security::Exception, | ||||||
|  |          "#{algorithm} algorithm not found. RSA, DSA, and EC algorithms are supported." | ||||||
|  | 
 | ||||||
|  | From 60067d4f09b7fb9c23bed38e91acfde0293f29a0 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Wed, 22 Dec 2021 01:49:05 +0900 | ||||||
|  | Subject: [PATCH 2/3] Use OpenSSL::X509::Certificate#check_private_key | ||||||
|  | 
 | ||||||
|  | The method is for the exact purpose: to check that an instance of | ||||||
|  | OpenSSL::PKey::PKey matches the public key in a certificate. | ||||||
|  | ---
 | ||||||
|  |  lib/rubygems/security.rb        | 2 +- | ||||||
|  |  lib/rubygems/security/policy.rb | 4 +--- | ||||||
|  |  2 files changed, 2 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
 | ||||||
|  | index 2aa07381d69..2906819bd34 100644
 | ||||||
|  | --- a/lib/rubygems/security.rb
 | ||||||
|  | +++ b/lib/rubygems/security.rb
 | ||||||
|  | @@ -530,7 +530,7 @@ def self.re_sign(expired_certificate, private_key, age = ONE_YEAR,
 | ||||||
|  |      raise Gem::Security::Exception, | ||||||
|  |            "incorrect signing key for re-signing " + | ||||||
|  |            "#{expired_certificate.subject}" unless | ||||||
|  | -      expired_certificate.public_key.to_pem == get_public_key(private_key).to_pem
 | ||||||
|  | +      expired_certificate.check_private_key(private_key)
 | ||||||
|  |   | ||||||
|  |      unless expired_certificate.subject.to_s == | ||||||
|  |             expired_certificate.issuer.to_s | ||||||
|  | diff --git a/lib/rubygems/security/policy.rb b/lib/rubygems/security/policy.rb
 | ||||||
|  | index 3c3cb647ee3..06eae073f4a 100644
 | ||||||
|  | --- a/lib/rubygems/security/policy.rb
 | ||||||
|  | +++ b/lib/rubygems/security/policy.rb
 | ||||||
|  | @@ -115,11 +115,9 @@ def check_key(signer, key)
 | ||||||
|  |        raise Gem::Security::Exception, 'missing key or signature' | ||||||
|  |      end | ||||||
|  |   | ||||||
|  | -    public_key = Gem::Security.get_public_key(key)
 | ||||||
|  | -
 | ||||||
|  |      raise Gem::Security::Exception, | ||||||
|  |        "certificate #{signer.subject} does not match the signing key" unless | ||||||
|  | -        signer.public_key.to_pem == public_key.to_pem
 | ||||||
|  | +        signer.check_private_key(key)
 | ||||||
|  |   | ||||||
|  |      true | ||||||
|  |    end | ||||||
|  | 
 | ||||||
|  | From 6819e3d0fadc10ce8d10919402eedb730cf0e43f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kazuki Yamaguchi <k@rhe.jp> | ||||||
|  | Date: Wed, 22 Dec 2021 01:54:10 +0900 | ||||||
|  | Subject: [PATCH 3/3] Fix Gem::Security.get_public_key on OpenSSL 3.0 | ||||||
|  | 
 | ||||||
|  | Ruby/OpenSSL 2.2 added OpenSSL::PKey::PKey#public_to_der for serializing | ||||||
|  | only the public key components contained in the instance. This works | ||||||
|  | for all possible key types. | ||||||
|  | ---
 | ||||||
|  |  lib/rubygems/security.rb | 2 ++ | ||||||
|  |  1 file changed, 2 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
 | ||||||
|  | index 2906819bd34..f21c1756422 100644
 | ||||||
|  | --- a/lib/rubygems/security.rb
 | ||||||
|  | +++ b/lib/rubygems/security.rb
 | ||||||
|  | @@ -424,6 +424,8 @@ def self.create_cert(subject, key, age = ONE_YEAR, extensions = EXTENSIONS,
 | ||||||
|  |    # Gets the right public key from a PKey instance | ||||||
|  |   | ||||||
|  |    def self.get_public_key(key) | ||||||
|  | +    # Ruby 3.0 (Ruby/OpenSSL 2.2) or later
 | ||||||
|  | +    return OpenSSL::PKey.read(key.public_to_der) if key.respond_to?(:public_to_der)
 | ||||||
|  |      return key.public_key unless key.is_a?(OpenSSL::PKey::EC) | ||||||
|  |   | ||||||
|  |      ec_key = OpenSSL::PKey::EC.new(key.group.curve_name) | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user