aboutsummaryrefslogtreecommitdiffstats
path: root/ext/openssl/ossl_pkey.c
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-09-23 01:15:13 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-09-23 18:31:07 +0900
commit0e49794521db899ab25774e932f83d6ce452a8ec (patch)
tree28601eaf1403a2a7ca293add5eb24b9a8ba946ee /ext/openssl/ossl_pkey.c
parent6ee36c1403ce410688d2d0f918e2c6d7dc5d1cb3 (diff)
downloadruby-openssl-0e49794521db899ab25774e932f83d6ce452a8ec.tar.gz
pkey: make PKey#verify check the existence of the public key
Check existence of the public key in the PKey object before starting verifying a signature. For RSA keys, EVP_VerifyFinal() internally calls RSA_size(), which requires the existence of RSA::n. Since we allow instatiating PKey::RSA without any key materials, calling PKey#verify against an empty PKey::RSA causes segfault. Reference: https://bugs.ruby-lang.org/issues/12783
Diffstat (limited to 'ext/openssl/ossl_pkey.c')
-rw-r--r--ext/openssl/ossl_pkey.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 3c7c5e17..2ce95b7c 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -166,6 +166,45 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
return ossl_pkey_new(pkey);
}
+static void
+pkey_check_public_key(EVP_PKEY *pkey)
+{
+ void *ptr;
+ const BIGNUM *n, *e, *pubkey;
+
+ if (EVP_PKEY_missing_parameters(pkey))
+ ossl_raise(ePKeyError, "parameters missing");
+
+ ptr = EVP_PKEY_get0(pkey);
+ switch (EVP_PKEY_base_id(pkey)) {
+ case EVP_PKEY_RSA:
+ RSA_get0_key(ptr, &n, &e, NULL);
+ if (n && e)
+ return;
+ break;
+ case EVP_PKEY_DSA:
+ DSA_get0_key(ptr, &pubkey, NULL);
+ if (pubkey)
+ return;
+ break;
+ case EVP_PKEY_DH:
+ DH_get0_key(ptr, &pubkey, NULL);
+ if (pubkey)
+ return;
+ break;
+#if !defined(OPENSSL_NO_EC)
+ case EVP_PKEY_EC:
+ if (EC_KEY_get0_public_key(ptr))
+ return;
+ break;
+#endif
+ default:
+ /* unsupported type; assuming ok */
+ return;
+ }
+ ossl_raise(ePKeyError, "public key missing");
+}
+
EVP_PKEY *
GetPKeyPtr(VALUE obj)
{
@@ -311,6 +350,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
int result;
GetPKey(self, pkey);
+ pkey_check_public_key(pkey);
md = GetDigestPtr(digest);
StringValue(sig);
StringValue(data);