openssl 2.2.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +33 -45
  3. data/History.md +300 -0
  4. data/README.md +36 -19
  5. data/ext/openssl/extconf.rb +119 -79
  6. data/ext/openssl/openssl_missing.c +0 -66
  7. data/ext/openssl/openssl_missing.h +26 -45
  8. data/ext/openssl/ossl.c +131 -233
  9. data/ext/openssl/ossl.h +31 -12
  10. data/ext/openssl/ossl_asn1.c +26 -13
  11. data/ext/openssl/ossl_bn.c +279 -143
  12. data/ext/openssl/ossl_bn.h +2 -1
  13. data/ext/openssl/ossl_cipher.c +13 -14
  14. data/ext/openssl/ossl_config.c +412 -41
  15. data/ext/openssl/ossl_config.h +4 -7
  16. data/ext/openssl/ossl_digest.c +16 -12
  17. data/ext/openssl/ossl_engine.c +17 -16
  18. data/ext/openssl/ossl_hmac.c +57 -136
  19. data/ext/openssl/ossl_kdf.c +12 -4
  20. data/ext/openssl/ossl_ns_spki.c +1 -1
  21. data/ext/openssl/ossl_ocsp.c +11 -59
  22. data/ext/openssl/ossl_pkcs12.c +22 -4
  23. data/ext/openssl/ossl_pkcs7.c +45 -62
  24. data/ext/openssl/ossl_pkey.c +1320 -196
  25. data/ext/openssl/ossl_pkey.h +36 -73
  26. data/ext/openssl/ossl_pkey_dh.c +152 -347
  27. data/ext/openssl/ossl_pkey_dsa.c +157 -413
  28. data/ext/openssl/ossl_pkey_ec.c +227 -343
  29. data/ext/openssl/ossl_pkey_rsa.c +159 -491
  30. data/ext/openssl/ossl_provider.c +211 -0
  31. data/ext/openssl/ossl_provider.h +5 -0
  32. data/ext/openssl/ossl_ssl.c +593 -467
  33. data/ext/openssl/ossl_ssl_session.c +29 -30
  34. data/ext/openssl/ossl_ts.c +67 -42
  35. data/ext/openssl/ossl_x509.c +0 -6
  36. data/ext/openssl/ossl_x509attr.c +1 -1
  37. data/ext/openssl/ossl_x509cert.c +168 -12
  38. data/ext/openssl/ossl_x509crl.c +14 -11
  39. data/ext/openssl/ossl_x509ext.c +14 -9
  40. data/ext/openssl/ossl_x509name.c +10 -3
  41. data/ext/openssl/ossl_x509req.c +14 -11
  42. data/ext/openssl/ossl_x509revoked.c +4 -4
  43. data/ext/openssl/ossl_x509store.c +204 -94
  44. data/lib/openssl/buffering.rb +10 -4
  45. data/lib/openssl/digest.rb +1 -5
  46. data/lib/openssl/hmac.rb +65 -0
  47. data/lib/openssl/pkey.rb +429 -0
  48. data/lib/openssl/ssl.rb +23 -18
  49. data/lib/openssl/version.rb +1 -1
  50. data/lib/openssl/x509.rb +22 -0
  51. data/lib/openssl.rb +0 -1
  52. metadata +13 -68
  53. data/ext/openssl/ruby_missing.h +0 -24
  54. data/lib/openssl/config.rb +0 -501
@@ -4,6 +4,7 @@
4
4
 
5
5
  #include "ossl.h"
6
6
 
7
+ #ifndef OPENSSL_NO_SOCK
7
8
  VALUE cSSLSession;
8
9
  static VALUE eSSLSession;
9
10
 
@@ -18,7 +19,7 @@ const rb_data_type_t ossl_ssl_session_type = {
18
19
  {
19
20
  0, ossl_ssl_session_free,
20
21
  },
21
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
22
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
22
23
  };
23
24
 
24
25
  static VALUE ossl_ssl_session_alloc(VALUE klass)
@@ -34,43 +35,38 @@ static VALUE ossl_ssl_session_alloc(VALUE klass)
34
35
  * Creates a new Session object from an instance of SSLSocket or DER/PEM encoded
35
36
  * String.
36
37
  */
37
- static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
38
+ static VALUE
39
+ ossl_ssl_session_initialize(VALUE self, VALUE arg1)
38
40
  {
39
- SSL_SESSION *ctx = NULL;
40
-
41
- if (RDATA(self)->data)
42
- ossl_raise(eSSLSession, "SSL Session already initialized");
43
-
44
- if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
45
- SSL *ssl;
46
-
47
- GetSSL(arg1, ssl);
48
-
49
- if ((ctx = SSL_get1_session(ssl)) == NULL)
50
- ossl_raise(eSSLSession, "no session available");
51
- } else {
52
- BIO *in = ossl_obj2bio(&arg1);
41
+ SSL_SESSION *ctx;
53
42
 
54
- ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
43
+ if (RTYPEDDATA_DATA(self))
44
+ ossl_raise(eSSLSession, "SSL Session already initialized");
55
45
 
56
- if (!ctx) {
57
- OSSL_BIO_reset(in);
58
- ctx = d2i_SSL_SESSION_bio(in, NULL);
59
- }
46
+ if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
47
+ SSL *ssl;
60
48
 
61
- BIO_free(in);
49
+ GetSSL(arg1, ssl);
62
50
 
63
- if (!ctx)
64
- ossl_raise(rb_eArgError, "unknown type");
65
- }
51
+ if ((ctx = SSL_get1_session(ssl)) == NULL)
52
+ ossl_raise(eSSLSession, "no session available");
53
+ }
54
+ else {
55
+ BIO *in = ossl_obj2bio(&arg1);
66
56
 
67
- /* should not happen */
68
- if (ctx == NULL)
69
- ossl_raise(eSSLSession, "ctx not set - internal error");
57
+ ctx = d2i_SSL_SESSION_bio(in, NULL);
58
+ if (!ctx) {
59
+ OSSL_BIO_reset(in);
60
+ ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
61
+ }
62
+ BIO_free(in);
63
+ if (!ctx)
64
+ ossl_raise(rb_eArgError, "unknown type");
65
+ }
70
66
 
71
- RDATA(self)->data = ctx;
67
+ RTYPEDDATA_DATA(self) = ctx;
72
68
 
73
- return self;
69
+ return self;
74
70
  }
75
71
 
76
72
  static VALUE
@@ -304,6 +300,7 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
304
300
  return ossl_membio2str(out);
305
301
  }
306
302
 
303
+ #endif /* !defined(OPENSSL_NO_SOCK) */
307
304
 
308
305
  void Init_ossl_ssl_session(void)
309
306
  {
@@ -312,6 +309,7 @@ void Init_ossl_ssl_session(void)
312
309
  mSSL = rb_define_module_under(mOSSL, "SSL");
313
310
  eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
314
311
  #endif
312
+ #ifndef OPENSSL_NO_SOCK
315
313
  cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
316
314
  eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
317
315
 
@@ -329,4 +327,5 @@ void Init_ossl_ssl_session(void)
329
327
  rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
330
328
  rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
331
329
  rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
330
+ #endif /* !defined(OPENSSL_NO_SOCK) */
332
331
  }
@@ -68,9 +68,9 @@ static VALUE cTimestampRequest;
68
68
  static VALUE cTimestampResponse;
69
69
  static VALUE cTimestampTokenInfo;
70
70
  static VALUE cTimestampFactory;
71
- static ID sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE;
72
- static ID sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE;
73
- static ID sSYSTEM_FAILURE;
71
+ static VALUE sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE;
72
+ static VALUE sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE;
73
+ static VALUE sSYSTEM_FAILURE;
74
74
 
75
75
  static void
76
76
  ossl_ts_req_free(void *ptr)
@@ -83,7 +83,7 @@ static const rb_data_type_t ossl_ts_req_type = {
83
83
  {
84
84
  0, ossl_ts_req_free,
85
85
  },
86
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
86
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
87
87
  };
88
88
 
89
89
  static void
@@ -97,7 +97,7 @@ static const rb_data_type_t ossl_ts_resp_type = {
97
97
  {
98
98
  0, ossl_ts_resp_free,
99
99
  },
100
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
100
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
101
101
  };
102
102
 
103
103
  static void
@@ -111,7 +111,7 @@ static const rb_data_type_t ossl_ts_token_info_type = {
111
111
  {
112
112
  0, ossl_ts_token_info_free,
113
113
  },
114
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
114
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
115
115
  };
116
116
 
117
117
  static VALUE
@@ -145,6 +145,12 @@ obj_to_asn1obj(VALUE obj)
145
145
  return a1obj;
146
146
  }
147
147
 
148
+ static VALUE
149
+ obj_to_asn1obj_i(VALUE obj)
150
+ {
151
+ return (VALUE)obj_to_asn1obj(obj);
152
+ }
153
+
148
154
  static VALUE
149
155
  get_asn1obj(ASN1_OBJECT *obj)
150
156
  {
@@ -205,8 +211,10 @@ ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
205
211
  in = ossl_obj2bio(&arg);
206
212
  ts_req = d2i_TS_REQ_bio(in, &ts_req);
207
213
  BIO_free(in);
208
- if (!ts_req)
214
+ if (!ts_req) {
215
+ DATA_PTR(self) = NULL;
209
216
  ossl_raise(eTimestampError, "Error when decoding the timestamp request");
217
+ }
210
218
  DATA_PTR(self) = ts_req;
211
219
 
212
220
  return self;
@@ -529,8 +537,10 @@ ossl_ts_resp_initialize(VALUE self, VALUE der)
529
537
  in = ossl_obj2bio(&der);
530
538
  ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
531
539
  BIO_free(in);
532
- if (!ts_resp)
540
+ if (!ts_resp) {
541
+ DATA_PTR(self) = NULL;
533
542
  ossl_raise(eTimestampError, "Error when decoding the timestamp response");
543
+ }
534
544
  DATA_PTR(self) = ts_resp;
535
545
 
536
546
  return self;
@@ -816,17 +826,14 @@ ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
816
826
  X509_up_ref(cert);
817
827
  }
818
828
 
819
- TS_VERIFY_CTS_set_certs(ctx, x509inter);
829
+ TS_VERIFY_CTX_set_certs(ctx, x509inter);
820
830
  TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
821
831
  TS_VERIFY_CTX_set_store(ctx, x509st);
822
832
 
823
833
  ok = TS_RESP_verify_response(ctx, resp);
824
-
825
- /* WORKAROUND:
826
- * X509_STORE can count references, but X509_STORE_free() doesn't check
827
- * this. To prevent our X509_STORE from being freed with our
828
- * TS_VERIFY_CTX we set the store to NULL first.
829
- * Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2)
834
+ /*
835
+ * TS_VERIFY_CTX_set_store() call above does not increment the reference
836
+ * counter, so it must be unset before TS_VERIFY_CTX_free() is called.
830
837
  */
831
838
  TS_VERIFY_CTX_set_store(ctx, NULL);
832
839
  TS_VERIFY_CTX_free(ctx);
@@ -871,8 +878,10 @@ ossl_ts_token_info_initialize(VALUE self, VALUE der)
871
878
  in = ossl_obj2bio(&der);
872
879
  info = d2i_TS_TST_INFO_bio(in, &info);
873
880
  BIO_free(in);
874
- if (!info)
881
+ if (!info) {
882
+ DATA_PTR(self) = NULL;
875
883
  ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
884
+ }
876
885
  DATA_PTR(self) = info;
877
886
 
878
887
  return self;
@@ -1074,13 +1083,29 @@ ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
1074
1083
  }
1075
1084
 
1076
1085
  static int
1086
+ #if !defined(LIBRESSL_VERSION_NUMBER)
1077
1087
  ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
1088
+ #else
1089
+ ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
1090
+ #endif
1078
1091
  {
1079
1092
  *sec = *((long *)data);
1080
1093
  *usec = 0;
1081
1094
  return 1;
1082
1095
  }
1083
1096
 
1097
+ static VALUE
1098
+ ossl_evp_get_digestbyname_i(VALUE arg)
1099
+ {
1100
+ return (VALUE)ossl_evp_get_digestbyname(arg);
1101
+ }
1102
+
1103
+ static VALUE
1104
+ ossl_obj2bio_i(VALUE arg)
1105
+ {
1106
+ return (VALUE)ossl_obj2bio((VALUE *)arg);
1107
+ }
1108
+
1084
1109
  /*
1085
1110
  * Creates a Response with the help of an OpenSSL::PKey, an
1086
1111
  * OpenSSL::X509::Certificate and a Request.
@@ -1149,7 +1174,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
1149
1174
  goto end;
1150
1175
  }
1151
1176
  if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
1152
- def_policy_id_obj = (ASN1_OBJECT*)rb_protect((VALUE (*)(VALUE))obj_to_asn1obj, (VALUE)def_policy_id, &status);
1177
+ def_policy_id_obj = (ASN1_OBJECT*)rb_protect(obj_to_asn1obj_i, (VALUE)def_policy_id, &status);
1153
1178
  if (status)
1154
1179
  goto end;
1155
1180
  }
@@ -1191,7 +1216,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
1191
1216
 
1192
1217
  for (i = 0; i < RARRAY_LEN(allowed_digests); i++) {
1193
1218
  rbmd = rb_ary_entry(allowed_digests, i);
1194
- md = (const EVP_MD *)rb_protect((VALUE (*)(VALUE))ossl_evp_get_digestbyname, rbmd, &status);
1219
+ md = (const EVP_MD *)rb_protect(ossl_evp_get_digestbyname_i, rbmd, &status);
1195
1220
  if (status)
1196
1221
  goto end;
1197
1222
  TS_RESP_CTX_add_md(ctx, md);
@@ -1202,7 +1227,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
1202
1227
  if (status)
1203
1228
  goto end;
1204
1229
 
1205
- req_bio = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, (VALUE)&str, &status);
1230
+ req_bio = (BIO*)rb_protect(ossl_obj2bio_i, (VALUE)&str, &status);
1206
1231
  if (status)
1207
1232
  goto end;
1208
1233
 
@@ -1226,7 +1251,7 @@ end:
1226
1251
  ASN1_OBJECT_free(def_policy_id_obj);
1227
1252
  TS_RESP_CTX_free(ctx);
1228
1253
  if (err_msg)
1229
- ossl_raise(eTimestampError, err_msg);
1254
+ rb_exc_raise(ossl_make_error(eTimestampError, rb_str_new_cstr(err_msg)));
1230
1255
  if (status)
1231
1256
  rb_jump_tag(status);
1232
1257
  return ret;
@@ -1247,24 +1272,24 @@ Init_ossl_ts(void)
1247
1272
  * timestamp server rejects the message imprint algorithm used in the
1248
1273
  * +Request+
1249
1274
  */
1250
- sBAD_ALG = rb_intern("BAD_ALG");
1275
+ sBAD_ALG = ID2SYM(rb_intern_const("BAD_ALG"));
1251
1276
 
1252
1277
  /*
1253
1278
  * Possible return value for +Response#failure_info+. Indicates that the
1254
1279
  * timestamp server was not able to process the +Request+ properly.
1255
1280
  */
1256
- sBAD_REQUEST = rb_intern("BAD_REQUEST");
1281
+ sBAD_REQUEST = ID2SYM(rb_intern_const("BAD_REQUEST"));
1257
1282
  /*
1258
1283
  * Possible return value for +Response#failure_info+. Indicates that the
1259
1284
  * timestamp server was not able to parse certain data in the +Request+.
1260
1285
  */
1261
- sBAD_DATA_FORMAT = rb_intern("BAD_DATA_FORMAT");
1286
+ sBAD_DATA_FORMAT = ID2SYM(rb_intern_const("BAD_DATA_FORMAT"));
1262
1287
 
1263
- sTIME_NOT_AVAILABLE = rb_intern("TIME_NOT_AVAILABLE");
1264
- sUNACCEPTED_POLICY = rb_intern("UNACCEPTED_POLICY");
1265
- sUNACCEPTED_EXTENSION = rb_intern("UNACCEPTED_EXTENSION");
1266
- sADD_INFO_NOT_AVAILABLE = rb_intern("ADD_INFO_NOT_AVAILABLE");
1267
- sSYSTEM_FAILURE = rb_intern("SYSTEM_FAILURE");
1288
+ sTIME_NOT_AVAILABLE = ID2SYM(rb_intern_const("TIME_NOT_AVAILABLE"));
1289
+ sUNACCEPTED_POLICY = ID2SYM(rb_intern_const("UNACCEPTED_POLICY"));
1290
+ sUNACCEPTED_EXTENSION = ID2SYM(rb_intern_const("UNACCEPTED_EXTENSION"));
1291
+ sADD_INFO_NOT_AVAILABLE = ID2SYM(rb_intern_const("ADD_INFO_NOT_AVAILABLE"));
1292
+ sSYSTEM_FAILURE = ID2SYM(rb_intern_const("SYSTEM_FAILURE"));
1268
1293
 
1269
1294
  /* Document-class: OpenSSL::Timestamp
1270
1295
  * Provides classes and methods to request, create and validate
@@ -1280,7 +1305,7 @@ Init_ossl_ts(void)
1280
1305
  * ===Create a Response:
1281
1306
  * #Assumes ts.p12 is a PKCS#12-compatible file with a private key
1282
1307
  * #and a certificate that has an extended key usage of 'timeStamping'
1283
- * p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
1308
+ * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd')
1284
1309
  * md = OpenSSL::Digest.new('SHA1')
1285
1310
  * hash = md.digest(data) #some binary data to be timestamped
1286
1311
  * req = OpenSSL::Timestamp::Request.new
@@ -1295,16 +1320,16 @@ Init_ossl_ts(void)
1295
1320
  *
1296
1321
  * ===Verify a timestamp response:
1297
1322
  * #Assume we have a timestamp token in a file called ts.der
1298
- * ts = OpenSSL::Timestamp::Response.new(File.open('ts.der', 'rb')
1323
+ * ts = OpenSSL::Timestamp::Response.new(File.binread('ts.der'))
1299
1324
  * #Assume we have the Request for this token in a file called req.der
1300
- * req = OpenSSL::Timestamp::Request.new(File.open('req.der', 'rb')
1325
+ * req = OpenSSL::Timestamp::Request.new(File.binread('req.der'))
1301
1326
  * # Assume the associated root CA certificate is contained in a
1302
1327
  * # DER-encoded file named root.cer
1303
- * root = OpenSSL::X509::Certificate.new(File.open('root.cer', 'rb')
1328
+ * root = OpenSSL::X509::Certificate.new(File.binread('root.cer'))
1304
1329
  * # get the necessary intermediate certificates, available in
1305
1330
  * # DER-encoded form in inter1.cer and inter2.cer
1306
- * inter1 = OpenSSL::X509::Certificate.new(File.open('inter1.cer', 'rb')
1307
- * inter2 = OpenSSL::X509::Certificate.new(File.open('inter2.cer', 'rb')
1331
+ * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer'))
1332
+ * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer'))
1308
1333
  * ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails
1309
1334
  *
1310
1335
  */
@@ -1437,9 +1462,9 @@ Init_ossl_ts(void)
1437
1462
  * timestamping certificate.
1438
1463
  *
1439
1464
  * req = OpenSSL::Timestamp::Request.new(raw_bytes)
1440
- * p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
1441
- * inter1 = OpenSSL::X509::Certificate.new(File.open('inter1.cer', 'rb')
1442
- * inter2 = OpenSSL::X509::Certificate.new(File.open('inter2.cer', 'rb')
1465
+ * p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd')
1466
+ * inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer'))
1467
+ * inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer'))
1443
1468
  * fac = OpenSSL::Timestamp::Factory.new
1444
1469
  * fac.gen_time = Time.now
1445
1470
  * fac.serial_number = 1
@@ -1503,11 +1528,11 @@ Init_ossl_ts(void)
1503
1528
  *
1504
1529
  */
1505
1530
  cTimestampFactory = rb_define_class_under(mTimestamp, "Factory", rb_cObject);
1506
- rb_attr(cTimestampFactory, rb_intern("allowed_digests"), 1, 1, 0);
1507
- rb_attr(cTimestampFactory, rb_intern("default_policy_id"), 1, 1, 0);
1508
- rb_attr(cTimestampFactory, rb_intern("serial_number"), 1, 1, 0);
1509
- rb_attr(cTimestampFactory, rb_intern("gen_time"), 1, 1, 0);
1510
- rb_attr(cTimestampFactory, rb_intern("additional_certs"), 1, 1, 0);
1531
+ rb_attr(cTimestampFactory, rb_intern_const("allowed_digests"), 1, 1, 0);
1532
+ rb_attr(cTimestampFactory, rb_intern_const("default_policy_id"), 1, 1, 0);
1533
+ rb_attr(cTimestampFactory, rb_intern_const("serial_number"), 1, 1, 0);
1534
+ rb_attr(cTimestampFactory, rb_intern_const("gen_time"), 1, 1, 0);
1535
+ rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0);
1511
1536
  rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3);
1512
1537
  }
1513
1538
 
@@ -115,11 +115,9 @@ Init_ossl_x509(void)
115
115
  DefX509Const(V_ERR_SUITE_B_LOS_NOT_ALLOWED);
116
116
  DefX509Const(V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256);
117
117
  #endif
118
- #if defined(X509_V_ERR_HOSTNAME_MISMATCH)
119
118
  DefX509Const(V_ERR_HOSTNAME_MISMATCH);
120
119
  DefX509Const(V_ERR_EMAIL_MISMATCH);
121
120
  DefX509Const(V_ERR_IP_ADDRESS_MISMATCH);
122
- #endif
123
121
  #if defined(X509_V_ERR_DANE_NO_MATCH)
124
122
  DefX509Const(V_ERR_DANE_NO_MATCH);
125
123
  #endif
@@ -187,12 +185,10 @@ Init_ossl_x509(void)
187
185
  /* Set by Store#flags= and StoreContext#flags=. Enables checking of the
188
186
  * signature of the root self-signed CA. */
189
187
  DefX509Const(V_FLAG_CHECK_SS_SIGNATURE);
190
- #if defined(X509_V_FLAG_TRUSTED_FIRST)
191
188
  /* Set by Store#flags= and StoreContext#flags=. When constructing a
192
189
  * certificate chain, search the Store first for the issuer certificate.
193
190
  * Enabled by default in OpenSSL >= 1.1.0. */
194
191
  DefX509Const(V_FLAG_TRUSTED_FIRST);
195
- #endif
196
192
  #if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY)
197
193
  /* Set by Store#flags= and StoreContext#flags=.
198
194
  * Enables Suite B 128 bit only mode. */
@@ -208,11 +204,9 @@ Init_ossl_x509(void)
208
204
  * Enables Suite B 128 bit mode allowing 192 bit algorithms. */
209
205
  DefX509Const(V_FLAG_SUITEB_128_LOS);
210
206
  #endif
211
- #if defined(X509_V_FLAG_PARTIAL_CHAIN)
212
207
  /* Set by Store#flags= and StoreContext#flags=.
213
208
  * Allows partial chains if at least one certificate is in trusted store. */
214
209
  DefX509Const(V_FLAG_PARTIAL_CHAIN);
215
- #endif
216
210
  #if defined(X509_V_FLAG_NO_ALT_CHAINS)
217
211
  /* Set by Store#flags= and StoreContext#flags=. Suppresses searching for
218
212
  * a alternative chain. No effect in OpenSSL >= 1.1.0. */
@@ -41,7 +41,7 @@ static const rb_data_type_t ossl_x509attr_type = {
41
41
  {
42
42
  0, ossl_x509attr_free,
43
43
  },
44
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
44
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
45
45
  };
46
46
 
47
47
  /*
@@ -41,7 +41,7 @@ static const rb_data_type_t ossl_x509_type = {
41
41
  {
42
42
  0, ossl_x509_free,
43
43
  },
44
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
44
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
45
45
  };
46
46
 
47
47
  /*
@@ -115,24 +115,27 @@ static VALUE
115
115
  ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
116
116
  {
117
117
  BIO *in;
118
- X509 *x509, *x = DATA_PTR(self);
118
+ X509 *x509, *x509_orig = RTYPEDDATA_DATA(self);
119
119
  VALUE arg;
120
120
 
121
+ rb_check_frozen(self);
121
122
  if (rb_scan_args(argc, argv, "01", &arg) == 0) {
122
123
  /* create just empty X509Cert */
123
124
  return self;
124
125
  }
125
126
  arg = ossl_to_der_if_possible(arg);
126
127
  in = ossl_obj2bio(&arg);
127
- x509 = PEM_read_bio_X509(in, &x, NULL, NULL);
128
- DATA_PTR(self) = x;
128
+ x509 = d2i_X509_bio(in, NULL);
129
129
  if (!x509) {
130
- OSSL_BIO_reset(in);
131
- x509 = d2i_X509_bio(in, &x);
132
- DATA_PTR(self) = x;
130
+ OSSL_BIO_reset(in);
131
+ x509 = PEM_read_bio_X509(in, NULL, NULL, NULL);
133
132
  }
134
133
  BIO_free(in);
135
- if (!x509) ossl_raise(eX509CertError, NULL);
134
+ if (!x509)
135
+ ossl_raise(eX509CertError, "PEM_read_bio_X509");
136
+
137
+ RTYPEDDATA_DATA(self) = x509;
138
+ X509_free(x509_orig);
136
139
 
137
140
  return self;
138
141
  }
@@ -639,12 +642,12 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
639
642
  OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
640
643
  }
641
644
  GetX509(self, x509);
642
- while ((ext = X509_delete_ext(x509, 0)))
643
- X509_EXTENSION_free(ext);
645
+ for (i = X509_get_ext_count(x509); i > 0; i--)
646
+ X509_EXTENSION_free(X509_delete_ext(x509, 0));
644
647
  for (i=0; i<RARRAY_LEN(ary); i++) {
645
648
  ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
646
649
  if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
647
- ossl_raise(eX509CertError, NULL);
650
+ ossl_raise(eX509CertError, "X509_add_ext");
648
651
  }
649
652
  }
650
653
 
@@ -704,6 +707,157 @@ ossl_x509_eq(VALUE self, VALUE other)
704
707
  return !X509_cmp(a, b) ? Qtrue : Qfalse;
705
708
  }
706
709
 
710
+ struct load_chained_certificates_arguments {
711
+ VALUE certificates;
712
+ X509 *certificate;
713
+ };
714
+
715
+ static VALUE
716
+ load_chained_certificates_append_push(VALUE _arguments) {
717
+ struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments;
718
+
719
+ if (arguments->certificates == Qnil) {
720
+ arguments->certificates = rb_ary_new();
721
+ }
722
+
723
+ rb_ary_push(arguments->certificates, ossl_x509_new(arguments->certificate));
724
+
725
+ return Qnil;
726
+ }
727
+
728
+ static VALUE
729
+ load_chained_certificate_append_ensure(VALUE _arguments) {
730
+ struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments;
731
+
732
+ X509_free(arguments->certificate);
733
+
734
+ return Qnil;
735
+ }
736
+
737
+ inline static VALUE
738
+ load_chained_certificates_append(VALUE certificates, X509 *certificate) {
739
+ struct load_chained_certificates_arguments arguments;
740
+ arguments.certificates = certificates;
741
+ arguments.certificate = certificate;
742
+
743
+ rb_ensure(load_chained_certificates_append_push, (VALUE)&arguments, load_chained_certificate_append_ensure, (VALUE)&arguments);
744
+
745
+ return arguments.certificates;
746
+ }
747
+
748
+ static VALUE
749
+ load_chained_certificates_PEM(BIO *in) {
750
+ VALUE certificates = Qnil;
751
+ X509 *certificate = PEM_read_bio_X509(in, NULL, NULL, NULL);
752
+
753
+ /* If we cannot read even one certificate: */
754
+ if (certificate == NULL) {
755
+ /* If we cannot read one certificate because we could not read the PEM encoding: */
756
+ if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
757
+ ossl_clear_error();
758
+ }
759
+
760
+ if (ERR_peek_last_error())
761
+ ossl_raise(eX509CertError, NULL);
762
+ else
763
+ return Qnil;
764
+ }
765
+
766
+ certificates = load_chained_certificates_append(Qnil, certificate);
767
+
768
+ while ((certificate = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
769
+ load_chained_certificates_append(certificates, certificate);
770
+ }
771
+
772
+ /* We tried to read one more certificate but could not read start line: */
773
+ if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
774
+ /* This is not an error, it means we are finished: */
775
+ ossl_clear_error();
776
+
777
+ return certificates;
778
+ }
779
+
780
+ /* Alternatively, if we reached the end of the file and there was no error: */
781
+ if (BIO_eof(in) && !ERR_peek_last_error()) {
782
+ return certificates;
783
+ } else {
784
+ /* Otherwise, we tried to read a certificate but failed somewhere: */
785
+ ossl_raise(eX509CertError, NULL);
786
+ }
787
+ }
788
+
789
+ static VALUE
790
+ load_chained_certificates_DER(BIO *in) {
791
+ X509 *certificate = d2i_X509_bio(in, NULL);
792
+
793
+ /* If we cannot read one certificate: */
794
+ if (certificate == NULL) {
795
+ /* Ignore error. We could not load. */
796
+ ossl_clear_error();
797
+
798
+ return Qnil;
799
+ }
800
+
801
+ return load_chained_certificates_append(Qnil, certificate);
802
+ }
803
+
804
+ static VALUE
805
+ load_chained_certificates(VALUE _io) {
806
+ BIO *in = (BIO*)_io;
807
+ VALUE certificates = Qnil;
808
+
809
+ /*
810
+ DER is a binary format and it may contain octets within it that look like
811
+ PEM encoded certificates. So we need to check DER first.
812
+ */
813
+ certificates = load_chained_certificates_DER(in);
814
+
815
+ if (certificates != Qnil)
816
+ return certificates;
817
+
818
+ OSSL_BIO_reset(in);
819
+
820
+ certificates = load_chained_certificates_PEM(in);
821
+
822
+ if (certificates != Qnil)
823
+ return certificates;
824
+
825
+ /* Otherwise we couldn't read the output correctly so fail: */
826
+ ossl_raise(eX509CertError, "Could not detect format of certificate data!");
827
+ }
828
+
829
+ static VALUE
830
+ load_chained_certificates_ensure(VALUE _io) {
831
+ BIO *in = (BIO*)_io;
832
+
833
+ BIO_free(in);
834
+
835
+ return Qnil;
836
+ }
837
+
838
+ /*
839
+ * call-seq:
840
+ * OpenSSL::X509::Certificate.load(string) -> [certs...]
841
+ * OpenSSL::X509::Certificate.load(file) -> [certs...]
842
+ *
843
+ * Read the chained certificates from the given input. Supports both PEM
844
+ * and DER encoded certificates.
845
+ *
846
+ * PEM is a text format and supports more than one certificate.
847
+ *
848
+ * DER is a binary format and only supports one certificate.
849
+ *
850
+ * If the file is empty, or contains only unrelated data, an
851
+ * +OpenSSL::X509::CertificateError+ exception will be raised.
852
+ */
853
+ static VALUE
854
+ ossl_x509_load(VALUE klass, VALUE buffer)
855
+ {
856
+ BIO *in = ossl_obj2bio(&buffer);
857
+
858
+ return rb_ensure(load_chained_certificates, (VALUE)in, load_chained_certificates_ensure, (VALUE)in);
859
+ }
860
+
707
861
  /*
708
862
  * INIT
709
863
  */
@@ -730,7 +884,7 @@ Init_ossl_x509cert(void)
730
884
  * Certificate is capable of handling DER-encoded certificates and
731
885
  * certificates encoded in OpenSSL's PEM format.
732
886
  *
733
- * raw = File.read "cert.cer" # DER- or PEM-encoded
887
+ * raw = File.binread "cert.cer" # DER- or PEM-encoded
734
888
  * certificate = OpenSSL::X509::Certificate.new raw
735
889
  *
736
890
  * === Saving a certificate to a file
@@ -812,6 +966,8 @@ Init_ossl_x509cert(void)
812
966
  */
813
967
  cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
814
968
 
969
+ rb_define_singleton_method(cX509Cert, "load", ossl_x509_load, 1);
970
+
815
971
  rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
816
972
  rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
817
973
  rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1);