openssl 2.1.0.beta1 → 2.1.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openssl might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/History.md +49 -6
- data/ext/openssl/openssl_missing.h +4 -0
- data/ext/openssl/ossl.c +48 -41
- data/ext/openssl/ossl.h +5 -0
- data/ext/openssl/ossl_bn.c +6 -6
- data/ext/openssl/ossl_cipher.c +9 -7
- data/ext/openssl/ossl_engine.c +34 -20
- data/ext/openssl/ossl_kdf.c +98 -0
- data/ext/openssl/ossl_ns_spki.c +14 -10
- data/ext/openssl/ossl_pkey.c +5 -4
- data/ext/openssl/ossl_pkey.h +1 -0
- data/ext/openssl/ossl_pkey_rsa.c +192 -0
- data/ext/openssl/ossl_ssl.c +170 -20
- data/ext/openssl/ossl_x509cert.c +31 -9
- data/ext/openssl/ossl_x509crl.c +6 -3
- data/ext/openssl/ossl_x509name.c +1 -1
- data/ext/openssl/ossl_x509req.c +6 -6
- data/ext/openssl/ossl_x509revoked.c +21 -0
- data/ext/openssl/ruby_missing.h +8 -2
- data/lib/openssl/buffering.rb +5 -3
- data/lib/openssl/ssl.rb +2 -1
- data/lib/openssl/x509.rb +33 -0
- metadata +4 -4
data/ext/openssl/ossl_kdf.c
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
* Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors
|
4
4
|
*/
|
5
5
|
#include "ossl.h"
|
6
|
+
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
7
|
+
# include <openssl/kdf.h>
|
8
|
+
#endif
|
6
9
|
|
7
10
|
static VALUE mKDF, eKDF;
|
8
11
|
|
@@ -138,6 +141,97 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
|
|
138
141
|
}
|
139
142
|
#endif
|
140
143
|
|
144
|
+
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
145
|
+
/*
|
146
|
+
* call-seq:
|
147
|
+
* KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String
|
148
|
+
*
|
149
|
+
* HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as specified in
|
150
|
+
* {RFC 5869}[https://tools.ietf.org/html/rfc5869].
|
151
|
+
*
|
152
|
+
* New in OpenSSL 1.1.0.
|
153
|
+
*
|
154
|
+
* === Parameters
|
155
|
+
* _ikm_::
|
156
|
+
* The input keying material.
|
157
|
+
* _salt_::
|
158
|
+
* The salt.
|
159
|
+
* _info_::
|
160
|
+
* The context and application specific information.
|
161
|
+
* _length_::
|
162
|
+
* The output length in octets. Must be <= <tt>255 * HashLen</tt>, where
|
163
|
+
* HashLen is the length of the hash function output in octets.
|
164
|
+
* _hash_::
|
165
|
+
* The hash function.
|
166
|
+
*/
|
167
|
+
static VALUE
|
168
|
+
kdf_hkdf(int argc, VALUE *argv, VALUE self)
|
169
|
+
{
|
170
|
+
VALUE ikm, salt, info, opts, kwargs[4], str;
|
171
|
+
static ID kwargs_ids[4];
|
172
|
+
int saltlen, ikmlen, infolen;
|
173
|
+
size_t len;
|
174
|
+
const EVP_MD *md;
|
175
|
+
EVP_PKEY_CTX *pctx;
|
176
|
+
|
177
|
+
if (!kwargs_ids[0]) {
|
178
|
+
kwargs_ids[0] = rb_intern_const("salt");
|
179
|
+
kwargs_ids[1] = rb_intern_const("info");
|
180
|
+
kwargs_ids[2] = rb_intern_const("length");
|
181
|
+
kwargs_ids[3] = rb_intern_const("hash");
|
182
|
+
}
|
183
|
+
rb_scan_args(argc, argv, "1:", &ikm, &opts);
|
184
|
+
rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs);
|
185
|
+
|
186
|
+
StringValue(ikm);
|
187
|
+
ikmlen = RSTRING_LENINT(ikm);
|
188
|
+
salt = StringValue(kwargs[0]);
|
189
|
+
saltlen = RSTRING_LENINT(salt);
|
190
|
+
info = StringValue(kwargs[1]);
|
191
|
+
infolen = RSTRING_LENINT(info);
|
192
|
+
len = (size_t)NUM2LONG(kwargs[2]);
|
193
|
+
if (len > LONG_MAX)
|
194
|
+
rb_raise(rb_eArgError, "length must be non-negative");
|
195
|
+
md = ossl_evp_get_digestbyname(kwargs[3]);
|
196
|
+
|
197
|
+
str = rb_str_new(NULL, (long)len);
|
198
|
+
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
|
199
|
+
if (!pctx)
|
200
|
+
ossl_raise(eKDF, "EVP_PKEY_CTX_new_id");
|
201
|
+
if (EVP_PKEY_derive_init(pctx) <= 0) {
|
202
|
+
EVP_PKEY_CTX_free(pctx);
|
203
|
+
ossl_raise(eKDF, "EVP_PKEY_derive_init");
|
204
|
+
}
|
205
|
+
if (EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0) {
|
206
|
+
EVP_PKEY_CTX_free(pctx);
|
207
|
+
ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_md");
|
208
|
+
}
|
209
|
+
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, (unsigned char *)RSTRING_PTR(salt),
|
210
|
+
saltlen) <= 0) {
|
211
|
+
EVP_PKEY_CTX_free(pctx);
|
212
|
+
ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_salt");
|
213
|
+
}
|
214
|
+
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, (unsigned char *)RSTRING_PTR(ikm),
|
215
|
+
ikmlen) <= 0) {
|
216
|
+
EVP_PKEY_CTX_free(pctx);
|
217
|
+
ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_key");
|
218
|
+
}
|
219
|
+
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, (unsigned char *)RSTRING_PTR(info),
|
220
|
+
infolen) <= 0) {
|
221
|
+
EVP_PKEY_CTX_free(pctx);
|
222
|
+
ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_info");
|
223
|
+
}
|
224
|
+
if (EVP_PKEY_derive(pctx, (unsigned char *)RSTRING_PTR(str), &len) <= 0) {
|
225
|
+
EVP_PKEY_CTX_free(pctx);
|
226
|
+
ossl_raise(eKDF, "EVP_PKEY_derive");
|
227
|
+
}
|
228
|
+
rb_str_set_len(str, (long)len);
|
229
|
+
EVP_PKEY_CTX_free(pctx);
|
230
|
+
|
231
|
+
return str;
|
232
|
+
}
|
233
|
+
#endif
|
234
|
+
|
141
235
|
void
|
142
236
|
Init_ossl_kdf(void)
|
143
237
|
{
|
@@ -162,6 +256,7 @@ Init_ossl_kdf(void)
|
|
162
256
|
* * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in
|
163
257
|
* combination with HMAC
|
164
258
|
* * scrypt
|
259
|
+
* * HKDF
|
165
260
|
*
|
166
261
|
* == Examples
|
167
262
|
* === Generating a 128 bit key for a Cipher (e.g. AES)
|
@@ -218,4 +313,7 @@ Init_ossl_kdf(void)
|
|
218
313
|
#if defined(HAVE_EVP_PBE_SCRYPT)
|
219
314
|
rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1);
|
220
315
|
#endif
|
316
|
+
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
317
|
+
rb_define_module_function(mKDF, "hkdf", kdf_hkdf, -1);
|
318
|
+
#endif
|
221
319
|
}
|
data/ext/openssl/ossl_ns_spki.c
CHANGED
@@ -208,12 +208,13 @@ static VALUE
|
|
208
208
|
ossl_spki_set_public_key(VALUE self, VALUE key)
|
209
209
|
{
|
210
210
|
NETSCAPE_SPKI *spki;
|
211
|
+
EVP_PKEY *pkey;
|
211
212
|
|
212
213
|
GetSPKI(self, spki);
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
214
|
+
pkey = GetPKeyPtr(key);
|
215
|
+
ossl_pkey_check_public_key(pkey);
|
216
|
+
if (!NETSCAPE_SPKI_set_pubkey(spki, pkey))
|
217
|
+
ossl_raise(eSPKIError, "NETSCAPE_SPKI_set_pubkey");
|
217
218
|
return key;
|
218
219
|
}
|
219
220
|
|
@@ -307,17 +308,20 @@ static VALUE
|
|
307
308
|
ossl_spki_verify(VALUE self, VALUE key)
|
308
309
|
{
|
309
310
|
NETSCAPE_SPKI *spki;
|
311
|
+
EVP_PKEY *pkey;
|
310
312
|
|
311
313
|
GetSPKI(self, spki);
|
312
|
-
|
313
|
-
|
314
|
+
pkey = GetPKeyPtr(key);
|
315
|
+
ossl_pkey_check_public_key(pkey);
|
316
|
+
switch (NETSCAPE_SPKI_verify(spki, pkey)) {
|
317
|
+
case 0:
|
318
|
+
ossl_clear_error();
|
314
319
|
return Qfalse;
|
315
|
-
|
320
|
+
case 1:
|
316
321
|
return Qtrue;
|
317
|
-
|
318
|
-
ossl_raise(eSPKIError,
|
322
|
+
default:
|
323
|
+
ossl_raise(eSPKIError, "NETSCAPE_SPKI_verify");
|
319
324
|
}
|
320
|
-
return Qnil; /* dummy */
|
321
325
|
}
|
322
326
|
|
323
327
|
/* Document-class: OpenSSL::Netscape::SPKI
|
data/ext/openssl/ossl_pkey.c
CHANGED
@@ -163,8 +163,8 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
|
|
163
163
|
return ossl_pkey_new(pkey);
|
164
164
|
}
|
165
165
|
|
166
|
-
|
167
|
-
|
166
|
+
void
|
167
|
+
ossl_pkey_check_public_key(const EVP_PKEY *pkey)
|
168
168
|
{
|
169
169
|
void *ptr;
|
170
170
|
const BIGNUM *n, *e, *pubkey;
|
@@ -172,7 +172,8 @@ pkey_check_public_key(EVP_PKEY *pkey)
|
|
172
172
|
if (EVP_PKEY_missing_parameters(pkey))
|
173
173
|
ossl_raise(ePKeyError, "parameters missing");
|
174
174
|
|
175
|
-
|
175
|
+
/* OpenSSL < 1.1.0 takes non-const pointer */
|
176
|
+
ptr = EVP_PKEY_get0((EVP_PKEY *)pkey);
|
176
177
|
switch (EVP_PKEY_base_id(pkey)) {
|
177
178
|
case EVP_PKEY_RSA:
|
178
179
|
RSA_get0_key(ptr, &n, &e, NULL);
|
@@ -352,7 +353,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
|
|
352
353
|
int siglen, result;
|
353
354
|
|
354
355
|
GetPKey(self, pkey);
|
355
|
-
|
356
|
+
ossl_pkey_check_public_key(pkey);
|
356
357
|
md = ossl_evp_get_digestbyname(digest);
|
357
358
|
StringValue(sig);
|
358
359
|
siglen = RSTRING_LENINT(sig);
|
data/ext/openssl/ossl_pkey.h
CHANGED
@@ -44,6 +44,7 @@ int ossl_generate_cb_2(int p, int n, BN_GENCB *cb);
|
|
44
44
|
void ossl_generate_cb_stop(void *ptr);
|
45
45
|
|
46
46
|
VALUE ossl_pkey_new(EVP_PKEY *);
|
47
|
+
void ossl_pkey_check_public_key(const EVP_PKEY *);
|
47
48
|
EVP_PKEY *GetPKeyPtr(VALUE);
|
48
49
|
EVP_PKEY *DupPKeyPtr(VALUE);
|
49
50
|
EVP_PKEY *GetPrivPKeyPtr(VALUE);
|
data/ext/openssl/ossl_pkey_rsa.c
CHANGED
@@ -536,6 +536,196 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
|
|
536
536
|
return str;
|
537
537
|
}
|
538
538
|
|
539
|
+
/*
|
540
|
+
* call-seq:
|
541
|
+
* rsa.sign_pss(digest, data, salt_length:, mgf1_hash:) -> String
|
542
|
+
*
|
543
|
+
* Signs _data_ using the Probabilistic Signature Scheme (RSA-PSS) and returns
|
544
|
+
* the calculated signature.
|
545
|
+
*
|
546
|
+
* RSAError will be raised if an error occurs.
|
547
|
+
*
|
548
|
+
* See #verify_pss for the verification operation.
|
549
|
+
*
|
550
|
+
* === Parameters
|
551
|
+
* _digest_::
|
552
|
+
* A String containing the message digest algorithm name.
|
553
|
+
* _data_::
|
554
|
+
* A String. The data to be signed.
|
555
|
+
* _salt_length_::
|
556
|
+
* The length in octets of the salt. Two special values are reserved:
|
557
|
+
* +:digest+ means the digest length, and +:max+ means the maximum possible
|
558
|
+
* length for the combination of the private key and the selected message
|
559
|
+
* digest algorithm.
|
560
|
+
* _mgf1_hash_::
|
561
|
+
* The hash algorithm used in MGF1 (the currently supported mask generation
|
562
|
+
* function (MGF)).
|
563
|
+
*
|
564
|
+
* === Example
|
565
|
+
* data = "Sign me!"
|
566
|
+
* pkey = OpenSSL::PKey::RSA.new(2048)
|
567
|
+
* signature = pkey.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256")
|
568
|
+
* pub_key = pkey.public_key
|
569
|
+
* puts pub_key.verify_pss("SHA256", signature, data,
|
570
|
+
* salt_length: :auto, mgf1_hash: "SHA256") # => true
|
571
|
+
*/
|
572
|
+
static VALUE
|
573
|
+
ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
|
574
|
+
{
|
575
|
+
VALUE digest, data, options, kwargs[2], signature;
|
576
|
+
static ID kwargs_ids[2];
|
577
|
+
EVP_PKEY *pkey;
|
578
|
+
EVP_PKEY_CTX *pkey_ctx;
|
579
|
+
const EVP_MD *md, *mgf1md;
|
580
|
+
EVP_MD_CTX *md_ctx;
|
581
|
+
size_t buf_len;
|
582
|
+
int salt_len;
|
583
|
+
|
584
|
+
if (!kwargs_ids[0]) {
|
585
|
+
kwargs_ids[0] = rb_intern_const("salt_length");
|
586
|
+
kwargs_ids[1] = rb_intern_const("mgf1_hash");
|
587
|
+
}
|
588
|
+
rb_scan_args(argc, argv, "2:", &digest, &data, &options);
|
589
|
+
rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
|
590
|
+
if (kwargs[0] == ID2SYM(rb_intern("max")))
|
591
|
+
salt_len = -2; /* RSA_PSS_SALTLEN_MAX_SIGN */
|
592
|
+
else if (kwargs[0] == ID2SYM(rb_intern("digest")))
|
593
|
+
salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
|
594
|
+
else
|
595
|
+
salt_len = NUM2INT(kwargs[0]);
|
596
|
+
mgf1md = ossl_evp_get_digestbyname(kwargs[1]);
|
597
|
+
|
598
|
+
pkey = GetPrivPKeyPtr(self);
|
599
|
+
buf_len = EVP_PKEY_size(pkey);
|
600
|
+
md = ossl_evp_get_digestbyname(digest);
|
601
|
+
StringValue(data);
|
602
|
+
signature = rb_str_new(NULL, (long)buf_len);
|
603
|
+
|
604
|
+
md_ctx = EVP_MD_CTX_new();
|
605
|
+
if (!md_ctx)
|
606
|
+
goto err;
|
607
|
+
|
608
|
+
if (EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
|
609
|
+
goto err;
|
610
|
+
|
611
|
+
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
|
612
|
+
goto err;
|
613
|
+
|
614
|
+
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
|
615
|
+
goto err;
|
616
|
+
|
617
|
+
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
|
618
|
+
goto err;
|
619
|
+
|
620
|
+
if (EVP_DigestSignUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
|
621
|
+
goto err;
|
622
|
+
|
623
|
+
if (EVP_DigestSignFinal(md_ctx, (unsigned char *)RSTRING_PTR(signature), &buf_len) != 1)
|
624
|
+
goto err;
|
625
|
+
|
626
|
+
rb_str_set_len(signature, (long)buf_len);
|
627
|
+
|
628
|
+
EVP_MD_CTX_free(md_ctx);
|
629
|
+
return signature;
|
630
|
+
|
631
|
+
err:
|
632
|
+
EVP_MD_CTX_free(md_ctx);
|
633
|
+
ossl_raise(eRSAError, NULL);
|
634
|
+
}
|
635
|
+
|
636
|
+
/*
|
637
|
+
* call-seq:
|
638
|
+
* rsa.verify_pss(digest, signature, data, salt_length:, mgf1_hash:) -> true | false
|
639
|
+
*
|
640
|
+
* Verifies _data_ using the Probabilistic Signature Scheme (RSA-PSS).
|
641
|
+
*
|
642
|
+
* The return value is +true+ if the signature is valid, +false+ otherwise.
|
643
|
+
* RSAError will be raised if an error occurs.
|
644
|
+
*
|
645
|
+
* See #sign_pss for the signing operation and an example code.
|
646
|
+
*
|
647
|
+
* === Parameters
|
648
|
+
* _digest_::
|
649
|
+
* A String containing the message digest algorithm name.
|
650
|
+
* _data_::
|
651
|
+
* A String. The data to be signed.
|
652
|
+
* _salt_length_::
|
653
|
+
* The length in octets of the salt. Two special values are reserved:
|
654
|
+
* +:digest+ means the digest length, and +:auto+ means automatically
|
655
|
+
* determining the length based on the signature.
|
656
|
+
* _mgf1_hash_::
|
657
|
+
* The hash algorithm used in MGF1.
|
658
|
+
*/
|
659
|
+
static VALUE
|
660
|
+
ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self)
|
661
|
+
{
|
662
|
+
VALUE digest, signature, data, options, kwargs[2];
|
663
|
+
static ID kwargs_ids[2];
|
664
|
+
EVP_PKEY *pkey;
|
665
|
+
EVP_PKEY_CTX *pkey_ctx;
|
666
|
+
const EVP_MD *md, *mgf1md;
|
667
|
+
EVP_MD_CTX *md_ctx;
|
668
|
+
int result, salt_len;
|
669
|
+
|
670
|
+
if (!kwargs_ids[0]) {
|
671
|
+
kwargs_ids[0] = rb_intern_const("salt_length");
|
672
|
+
kwargs_ids[1] = rb_intern_const("mgf1_hash");
|
673
|
+
}
|
674
|
+
rb_scan_args(argc, argv, "3:", &digest, &signature, &data, &options);
|
675
|
+
rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
|
676
|
+
if (kwargs[0] == ID2SYM(rb_intern("auto")))
|
677
|
+
salt_len = -2; /* RSA_PSS_SALTLEN_AUTO */
|
678
|
+
else if (kwargs[0] == ID2SYM(rb_intern("digest")))
|
679
|
+
salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
|
680
|
+
else
|
681
|
+
salt_len = NUM2INT(kwargs[0]);
|
682
|
+
mgf1md = ossl_evp_get_digestbyname(kwargs[1]);
|
683
|
+
|
684
|
+
GetPKey(self, pkey);
|
685
|
+
md = ossl_evp_get_digestbyname(digest);
|
686
|
+
StringValue(signature);
|
687
|
+
StringValue(data);
|
688
|
+
|
689
|
+
md_ctx = EVP_MD_CTX_new();
|
690
|
+
if (!md_ctx)
|
691
|
+
goto err;
|
692
|
+
|
693
|
+
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
|
694
|
+
goto err;
|
695
|
+
|
696
|
+
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
|
697
|
+
goto err;
|
698
|
+
|
699
|
+
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
|
700
|
+
goto err;
|
701
|
+
|
702
|
+
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
|
703
|
+
goto err;
|
704
|
+
|
705
|
+
if (EVP_DigestVerifyUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
|
706
|
+
goto err;
|
707
|
+
|
708
|
+
result = EVP_DigestVerifyFinal(md_ctx,
|
709
|
+
(unsigned char *)RSTRING_PTR(signature),
|
710
|
+
RSTRING_LEN(signature));
|
711
|
+
|
712
|
+
switch (result) {
|
713
|
+
case 0:
|
714
|
+
ossl_clear_error();
|
715
|
+
EVP_MD_CTX_free(md_ctx);
|
716
|
+
return Qfalse;
|
717
|
+
case 1:
|
718
|
+
EVP_MD_CTX_free(md_ctx);
|
719
|
+
return Qtrue;
|
720
|
+
default:
|
721
|
+
goto err;
|
722
|
+
}
|
723
|
+
|
724
|
+
err:
|
725
|
+
EVP_MD_CTX_free(md_ctx);
|
726
|
+
ossl_raise(eRSAError, NULL);
|
727
|
+
}
|
728
|
+
|
539
729
|
/*
|
540
730
|
* call-seq:
|
541
731
|
* rsa.params => hash
|
@@ -731,6 +921,8 @@ Init_ossl_rsa(void)
|
|
731
921
|
rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
|
732
922
|
rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
|
733
923
|
rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
|
924
|
+
rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1);
|
925
|
+
rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1);
|
734
926
|
|
735
927
|
DEF_OSSL_PKEY_BN(cRSA, rsa, n);
|
736
928
|
DEF_OSSL_PKEY_BN(cRSA, rsa, e);
|
data/ext/openssl/ossl_ssl.c
CHANGED
@@ -32,7 +32,7 @@ VALUE cSSLSocket;
|
|
32
32
|
static VALUE eSSLErrorWaitReadable;
|
33
33
|
static VALUE eSSLErrorWaitWritable;
|
34
34
|
|
35
|
-
static ID ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
|
35
|
+
static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
|
36
36
|
id_npn_protocols_encoded;
|
37
37
|
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
|
38
38
|
|
@@ -205,7 +205,7 @@ ossl_call_client_cert_cb(VALUE obj)
|
|
205
205
|
if (NIL_P(cb))
|
206
206
|
return Qnil;
|
207
207
|
|
208
|
-
ary =
|
208
|
+
ary = rb_funcallv(cb, id_call, 1, &obj);
|
209
209
|
Check_Type(ary, T_ARRAY);
|
210
210
|
GetX509CertPtr(cert = rb_ary_entry(ary, 0));
|
211
211
|
GetPrivPKeyPtr(key = rb_ary_entry(ary, 1));
|
@@ -248,8 +248,8 @@ ossl_call_tmp_dh_callback(struct tmp_dh_callback_args *args)
|
|
248
248
|
cb = rb_funcall(args->ssl_obj, args->id, 0);
|
249
249
|
if (NIL_P(cb))
|
250
250
|
return NULL;
|
251
|
-
dh = rb_funcall(cb,
|
252
|
-
|
251
|
+
dh = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
|
252
|
+
INT2NUM(args->keylength));
|
253
253
|
pkey = GetPKeyPtr(dh);
|
254
254
|
if (EVP_PKEY_base_id(pkey) != args->type)
|
255
255
|
return NULL;
|
@@ -374,12 +374,12 @@ ossl_call_session_get_cb(VALUE ary)
|
|
374
374
|
cb = rb_funcall(ssl_obj, rb_intern("session_get_cb"), 0);
|
375
375
|
if (NIL_P(cb)) return Qnil;
|
376
376
|
|
377
|
-
return
|
377
|
+
return rb_funcallv(cb, id_call, 1, &ary);
|
378
378
|
}
|
379
379
|
|
380
380
|
/* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
|
381
381
|
static SSL_SESSION *
|
382
|
-
#if OPENSSL_VERSION_NUMBER >=
|
382
|
+
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
|
383
383
|
ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
|
384
384
|
#else
|
385
385
|
ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
|
@@ -420,7 +420,7 @@ ossl_call_session_new_cb(VALUE ary)
|
|
420
420
|
cb = rb_funcall(ssl_obj, rb_intern("session_new_cb"), 0);
|
421
421
|
if (NIL_P(cb)) return Qnil;
|
422
422
|
|
423
|
-
return
|
423
|
+
return rb_funcallv(cb, id_call, 1, &ary);
|
424
424
|
}
|
425
425
|
|
426
426
|
/* return 1 normal. return 0 removes the session */
|
@@ -467,7 +467,7 @@ ossl_call_session_remove_cb(VALUE ary)
|
|
467
467
|
cb = rb_attr_get(sslctx_obj, id_i_session_remove_cb);
|
468
468
|
if (NIL_P(cb)) return Qnil;
|
469
469
|
|
470
|
-
return
|
470
|
+
return rb_funcallv(cb, id_call, 1, &ary);
|
471
471
|
}
|
472
472
|
|
473
473
|
static void
|
@@ -533,7 +533,7 @@ ossl_call_servername_cb(VALUE ary)
|
|
533
533
|
cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
|
534
534
|
if (NIL_P(cb)) return Qnil;
|
535
535
|
|
536
|
-
ret_obj =
|
536
|
+
ret_obj = rb_funcallv(cb, id_call, 1, &ary);
|
537
537
|
if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
|
538
538
|
SSL *ssl;
|
539
539
|
SSL_CTX *ctx2;
|
@@ -585,7 +585,7 @@ ssl_renegotiation_cb(const SSL *ssl)
|
|
585
585
|
cb = rb_attr_get(sslctx_obj, id_i_renegotiation_cb);
|
586
586
|
if (NIL_P(cb)) return;
|
587
587
|
|
588
|
-
(
|
588
|
+
rb_funcallv(cb, id_call, 1, &ssl_obj);
|
589
589
|
}
|
590
590
|
|
591
591
|
#if !defined(OPENSSL_NO_NEXTPROTONEG) || \
|
@@ -635,7 +635,7 @@ npn_select_cb_common_i(VALUE tmp)
|
|
635
635
|
in += l;
|
636
636
|
}
|
637
637
|
|
638
|
-
selected =
|
638
|
+
selected = rb_funcallv(args->cb, id_call, 1, &protocols);
|
639
639
|
StringValue(selected);
|
640
640
|
len = RSTRING_LEN(selected);
|
641
641
|
if (len < 1 || len >= 256) {
|
@@ -1193,6 +1193,134 @@ ossl_sslctx_set_security_level(VALUE self, VALUE value)
|
|
1193
1193
|
return value;
|
1194
1194
|
}
|
1195
1195
|
|
1196
|
+
#ifdef SSL_MODE_SEND_FALLBACK_SCSV
|
1197
|
+
/*
|
1198
|
+
* call-seq:
|
1199
|
+
* ctx.enable_fallback_scsv() => nil
|
1200
|
+
*
|
1201
|
+
* Activate TLS_FALLBACK_SCSV for this context.
|
1202
|
+
* See RFC 7507.
|
1203
|
+
*/
|
1204
|
+
static VALUE
|
1205
|
+
ossl_sslctx_enable_fallback_scsv(VALUE self)
|
1206
|
+
{
|
1207
|
+
SSL_CTX *ctx;
|
1208
|
+
|
1209
|
+
GetSSLCTX(self, ctx);
|
1210
|
+
SSL_CTX_set_mode(ctx, SSL_MODE_SEND_FALLBACK_SCSV);
|
1211
|
+
|
1212
|
+
return Qnil;
|
1213
|
+
}
|
1214
|
+
#endif
|
1215
|
+
|
1216
|
+
/*
|
1217
|
+
* call-seq:
|
1218
|
+
* ctx.add_certificate(certiticate, pkey [, extra_certs]) -> self
|
1219
|
+
*
|
1220
|
+
* Adds a certificate to the context. _pkey_ must be a corresponding private
|
1221
|
+
* key with _certificate_.
|
1222
|
+
*
|
1223
|
+
* Multiple certificates with different public key type can be added by
|
1224
|
+
* repeated calls of this method, and OpenSSL will choose the most appropriate
|
1225
|
+
* certificate during the handshake.
|
1226
|
+
*
|
1227
|
+
* #cert=, #key=, and #extra_chain_cert= are old accessor methods for setting
|
1228
|
+
* certificate and internally call this method.
|
1229
|
+
*
|
1230
|
+
* === Parameters
|
1231
|
+
* _certificate_::
|
1232
|
+
* A certificate. An instance of OpenSSL::X509::Certificate.
|
1233
|
+
* _pkey_::
|
1234
|
+
* The private key for _certificate_. An instance of OpenSSL::PKey::PKey.
|
1235
|
+
* _extra_certs_::
|
1236
|
+
* Optional. An array of OpenSSL::X509::Certificate. When sending a
|
1237
|
+
* certificate chain, the certificates specified by this are sent following
|
1238
|
+
* _certificate_, in the order in the array.
|
1239
|
+
*
|
1240
|
+
* === Example
|
1241
|
+
* rsa_cert = OpenSSL::X509::Certificate.new(...)
|
1242
|
+
* rsa_pkey = OpenSSL::PKey.read(...)
|
1243
|
+
* ca_intermediate_cert = OpenSSL::X509::Certificate.new(...)
|
1244
|
+
* ctx.add_certificate(rsa_cert, rsa_pkey, [ca_intermediate_cert])
|
1245
|
+
*
|
1246
|
+
* ecdsa_cert = ...
|
1247
|
+
* ecdsa_pkey = ...
|
1248
|
+
* another_ca_cert = ...
|
1249
|
+
* ctx.add_certificate(ecdsa_cert, ecdsa_pkey, [another_ca_cert])
|
1250
|
+
*
|
1251
|
+
* === Note
|
1252
|
+
* OpenSSL before the version 1.0.2 could handle only one extra chain across
|
1253
|
+
* all key types. Calling this method discards the chain set previously.
|
1254
|
+
*/
|
1255
|
+
static VALUE
|
1256
|
+
ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
|
1257
|
+
{
|
1258
|
+
VALUE cert, key, extra_chain_ary;
|
1259
|
+
SSL_CTX *ctx;
|
1260
|
+
X509 *x509;
|
1261
|
+
STACK_OF(X509) *extra_chain = NULL;
|
1262
|
+
EVP_PKEY *pkey, *pub_pkey;
|
1263
|
+
|
1264
|
+
GetSSLCTX(self, ctx);
|
1265
|
+
rb_scan_args(argc, argv, "21", &cert, &key, &extra_chain_ary);
|
1266
|
+
rb_check_frozen(self);
|
1267
|
+
x509 = GetX509CertPtr(cert);
|
1268
|
+
pkey = GetPrivPKeyPtr(key);
|
1269
|
+
|
1270
|
+
/*
|
1271
|
+
* The reference counter is bumped, and decremented immediately.
|
1272
|
+
* X509_get0_pubkey() is only available in OpenSSL >= 1.1.0.
|
1273
|
+
*/
|
1274
|
+
pub_pkey = X509_get_pubkey(x509);
|
1275
|
+
EVP_PKEY_free(pub_pkey);
|
1276
|
+
if (!pub_pkey)
|
1277
|
+
rb_raise(rb_eArgError, "certificate does not contain public key");
|
1278
|
+
if (EVP_PKEY_cmp(pub_pkey, pkey) != 1)
|
1279
|
+
rb_raise(rb_eArgError, "public key mismatch");
|
1280
|
+
|
1281
|
+
if (argc >= 3)
|
1282
|
+
extra_chain = ossl_x509_ary2sk(extra_chain_ary);
|
1283
|
+
|
1284
|
+
if (!SSL_CTX_use_certificate(ctx, x509)) {
|
1285
|
+
sk_X509_pop_free(extra_chain, X509_free);
|
1286
|
+
ossl_raise(eSSLError, "SSL_CTX_use_certificate");
|
1287
|
+
}
|
1288
|
+
if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
|
1289
|
+
sk_X509_pop_free(extra_chain, X509_free);
|
1290
|
+
ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
|
1291
|
+
}
|
1292
|
+
|
1293
|
+
if (extra_chain) {
|
1294
|
+
#if OPENSSL_VERSION_NUMBER >= 0x10002000 && !defined(LIBRESSL_VERSION_NUMBER)
|
1295
|
+
if (!SSL_CTX_set0_chain(ctx, extra_chain)) {
|
1296
|
+
sk_X509_pop_free(extra_chain, X509_free);
|
1297
|
+
ossl_raise(eSSLError, "SSL_CTX_set0_chain");
|
1298
|
+
}
|
1299
|
+
#else
|
1300
|
+
STACK_OF(X509) *orig_extra_chain;
|
1301
|
+
X509 *x509_tmp;
|
1302
|
+
|
1303
|
+
/* First, clear the existing chain */
|
1304
|
+
SSL_CTX_get_extra_chain_certs(ctx, &orig_extra_chain);
|
1305
|
+
if (orig_extra_chain && sk_X509_num(orig_extra_chain)) {
|
1306
|
+
rb_warning("SSL_CTX_set0_chain() is not available; " \
|
1307
|
+
"clearing previously set certificate chain");
|
1308
|
+
SSL_CTX_clear_extra_chain_certs(ctx);
|
1309
|
+
}
|
1310
|
+
while ((x509_tmp = sk_X509_shift(extra_chain))) {
|
1311
|
+
/* Transfers ownership */
|
1312
|
+
if (!SSL_CTX_add_extra_chain_cert(ctx, x509_tmp)) {
|
1313
|
+
X509_free(x509_tmp);
|
1314
|
+
sk_X509_pop_free(extra_chain, X509_free);
|
1315
|
+
ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert");
|
1316
|
+
}
|
1317
|
+
}
|
1318
|
+
sk_X509_free(extra_chain);
|
1319
|
+
#endif
|
1320
|
+
}
|
1321
|
+
return self;
|
1322
|
+
}
|
1323
|
+
|
1196
1324
|
/*
|
1197
1325
|
* call-seq:
|
1198
1326
|
* ctx.session_add(session) -> true | false
|
@@ -1694,20 +1822,26 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
|
|
1694
1822
|
}
|
1695
1823
|
|
1696
1824
|
ilen = NUM2INT(len);
|
1697
|
-
if(NIL_P(str))
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1825
|
+
if (NIL_P(str))
|
1826
|
+
str = rb_str_new(0, ilen);
|
1827
|
+
else {
|
1828
|
+
StringValue(str);
|
1829
|
+
if (RSTRING_LEN(str) >= ilen)
|
1830
|
+
rb_str_modify(str);
|
1831
|
+
else
|
1832
|
+
rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
|
1702
1833
|
}
|
1703
|
-
|
1834
|
+
OBJ_TAINT(str);
|
1835
|
+
rb_str_set_len(str, 0);
|
1836
|
+
if (ilen == 0)
|
1837
|
+
return str;
|
1704
1838
|
|
1705
1839
|
GetSSL(self, ssl);
|
1706
1840
|
io = rb_attr_get(self, id_i_io);
|
1707
1841
|
GetOpenFile(io, fptr);
|
1708
1842
|
if (ssl_started(ssl)) {
|
1709
1843
|
for (;;){
|
1710
|
-
nread = SSL_read(ssl, RSTRING_PTR(str),
|
1844
|
+
nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
|
1711
1845
|
switch(ssl_get_error(ssl, nread)){
|
1712
1846
|
case SSL_ERROR_NONE:
|
1713
1847
|
goto end;
|
@@ -1757,8 +1891,6 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
|
|
1757
1891
|
|
1758
1892
|
end:
|
1759
1893
|
rb_str_set_len(str, nread);
|
1760
|
-
OBJ_TAINT(str);
|
1761
|
-
|
1762
1894
|
return str;
|
1763
1895
|
}
|
1764
1896
|
|
@@ -2257,6 +2389,7 @@ Init_ossl_ssl(void)
|
|
2257
2389
|
rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
|
2258
2390
|
#endif
|
2259
2391
|
|
2392
|
+
id_call = rb_intern("call");
|
2260
2393
|
ID_callback_state = rb_intern("callback_state");
|
2261
2394
|
|
2262
2395
|
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_vcb_idx", 0, 0, 0);
|
@@ -2320,11 +2453,17 @@ Init_ossl_ssl(void)
|
|
2320
2453
|
|
2321
2454
|
/*
|
2322
2455
|
* Context certificate
|
2456
|
+
*
|
2457
|
+
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
|
2458
|
+
* It is recommended to use #add_certificate instead.
|
2323
2459
|
*/
|
2324
2460
|
rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
|
2325
2461
|
|
2326
2462
|
/*
|
2327
2463
|
* Context private key
|
2464
|
+
*
|
2465
|
+
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
|
2466
|
+
* It is recommended to use #add_certificate instead.
|
2328
2467
|
*/
|
2329
2468
|
rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
|
2330
2469
|
|
@@ -2398,6 +2537,9 @@ Init_ossl_ssl(void)
|
|
2398
2537
|
/*
|
2399
2538
|
* An Array of extra X509 certificates to be added to the certificate
|
2400
2539
|
* chain.
|
2540
|
+
*
|
2541
|
+
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
|
2542
|
+
* It is recommended to use #add_certificate instead.
|
2401
2543
|
*/
|
2402
2544
|
rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse);
|
2403
2545
|
|
@@ -2453,6 +2595,10 @@ Init_ossl_ssl(void)
|
|
2453
2595
|
* A callback invoked when a session is removed from the internal cache.
|
2454
2596
|
*
|
2455
2597
|
* The callback is invoked with an SSLContext and a Session.
|
2598
|
+
*
|
2599
|
+
* IMPORTANT NOTE: It is currently not possible to use this safely in a
|
2600
|
+
* multi-threaded application. The callback is called inside a global lock
|
2601
|
+
* and it can randomly cause deadlock on Ruby thread switching.
|
2456
2602
|
*/
|
2457
2603
|
rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
|
2458
2604
|
|
@@ -2553,6 +2699,10 @@ Init_ossl_ssl(void)
|
|
2553
2699
|
rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
|
2554
2700
|
rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
|
2555
2701
|
rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
|
2702
|
+
#ifdef SSL_MODE_SEND_FALLBACK_SCSV
|
2703
|
+
rb_define_method(cSSLContext, "enable_fallback_scsv", ossl_sslctx_enable_fallback_scsv, 0);
|
2704
|
+
#endif
|
2705
|
+
rb_define_method(cSSLContext, "add_certificate", ossl_sslctx_add_certificate, -1);
|
2556
2706
|
|
2557
2707
|
rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
|
2558
2708
|
rb_define_alias(cSSLContext, "freeze", "setup");
|