openssl 2.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openssl might be problematic. Click here for more details.

Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CONTRIBUTING.md +130 -0
  4. data/History.md +118 -0
  5. data/LICENSE.txt +56 -0
  6. data/README.md +70 -0
  7. data/ext/openssl/deprecation.rb +26 -0
  8. data/ext/openssl/extconf.rb +158 -0
  9. data/ext/openssl/openssl_missing.c +173 -0
  10. data/ext/openssl/openssl_missing.h +244 -0
  11. data/ext/openssl/ossl.c +1201 -0
  12. data/ext/openssl/ossl.h +222 -0
  13. data/ext/openssl/ossl_asn1.c +1992 -0
  14. data/ext/openssl/ossl_asn1.h +66 -0
  15. data/ext/openssl/ossl_bio.c +87 -0
  16. data/ext/openssl/ossl_bio.h +19 -0
  17. data/ext/openssl/ossl_bn.c +1153 -0
  18. data/ext/openssl/ossl_bn.h +23 -0
  19. data/ext/openssl/ossl_cipher.c +1085 -0
  20. data/ext/openssl/ossl_cipher.h +20 -0
  21. data/ext/openssl/ossl_config.c +89 -0
  22. data/ext/openssl/ossl_config.h +19 -0
  23. data/ext/openssl/ossl_digest.c +453 -0
  24. data/ext/openssl/ossl_digest.h +20 -0
  25. data/ext/openssl/ossl_engine.c +580 -0
  26. data/ext/openssl/ossl_engine.h +19 -0
  27. data/ext/openssl/ossl_hmac.c +398 -0
  28. data/ext/openssl/ossl_hmac.h +18 -0
  29. data/ext/openssl/ossl_ns_spki.c +406 -0
  30. data/ext/openssl/ossl_ns_spki.h +19 -0
  31. data/ext/openssl/ossl_ocsp.c +2013 -0
  32. data/ext/openssl/ossl_ocsp.h +23 -0
  33. data/ext/openssl/ossl_pkcs12.c +259 -0
  34. data/ext/openssl/ossl_pkcs12.h +13 -0
  35. data/ext/openssl/ossl_pkcs5.c +180 -0
  36. data/ext/openssl/ossl_pkcs5.h +6 -0
  37. data/ext/openssl/ossl_pkcs7.c +1125 -0
  38. data/ext/openssl/ossl_pkcs7.h +20 -0
  39. data/ext/openssl/ossl_pkey.c +435 -0
  40. data/ext/openssl/ossl_pkey.h +245 -0
  41. data/ext/openssl/ossl_pkey_dh.c +650 -0
  42. data/ext/openssl/ossl_pkey_dsa.c +672 -0
  43. data/ext/openssl/ossl_pkey_ec.c +1899 -0
  44. data/ext/openssl/ossl_pkey_rsa.c +768 -0
  45. data/ext/openssl/ossl_rand.c +238 -0
  46. data/ext/openssl/ossl_rand.h +18 -0
  47. data/ext/openssl/ossl_ssl.c +2679 -0
  48. data/ext/openssl/ossl_ssl.h +41 -0
  49. data/ext/openssl/ossl_ssl_session.c +352 -0
  50. data/ext/openssl/ossl_version.h +15 -0
  51. data/ext/openssl/ossl_x509.c +186 -0
  52. data/ext/openssl/ossl_x509.h +119 -0
  53. data/ext/openssl/ossl_x509attr.c +328 -0
  54. data/ext/openssl/ossl_x509cert.c +860 -0
  55. data/ext/openssl/ossl_x509crl.c +565 -0
  56. data/ext/openssl/ossl_x509ext.c +480 -0
  57. data/ext/openssl/ossl_x509name.c +547 -0
  58. data/ext/openssl/ossl_x509req.c +492 -0
  59. data/ext/openssl/ossl_x509revoked.c +279 -0
  60. data/ext/openssl/ossl_x509store.c +846 -0
  61. data/ext/openssl/ruby_missing.h +32 -0
  62. data/lib/openssl.rb +21 -0
  63. data/lib/openssl/bn.rb +39 -0
  64. data/lib/openssl/buffering.rb +451 -0
  65. data/lib/openssl/cipher.rb +67 -0
  66. data/lib/openssl/config.rb +473 -0
  67. data/lib/openssl/digest.rb +78 -0
  68. data/lib/openssl/pkey.rb +44 -0
  69. data/lib/openssl/ssl.rb +416 -0
  70. data/lib/openssl/x509.rb +176 -0
  71. metadata +178 -0
@@ -0,0 +1,245 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licensed under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #if !defined(_OSSL_PKEY_H_)
11
+ #define _OSSL_PKEY_H_
12
+
13
+ extern VALUE mPKey;
14
+ extern VALUE cPKey;
15
+ extern VALUE ePKeyError;
16
+ extern const rb_data_type_t ossl_evp_pkey_type;
17
+
18
+ #define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
19
+ #define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse)
20
+ #define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue)
21
+
22
+ #define NewPKey(klass) \
23
+ TypedData_Wrap_Struct((klass), &ossl_evp_pkey_type, 0)
24
+ #define SetPKey(obj, pkey) do { \
25
+ if (!(pkey)) { \
26
+ rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \
27
+ } \
28
+ RTYPEDDATA_DATA(obj) = (pkey); \
29
+ OSSL_PKEY_SET_PUBLIC(obj); \
30
+ } while (0)
31
+ #define GetPKey(obj, pkey) do {\
32
+ TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \
33
+ if (!(pkey)) { \
34
+ rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\
35
+ } \
36
+ } while (0)
37
+ #define SafeGetPKey(obj, pkey) do { \
38
+ OSSL_Check_Kind((obj), cPKey); \
39
+ GetPKey((obj), (pkey)); \
40
+ } while (0)
41
+
42
+ struct ossl_generate_cb_arg {
43
+ int yield;
44
+ int stop;
45
+ int state;
46
+ };
47
+ int ossl_generate_cb_2(int p, int n, BN_GENCB *cb);
48
+ void ossl_generate_cb_stop(void *ptr);
49
+
50
+ VALUE ossl_pkey_new(EVP_PKEY *);
51
+ VALUE ossl_pkey_new_from_file(VALUE);
52
+ EVP_PKEY *GetPKeyPtr(VALUE);
53
+ EVP_PKEY *DupPKeyPtr(VALUE);
54
+ EVP_PKEY *GetPrivPKeyPtr(VALUE);
55
+ void Init_ossl_pkey(void);
56
+
57
+ /*
58
+ * RSA
59
+ */
60
+ extern VALUE cRSA;
61
+ extern VALUE eRSAError;
62
+
63
+ VALUE ossl_rsa_new(EVP_PKEY *);
64
+ void Init_ossl_rsa(void);
65
+
66
+ /*
67
+ * DSA
68
+ */
69
+ extern VALUE cDSA;
70
+ extern VALUE eDSAError;
71
+
72
+ VALUE ossl_dsa_new(EVP_PKEY *);
73
+ void Init_ossl_dsa(void);
74
+
75
+ /*
76
+ * DH
77
+ */
78
+ extern VALUE cDH;
79
+ extern VALUE eDHError;
80
+
81
+ VALUE ossl_dh_new(EVP_PKEY *);
82
+ void Init_ossl_dh(void);
83
+
84
+ /*
85
+ * EC
86
+ */
87
+ extern VALUE cEC;
88
+ extern VALUE eECError;
89
+ extern VALUE cEC_GROUP;
90
+ extern VALUE eEC_GROUP;
91
+ extern VALUE cEC_POINT;
92
+ extern VALUE eEC_POINT;
93
+ VALUE ossl_ec_new(EVP_PKEY *);
94
+ void Init_ossl_ec(void);
95
+
96
+ #define OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, _name, _get) \
97
+ /* \
98
+ * call-seq: \
99
+ * _keytype##.##_name -> aBN \
100
+ */ \
101
+ static VALUE ossl_##_keytype##_get_##_name(VALUE self) \
102
+ { \
103
+ _type *obj; \
104
+ const BIGNUM *bn; \
105
+ \
106
+ Get##_type(self, obj); \
107
+ _get; \
108
+ if (bn == NULL) \
109
+ return Qnil; \
110
+ return ossl_bn_new(bn); \
111
+ }
112
+
113
+ #define OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \
114
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \
115
+ _type##_get0_##_group(obj, &bn, NULL, NULL)) \
116
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
117
+ _type##_get0_##_group(obj, NULL, &bn, NULL)) \
118
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a3, \
119
+ _type##_get0_##_group(obj, NULL, NULL, &bn))
120
+
121
+ #define OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \
122
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \
123
+ _type##_get0_##_group(obj, &bn, NULL)) \
124
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
125
+ _type##_get0_##_group(obj, NULL, &bn))
126
+
127
+ #define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
128
+ /* \
129
+ * call-seq: \
130
+ * _keytype##.set_##_group(a1, a2, a3) -> self \
131
+ */ \
132
+ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \
133
+ { \
134
+ _type *obj; \
135
+ BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\
136
+ BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\
137
+ BIGNUM *bn3 = NULL, *orig_bn3 = NIL_P(v3) ? NULL : GetBNPtr(v3);\
138
+ \
139
+ Get##_type(self, obj); \
140
+ if (orig_bn1 && !(bn1 = BN_dup(orig_bn1)) || \
141
+ orig_bn2 && !(bn2 = BN_dup(orig_bn2)) || \
142
+ orig_bn3 && !(bn3 = BN_dup(orig_bn3))) { \
143
+ BN_clear_free(bn1); \
144
+ BN_clear_free(bn2); \
145
+ BN_clear_free(bn3); \
146
+ ossl_raise(eBNError, NULL); \
147
+ } \
148
+ \
149
+ if (!_type##_set0_##_group(obj, bn1, bn2, bn3)) { \
150
+ BN_clear_free(bn1); \
151
+ BN_clear_free(bn2); \
152
+ BN_clear_free(bn3); \
153
+ ossl_raise(ePKeyError, #_type"_set0_"#_group); \
154
+ } \
155
+ return self; \
156
+ }
157
+
158
+ #define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
159
+ /* \
160
+ * call-seq: \
161
+ * _keytype##.set_##_group(a1, a2) -> self \
162
+ */ \
163
+ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
164
+ { \
165
+ _type *obj; \
166
+ BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\
167
+ BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\
168
+ \
169
+ Get##_type(self, obj); \
170
+ if (orig_bn1 && !(bn1 = BN_dup(orig_bn1)) || \
171
+ orig_bn2 && !(bn2 = BN_dup(orig_bn2))) { \
172
+ BN_clear_free(bn1); \
173
+ BN_clear_free(bn2); \
174
+ ossl_raise(eBNError, NULL); \
175
+ } \
176
+ \
177
+ if (!_type##_set0_##_group(obj, bn1, bn2)) { \
178
+ BN_clear_free(bn1); \
179
+ BN_clear_free(bn2); \
180
+ ossl_raise(ePKeyError, #_type"_set0_"#_group); \
181
+ } \
182
+ return self; \
183
+ }
184
+
185
+ #define OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, _name) \
186
+ /* \
187
+ * call-seq: \
188
+ * _keytype##.##_name = bn -> bn \
189
+ */ \
190
+ static VALUE ossl_##_keytype##_set_##_name(VALUE self, VALUE bignum) \
191
+ { \
192
+ _type *obj; \
193
+ BIGNUM *bn; \
194
+ \
195
+ rb_warning("#"#_name"= is deprecated; use #set_"#_group); \
196
+ Get##_type(self, obj); \
197
+ if (NIL_P(bignum)) { \
198
+ BN_clear_free(obj->_name); \
199
+ obj->_name = NULL; \
200
+ return Qnil; \
201
+ } \
202
+ \
203
+ bn = GetBNPtr(bignum); \
204
+ if (obj->_name == NULL) \
205
+ obj->_name = BN_new(); \
206
+ if (obj->_name == NULL) \
207
+ ossl_raise(eBNError, NULL); \
208
+ if (BN_copy(obj->_name, bn) == NULL) \
209
+ ossl_raise(eBNError, NULL); \
210
+ return bignum; \
211
+ }
212
+
213
+ #if defined(HAVE_OPAQUE_OPENSSL) /* OpenSSL 1.1.0 */
214
+ #define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \
215
+ OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \
216
+ OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3)
217
+
218
+ #define OSSL_PKEY_BN_DEF2(_keytype, _type, _group, a1, a2) \
219
+ OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \
220
+ OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2)
221
+
222
+ #define DEF_OSSL_PKEY_BN(class, keytype, name) \
223
+ rb_define_method((class), #name, ossl_##keytype##_get_##name, 0)
224
+
225
+ #else
226
+ #define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \
227
+ OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \
228
+ OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
229
+ OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a1) \
230
+ OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a2) \
231
+ OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a3)
232
+
233
+ #define OSSL_PKEY_BN_DEF2(_keytype, _type, _group, a1, a2) \
234
+ OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \
235
+ OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
236
+ OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a1) \
237
+ OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a2)
238
+
239
+ #define DEF_OSSL_PKEY_BN(class, keytype, name) do { \
240
+ rb_define_method((class), #name, ossl_##keytype##_get_##name, 0);\
241
+ rb_define_method((class), #name "=", ossl_##keytype##_set_##name, 1);\
242
+ } while (0)
243
+ #endif /* HAVE_OPAQUE_OPENSSL */
244
+
245
+ #endif /* _OSSL_PKEY_H_ */
@@ -0,0 +1,650 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licensed under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #include "ossl.h"
11
+
12
+ #if !defined(OPENSSL_NO_DH)
13
+
14
+ #define GetPKeyDH(obj, pkey) do { \
15
+ GetPKey((obj), (pkey)); \
16
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) { /* PARANOIA? */ \
17
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
18
+ } \
19
+ } while (0)
20
+ #define GetDH(obj, dh) do { \
21
+ EVP_PKEY *_pkey; \
22
+ GetPKeyDH((obj), _pkey); \
23
+ (dh) = EVP_PKEY_get0_DH(_pkey); \
24
+ } while (0)
25
+
26
+ /*
27
+ * Classes
28
+ */
29
+ VALUE cDH;
30
+ VALUE eDHError;
31
+
32
+ /*
33
+ * Public
34
+ */
35
+ static VALUE
36
+ dh_instance(VALUE klass, DH *dh)
37
+ {
38
+ EVP_PKEY *pkey;
39
+ VALUE obj;
40
+
41
+ if (!dh) {
42
+ return Qfalse;
43
+ }
44
+ obj = NewPKey(klass);
45
+ if (!(pkey = EVP_PKEY_new())) {
46
+ return Qfalse;
47
+ }
48
+ if (!EVP_PKEY_assign_DH(pkey, dh)) {
49
+ EVP_PKEY_free(pkey);
50
+ return Qfalse;
51
+ }
52
+ SetPKey(obj, pkey);
53
+
54
+ return obj;
55
+ }
56
+
57
+ VALUE
58
+ ossl_dh_new(EVP_PKEY *pkey)
59
+ {
60
+ VALUE obj;
61
+
62
+ if (!pkey) {
63
+ obj = dh_instance(cDH, DH_new());
64
+ } else {
65
+ obj = NewPKey(cDH);
66
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) {
67
+ ossl_raise(rb_eTypeError, "Not a DH key!");
68
+ }
69
+ SetPKey(obj, pkey);
70
+ }
71
+ if (obj == Qfalse) {
72
+ ossl_raise(eDHError, NULL);
73
+ }
74
+
75
+ return obj;
76
+ }
77
+
78
+ /*
79
+ * Private
80
+ */
81
+ struct dh_blocking_gen_arg {
82
+ DH *dh;
83
+ int size;
84
+ int gen;
85
+ BN_GENCB *cb;
86
+ int result;
87
+ };
88
+
89
+ static void *
90
+ dh_blocking_gen(void *arg)
91
+ {
92
+ struct dh_blocking_gen_arg *gen = (struct dh_blocking_gen_arg *)arg;
93
+ gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb);
94
+ return 0;
95
+ }
96
+
97
+ static DH *
98
+ dh_generate(int size, int gen)
99
+ {
100
+ struct ossl_generate_cb_arg cb_arg = { 0 };
101
+ struct dh_blocking_gen_arg gen_arg;
102
+ DH *dh = DH_new();
103
+ BN_GENCB *cb = BN_GENCB_new();
104
+
105
+ if (!dh || !cb) {
106
+ DH_free(dh);
107
+ BN_GENCB_free(cb);
108
+ return NULL;
109
+ }
110
+
111
+ if (rb_block_given_p())
112
+ cb_arg.yield = 1;
113
+ BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
114
+ gen_arg.dh = dh;
115
+ gen_arg.size = size;
116
+ gen_arg.gen = gen;
117
+ gen_arg.cb = cb;
118
+ if (cb_arg.yield == 1) {
119
+ /* we cannot release GVL when callback proc is supplied */
120
+ dh_blocking_gen(&gen_arg);
121
+ } else {
122
+ /* there's a chance to unblock */
123
+ rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
124
+ }
125
+
126
+ BN_GENCB_free(cb);
127
+ if (!gen_arg.result) {
128
+ DH_free(dh);
129
+ if (cb_arg.state) {
130
+ /* Clear OpenSSL error queue before re-raising. */
131
+ ossl_clear_error();
132
+ rb_jump_tag(cb_arg.state);
133
+ }
134
+ return NULL;
135
+ }
136
+
137
+ if (!DH_generate_key(dh)) {
138
+ DH_free(dh);
139
+ return NULL;
140
+ }
141
+
142
+ return dh;
143
+ }
144
+
145
+ /*
146
+ * call-seq:
147
+ * DH.generate(size [, generator]) -> dh
148
+ *
149
+ * Creates a new DH instance from scratch by generating the private and public
150
+ * components alike.
151
+ *
152
+ * === Parameters
153
+ * * +size+ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
154
+ * * +generator+ is a small number > 1, typically 2 or 5.
155
+ *
156
+ */
157
+ static VALUE
158
+ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
159
+ {
160
+ DH *dh ;
161
+ int g = 2;
162
+ VALUE size, gen, obj;
163
+
164
+ if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
165
+ g = NUM2INT(gen);
166
+ }
167
+ dh = dh_generate(NUM2INT(size), g);
168
+ obj = dh_instance(klass, dh);
169
+ if (obj == Qfalse) {
170
+ DH_free(dh);
171
+ ossl_raise(eDHError, NULL);
172
+ }
173
+
174
+ return obj;
175
+ }
176
+
177
+ /*
178
+ * call-seq:
179
+ * DH.new -> dh
180
+ * DH.new(string) -> dh
181
+ * DH.new(size [, generator]) -> dh
182
+ *
183
+ * Either generates a DH instance from scratch or by reading already existing
184
+ * DH parameters from +string+. Note that when reading a DH instance from
185
+ * data that was encoded from a DH instance by using DH#to_pem or DH#to_der
186
+ * the result will *not* contain a public/private key pair yet. This needs to
187
+ * be generated using DH#generate_key! first.
188
+ *
189
+ * === Parameters
190
+ * * +size+ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
191
+ * * +generator+ is a small number > 1, typically 2 or 5.
192
+ * * +string+ contains the DER or PEM encoded key.
193
+ *
194
+ * === Examples
195
+ * DH.new # -> dh
196
+ * DH.new(1024) # -> dh
197
+ * DH.new(1024, 5) # -> dh
198
+ * #Reading DH parameters
199
+ * dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
200
+ * dh.generate_key! # -> dh with public and private key
201
+ */
202
+ static VALUE
203
+ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
204
+ {
205
+ EVP_PKEY *pkey;
206
+ DH *dh;
207
+ int g = 2;
208
+ BIO *in;
209
+ VALUE arg, gen;
210
+
211
+ GetPKey(self, pkey);
212
+ if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
213
+ dh = DH_new();
214
+ }
215
+ else if (RB_INTEGER_TYPE_P(arg)) {
216
+ if (!NIL_P(gen)) {
217
+ g = NUM2INT(gen);
218
+ }
219
+ if (!(dh = dh_generate(NUM2INT(arg), g))) {
220
+ ossl_raise(eDHError, NULL);
221
+ }
222
+ }
223
+ else {
224
+ arg = ossl_to_der_if_possible(arg);
225
+ in = ossl_obj2bio(arg);
226
+ dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
227
+ if (!dh){
228
+ OSSL_BIO_reset(in);
229
+ dh = d2i_DHparams_bio(in, NULL);
230
+ }
231
+ BIO_free(in);
232
+ if (!dh) {
233
+ ossl_raise(eDHError, NULL);
234
+ }
235
+ }
236
+ if (!EVP_PKEY_assign_DH(pkey, dh)) {
237
+ DH_free(dh);
238
+ ossl_raise(eDHError, NULL);
239
+ }
240
+ return self;
241
+ }
242
+
243
+ static VALUE
244
+ ossl_dh_initialize_copy(VALUE self, VALUE other)
245
+ {
246
+ EVP_PKEY *pkey;
247
+ DH *dh, *dh_other;
248
+ const BIGNUM *pub, *priv;
249
+
250
+ GetPKey(self, pkey);
251
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
252
+ ossl_raise(eDHError, "DH already initialized");
253
+ GetDH(other, dh_other);
254
+
255
+ dh = DHparams_dup(dh_other);
256
+ if (!dh)
257
+ ossl_raise(eDHError, "DHparams_dup");
258
+ EVP_PKEY_assign_DH(pkey, dh);
259
+
260
+ DH_get0_key(dh_other, &pub, &priv);
261
+ if (pub) {
262
+ BIGNUM *pub2 = BN_dup(pub);
263
+ BIGNUM *priv2 = BN_dup(priv);
264
+
265
+ if (!pub2 || priv && !priv2) {
266
+ BN_clear_free(pub2);
267
+ BN_clear_free(priv2);
268
+ ossl_raise(eDHError, "BN_dup");
269
+ }
270
+ DH_set0_key(dh, pub2, priv2);
271
+ }
272
+
273
+ return self;
274
+ }
275
+
276
+ /*
277
+ * call-seq:
278
+ * dh.public? -> true | false
279
+ *
280
+ * Indicates whether this DH instance has a public key associated with it or
281
+ * not. The public key may be retrieved with DH#pub_key.
282
+ */
283
+ static VALUE
284
+ ossl_dh_is_public(VALUE self)
285
+ {
286
+ DH *dh;
287
+ const BIGNUM *bn;
288
+
289
+ GetDH(self, dh);
290
+ DH_get0_key(dh, &bn, NULL);
291
+
292
+ return bn ? Qtrue : Qfalse;
293
+ }
294
+
295
+ /*
296
+ * call-seq:
297
+ * dh.private? -> true | false
298
+ *
299
+ * Indicates whether this DH instance has a private key associated with it or
300
+ * not. The private key may be retrieved with DH#priv_key.
301
+ */
302
+ static VALUE
303
+ ossl_dh_is_private(VALUE self)
304
+ {
305
+ DH *dh;
306
+ const BIGNUM *bn;
307
+
308
+ GetDH(self, dh);
309
+ DH_get0_key(dh, NULL, &bn);
310
+
311
+ #if !defined(OPENSSL_NO_ENGINE)
312
+ return (bn || DH_get0_engine(dh)) ? Qtrue : Qfalse;
313
+ #else
314
+ return bn ? Qtrue : Qfalse;
315
+ #endif
316
+ }
317
+
318
+ /*
319
+ * call-seq:
320
+ * dh.export -> aString
321
+ * dh.to_pem -> aString
322
+ * dh.to_s -> aString
323
+ *
324
+ * Encodes this DH to its PEM encoding. Note that any existing per-session
325
+ * public/private keys will *not* get encoded, just the Diffie-Hellman
326
+ * parameters will be encoded.
327
+ */
328
+ static VALUE
329
+ ossl_dh_export(VALUE self)
330
+ {
331
+ DH *dh;
332
+ BIO *out;
333
+ VALUE str;
334
+
335
+ GetDH(self, dh);
336
+ if (!(out = BIO_new(BIO_s_mem()))) {
337
+ ossl_raise(eDHError, NULL);
338
+ }
339
+ if (!PEM_write_bio_DHparams(out, dh)) {
340
+ BIO_free(out);
341
+ ossl_raise(eDHError, NULL);
342
+ }
343
+ str = ossl_membio2str(out);
344
+
345
+ return str;
346
+ }
347
+
348
+ /*
349
+ * call-seq:
350
+ * dh.to_der -> aString
351
+ *
352
+ * Encodes this DH to its DER encoding. Note that any existing per-session
353
+ * public/private keys will *not* get encoded, just the Diffie-Hellman
354
+ * parameters will be encoded.
355
+
356
+ */
357
+ static VALUE
358
+ ossl_dh_to_der(VALUE self)
359
+ {
360
+ DH *dh;
361
+ unsigned char *p;
362
+ long len;
363
+ VALUE str;
364
+
365
+ GetDH(self, dh);
366
+ if((len = i2d_DHparams(dh, NULL)) <= 0)
367
+ ossl_raise(eDHError, NULL);
368
+ str = rb_str_new(0, len);
369
+ p = (unsigned char *)RSTRING_PTR(str);
370
+ if(i2d_DHparams(dh, &p) < 0)
371
+ ossl_raise(eDHError, NULL);
372
+ ossl_str_adjust(str, p);
373
+
374
+ return str;
375
+ }
376
+
377
+ /*
378
+ * call-seq:
379
+ * dh.params -> hash
380
+ *
381
+ * Stores all parameters of key to the hash
382
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
383
+ * Don't use :-)) (I's up to you)
384
+ */
385
+ static VALUE
386
+ ossl_dh_get_params(VALUE self)
387
+ {
388
+ DH *dh;
389
+ VALUE hash;
390
+ const BIGNUM *p, *q, *g, *pub_key, *priv_key;
391
+
392
+ GetDH(self, dh);
393
+ DH_get0_pqg(dh, &p, &q, &g);
394
+ DH_get0_key(dh, &pub_key, &priv_key);
395
+
396
+ hash = rb_hash_new();
397
+ rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
398
+ rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
399
+ rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
400
+ rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
401
+ rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
402
+
403
+ return hash;
404
+ }
405
+
406
+ /*
407
+ * call-seq:
408
+ * dh.to_text -> aString
409
+ *
410
+ * Prints all parameters of key to buffer
411
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
412
+ * Don't use :-)) (I's up to you)
413
+ */
414
+ static VALUE
415
+ ossl_dh_to_text(VALUE self)
416
+ {
417
+ DH *dh;
418
+ BIO *out;
419
+ VALUE str;
420
+
421
+ GetDH(self, dh);
422
+ if (!(out = BIO_new(BIO_s_mem()))) {
423
+ ossl_raise(eDHError, NULL);
424
+ }
425
+ if (!DHparams_print(out, dh)) {
426
+ BIO_free(out);
427
+ ossl_raise(eDHError, NULL);
428
+ }
429
+ str = ossl_membio2str(out);
430
+
431
+ return str;
432
+ }
433
+
434
+ /*
435
+ * call-seq:
436
+ * dh.public_key -> aDH
437
+ *
438
+ * Returns a new DH instance that carries just the public information, i.e.
439
+ * the prime +p+ and the generator +g+, but no public/private key yet. Such
440
+ * a pair may be generated using DH#generate_key!. The "public key" needed
441
+ * for a key exchange with DH#compute_key is considered as per-session
442
+ * information and may be retrieved with DH#pub_key once a key pair has
443
+ * been generated.
444
+ * If the current instance already contains private information (and thus a
445
+ * valid public/private key pair), this information will no longer be present
446
+ * in the new instance generated by DH#public_key. This feature is helpful for
447
+ * publishing the Diffie-Hellman parameters without leaking any of the private
448
+ * per-session information.
449
+ *
450
+ * === Example
451
+ * dh = OpenSSL::PKey::DH.new(2048) # has public and private key set
452
+ * public_key = dh.public_key # contains only prime and generator
453
+ * parameters = public_key.to_der # it's safe to publish this
454
+ */
455
+ static VALUE
456
+ ossl_dh_to_public_key(VALUE self)
457
+ {
458
+ DH *orig_dh, *dh;
459
+ VALUE obj;
460
+
461
+ GetDH(self, orig_dh);
462
+ dh = DHparams_dup(orig_dh); /* err check perfomed by dh_instance */
463
+ obj = dh_instance(CLASS_OF(self), dh);
464
+ if (obj == Qfalse) {
465
+ DH_free(dh);
466
+ ossl_raise(eDHError, NULL);
467
+ }
468
+
469
+ return obj;
470
+ }
471
+
472
+ /*
473
+ * call-seq:
474
+ * dh.params_ok? -> true | false
475
+ *
476
+ * Validates the Diffie-Hellman parameters associated with this instance.
477
+ * It checks whether a safe prime and a suitable generator are used. If this
478
+ * is not the case, +false+ is returned.
479
+ */
480
+ static VALUE
481
+ ossl_dh_check_params(VALUE self)
482
+ {
483
+ DH *dh;
484
+ int codes;
485
+
486
+ GetDH(self, dh);
487
+ if (!DH_check(dh, &codes)) {
488
+ return Qfalse;
489
+ }
490
+
491
+ return codes == 0 ? Qtrue : Qfalse;
492
+ }
493
+
494
+ /*
495
+ * call-seq:
496
+ * dh.generate_key! -> self
497
+ *
498
+ * Generates a private and public key unless a private key already exists.
499
+ * If this DH instance was generated from public DH parameters (e.g. by
500
+ * encoding the result of DH#public_key), then this method needs to be
501
+ * called first in order to generate the per-session keys before performing
502
+ * the actual key exchange.
503
+ *
504
+ * === Example
505
+ * dh = OpenSSL::PKey::DH.new(2048)
506
+ * public_key = dh.public_key #contains no private/public key yet
507
+ * public_key.generate_key!
508
+ * puts public_key.private? # => true
509
+ */
510
+ static VALUE
511
+ ossl_dh_generate_key(VALUE self)
512
+ {
513
+ DH *dh;
514
+
515
+ GetDH(self, dh);
516
+ if (!DH_generate_key(dh))
517
+ ossl_raise(eDHError, "Failed to generate key");
518
+ return self;
519
+ }
520
+
521
+ /*
522
+ * call-seq:
523
+ * dh.compute_key(pub_bn) -> aString
524
+ *
525
+ * Returns a String containing a shared secret computed from the other party's public value.
526
+ * See DH_compute_key() for further information.
527
+ *
528
+ * === Parameters
529
+ * * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by
530
+ * DH#public_key as that contains the DH parameters only.
531
+ */
532
+ static VALUE
533
+ ossl_dh_compute_key(VALUE self, VALUE pub)
534
+ {
535
+ DH *dh;
536
+ const BIGNUM *pub_key, *dh_p;
537
+ VALUE str;
538
+ int len;
539
+
540
+ GetDH(self, dh);
541
+ DH_get0_pqg(dh, &dh_p, NULL, NULL);
542
+ if (!dh_p)
543
+ ossl_raise(eDHError, "incomplete DH");
544
+ pub_key = GetBNPtr(pub);
545
+ len = DH_size(dh);
546
+ str = rb_str_new(0, len);
547
+ if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
548
+ ossl_raise(eDHError, NULL);
549
+ }
550
+ rb_str_set_len(str, len);
551
+
552
+ return str;
553
+ }
554
+
555
+ /*
556
+ * Document-method: OpenSSL::PKey::DH#set_pqg
557
+ * call-seq:
558
+ * dh.set_pqg(p, q, g) -> self
559
+ *
560
+ * Sets +p+, +q+, +g+ for the DH instance.
561
+ */
562
+ OSSL_PKEY_BN_DEF3(dh, DH, pqg, p, q, g)
563
+ /*
564
+ * Document-method: OpenSSL::PKey::DH#set_key
565
+ * call-seq:
566
+ * dh.set_key(pub_key, priv_key) -> self
567
+ *
568
+ * Sets +pub_key+ and +priv_key+ for the DH instance. +priv_key+ may be nil.
569
+ */
570
+ OSSL_PKEY_BN_DEF2(dh, DH, key, pub_key, priv_key)
571
+
572
+ /*
573
+ * INIT
574
+ */
575
+ void
576
+ Init_ossl_dh(void)
577
+ {
578
+ #if 0
579
+ mPKey = rb_define_module_under(mOSSL, "PKey");
580
+ cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
581
+ ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
582
+ #endif
583
+
584
+ /* Document-class: OpenSSL::PKey::DHError
585
+ *
586
+ * Generic exception that is raised if an operation on a DH PKey
587
+ * fails unexpectedly or in case an instantiation of an instance of DH
588
+ * fails due to non-conformant input data.
589
+ */
590
+ eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
591
+ /* Document-class: OpenSSL::PKey::DH
592
+ *
593
+ * An implementation of the Diffie-Hellman key exchange protocol based on
594
+ * discrete logarithms in finite fields, the same basis that DSA is built
595
+ * on.
596
+ *
597
+ * === Accessor methods for the Diffie-Hellman parameters
598
+ * DH#p::
599
+ * The prime (an OpenSSL::BN) of the Diffie-Hellman parameters.
600
+ * DH#g::
601
+ * The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters.
602
+ * DH#pub_key::
603
+ * The per-session public key (an OpenSSL::BN) matching the private key.
604
+ * This needs to be passed to DH#compute_key.
605
+ * DH#priv_key::
606
+ * The per-session private key, an OpenSSL::BN.
607
+ *
608
+ * === Example of a key exchange
609
+ * dh1 = OpenSSL::PKey::DH.new(2048)
610
+ * der = dh1.public_key.to_der #you may send this publicly to the participating party
611
+ * dh2 = OpenSSL::PKey::DH.new(der)
612
+ * dh2.generate_key! #generate the per-session key pair
613
+ * symm_key1 = dh1.compute_key(dh2.pub_key)
614
+ * symm_key2 = dh2.compute_key(dh1.pub_key)
615
+ *
616
+ * puts symm_key1 == symm_key2 # => true
617
+ */
618
+ cDH = rb_define_class_under(mPKey, "DH", cPKey);
619
+ rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
620
+ rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
621
+ rb_define_copy_func(cDH, ossl_dh_initialize_copy);
622
+ rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
623
+ rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
624
+ rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
625
+ rb_define_method(cDH, "export", ossl_dh_export, 0);
626
+ rb_define_alias(cDH, "to_pem", "export");
627
+ rb_define_alias(cDH, "to_s", "export");
628
+ rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
629
+ rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
630
+ rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
631
+ rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
632
+ rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
633
+
634
+ DEF_OSSL_PKEY_BN(cDH, dh, p);
635
+ DEF_OSSL_PKEY_BN(cDH, dh, q);
636
+ DEF_OSSL_PKEY_BN(cDH, dh, g);
637
+ DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
638
+ DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
639
+ rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3);
640
+ rb_define_method(cDH, "set_key", ossl_dh_set_key, 2);
641
+
642
+ rb_define_method(cDH, "params", ossl_dh_get_params, 0);
643
+ }
644
+
645
+ #else /* defined NO_DH */
646
+ void
647
+ Init_ossl_dh(void)
648
+ {
649
+ }
650
+ #endif /* NO_DH */