openssl 2.1.2 → 2.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +9 -7
  3. data/History.md +77 -0
  4. data/README.md +2 -2
  5. data/ext/openssl/extconf.rb +24 -14
  6. data/ext/openssl/openssl_missing.h +37 -2
  7. data/ext/openssl/ossl.c +51 -25
  8. data/ext/openssl/ossl.h +8 -5
  9. data/ext/openssl/ossl_asn1.c +26 -1
  10. data/ext/openssl/ossl_bn.c +9 -3
  11. data/ext/openssl/ossl_cipher.c +33 -24
  12. data/ext/openssl/ossl_digest.c +16 -51
  13. data/ext/openssl/ossl_engine.c +2 -12
  14. data/ext/openssl/ossl_hmac.c +5 -11
  15. data/ext/openssl/ossl_kdf.c +3 -19
  16. data/ext/openssl/ossl_ns_spki.c +1 -1
  17. data/ext/openssl/ossl_ocsp.c +6 -11
  18. data/ext/openssl/ossl_ocsp.h +3 -3
  19. data/ext/openssl/ossl_pkcs7.c +3 -19
  20. data/ext/openssl/ossl_pkcs7.h +16 -0
  21. data/ext/openssl/ossl_pkey.c +180 -14
  22. data/ext/openssl/ossl_pkey.h +5 -5
  23. data/ext/openssl/ossl_pkey_dh.c +1 -1
  24. data/ext/openssl/ossl_pkey_dsa.c +2 -2
  25. data/ext/openssl/ossl_pkey_ec.c +29 -0
  26. data/ext/openssl/ossl_pkey_rsa.c +17 -9
  27. data/ext/openssl/ossl_rand.c +2 -40
  28. data/ext/openssl/ossl_ssl.c +109 -25
  29. data/ext/openssl/ossl_ts.c +1514 -0
  30. data/ext/openssl/ossl_ts.h +16 -0
  31. data/ext/openssl/ossl_x509.c +91 -0
  32. data/ext/openssl/ossl_x509cert.c +2 -2
  33. data/ext/openssl/ossl_x509ext.c +14 -0
  34. data/ext/openssl/ossl_x509name.c +8 -4
  35. data/ext/openssl/ossl_x509store.c +0 -2
  36. data/lib/openssl.rb +25 -9
  37. data/lib/openssl/bn.rb +1 -1
  38. data/lib/openssl/buffering.rb +33 -17
  39. data/lib/openssl/cipher.rb +1 -1
  40. data/lib/openssl/config.rb +53 -26
  41. data/lib/openssl/digest.rb +10 -12
  42. data/lib/openssl/hmac.rb +13 -0
  43. data/lib/openssl/marshal.rb +30 -0
  44. data/lib/openssl/pkcs5.rb +1 -1
  45. data/lib/openssl/pkey.rb +18 -1
  46. data/lib/openssl/ssl.rb +46 -7
  47. data/lib/openssl/version.rb +5 -0
  48. data/lib/openssl/x509.rb +155 -1
  49. metadata +8 -6
  50. data/ext/openssl/deprecation.rb +0 -23
  51. data/ext/openssl/ossl_version.h +0 -15
@@ -1562,6 +1562,34 @@ ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form)
1562
1562
  return str;
1563
1563
  }
1564
1564
 
1565
+ /*
1566
+ * call-seq:
1567
+ * point.add(point) => point
1568
+ *
1569
+ * Performs elliptic curve point addition.
1570
+ */
1571
+ static VALUE ossl_ec_point_add(VALUE self, VALUE other)
1572
+ {
1573
+ EC_POINT *point_self, *point_other, *point_result;
1574
+ const EC_GROUP *group;
1575
+ VALUE group_v = rb_attr_get(self, id_i_group);
1576
+ VALUE result;
1577
+
1578
+ GetECPoint(self, point_self);
1579
+ GetECPoint(other, point_other);
1580
+ GetECGroup(group_v, group);
1581
+
1582
+ result = rb_obj_alloc(cEC_POINT);
1583
+ ossl_ec_point_initialize(1, &group_v, result);
1584
+ GetECPoint(result, point_result);
1585
+
1586
+ if (EC_POINT_add(group, point_result, point_self, point_other, ossl_bn_ctx) != 1) {
1587
+ ossl_raise(eEC_POINT, "EC_POINT_add");
1588
+ }
1589
+
1590
+ return result;
1591
+ }
1592
+
1565
1593
  /*
1566
1594
  * call-seq:
1567
1595
  * point.mul(bn1 [, bn2]) => point
@@ -1786,6 +1814,7 @@ void Init_ossl_ec(void)
1786
1814
  /* all the other methods */
1787
1815
 
1788
1816
  rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1);
1817
+ rb_define_method(cEC_POINT, "add", ossl_ec_point_add, 1);
1789
1818
  rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
1790
1819
 
1791
1820
  id_i_group = rb_intern("@group");
@@ -26,10 +26,10 @@
26
26
  static inline int
27
27
  RSA_HAS_PRIVATE(RSA *rsa)
28
28
  {
29
- const BIGNUM *p, *q;
29
+ const BIGNUM *e, *d;
30
30
 
31
- RSA_get0_factors(rsa, &p, &q);
32
- return p && q; /* d? why? */
31
+ RSA_get0_key(rsa, NULL, &e, &d);
32
+ return e && d;
33
33
  }
34
34
 
35
35
  static inline int
@@ -341,6 +341,7 @@ static VALUE
341
341
  ossl_rsa_export(int argc, VALUE *argv, VALUE self)
342
342
  {
343
343
  RSA *rsa;
344
+ const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
344
345
  BIO *out;
345
346
  const EVP_CIPHER *ciph = NULL;
346
347
  VALUE cipher, pass, str;
@@ -356,7 +357,10 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self)
356
357
  if (!(out = BIO_new(BIO_s_mem()))) {
357
358
  ossl_raise(eRSAError, NULL);
358
359
  }
359
- if (RSA_HAS_PRIVATE(rsa)) {
360
+ RSA_get0_key(rsa, &n, &e, &d);
361
+ RSA_get0_factors(rsa, &p, &q);
362
+ RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
363
+ if (n && e && d && p && q && dmp1 && dmq1 && iqmp) {
360
364
  if (!PEM_write_bio_RSAPrivateKey(out, rsa, ciph, NULL, 0,
361
365
  ossl_pem_passwd_cb, (void *)pass)) {
362
366
  BIO_free(out);
@@ -383,23 +387,27 @@ static VALUE
383
387
  ossl_rsa_to_der(VALUE self)
384
388
  {
385
389
  RSA *rsa;
390
+ const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
386
391
  int (*i2d_func)(const RSA *, unsigned char **);
387
- unsigned char *p;
392
+ unsigned char *ptr;
388
393
  long len;
389
394
  VALUE str;
390
395
 
391
396
  GetRSA(self, rsa);
392
- if (RSA_HAS_PRIVATE(rsa))
397
+ RSA_get0_key(rsa, &n, &e, &d);
398
+ RSA_get0_factors(rsa, &p, &q);
399
+ RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
400
+ if (n && e && d && p && q && dmp1 && dmq1 && iqmp)
393
401
  i2d_func = i2d_RSAPrivateKey;
394
402
  else
395
403
  i2d_func = (int (*)(const RSA *, unsigned char **))i2d_RSA_PUBKEY;
396
404
  if((len = i2d_func(rsa, NULL)) <= 0)
397
405
  ossl_raise(eRSAError, NULL);
398
406
  str = rb_str_new(0, len);
399
- p = (unsigned char *)RSTRING_PTR(str);
400
- if(i2d_func(rsa, &p) < 0)
407
+ ptr = (unsigned char *)RSTRING_PTR(str);
408
+ if(i2d_func(rsa, &ptr) < 0)
401
409
  ossl_raise(eRSAError, NULL);
402
- ossl_str_adjust(str, p);
410
+ ossl_str_adjust(str, ptr);
403
411
 
404
412
  return str;
405
413
  }
@@ -67,8 +67,6 @@ ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
67
67
  static VALUE
68
68
  ossl_rand_load_file(VALUE self, VALUE filename)
69
69
  {
70
- rb_check_safe_obj(filename);
71
-
72
70
  if(!RAND_load_file(StringValueCStr(filename), -1)) {
73
71
  ossl_raise(eRandomError, NULL);
74
72
  }
@@ -86,8 +84,6 @@ ossl_rand_load_file(VALUE self, VALUE filename)
86
84
  static VALUE
87
85
  ossl_rand_write_file(VALUE self, VALUE filename)
88
86
  {
89
- rb_check_safe_obj(filename);
90
-
91
87
  if (RAND_write_file(StringValueCStr(filename)) == -1) {
92
88
  ossl_raise(eRandomError, NULL);
93
89
  }
@@ -124,36 +120,6 @@ ossl_rand_bytes(VALUE self, VALUE len)
124
120
  return str;
125
121
  }
126
122
 
127
- #if defined(HAVE_RAND_PSEUDO_BYTES)
128
- /*
129
- * call-seq:
130
- * pseudo_bytes(length) -> string
131
- *
132
- * Generates a String with _length_ number of pseudo-random bytes.
133
- *
134
- * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if
135
- * they are of sufficient length, but are not necessarily unpredictable.
136
- *
137
- * === Example
138
- *
139
- * OpenSSL::Random.pseudo_bytes(12)
140
- * #=> "..."
141
- */
142
- static VALUE
143
- ossl_rand_pseudo_bytes(VALUE self, VALUE len)
144
- {
145
- VALUE str;
146
- int n = NUM2INT(len);
147
-
148
- str = rb_str_new(0, n);
149
- if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) {
150
- ossl_raise(eRandomError, NULL);
151
- }
152
-
153
- return str;
154
- }
155
- #endif
156
-
157
123
  #ifdef HAVE_RAND_EGD
158
124
  /*
159
125
  * call-seq:
@@ -164,8 +130,6 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
164
130
  static VALUE
165
131
  ossl_rand_egd(VALUE self, VALUE filename)
166
132
  {
167
- rb_check_safe_obj(filename);
168
-
169
133
  if (RAND_egd(StringValueCStr(filename)) == -1) {
170
134
  ossl_raise(eRandomError, NULL);
171
135
  }
@@ -186,8 +150,6 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
186
150
  {
187
151
  int n = NUM2INT(len);
188
152
 
189
- rb_check_safe_obj(filename);
190
-
191
153
  if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
192
154
  ossl_raise(eRandomError, NULL);
193
155
  }
@@ -227,8 +189,8 @@ Init_ossl_rand(void)
227
189
  rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
228
190
  rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
229
191
  rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
230
- #if defined(HAVE_RAND_PSEUDO_BYTES)
231
- rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
192
+ #if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
193
+ rb_define_alias(rb_singleton_class(mRandom), "pseudo_bytes", "random_bytes");
232
194
  #endif
233
195
  #ifdef HAVE_RAND_EGD
234
196
  rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
@@ -184,8 +184,10 @@ ossl_sslctx_set_minmax_proto_version(VALUE self, VALUE min_v, VALUE max_v)
184
184
 
185
185
  for (i = 0; i < numberof(options_map); i++) {
186
186
  sum |= options_map[i].opts;
187
- if (min && min > options_map[i].ver || max && max < options_map[i].ver)
187
+ if ((min && min > options_map[i].ver) ||
188
+ (max && max < options_map[i].ver)) {
188
189
  opts |= options_map[i].opts;
190
+ }
189
191
  }
190
192
  SSL_CTX_clear_options(ctx, sum);
191
193
  SSL_CTX_set_options(ctx, opts);
@@ -357,7 +359,14 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
357
359
  rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
358
360
  return 0;
359
361
  }
360
- preverify_ok = ret == Qtrue;
362
+ if (ret != Qtrue) {
363
+ preverify_ok = 0;
364
+ #if defined(X509_V_ERR_HOSTNAME_MISMATCH)
365
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH);
366
+ #else
367
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
368
+ #endif
369
+ }
361
370
  }
362
371
 
363
372
  return ossl_verify_cb_call(cb, preverify_ok, ctx);
@@ -378,7 +387,7 @@ ossl_call_session_get_cb(VALUE ary)
378
387
  }
379
388
 
380
389
  static SSL_SESSION *
381
- #if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
390
+ #if (!defined(LIBRESSL_VERSION_NUMBER) ? OPENSSL_VERSION_NUMBER >= 0x10100000 : LIBRESSL_VERSION_NUMBER >= 0x2080000f)
382
391
  ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
383
392
  #else
384
393
  ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
@@ -590,7 +599,7 @@ ssl_renegotiation_cb(const SSL *ssl)
590
599
  #if !defined(OPENSSL_NO_NEXTPROTONEG) || \
591
600
  defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
592
601
  static VALUE
593
- ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded)
602
+ ssl_npn_encode_protocol_i(RB_BLOCK_CALL_FUNC_ARGLIST(cur, encoded))
594
603
  {
595
604
  int len = RSTRING_LENINT(cur);
596
605
  char len_byte;
@@ -808,6 +817,10 @@ ossl_sslctx_setup(VALUE self)
808
817
  }
809
818
  #endif /* OPENSSL_NO_EC */
810
819
 
820
+ #ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
821
+ SSL_CTX_set_post_handshake_auth(ctx, 1);
822
+ #endif
823
+
811
824
  val = rb_attr_get(self, id_i_cert_store);
812
825
  if (!NIL_P(val)) {
813
826
  X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
@@ -1826,7 +1839,6 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1826
1839
  else
1827
1840
  rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
1828
1841
  }
1829
- OBJ_TAINT(str);
1830
1842
  rb_str_set_len(str, 0);
1831
1843
  if (ilen == 0)
1832
1844
  return str;
@@ -1869,19 +1881,31 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1869
1881
  rb_eof_error();
1870
1882
  }
1871
1883
  }
1884
+ /* fall through */
1872
1885
  default:
1873
1886
  ossl_raise(eSSLError, "SSL_read");
1874
1887
  }
1875
1888
  }
1876
1889
  }
1877
1890
  else {
1878
- ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
1879
-
1880
- rb_warning("SSL session is not started yet.");
1881
- if (nonblock)
1882
- return rb_funcall(io, meth, 3, len, str, opts);
1883
- else
1884
- return rb_funcall(io, meth, 2, len, str);
1891
+ ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
1892
+
1893
+ rb_warning("SSL session is not started yet.");
1894
+ #if defined(RB_PASS_KEYWORDS)
1895
+ if (nonblock) {
1896
+ VALUE argv[3];
1897
+ argv[0] = len;
1898
+ argv[1] = str;
1899
+ argv[2] = opts;
1900
+ return rb_funcallv_kw(io, meth, 3, argv, RB_PASS_KEYWORDS);
1901
+ }
1902
+ #else
1903
+ if (nonblock) {
1904
+ return rb_funcall(io, meth, 3, len, str, opts);
1905
+ }
1906
+ #endif
1907
+ else
1908
+ return rb_funcall(io, meth, 2, len, str);
1885
1909
  }
1886
1910
 
1887
1911
  end:
@@ -1968,11 +1992,21 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
1968
1992
  ID meth = nonblock ?
1969
1993
  rb_intern("write_nonblock") : rb_intern("syswrite");
1970
1994
 
1971
- rb_warning("SSL session is not started yet.");
1972
- if (nonblock)
1973
- return rb_funcall(io, meth, 2, str, opts);
1974
- else
1975
- return rb_funcall(io, meth, 1, str);
1995
+ rb_warning("SSL session is not started yet.");
1996
+ #if defined(RB_PASS_KEYWORDS)
1997
+ if (nonblock) {
1998
+ VALUE argv[2];
1999
+ argv[0] = str;
2000
+ argv[1] = opts;
2001
+ return rb_funcallv_kw(io, meth, 2, argv, RB_PASS_KEYWORDS);
2002
+ }
2003
+ #else
2004
+ if (nonblock) {
2005
+ return rb_funcall(io, meth, 2, str, opts);
2006
+ }
2007
+ #endif
2008
+ else
2009
+ return rb_funcall(io, meth, 1, str);
1976
2010
  }
1977
2011
 
1978
2012
  end:
@@ -2275,7 +2309,57 @@ ossl_ssl_get_verify_result(VALUE self)
2275
2309
 
2276
2310
  GetSSL(self, ssl);
2277
2311
 
2278
- return INT2NUM(SSL_get_verify_result(ssl));
2312
+ return LONG2NUM(SSL_get_verify_result(ssl));
2313
+ }
2314
+
2315
+ /*
2316
+ * call-seq:
2317
+ * ssl.finished_message => "finished message"
2318
+ *
2319
+ * Returns the last *Finished* message sent
2320
+ *
2321
+ */
2322
+ static VALUE
2323
+ ossl_ssl_get_finished(VALUE self)
2324
+ {
2325
+ SSL *ssl;
2326
+ char sizer[1], *buf;
2327
+ size_t len;
2328
+
2329
+ GetSSL(self, ssl);
2330
+
2331
+ len = SSL_get_finished(ssl, sizer, 0);
2332
+ if (len == 0)
2333
+ return Qnil;
2334
+
2335
+ buf = ALLOCA_N(char, len);
2336
+ SSL_get_finished(ssl, buf, len);
2337
+ return rb_str_new(buf, len);
2338
+ }
2339
+
2340
+ /*
2341
+ * call-seq:
2342
+ * ssl.peer_finished_message => "peer finished message"
2343
+ *
2344
+ * Returns the last *Finished* message received
2345
+ *
2346
+ */
2347
+ static VALUE
2348
+ ossl_ssl_get_peer_finished(VALUE self)
2349
+ {
2350
+ SSL *ssl;
2351
+ char sizer[1], *buf;
2352
+ size_t len;
2353
+
2354
+ GetSSL(self, ssl);
2355
+
2356
+ len = SSL_get_peer_finished(ssl, sizer, 0);
2357
+ if (len == 0)
2358
+ return Qnil;
2359
+
2360
+ buf = ALLOCA_N(char, len);
2361
+ SSL_get_peer_finished(ssl, buf, len);
2362
+ return rb_str_new(buf, len);
2279
2363
  }
2280
2364
 
2281
2365
  /*
@@ -2600,13 +2684,13 @@ Init_ossl_ssl(void)
2600
2684
  rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qtrue);
2601
2685
 
2602
2686
  /*
2603
- * A callback invoked whenever a new handshake is initiated. May be used
2604
- * to disable renegotiation entirely.
2687
+ * A callback invoked whenever a new handshake is initiated on an
2688
+ * established connection. May be used to disable renegotiation entirely.
2605
2689
  *
2606
2690
  * The callback is invoked with the active SSLSocket. The callback's
2607
- * return value is irrelevant, normal return indicates "approval" of the
2691
+ * return value is ignored. A normal return indicates "approval" of the
2608
2692
  * renegotiation and will continue the process. To forbid renegotiation
2609
- * and to cancel the process, an Error may be raised within the callback.
2693
+ * and to cancel the process, raise an exception within the callback.
2610
2694
  *
2611
2695
  * === Disable client renegotiation
2612
2696
  *
@@ -2614,10 +2698,8 @@ Init_ossl_ssl(void)
2614
2698
  * renegotiation entirely. You may use a callback as follows to implement
2615
2699
  * this feature:
2616
2700
  *
2617
- * num_handshakes = 0
2618
2701
  * ctx.renegotiation_cb = lambda do |ssl|
2619
- * num_handshakes += 1
2620
- * raise RuntimeError.new("Client renegotiation disabled") if num_handshakes > 1
2702
+ * raise RuntimeError, "Client renegotiation disabled"
2621
2703
  * end
2622
2704
  */
2623
2705
  rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse);
@@ -2795,6 +2877,8 @@ Init_ossl_ssl(void)
2795
2877
  rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
2796
2878
  /* #hostname is defined in lib/openssl/ssl.rb */
2797
2879
  rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1);
2880
+ rb_define_method(cSSLSocket, "finished_message", ossl_ssl_get_finished, 0);
2881
+ rb_define_method(cSSLSocket, "peer_finished_message", ossl_ssl_get_peer_finished, 0);
2798
2882
  # ifdef HAVE_SSL_GET_SERVER_TMP_KEY
2799
2883
  rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
2800
2884
  # endif
@@ -0,0 +1,1514 @@
1
+ /*
2
+ *
3
+ * Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licenced under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #include "ossl.h"
11
+
12
+ #ifndef OPENSSL_NO_TS
13
+
14
+ #define NewTSRequest(klass) \
15
+ TypedData_Wrap_Struct((klass), &ossl_ts_req_type, 0)
16
+ #define SetTSRequest(obj, req) do { \
17
+ if (!(req)) { \
18
+ ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \
19
+ } \
20
+ RTYPEDDATA_DATA(obj) = (req); \
21
+ } while (0)
22
+ #define GetTSRequest(obj, req) do { \
23
+ TypedData_Get_Struct((obj), TS_REQ, &ossl_ts_req_type, (req)); \
24
+ if (!(req)) { \
25
+ ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \
26
+ } \
27
+ } while (0)
28
+
29
+ #define NewTSResponse(klass) \
30
+ TypedData_Wrap_Struct((klass), &ossl_ts_resp_type, 0)
31
+ #define SetTSResponse(obj, resp) do { \
32
+ if (!(resp)) { \
33
+ ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \
34
+ } \
35
+ RTYPEDDATA_DATA(obj) = (resp); \
36
+ } while (0)
37
+ #define GetTSResponse(obj, resp) do { \
38
+ TypedData_Get_Struct((obj), TS_RESP, &ossl_ts_resp_type, (resp)); \
39
+ if (!(resp)) { \
40
+ ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \
41
+ } \
42
+ } while (0)
43
+
44
+ #define NewTSTokenInfo(klass) \
45
+ TypedData_Wrap_Struct((klass), &ossl_ts_token_info_type, 0)
46
+ #define SetTSTokenInfo(obj, info) do { \
47
+ if (!(info)) { \
48
+ ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \
49
+ } \
50
+ RTYPEDDATA_DATA(obj) = (info); \
51
+ } while (0)
52
+ #define GetTSTokenInfo(obj, info) do { \
53
+ TypedData_Get_Struct((obj), TS_TST_INFO, &ossl_ts_token_info_type, (info)); \
54
+ if (!(info)) { \
55
+ ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \
56
+ } \
57
+ } while (0)
58
+
59
+ #define ossl_tsfac_get_default_policy_id(o) rb_attr_get((o),rb_intern("@default_policy_id"))
60
+ #define ossl_tsfac_get_serial_number(o) rb_attr_get((o),rb_intern("@serial_number"))
61
+ #define ossl_tsfac_get_gen_time(o) rb_attr_get((o),rb_intern("@gen_time"))
62
+ #define ossl_tsfac_get_additional_certs(o) rb_attr_get((o),rb_intern("@additional_certs"))
63
+ #define ossl_tsfac_get_allowed_digests(o) rb_attr_get((o),rb_intern("@allowed_digests"))
64
+
65
+ static VALUE mTimestamp;
66
+ static VALUE eTimestampError;
67
+ static VALUE cTimestampRequest;
68
+ static VALUE cTimestampResponse;
69
+ static VALUE cTimestampTokenInfo;
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;
74
+
75
+ static void
76
+ ossl_ts_req_free(void *ptr)
77
+ {
78
+ TS_REQ_free(ptr);
79
+ }
80
+
81
+ static const rb_data_type_t ossl_ts_req_type = {
82
+ "OpenSSL/Timestamp/Request",
83
+ {
84
+ 0, ossl_ts_req_free,
85
+ },
86
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
87
+ };
88
+
89
+ static void
90
+ ossl_ts_resp_free(void *ptr)
91
+ {
92
+ TS_RESP_free(ptr);
93
+ }
94
+
95
+ static const rb_data_type_t ossl_ts_resp_type = {
96
+ "OpenSSL/Timestamp/Response",
97
+ {
98
+ 0, ossl_ts_resp_free,
99
+ },
100
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
101
+ };
102
+
103
+ static void
104
+ ossl_ts_token_info_free(void *ptr)
105
+ {
106
+ TS_TST_INFO_free(ptr);
107
+ }
108
+
109
+ static const rb_data_type_t ossl_ts_token_info_type = {
110
+ "OpenSSL/Timestamp/TokenInfo",
111
+ {
112
+ 0, ossl_ts_token_info_free,
113
+ },
114
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
115
+ };
116
+
117
+ static VALUE
118
+ asn1_to_der(void *template, int (*i2d)(void *template, unsigned char **pp))
119
+ {
120
+ VALUE str;
121
+ int len;
122
+ unsigned char *p;
123
+
124
+ if((len = i2d(template, NULL)) <= 0)
125
+ ossl_raise(eTimestampError, "Error when encoding to DER");
126
+ str = rb_str_new(0, len);
127
+ p = (unsigned char *)RSTRING_PTR(str);
128
+ if(i2d(template, &p) <= 0)
129
+ ossl_raise(eTimestampError, "Error when encoding to DER");
130
+ rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
131
+
132
+ return str;
133
+ }
134
+
135
+ static ASN1_OBJECT*
136
+ obj_to_asn1obj(VALUE obj)
137
+ {
138
+ ASN1_OBJECT *a1obj;
139
+
140
+ StringValue(obj);
141
+ a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
142
+ if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
143
+ if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
144
+
145
+ return a1obj;
146
+ }
147
+
148
+ static VALUE
149
+ get_asn1obj(ASN1_OBJECT *obj)
150
+ {
151
+ BIO *out;
152
+ VALUE ret;
153
+ int nid;
154
+ if ((nid = OBJ_obj2nid(obj)) != NID_undef)
155
+ ret = rb_str_new2(OBJ_nid2sn(nid));
156
+ else{
157
+ if (!(out = BIO_new(BIO_s_mem())))
158
+ ossl_raise(eX509AttrError, NULL);
159
+ i2a_ASN1_OBJECT(out, obj);
160
+ ret = ossl_membio2str(out);
161
+ }
162
+
163
+ return ret;
164
+ }
165
+
166
+ static VALUE
167
+ ossl_ts_req_alloc(VALUE klass)
168
+ {
169
+ TS_REQ *req;
170
+ VALUE obj;
171
+
172
+ obj = NewTSRequest(klass);
173
+ if (!(req = TS_REQ_new()))
174
+ ossl_raise(eTimestampError, NULL);
175
+ SetTSRequest(obj, req);
176
+
177
+ /* Defaults */
178
+ TS_REQ_set_version(req, 1);
179
+ TS_REQ_set_cert_req(req, 1);
180
+
181
+ return obj;
182
+ }
183
+
184
+ /*
185
+ * When creating a Request with the +File+ or +string+ parameter, the
186
+ * corresponding +File+ or +string+ must be DER-encoded.
187
+ *
188
+ * call-seq:
189
+ * OpenSSL::Timestamp::Request.new(file) -> request
190
+ * OpenSSL::Timestamp::Request.new(string) -> request
191
+ * OpenSSL::Timestamp::Request.new -> empty request
192
+ */
193
+ static VALUE
194
+ ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
195
+ {
196
+ TS_REQ *ts_req = DATA_PTR(self);
197
+ BIO *in;
198
+ VALUE arg;
199
+
200
+ if(rb_scan_args(argc, argv, "01", &arg) == 0) {
201
+ return self;
202
+ }
203
+
204
+ arg = ossl_to_der_if_possible(arg);
205
+ in = ossl_obj2bio(&arg);
206
+ ts_req = d2i_TS_REQ_bio(in, &ts_req);
207
+ BIO_free(in);
208
+ if (!ts_req)
209
+ ossl_raise(eTimestampError, "Error when decoding the timestamp request");
210
+ DATA_PTR(self) = ts_req;
211
+
212
+ return self;
213
+ }
214
+
215
+ /*
216
+ * Returns the 'short name' of the object identifier that represents the
217
+ * algorithm that was used to create the message imprint digest.
218
+ *
219
+ * call-seq:
220
+ * request.algorithm -> string
221
+ */
222
+ static VALUE
223
+ ossl_ts_req_get_algorithm(VALUE self)
224
+ {
225
+ TS_REQ *req;
226
+ TS_MSG_IMPRINT *mi;
227
+ X509_ALGOR *algor;
228
+
229
+ GetTSRequest(self, req);
230
+ mi = TS_REQ_get_msg_imprint(req);
231
+ algor = TS_MSG_IMPRINT_get_algo(mi);
232
+ return get_asn1obj(algor->algorithm);
233
+ }
234
+
235
+ /*
236
+ * Allows to set the object identifier or the 'short name' of the
237
+ * algorithm that was used to create the message imprint digest.
238
+ *
239
+ * ===Example:
240
+ * request.algorithm = "SHA1"
241
+ *
242
+ * call-seq:
243
+ * request.algorithm = "string" -> string
244
+ */
245
+ static VALUE
246
+ ossl_ts_req_set_algorithm(VALUE self, VALUE algo)
247
+ {
248
+ TS_REQ *req;
249
+ TS_MSG_IMPRINT *mi;
250
+ ASN1_OBJECT *obj;
251
+ X509_ALGOR *algor;
252
+
253
+ GetTSRequest(self, req);
254
+ obj = obj_to_asn1obj(algo);
255
+ mi = TS_REQ_get_msg_imprint(req);
256
+ algor = TS_MSG_IMPRINT_get_algo(mi);
257
+ if (!X509_ALGOR_set0(algor, obj, V_ASN1_NULL, NULL)) {
258
+ ASN1_OBJECT_free(obj);
259
+ ossl_raise(eTimestampError, "X509_ALGOR_set0");
260
+ }
261
+
262
+ return algo;
263
+ }
264
+
265
+ /*
266
+ * Returns the message imprint (digest) of the data to be timestamped.
267
+ *
268
+ * call-seq:
269
+ * request.message_imprint -> string or nil
270
+ */
271
+ static VALUE
272
+ ossl_ts_req_get_msg_imprint(VALUE self)
273
+ {
274
+ TS_REQ *req;
275
+ TS_MSG_IMPRINT *mi;
276
+ ASN1_OCTET_STRING *hashed_msg;
277
+ VALUE ret;
278
+
279
+ GetTSRequest(self, req);
280
+ mi = TS_REQ_get_msg_imprint(req);
281
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
282
+
283
+ ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length);
284
+
285
+ return ret;
286
+ }
287
+
288
+ /*
289
+ * Set the message imprint digest.
290
+ *
291
+ * call-seq:
292
+ * request.message_imprint = "string" -> string
293
+ */
294
+ static VALUE
295
+ ossl_ts_req_set_msg_imprint(VALUE self, VALUE hash)
296
+ {
297
+ TS_REQ *req;
298
+ TS_MSG_IMPRINT *mi;
299
+ StringValue(hash);
300
+
301
+ GetTSRequest(self, req);
302
+ mi = TS_REQ_get_msg_imprint(req);
303
+ if (!TS_MSG_IMPRINT_set_msg(mi, (unsigned char *)RSTRING_PTR(hash), RSTRING_LENINT(hash)))
304
+ ossl_raise(eTimestampError, "TS_MSG_IMPRINT_set_msg");
305
+
306
+ return hash;
307
+ }
308
+
309
+ /*
310
+ * Returns the version of this request. +1+ is the default value.
311
+ *
312
+ * call-seq:
313
+ * request.version -> Integer
314
+ */
315
+ static VALUE
316
+ ossl_ts_req_get_version(VALUE self)
317
+ {
318
+ TS_REQ *req;
319
+
320
+ GetTSRequest(self, req);
321
+ return LONG2NUM(TS_REQ_get_version(req));
322
+ }
323
+
324
+ /*
325
+ * Sets the version number for this Request. This should be +1+ for compliant
326
+ * servers.
327
+ *
328
+ * call-seq:
329
+ * request.version = number -> Integer
330
+ */
331
+ static VALUE
332
+ ossl_ts_req_set_version(VALUE self, VALUE version)
333
+ {
334
+ TS_REQ *req;
335
+ long ver;
336
+
337
+ if ((ver = NUM2LONG(version)) < 0)
338
+ ossl_raise(eTimestampError, "version must be >= 0!");
339
+ GetTSRequest(self, req);
340
+ if (!TS_REQ_set_version(req, ver))
341
+ ossl_raise(eTimestampError, "TS_REQ_set_version");
342
+
343
+ return version;
344
+ }
345
+
346
+ /*
347
+ * Returns the 'short name' of the object identifier that represents the
348
+ * timestamp policy under which the server shall create the timestamp.
349
+ *
350
+ * call-seq:
351
+ * request.policy_id -> string or nil
352
+ */
353
+ static VALUE
354
+ ossl_ts_req_get_policy_id(VALUE self)
355
+ {
356
+ TS_REQ *req;
357
+
358
+ GetTSRequest(self, req);
359
+ if (!TS_REQ_get_policy_id(req))
360
+ return Qnil;
361
+ return get_asn1obj(TS_REQ_get_policy_id(req));
362
+ }
363
+
364
+ /*
365
+ * Allows to set the object identifier that represents the
366
+ * timestamp policy under which the server shall create the timestamp. This
367
+ * may be left +nil+, implying that the timestamp server will issue the
368
+ * timestamp using some default policy.
369
+ *
370
+ * ===Example:
371
+ * request.policy_id = "1.2.3.4.5"
372
+ *
373
+ * call-seq:
374
+ * request.policy_id = "string" -> string
375
+ */
376
+ static VALUE
377
+ ossl_ts_req_set_policy_id(VALUE self, VALUE oid)
378
+ {
379
+ TS_REQ *req;
380
+ ASN1_OBJECT *obj;
381
+ int ok;
382
+
383
+ GetTSRequest(self, req);
384
+ obj = obj_to_asn1obj(oid);
385
+ ok = TS_REQ_set_policy_id(req, obj);
386
+ ASN1_OBJECT_free(obj);
387
+ if (!ok)
388
+ ossl_raise(eTimestampError, "TS_REQ_set_policy_id");
389
+
390
+ return oid;
391
+ }
392
+
393
+ /*
394
+ * Returns the nonce (number used once) that the server shall include in its
395
+ * response.
396
+ *
397
+ * call-seq:
398
+ * request.nonce -> BN or nil
399
+ */
400
+ static VALUE
401
+ ossl_ts_req_get_nonce(VALUE self)
402
+ {
403
+ TS_REQ *req;
404
+ const ASN1_INTEGER * nonce;
405
+
406
+ GetTSRequest(self, req);
407
+ if (!(nonce = TS_REQ_get_nonce(req)))
408
+ return Qnil;
409
+ return asn1integer_to_num(nonce);
410
+ }
411
+
412
+ /*
413
+ * Sets the nonce (number used once) that the server shall include in its
414
+ * response. If the nonce is set, the server must return the same nonce value in
415
+ * a valid Response.
416
+ *
417
+ * call-seq:
418
+ * request.nonce = number -> BN
419
+ */
420
+ static VALUE
421
+ ossl_ts_req_set_nonce(VALUE self, VALUE num)
422
+ {
423
+ TS_REQ *req;
424
+ ASN1_INTEGER *nonce;
425
+ int ok;
426
+
427
+ GetTSRequest(self, req);
428
+ nonce = num_to_asn1integer(num, NULL);
429
+ ok = TS_REQ_set_nonce(req, nonce);
430
+ ASN1_INTEGER_free(nonce);
431
+ if (!ok)
432
+ ossl_raise(eTimestampError, NULL);
433
+ return num;
434
+ }
435
+
436
+ /*
437
+ * Indicates whether the response shall contain the timestamp authority's
438
+ * certificate or not.
439
+ *
440
+ * call-seq:
441
+ * request.cert_requested? -> true or false
442
+ */
443
+ static VALUE
444
+ ossl_ts_req_get_cert_requested(VALUE self)
445
+ {
446
+ TS_REQ *req;
447
+
448
+ GetTSRequest(self, req);
449
+ return TS_REQ_get_cert_req(req) ? Qtrue: Qfalse;
450
+ }
451
+
452
+ /*
453
+ * Specify whether the response shall contain the timestamp authority's
454
+ * certificate or not. The default value is +true+.
455
+ *
456
+ * call-seq:
457
+ * request.cert_requested = boolean -> true or false
458
+ */
459
+ static VALUE
460
+ ossl_ts_req_set_cert_requested(VALUE self, VALUE requested)
461
+ {
462
+ TS_REQ *req;
463
+
464
+ GetTSRequest(self, req);
465
+ TS_REQ_set_cert_req(req, RTEST(requested));
466
+
467
+ return requested;
468
+ }
469
+
470
+ /*
471
+ * DER-encodes this Request.
472
+ *
473
+ * call-seq:
474
+ * request.to_der -> DER-encoded string
475
+ */
476
+ static VALUE
477
+ ossl_ts_req_to_der(VALUE self)
478
+ {
479
+ TS_REQ *req;
480
+ TS_MSG_IMPRINT *mi;
481
+ X509_ALGOR *algo;
482
+ ASN1_OCTET_STRING *hashed_msg;
483
+
484
+ GetTSRequest(self, req);
485
+ mi = TS_REQ_get_msg_imprint(req);
486
+
487
+ algo = TS_MSG_IMPRINT_get_algo(mi);
488
+ if (OBJ_obj2nid(algo->algorithm) == NID_undef)
489
+ ossl_raise(eTimestampError, "Message imprint missing algorithm");
490
+
491
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
492
+ if (!hashed_msg->length)
493
+ ossl_raise(eTimestampError, "Message imprint missing hashed message");
494
+
495
+ return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ);
496
+ }
497
+
498
+ static VALUE
499
+ ossl_ts_resp_alloc(VALUE klass)
500
+ {
501
+ TS_RESP *resp;
502
+ VALUE obj;
503
+
504
+ obj = NewTSResponse(klass);
505
+ if (!(resp = TS_RESP_new()))
506
+ ossl_raise(eTimestampError, NULL);
507
+ SetTSResponse(obj, resp);
508
+
509
+ return obj;
510
+ }
511
+
512
+ /*
513
+ * Creates a Response from a +File+ or +string+ parameter, the
514
+ * corresponding +File+ or +string+ must be DER-encoded. Please note
515
+ * that Response is an immutable read-only class. If you'd like to create
516
+ * timestamps please refer to Factory instead.
517
+ *
518
+ * call-seq:
519
+ * OpenSSL::Timestamp::Response.new(file) -> response
520
+ * OpenSSL::Timestamp::Response.new(string) -> response
521
+ */
522
+ static VALUE
523
+ ossl_ts_resp_initialize(VALUE self, VALUE der)
524
+ {
525
+ TS_RESP *ts_resp = DATA_PTR(self);
526
+ BIO *in;
527
+
528
+ der = ossl_to_der_if_possible(der);
529
+ in = ossl_obj2bio(&der);
530
+ ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
531
+ BIO_free(in);
532
+ if (!ts_resp)
533
+ ossl_raise(eTimestampError, "Error when decoding the timestamp response");
534
+ DATA_PTR(self) = ts_resp;
535
+
536
+ return self;
537
+ }
538
+
539
+ /*
540
+ * Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING,
541
+ * REVOCATION_WARNING or REVOCATION_NOTIFICATION. A timestamp token has
542
+ * been created only in case +status+ is equal to GRANTED or GRANTED_WITH_MODS.
543
+ *
544
+ * call-seq:
545
+ * response.status -> BN (never nil)
546
+ */
547
+ static VALUE
548
+ ossl_ts_resp_get_status(VALUE self)
549
+ {
550
+ TS_RESP *resp;
551
+ TS_STATUS_INFO *si;
552
+ const ASN1_INTEGER *st;
553
+
554
+ GetTSResponse(self, resp);
555
+ si = TS_RESP_get_status_info(resp);
556
+ st = TS_STATUS_INFO_get0_status(si);
557
+
558
+ return asn1integer_to_num(st);
559
+ }
560
+
561
+ /*
562
+ * In cases no timestamp token has been created, this field contains further
563
+ * info about the reason why response creation failed. The method returns either
564
+ * nil (the request was successful and a timestamp token was created) or one of
565
+ * the following:
566
+ * * :BAD_ALG - Indicates that the timestamp server rejects the message
567
+ * imprint algorithm used in the Request
568
+ * * :BAD_REQUEST - Indicates that the timestamp server was not able to process
569
+ * the Request properly
570
+ * * :BAD_DATA_FORMAT - Indicates that the timestamp server was not able to
571
+ * parse certain data in the Request
572
+ * * :TIME_NOT_AVAILABLE - Indicates that the server could not access its time
573
+ * source
574
+ * * :UNACCEPTED_POLICY - Indicates that the requested policy identifier is not
575
+ * recognized or supported by the timestamp server
576
+ * * :UNACCEPTED_EXTENSIION - Indicates that an extension in the Request is
577
+ * not supported by the timestamp server
578
+ * * :ADD_INFO_NOT_AVAILABLE -Indicates that additional information requested
579
+ * is either not understood or currently not available
580
+ * * :SYSTEM_FAILURE - Timestamp creation failed due to an internal error that
581
+ * occurred on the timestamp server
582
+ *
583
+ * call-seq:
584
+ * response.failure_info -> nil or symbol
585
+ */
586
+ static VALUE
587
+ ossl_ts_resp_get_failure_info(VALUE self)
588
+ {
589
+ TS_RESP *resp;
590
+ TS_STATUS_INFO *si;
591
+
592
+ /* The ASN1_BIT_STRING_get_bit changed from 1.0.0. to 1.1.0, making this
593
+ * const. */
594
+ #if defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO)
595
+ const ASN1_BIT_STRING *fi;
596
+ #else
597
+ ASN1_BIT_STRING *fi;
598
+ #endif
599
+
600
+ GetTSResponse(self, resp);
601
+ si = TS_RESP_get_status_info(resp);
602
+ fi = TS_STATUS_INFO_get0_failure_info(si);
603
+ if (!fi)
604
+ return Qnil;
605
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG))
606
+ return sBAD_ALG;
607
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST))
608
+ return sBAD_REQUEST;
609
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT))
610
+ return sBAD_DATA_FORMAT;
611
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE))
612
+ return sTIME_NOT_AVAILABLE;
613
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY))
614
+ return sUNACCEPTED_POLICY;
615
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION))
616
+ return sUNACCEPTED_EXTENSION;
617
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE))
618
+ return sADD_INFO_NOT_AVAILABLE;
619
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE))
620
+ return sSYSTEM_FAILURE;
621
+
622
+ ossl_raise(eTimestampError, "Unrecognized failure info.");
623
+ }
624
+
625
+ /*
626
+ * In cases of failure this field may contain an array of strings further
627
+ * describing the origin of the failure.
628
+ *
629
+ * call-seq:
630
+ * response.status_text -> Array of strings or nil
631
+ */
632
+ static VALUE
633
+ ossl_ts_resp_get_status_text(VALUE self)
634
+ {
635
+ TS_RESP *resp;
636
+ TS_STATUS_INFO *si;
637
+ const STACK_OF(ASN1_UTF8STRING) *text;
638
+ ASN1_UTF8STRING *current;
639
+ int i;
640
+ VALUE ret = rb_ary_new();
641
+
642
+ GetTSResponse(self, resp);
643
+ si = TS_RESP_get_status_info(resp);
644
+ if ((text = TS_STATUS_INFO_get0_text(si))) {
645
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
646
+ current = sk_ASN1_UTF8STRING_value(text, i);
647
+ rb_ary_push(ret, asn1str_to_str(current));
648
+ }
649
+ }
650
+
651
+ return ret;
652
+ }
653
+
654
+ /*
655
+ * If a timestamp token is present, this returns it in the form of a
656
+ * OpenSSL::PKCS7.
657
+ *
658
+ * call-seq:
659
+ * response.token -> nil or OpenSSL::PKCS7
660
+ */
661
+ static VALUE
662
+ ossl_ts_resp_get_token(VALUE self)
663
+ {
664
+ TS_RESP *resp;
665
+ PKCS7 *p7, *copy;
666
+ VALUE obj;
667
+
668
+ GetTSResponse(self, resp);
669
+ if (!(p7 = TS_RESP_get_token(resp)))
670
+ return Qnil;
671
+
672
+ obj = NewPKCS7(cPKCS7);
673
+
674
+ if (!(copy = PKCS7_dup(p7)))
675
+ ossl_raise(eTimestampError, NULL);
676
+
677
+ SetPKCS7(obj, copy);
678
+
679
+ return obj;
680
+ }
681
+
682
+ /*
683
+ * Get the response's token info if present.
684
+ *
685
+ * call-seq:
686
+ * response.token_info -> nil or OpenSSL::Timestamp::TokenInfo
687
+ */
688
+ static VALUE
689
+ ossl_ts_resp_get_token_info(VALUE self)
690
+ {
691
+ TS_RESP *resp;
692
+ TS_TST_INFO *info, *copy;
693
+ VALUE obj;
694
+
695
+ GetTSResponse(self, resp);
696
+ if (!(info = TS_RESP_get_tst_info(resp)))
697
+ return Qnil;
698
+
699
+ obj = NewTSTokenInfo(cTimestampTokenInfo);
700
+
701
+ if (!(copy = TS_TST_INFO_dup(info)))
702
+ ossl_raise(eTimestampError, NULL);
703
+
704
+ SetTSTokenInfo(obj, copy);
705
+
706
+ return obj;
707
+ }
708
+
709
+ /*
710
+ * If the Request specified to request the TSA certificate
711
+ * (Request#cert_requested = true), then this field contains the
712
+ * certificate of the timestamp authority.
713
+ *
714
+ * call-seq:
715
+ * response.tsa_certificate -> OpenSSL::X509::Certificate or nil
716
+ */
717
+ static VALUE
718
+ ossl_ts_resp_get_tsa_certificate(VALUE self)
719
+ {
720
+ TS_RESP *resp;
721
+ PKCS7 *p7;
722
+ PKCS7_SIGNER_INFO *ts_info;
723
+ X509 *cert;
724
+
725
+ GetTSResponse(self, resp);
726
+ if (!(p7 = TS_RESP_get_token(resp)))
727
+ return Qnil;
728
+ ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0);
729
+ cert = PKCS7_cert_from_signer_info(p7, ts_info);
730
+ if (!cert)
731
+ return Qnil;
732
+ return ossl_x509_new(cert);
733
+ }
734
+
735
+ /*
736
+ * Returns the Response in DER-encoded form.
737
+ *
738
+ * call-seq:
739
+ * response.to_der -> string
740
+ */
741
+ static VALUE
742
+ ossl_ts_resp_to_der(VALUE self)
743
+ {
744
+ TS_RESP *resp;
745
+
746
+ GetTSResponse(self, resp);
747
+ return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP);
748
+ }
749
+
750
+ /*
751
+ * Verifies a timestamp token by checking the signature, validating the
752
+ * certificate chain implied by tsa_certificate and by checking conformance to
753
+ * a given Request. Mandatory parameters are the Request associated to this
754
+ * Response, and an OpenSSL::X509::Store of trusted roots.
755
+ *
756
+ * Intermediate certificates can optionally be supplied for creating the
757
+ * certificate chain. These intermediate certificates must all be
758
+ * instances of OpenSSL::X509::Certificate.
759
+ *
760
+ * If validation fails, several kinds of exceptions can be raised:
761
+ * * TypeError if types don't fit
762
+ * * TimestampError if something is wrong with the timestamp token itself, if
763
+ * it is not conformant to the Request, or if validation of the timestamp
764
+ * certificate chain fails.
765
+ *
766
+ * call-seq:
767
+ * response.verify(Request, root_store) -> Response
768
+ * response.verify(Request, root_store, [intermediate_cert]) -> Response
769
+ */
770
+ static VALUE
771
+ ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
772
+ {
773
+ VALUE ts_req, store, intermediates;
774
+ TS_RESP *resp;
775
+ TS_REQ *req;
776
+ X509_STORE *x509st;
777
+ TS_VERIFY_CTX *ctx;
778
+ STACK_OF(X509) *x509inter = NULL;
779
+ PKCS7* p7;
780
+ X509 *cert;
781
+ int status, i, ok;
782
+
783
+ rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates);
784
+
785
+ GetTSResponse(self, resp);
786
+ GetTSRequest(ts_req, req);
787
+ x509st = GetX509StorePtr(store);
788
+
789
+ if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) {
790
+ ossl_raise(eTimestampError, "Error when creating the verification context.");
791
+ }
792
+
793
+ if (!NIL_P(intermediates)) {
794
+ x509inter = ossl_protect_x509_ary2sk(intermediates, &status);
795
+ if (status) {
796
+ TS_VERIFY_CTX_free(ctx);
797
+ rb_jump_tag(status);
798
+ }
799
+ } else if (!(x509inter = sk_X509_new_null())) {
800
+ TS_VERIFY_CTX_free(ctx);
801
+ ossl_raise(eTimestampError, "sk_X509_new_null");
802
+ }
803
+
804
+ if (!(p7 = TS_RESP_get_token(resp))) {
805
+ TS_VERIFY_CTX_free(ctx);
806
+ sk_X509_pop_free(x509inter, X509_free);
807
+ ossl_raise(eTimestampError, "TS_RESP_get_token");
808
+ }
809
+ for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) {
810
+ cert = sk_X509_value(p7->d.sign->cert, i);
811
+ if (!sk_X509_push(x509inter, cert)) {
812
+ sk_X509_pop_free(x509inter, X509_free);
813
+ TS_VERIFY_CTX_free(ctx);
814
+ ossl_raise(eTimestampError, "sk_X509_push");
815
+ }
816
+ X509_up_ref(cert);
817
+ }
818
+
819
+ TS_VERIFY_CTS_set_certs(ctx, x509inter);
820
+ TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
821
+ TS_VERIFY_CTX_set_store(ctx, x509st);
822
+
823
+ 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)
830
+ */
831
+ TS_VERIFY_CTX_set_store(ctx, NULL);
832
+ TS_VERIFY_CTX_free(ctx);
833
+
834
+ if (!ok)
835
+ ossl_raise(eTimestampError, "TS_RESP_verify_response");
836
+
837
+ return self;
838
+ }
839
+
840
+ static VALUE
841
+ ossl_ts_token_info_alloc(VALUE klass)
842
+ {
843
+ TS_TST_INFO *info;
844
+ VALUE obj;
845
+
846
+ obj = NewTSTokenInfo(klass);
847
+ if (!(info = TS_TST_INFO_new()))
848
+ ossl_raise(eTimestampError, NULL);
849
+ SetTSTokenInfo(obj, info);
850
+
851
+ return obj;
852
+ }
853
+
854
+ /*
855
+ * Creates a TokenInfo from a +File+ or +string+ parameter, the
856
+ * corresponding +File+ or +string+ must be DER-encoded. Please note
857
+ * that TokenInfo is an immutable read-only class. If you'd like to create
858
+ * timestamps please refer to Factory instead.
859
+ *
860
+ * call-seq:
861
+ * OpenSSL::Timestamp::TokenInfo.new(file) -> token-info
862
+ * OpenSSL::Timestamp::TokenInfo.new(string) -> token-info
863
+ */
864
+ static VALUE
865
+ ossl_ts_token_info_initialize(VALUE self, VALUE der)
866
+ {
867
+ TS_TST_INFO *info = DATA_PTR(self);
868
+ BIO *in;
869
+
870
+ der = ossl_to_der_if_possible(der);
871
+ in = ossl_obj2bio(&der);
872
+ info = d2i_TS_TST_INFO_bio(in, &info);
873
+ BIO_free(in);
874
+ if (!info)
875
+ ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
876
+ DATA_PTR(self) = info;
877
+
878
+ return self;
879
+ }
880
+
881
+ /*
882
+ * Returns the version number of the token info. With compliant servers,
883
+ * this value should be +1+ if present. If status is GRANTED or
884
+ * GRANTED_WITH_MODS.
885
+ *
886
+ * call-seq:
887
+ * token_info.version -> Integer or nil
888
+ */
889
+ static VALUE
890
+ ossl_ts_token_info_get_version(VALUE self)
891
+ {
892
+ TS_TST_INFO *info;
893
+
894
+ GetTSTokenInfo(self, info);
895
+ return LONG2NUM(TS_TST_INFO_get_version(info));
896
+ }
897
+
898
+ /*
899
+ * Returns the timestamp policy object identifier of the policy this timestamp
900
+ * was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never
901
+ * +nil+.
902
+ *
903
+ * ===Example:
904
+ * id = token_info.policy_id
905
+ * puts id -> "1.2.3.4.5"
906
+ *
907
+ * call-seq:
908
+ * token_info.policy_id -> string or nil
909
+ */
910
+ static VALUE
911
+ ossl_ts_token_info_get_policy_id(VALUE self)
912
+ {
913
+ TS_TST_INFO *info;
914
+
915
+ GetTSTokenInfo(self, info);
916
+ return get_asn1obj(TS_TST_INFO_get_policy_id(info));
917
+ }
918
+
919
+ /*
920
+ * Returns the 'short name' of the object identifier representing the algorithm
921
+ * that was used to derive the message imprint digest. For valid timestamps,
922
+ * this is the same value that was already given in the Request. If status is
923
+ * GRANTED or GRANTED_WITH_MODS, this is never +nil+.
924
+ *
925
+ * ===Example:
926
+ * algo = token_info.algorithm
927
+ * puts algo -> "SHA1"
928
+ *
929
+ * call-seq:
930
+ * token_info.algorithm -> string or nil
931
+ */
932
+ static VALUE
933
+ ossl_ts_token_info_get_algorithm(VALUE self)
934
+ {
935
+ TS_TST_INFO *info;
936
+ TS_MSG_IMPRINT *mi;
937
+ X509_ALGOR *algo;
938
+
939
+ GetTSTokenInfo(self, info);
940
+ mi = TS_TST_INFO_get_msg_imprint(info);
941
+ algo = TS_MSG_IMPRINT_get_algo(mi);
942
+ return get_asn1obj(algo->algorithm);
943
+ }
944
+
945
+ /*
946
+ * Returns the message imprint digest. For valid timestamps,
947
+ * this is the same value that was already given in the Request.
948
+ * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+.
949
+ *
950
+ * ===Example:
951
+ * mi = token_info.msg_imprint
952
+ * puts mi -> "DEADBEEF"
953
+ *
954
+ * call-seq:
955
+ * token_info.msg_imprint -> string.
956
+ */
957
+ static VALUE
958
+ ossl_ts_token_info_get_msg_imprint(VALUE self)
959
+ {
960
+ TS_TST_INFO *info;
961
+ TS_MSG_IMPRINT *mi;
962
+ ASN1_OCTET_STRING *hashed_msg;
963
+ VALUE ret;
964
+
965
+ GetTSTokenInfo(self, info);
966
+ mi = TS_TST_INFO_get_msg_imprint(info);
967
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
968
+ ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length);
969
+
970
+ return ret;
971
+ }
972
+
973
+ /*
974
+ * Returns serial number of the timestamp token. This value shall never be the
975
+ * same for two timestamp tokens issued by a dedicated timestamp authority.
976
+ * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+.
977
+ *
978
+ * call-seq:
979
+ * token_info.serial_number -> BN or nil
980
+ */
981
+ static VALUE
982
+ ossl_ts_token_info_get_serial_number(VALUE self)
983
+ {
984
+ TS_TST_INFO *info;
985
+
986
+ GetTSTokenInfo(self, info);
987
+ return asn1integer_to_num(TS_TST_INFO_get_serial(info));
988
+ }
989
+
990
+ /*
991
+ * Returns time when this timestamp token was created. If status is GRANTED or
992
+ * GRANTED_WITH_MODS, this is never +nil+.
993
+ *
994
+ * call-seq:
995
+ * token_info.gen_time -> Time
996
+ */
997
+ static VALUE
998
+ ossl_ts_token_info_get_gen_time(VALUE self)
999
+ {
1000
+ TS_TST_INFO *info;
1001
+
1002
+ GetTSTokenInfo(self, info);
1003
+ return asn1time_to_time(TS_TST_INFO_get_time(info));
1004
+ }
1005
+
1006
+ /*
1007
+ * If the ordering field is missing, or if the ordering field is present
1008
+ * and set to false, then the genTime field only indicates the time at
1009
+ * which the time-stamp token has been created by the TSA. In such a
1010
+ * case, the ordering of time-stamp tokens issued by the same TSA or
1011
+ * different TSAs is only possible when the difference between the
1012
+ * genTime of the first time-stamp token and the genTime of the second
1013
+ * time-stamp token is greater than the sum of the accuracies of the
1014
+ * genTime for each time-stamp token.
1015
+ *
1016
+ * If the ordering field is present and set to true, every time-stamp
1017
+ * token from the same TSA can always be ordered based on the genTime
1018
+ * field, regardless of the genTime accuracy.
1019
+ *
1020
+ * call-seq:
1021
+ * token_info.ordering -> true, falses or nil
1022
+ */
1023
+ static VALUE
1024
+ ossl_ts_token_info_get_ordering(VALUE self)
1025
+ {
1026
+ TS_TST_INFO *info;
1027
+
1028
+ GetTSTokenInfo(self, info);
1029
+ return TS_TST_INFO_get_ordering(info) ? Qtrue : Qfalse;
1030
+ }
1031
+
1032
+ /*
1033
+ * If the timestamp token is valid then this field contains the same nonce that
1034
+ * was passed to the timestamp server in the initial Request.
1035
+ *
1036
+ * call-seq:
1037
+ * token_info.nonce -> BN or nil
1038
+ */
1039
+ static VALUE
1040
+ ossl_ts_token_info_get_nonce(VALUE self)
1041
+ {
1042
+ TS_TST_INFO *info;
1043
+ const ASN1_INTEGER *nonce;
1044
+
1045
+ GetTSTokenInfo(self, info);
1046
+ if (!(nonce = TS_TST_INFO_get_nonce(info)))
1047
+ return Qnil;
1048
+
1049
+ return asn1integer_to_num(nonce);
1050
+ }
1051
+
1052
+ /*
1053
+ * Returns the TokenInfo in DER-encoded form.
1054
+ *
1055
+ * call-seq:
1056
+ * token_info.to_der -> string
1057
+ */
1058
+ static VALUE
1059
+ ossl_ts_token_info_to_der(VALUE self)
1060
+ {
1061
+ TS_TST_INFO *info;
1062
+
1063
+ GetTSTokenInfo(self, info);
1064
+ return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO);
1065
+ }
1066
+
1067
+ static ASN1_INTEGER *
1068
+ ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
1069
+ {
1070
+ ASN1_INTEGER **snptr = (ASN1_INTEGER **)data;
1071
+ ASN1_INTEGER *sn = *snptr;
1072
+ *snptr = NULL;
1073
+ return sn;
1074
+ }
1075
+
1076
+ static int
1077
+ ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
1078
+ {
1079
+ *sec = *((long *)data);
1080
+ *usec = 0;
1081
+ return 1;
1082
+ }
1083
+
1084
+ /*
1085
+ * Creates a Response with the help of an OpenSSL::PKey, an
1086
+ * OpenSSL::X509::Certificate and a Request.
1087
+ *
1088
+ * Mandatory parameters for timestamp creation that need to be set in the
1089
+ * Request:
1090
+ *
1091
+ * * Request#algorithm
1092
+ * * Request#message_imprint
1093
+ *
1094
+ * Mandatory parameters that need to be set in the Factory:
1095
+ * * Factory#serial_number
1096
+ * * Factory#gen_time
1097
+ * * Factory#allowed_digests
1098
+ *
1099
+ * In addition one of either Request#policy_id or Factory#default_policy_id
1100
+ * must be set.
1101
+ *
1102
+ * Raises a TimestampError if creation fails, though successfully created error
1103
+ * responses may be returned.
1104
+ *
1105
+ * call-seq:
1106
+ * factory.create_timestamp(key, certificate, request) -> Response
1107
+ */
1108
+ static VALUE
1109
+ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
1110
+ {
1111
+ VALUE serial_number, def_policy_id, gen_time, additional_certs, allowed_digests;
1112
+ VALUE str;
1113
+ STACK_OF(X509) *inter_certs;
1114
+ VALUE tsresp, ret = Qnil;
1115
+ EVP_PKEY *sign_key;
1116
+ X509 *tsa_cert;
1117
+ TS_REQ *req;
1118
+ TS_RESP *response = NULL;
1119
+ TS_RESP_CTX *ctx = NULL;
1120
+ BIO *req_bio;
1121
+ ASN1_INTEGER *asn1_serial = NULL;
1122
+ ASN1_OBJECT *def_policy_id_obj = NULL;
1123
+ long lgen_time;
1124
+ const char * err_msg = NULL;
1125
+ int status = 0;
1126
+
1127
+ tsresp = NewTSResponse(cTimestampResponse);
1128
+ tsa_cert = GetX509CertPtr(certificate);
1129
+ sign_key = GetPrivPKeyPtr(key);
1130
+ GetTSRequest(request, req);
1131
+
1132
+ gen_time = ossl_tsfac_get_gen_time(self);
1133
+ if (!rb_obj_is_instance_of(gen_time, rb_cTime)) {
1134
+ err_msg = "@gen_time must be a Time.";
1135
+ goto end;
1136
+ }
1137
+ lgen_time = NUM2LONG(rb_funcall(gen_time, rb_intern("to_i"), 0));
1138
+
1139
+ serial_number = ossl_tsfac_get_serial_number(self);
1140
+ if (NIL_P(serial_number)) {
1141
+ err_msg = "@serial_number must be set.";
1142
+ goto end;
1143
+ }
1144
+ asn1_serial = num_to_asn1integer(serial_number, NULL);
1145
+
1146
+ def_policy_id = ossl_tsfac_get_default_policy_id(self);
1147
+ if (NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
1148
+ err_msg = "No policy id in the request and no default policy set";
1149
+ goto end;
1150
+ }
1151
+ 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);
1153
+ if (status)
1154
+ goto end;
1155
+ }
1156
+
1157
+ if (!(ctx = TS_RESP_CTX_new())) {
1158
+ err_msg = "Memory allocation failed.";
1159
+ goto end;
1160
+ }
1161
+
1162
+ TS_RESP_CTX_set_serial_cb(ctx, ossl_tsfac_serial_cb, &asn1_serial);
1163
+ if (!TS_RESP_CTX_set_signer_cert(ctx, tsa_cert)) {
1164
+ err_msg = "Certificate does not contain the timestamping extension";
1165
+ goto end;
1166
+ }
1167
+
1168
+ additional_certs = ossl_tsfac_get_additional_certs(self);
1169
+ if (rb_obj_is_kind_of(additional_certs, rb_cArray)) {
1170
+ inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status);
1171
+ if (status)
1172
+ goto end;
1173
+
1174
+ /* this dups the sk_X509 and ups each cert's ref count */
1175
+ TS_RESP_CTX_set_certs(ctx, inter_certs);
1176
+ sk_X509_pop_free(inter_certs, X509_free);
1177
+ }
1178
+
1179
+ TS_RESP_CTX_set_signer_key(ctx, sign_key);
1180
+ if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req))
1181
+ TS_RESP_CTX_set_def_policy(ctx, def_policy_id_obj);
1182
+ if (TS_REQ_get_policy_id(req))
1183
+ TS_RESP_CTX_set_def_policy(ctx, TS_REQ_get_policy_id(req));
1184
+ TS_RESP_CTX_set_time_cb(ctx, ossl_tsfac_time_cb, &lgen_time);
1185
+
1186
+ allowed_digests = ossl_tsfac_get_allowed_digests(self);
1187
+ if (rb_obj_is_kind_of(allowed_digests, rb_cArray)) {
1188
+ int i;
1189
+ VALUE rbmd;
1190
+ const EVP_MD *md;
1191
+
1192
+ for (i = 0; i < RARRAY_LEN(allowed_digests); i++) {
1193
+ rbmd = rb_ary_entry(allowed_digests, i);
1194
+ md = (const EVP_MD *)rb_protect((VALUE (*)(VALUE))ossl_evp_get_digestbyname, rbmd, &status);
1195
+ if (status)
1196
+ goto end;
1197
+ TS_RESP_CTX_add_md(ctx, md);
1198
+ }
1199
+ }
1200
+
1201
+ str = rb_protect(ossl_to_der, request, &status);
1202
+ if (status)
1203
+ goto end;
1204
+
1205
+ req_bio = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, (VALUE)&str, &status);
1206
+ if (status)
1207
+ goto end;
1208
+
1209
+ response = TS_RESP_create_response(ctx, req_bio);
1210
+ BIO_free(req_bio);
1211
+
1212
+ if (!response) {
1213
+ err_msg = "Error during response generation";
1214
+ goto end;
1215
+ }
1216
+
1217
+ /* bad responses aren't exceptional, but openssl still sets error
1218
+ * information. */
1219
+ ossl_clear_error();
1220
+
1221
+ SetTSResponse(tsresp, response);
1222
+ ret = tsresp;
1223
+
1224
+ end:
1225
+ ASN1_INTEGER_free(asn1_serial);
1226
+ ASN1_OBJECT_free(def_policy_id_obj);
1227
+ TS_RESP_CTX_free(ctx);
1228
+ if (err_msg)
1229
+ ossl_raise(eTimestampError, err_msg);
1230
+ if (status)
1231
+ rb_jump_tag(status);
1232
+ return ret;
1233
+ }
1234
+
1235
+ /*
1236
+ * INIT
1237
+ */
1238
+ void
1239
+ Init_ossl_ts(void)
1240
+ {
1241
+ #if 0
1242
+ mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
1243
+ #endif
1244
+
1245
+ /*
1246
+ * Possible return value for +Response#failure_info+. Indicates that the
1247
+ * timestamp server rejects the message imprint algorithm used in the
1248
+ * +Request+
1249
+ */
1250
+ sBAD_ALG = rb_intern("BAD_ALG");
1251
+
1252
+ /*
1253
+ * Possible return value for +Response#failure_info+. Indicates that the
1254
+ * timestamp server was not able to process the +Request+ properly.
1255
+ */
1256
+ sBAD_REQUEST = rb_intern("BAD_REQUEST");
1257
+ /*
1258
+ * Possible return value for +Response#failure_info+. Indicates that the
1259
+ * timestamp server was not able to parse certain data in the +Request+.
1260
+ */
1261
+ sBAD_DATA_FORMAT = rb_intern("BAD_DATA_FORMAT");
1262
+
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");
1268
+
1269
+ /* Document-class: OpenSSL::Timestamp
1270
+ * Provides classes and methods to request, create and validate
1271
+ * {RFC3161-compliant}[http://www.ietf.org/rfc/rfc3161.txt] timestamps.
1272
+ * Request may be used to either create requests from scratch or to parse
1273
+ * existing requests that again can be used to request timestamps from a
1274
+ * timestamp server, e.g. via the net/http. The resulting timestamp
1275
+ * response may be parsed using Response.
1276
+ *
1277
+ * Please note that Response is read-only and immutable. To create a
1278
+ * Response, an instance of Factory as well as a valid Request are needed.
1279
+ *
1280
+ * ===Create a Response:
1281
+ * #Assumes ts.p12 is a PKCS#12-compatible file with a private key
1282
+ * #and a certificate that has an extended key usage of 'timeStamping'
1283
+ * p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
1284
+ * md = OpenSSL::Digest.new('SHA1')
1285
+ * hash = md.digest(data) #some binary data to be timestamped
1286
+ * req = OpenSSL::Timestamp::Request.new
1287
+ * req.algorithm = 'SHA1'
1288
+ * req.message_imprint = hash
1289
+ * req.policy_id = "1.2.3.4.5"
1290
+ * req.nonce = 42
1291
+ * fac = OpenSSL::Timestamp::Factory.new
1292
+ * fac.gen_time = Time.now
1293
+ * fac.serial_number = 1
1294
+ * timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
1295
+ *
1296
+ * ===Verify a timestamp response:
1297
+ * #Assume we have a timestamp token in a file called ts.der
1298
+ * ts = OpenSSL::Timestamp::Response.new(File.open('ts.der', 'rb')
1299
+ * #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')
1301
+ * # Assume the associated root CA certificate is contained in a
1302
+ * # DER-encoded file named root.cer
1303
+ * root = OpenSSL::X509::Certificate.new(File.open('root.cer', 'rb')
1304
+ * # get the necessary intermediate certificates, available in
1305
+ * # 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')
1308
+ * ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails
1309
+ *
1310
+ */
1311
+ mTimestamp = rb_define_module_under(mOSSL, "Timestamp");
1312
+
1313
+ /* Document-class: OpenSSL::Timestamp::TimestampError
1314
+ * Generic exception class of the Timestamp module.
1315
+ */
1316
+ eTimestampError = rb_define_class_under(mTimestamp, "TimestampError", eOSSLError);
1317
+
1318
+ /* Document-class: OpenSSL::Timestamp::Response
1319
+ * Immutable and read-only representation of a timestamp response returned
1320
+ * from a timestamp server after receiving an associated Request. Allows
1321
+ * access to specific information about the response but also allows to
1322
+ * verify the Response.
1323
+ */
1324
+ cTimestampResponse = rb_define_class_under(mTimestamp, "Response", rb_cObject);
1325
+ rb_define_alloc_func(cTimestampResponse, ossl_ts_resp_alloc);
1326
+ rb_define_method(cTimestampResponse, "initialize", ossl_ts_resp_initialize, 1);
1327
+ rb_define_method(cTimestampResponse, "status", ossl_ts_resp_get_status, 0);
1328
+ rb_define_method(cTimestampResponse, "failure_info", ossl_ts_resp_get_failure_info, 0);
1329
+ rb_define_method(cTimestampResponse, "status_text", ossl_ts_resp_get_status_text, 0);
1330
+ rb_define_method(cTimestampResponse, "token", ossl_ts_resp_get_token, 0);
1331
+ rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0);
1332
+ rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0);
1333
+ rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0);
1334
+ rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1);
1335
+
1336
+ /* Document-class: OpenSSL::Timestamp::TokenInfo
1337
+ * Immutable and read-only representation of a timestamp token info from a
1338
+ * Response.
1339
+ */
1340
+ cTimestampTokenInfo = rb_define_class_under(mTimestamp, "TokenInfo", rb_cObject);
1341
+ rb_define_alloc_func(cTimestampTokenInfo, ossl_ts_token_info_alloc);
1342
+ rb_define_method(cTimestampTokenInfo, "initialize", ossl_ts_token_info_initialize, 1);
1343
+ rb_define_method(cTimestampTokenInfo, "version", ossl_ts_token_info_get_version, 0);
1344
+ rb_define_method(cTimestampTokenInfo, "policy_id", ossl_ts_token_info_get_policy_id, 0);
1345
+ rb_define_method(cTimestampTokenInfo, "algorithm", ossl_ts_token_info_get_algorithm, 0);
1346
+ rb_define_method(cTimestampTokenInfo, "message_imprint", ossl_ts_token_info_get_msg_imprint, 0);
1347
+ rb_define_method(cTimestampTokenInfo, "serial_number", ossl_ts_token_info_get_serial_number, 0);
1348
+ rb_define_method(cTimestampTokenInfo, "gen_time", ossl_ts_token_info_get_gen_time, 0);
1349
+ rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0);
1350
+ rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0);
1351
+ rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0);
1352
+
1353
+ /* Document-class: OpenSSL::Timestamp::Request
1354
+ * Allows to create timestamp requests or parse existing ones. A Request is
1355
+ * also needed for creating timestamps from scratch with Factory. When
1356
+ * created from scratch, some default values are set:
1357
+ * * version is set to +1+
1358
+ * * cert_requested is set to +true+
1359
+ * * algorithm, message_imprint, policy_id, and nonce are set to +false+
1360
+ */
1361
+ cTimestampRequest = rb_define_class_under(mTimestamp, "Request", rb_cObject);
1362
+ rb_define_alloc_func(cTimestampRequest, ossl_ts_req_alloc);
1363
+ rb_define_method(cTimestampRequest, "initialize", ossl_ts_req_initialize, -1);
1364
+ rb_define_method(cTimestampRequest, "version=", ossl_ts_req_set_version, 1);
1365
+ rb_define_method(cTimestampRequest, "version", ossl_ts_req_get_version, 0);
1366
+ rb_define_method(cTimestampRequest, "algorithm=", ossl_ts_req_set_algorithm, 1);
1367
+ rb_define_method(cTimestampRequest, "algorithm", ossl_ts_req_get_algorithm, 0);
1368
+ rb_define_method(cTimestampRequest, "message_imprint=", ossl_ts_req_set_msg_imprint, 1);
1369
+ rb_define_method(cTimestampRequest, "message_imprint", ossl_ts_req_get_msg_imprint, 0);
1370
+ rb_define_method(cTimestampRequest, "policy_id=", ossl_ts_req_set_policy_id, 1);
1371
+ rb_define_method(cTimestampRequest, "policy_id", ossl_ts_req_get_policy_id, 0);
1372
+ rb_define_method(cTimestampRequest, "nonce=", ossl_ts_req_set_nonce, 1);
1373
+ rb_define_method(cTimestampRequest, "nonce", ossl_ts_req_get_nonce, 0);
1374
+ rb_define_method(cTimestampRequest, "cert_requested=", ossl_ts_req_set_cert_requested, 1);
1375
+ rb_define_method(cTimestampRequest, "cert_requested?", ossl_ts_req_get_cert_requested, 0);
1376
+ rb_define_method(cTimestampRequest, "to_der", ossl_ts_req_to_der, 0);
1377
+
1378
+ /*
1379
+ * Indicates a successful response. Equal to +0+.
1380
+ */
1381
+ rb_define_const(cTimestampResponse, "GRANTED", INT2NUM(TS_STATUS_GRANTED));
1382
+ /*
1383
+ * Indicates a successful response that probably contains modifications
1384
+ * from the initial request. Equal to +1+.
1385
+ */
1386
+ rb_define_const(cTimestampResponse, "GRANTED_WITH_MODS", INT2NUM(TS_STATUS_GRANTED_WITH_MODS));
1387
+ /*
1388
+ * Indicates a failure. No timestamp token was created. Equal to +2+.
1389
+ */
1390
+ rb_define_const(cTimestampResponse, "REJECTION", INT2NUM(TS_STATUS_REJECTION));
1391
+ /*
1392
+ * Indicates a failure. No timestamp token was created. Equal to +3+.
1393
+ */
1394
+ rb_define_const(cTimestampResponse, "WAITING", INT2NUM(TS_STATUS_WAITING));
1395
+ /*
1396
+ * Indicates a failure. No timestamp token was created. Revocation of a
1397
+ * certificate is imminent. Equal to +4+.
1398
+ */
1399
+ rb_define_const(cTimestampResponse, "REVOCATION_WARNING", INT2NUM(TS_STATUS_REVOCATION_WARNING));
1400
+ /*
1401
+ * Indicates a failure. No timestamp token was created. A certificate
1402
+ * has been revoked. Equal to +5+.
1403
+ */
1404
+ rb_define_const(cTimestampResponse, "REVOCATION_NOTIFICATION", INT2NUM(TS_STATUS_REVOCATION_NOTIFICATION));
1405
+
1406
+ /* Document-class: OpenSSL::Timestamp::Factory
1407
+ *
1408
+ * Used to generate a Response from scratch.
1409
+ *
1410
+ * Please bear in mind that the implementation will always apply and prefer
1411
+ * the policy object identifier given in the request over the default policy
1412
+ * id specified in the Factory. As a consequence, +default_policy_id+ will
1413
+ * only be applied if no Request#policy_id was given. But this also means
1414
+ * that one needs to check the policy identifier in the request manually
1415
+ * before creating the Response, e.g. to check whether it complies to a
1416
+ * specific set of acceptable policies.
1417
+ *
1418
+ * There exists also the possibility to add certificates (instances of
1419
+ * OpenSSL::X509::Certificate) besides the timestamping certificate
1420
+ * that will be included in the resulting timestamp token if
1421
+ * Request#cert_requested? is +true+. Ideally, one would also include any
1422
+ * intermediate certificates (the root certificate can be left out - in
1423
+ * order to trust it any verifying party will have to be in its possession
1424
+ * anyway). This simplifies validation of the timestamp since these
1425
+ * intermediate certificates are "already there" and need not be passed as
1426
+ * external parameters to Response#verify anymore, thus minimizing external
1427
+ * resources needed for verification.
1428
+ *
1429
+ * ===Example: Inclusion of (untrusted) intermediate certificates
1430
+ *
1431
+ * Assume we received a timestamp request that has set Request#policy_id to
1432
+ * +nil+ and Request#cert_requested? to true. The raw request bytes are
1433
+ * stored in a variable called +req_raw+. We'd still like to integrate
1434
+ * the necessary intermediate certificates (in +inter1.cer+ and
1435
+ * +inter2.cer+) to simplify validation of the resulting Response. +ts.p12+
1436
+ * is a PKCS#12-compatible file including the private key and the
1437
+ * timestamping certificate.
1438
+ *
1439
+ * 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')
1443
+ * fac = OpenSSL::Timestamp::Factory.new
1444
+ * fac.gen_time = Time.now
1445
+ * fac.serial_number = 1
1446
+ * fac.allowed_digests = ["sha256", "sha384", "sha512"]
1447
+ * #needed because the Request contained no policy identifier
1448
+ * fac.default_policy_id = '1.2.3.4.5'
1449
+ * fac.additional_certificates = [ inter1, inter2 ]
1450
+ * timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
1451
+ *
1452
+ * ==Attributes
1453
+ *
1454
+ * ===default_policy_id
1455
+ *
1456
+ * Request#policy_id will always be preferred over this if present in the
1457
+ * Request, only if Request#policy_id is nil default_policy will be used.
1458
+ * If none of both is present, a TimestampError will be raised when trying
1459
+ * to create a Response.
1460
+ *
1461
+ * call-seq:
1462
+ * factory.default_policy_id = "string" -> string
1463
+ * factory.default_policy_id -> string or nil
1464
+ *
1465
+ * ===serial_number
1466
+ *
1467
+ * Sets or retrieves the serial number to be used for timestamp creation.
1468
+ * Must be present for timestamp creation.
1469
+ *
1470
+ * call-seq:
1471
+ * factory.serial_number = number -> number
1472
+ * factory.serial_number -> number or nil
1473
+ *
1474
+ * ===gen_time
1475
+ *
1476
+ * Sets or retrieves the Time value to be used in the Response. Must be
1477
+ * present for timestamp creation.
1478
+ *
1479
+ * call-seq:
1480
+ * factory.gen_time = Time -> Time
1481
+ * factory.gen_time -> Time or nil
1482
+ *
1483
+ * ===additional_certs
1484
+ *
1485
+ * Sets or retrieves additional certificates apart from the timestamp
1486
+ * certificate (e.g. intermediate certificates) to be added to the Response.
1487
+ * Must be an Array of OpenSSL::X509::Certificate.
1488
+ *
1489
+ * call-seq:
1490
+ * factory.additional_certs = [cert1, cert2] -> [ cert1, cert2 ]
1491
+ * factory.additional_certs -> array or nil
1492
+ *
1493
+ * ===allowed_digests
1494
+ *
1495
+ * Sets or retrieves the digest algorithms that the factory is allowed
1496
+ * create timestamps for. Known vulnerable or weak algorithms should not be
1497
+ * allowed where possible.
1498
+ * Must be an Array of String or OpenSSL::Digest subclass instances.
1499
+ *
1500
+ * call-seq:
1501
+ * factory.allowed_digests = ["sha1", OpenSSL::Digest.new('SHA256').new] -> [ "sha1", OpenSSL::Digest) ]
1502
+ * factory.allowed_digests -> array or nil
1503
+ *
1504
+ */
1505
+ 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);
1511
+ rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3);
1512
+ }
1513
+
1514
+ #endif