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.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +9 -7
- data/History.md +77 -0
- data/README.md +2 -2
- data/ext/openssl/extconf.rb +24 -14
- data/ext/openssl/openssl_missing.h +37 -2
- data/ext/openssl/ossl.c +51 -25
- data/ext/openssl/ossl.h +8 -5
- data/ext/openssl/ossl_asn1.c +26 -1
- data/ext/openssl/ossl_bn.c +9 -3
- data/ext/openssl/ossl_cipher.c +33 -24
- data/ext/openssl/ossl_digest.c +16 -51
- data/ext/openssl/ossl_engine.c +2 -12
- data/ext/openssl/ossl_hmac.c +5 -11
- data/ext/openssl/ossl_kdf.c +3 -19
- data/ext/openssl/ossl_ns_spki.c +1 -1
- data/ext/openssl/ossl_ocsp.c +6 -11
- data/ext/openssl/ossl_ocsp.h +3 -3
- data/ext/openssl/ossl_pkcs7.c +3 -19
- data/ext/openssl/ossl_pkcs7.h +16 -0
- data/ext/openssl/ossl_pkey.c +180 -14
- data/ext/openssl/ossl_pkey.h +5 -5
- data/ext/openssl/ossl_pkey_dh.c +1 -1
- data/ext/openssl/ossl_pkey_dsa.c +2 -2
- data/ext/openssl/ossl_pkey_ec.c +29 -0
- data/ext/openssl/ossl_pkey_rsa.c +17 -9
- data/ext/openssl/ossl_rand.c +2 -40
- data/ext/openssl/ossl_ssl.c +109 -25
- data/ext/openssl/ossl_ts.c +1514 -0
- data/ext/openssl/ossl_ts.h +16 -0
- data/ext/openssl/ossl_x509.c +91 -0
- data/ext/openssl/ossl_x509cert.c +2 -2
- data/ext/openssl/ossl_x509ext.c +14 -0
- data/ext/openssl/ossl_x509name.c +8 -4
- data/ext/openssl/ossl_x509store.c +0 -2
- data/lib/openssl.rb +25 -9
- data/lib/openssl/bn.rb +1 -1
- data/lib/openssl/buffering.rb +33 -17
- data/lib/openssl/cipher.rb +1 -1
- data/lib/openssl/config.rb +53 -26
- data/lib/openssl/digest.rb +10 -12
- data/lib/openssl/hmac.rb +13 -0
- data/lib/openssl/marshal.rb +30 -0
- data/lib/openssl/pkcs5.rb +1 -1
- data/lib/openssl/pkey.rb +18 -1
- data/lib/openssl/ssl.rb +46 -7
- data/lib/openssl/version.rb +5 -0
- data/lib/openssl/x509.rb +155 -1
- metadata +8 -6
- data/ext/openssl/deprecation.rb +0 -23
- data/ext/openssl/ossl_version.h +0 -15
data/ext/openssl/ossl_pkey_ec.c
CHANGED
@@ -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");
|
data/ext/openssl/ossl_pkey_rsa.c
CHANGED
@@ -26,10 +26,10 @@
|
|
26
26
|
static inline int
|
27
27
|
RSA_HAS_PRIVATE(RSA *rsa)
|
28
28
|
{
|
29
|
-
const BIGNUM *
|
29
|
+
const BIGNUM *e, *d;
|
30
30
|
|
31
|
-
|
32
|
-
return
|
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
|
-
|
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 *
|
392
|
+
unsigned char *ptr;
|
388
393
|
long len;
|
389
394
|
VALUE str;
|
390
395
|
|
391
396
|
GetRSA(self, rsa);
|
392
|
-
|
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
|
-
|
400
|
-
if(i2d_func(rsa, &
|
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,
|
410
|
+
ossl_str_adjust(str, ptr);
|
403
411
|
|
404
412
|
return str;
|
405
413
|
}
|
data/ext/openssl/ossl_rand.c
CHANGED
@@ -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(
|
231
|
-
|
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);
|
data/ext/openssl/ossl_ssl.c
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
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(
|
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
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
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
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
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
|
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
|
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
|
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
|
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
|
-
*
|
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
|