rubysl-openssl 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -6
  3. data/ext/rubysl/openssl/.gitignore +3 -0
  4. data/ext/rubysl/openssl/deprecation.rb +21 -0
  5. data/ext/rubysl/openssl/extconf.rb +45 -32
  6. data/ext/rubysl/openssl/openssl_missing.c +20 -7
  7. data/ext/rubysl/openssl/openssl_missing.h +22 -15
  8. data/ext/rubysl/openssl/ossl.c +610 -61
  9. data/ext/rubysl/openssl/ossl.h +31 -17
  10. data/ext/rubysl/openssl/ossl_asn1.c +974 -183
  11. data/ext/rubysl/openssl/ossl_asn1.h +3 -3
  12. data/ext/rubysl/openssl/ossl_bio.c +4 -3
  13. data/ext/rubysl/openssl/ossl_bio.h +1 -1
  14. data/ext/rubysl/openssl/ossl_bn.c +32 -28
  15. data/ext/rubysl/openssl/ossl_bn.h +1 -1
  16. data/ext/rubysl/openssl/ossl_cipher.c +494 -93
  17. data/ext/rubysl/openssl/ossl_cipher.h +1 -1
  18. data/ext/rubysl/openssl/ossl_config.c +4 -5
  19. data/ext/rubysl/openssl/ossl_config.h +1 -1
  20. data/ext/rubysl/openssl/ossl_digest.c +206 -24
  21. data/ext/rubysl/openssl/ossl_digest.h +1 -1
  22. data/ext/rubysl/openssl/ossl_engine.c +48 -26
  23. data/ext/rubysl/openssl/ossl_engine.h +1 -1
  24. data/ext/rubysl/openssl/ossl_hmac.c +40 -38
  25. data/ext/rubysl/openssl/ossl_hmac.h +1 -1
  26. data/ext/rubysl/openssl/ossl_ns_spki.c +157 -25
  27. data/ext/rubysl/openssl/ossl_ns_spki.h +1 -1
  28. data/ext/rubysl/openssl/ossl_ocsp.c +57 -40
  29. data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
  30. data/ext/rubysl/openssl/ossl_pkcs12.c +15 -13
  31. data/ext/rubysl/openssl/ossl_pkcs12.h +1 -1
  32. data/ext/rubysl/openssl/ossl_pkcs5.c +108 -18
  33. data/ext/rubysl/openssl/ossl_pkcs7.c +44 -37
  34. data/ext/rubysl/openssl/ossl_pkcs7.h +1 -1
  35. data/ext/rubysl/openssl/ossl_pkey.c +211 -15
  36. data/ext/rubysl/openssl/ossl_pkey.h +19 -9
  37. data/ext/rubysl/openssl/ossl_pkey_dh.c +180 -47
  38. data/ext/rubysl/openssl/ossl_pkey_dsa.c +184 -47
  39. data/ext/rubysl/openssl/ossl_pkey_ec.c +177 -93
  40. data/ext/rubysl/openssl/ossl_pkey_rsa.c +209 -102
  41. data/ext/rubysl/openssl/ossl_rand.c +15 -15
  42. data/ext/rubysl/openssl/ossl_rand.h +1 -1
  43. data/ext/rubysl/openssl/ossl_ssl.c +939 -192
  44. data/ext/rubysl/openssl/ossl_ssl.h +6 -6
  45. data/ext/rubysl/openssl/ossl_ssl_session.c +78 -62
  46. data/ext/rubysl/openssl/ossl_version.h +2 -2
  47. data/ext/rubysl/openssl/ossl_x509.c +1 -1
  48. data/ext/rubysl/openssl/ossl_x509.h +1 -1
  49. data/ext/rubysl/openssl/ossl_x509attr.c +20 -19
  50. data/ext/rubysl/openssl/ossl_x509cert.c +169 -67
  51. data/ext/rubysl/openssl/ossl_x509crl.c +41 -39
  52. data/ext/rubysl/openssl/ossl_x509ext.c +51 -38
  53. data/ext/rubysl/openssl/ossl_x509name.c +139 -29
  54. data/ext/rubysl/openssl/ossl_x509req.c +42 -40
  55. data/ext/rubysl/openssl/ossl_x509revoked.c +20 -20
  56. data/ext/rubysl/openssl/ossl_x509store.c +99 -47
  57. data/ext/rubysl/openssl/ruby_missing.h +3 -16
  58. data/lib/openssl/bn.rb +19 -19
  59. data/lib/openssl/buffering.rb +222 -14
  60. data/lib/openssl/cipher.rb +20 -20
  61. data/lib/openssl/config.rb +1 -4
  62. data/lib/openssl/digest.rb +47 -19
  63. data/lib/openssl/ssl.rb +197 -1
  64. data/lib/openssl/x509.rb +162 -1
  65. data/lib/rubysl/openssl.rb +4 -8
  66. data/lib/rubysl/openssl/version.rb +1 -1
  67. data/rubysl-openssl.gemspec +1 -2
  68. metadata +16 -34
  69. data/ext/rubysl/openssl/extconf.h +0 -50
  70. data/lib/openssl/net/ftptls.rb +0 -53
  71. data/lib/openssl/net/telnets.rb +0 -251
  72. data/lib/openssl/pkcs7.rb +0 -25
  73. data/lib/openssl/ssl-internal.rb +0 -187
  74. data/lib/openssl/x509-internal.rb +0 -153
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl_pkcs7.c 28367 2010-06-21 09:18:59Z shyouhei $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' project
4
4
  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
5
  * All rights reserved.
@@ -11,64 +11,64 @@
11
11
  #include "ossl.h"
12
12
 
13
13
  #define WrapPKCS7(klass, obj, pkcs7) do { \
14
- if (!pkcs7) { \
14
+ if (!(pkcs7)) { \
15
15
  ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
16
16
  } \
17
- obj = Data_Wrap_Struct(klass, 0, PKCS7_free, pkcs7); \
17
+ (obj) = Data_Wrap_Struct((klass), 0, PKCS7_free, (pkcs7)); \
18
18
  } while (0)
19
19
  #define GetPKCS7(obj, pkcs7) do { \
20
- Data_Get_Struct(obj, PKCS7, pkcs7); \
21
- if (!pkcs7) { \
20
+ Data_Get_Struct((obj), PKCS7, (pkcs7)); \
21
+ if (!(pkcs7)) { \
22
22
  ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
23
23
  } \
24
24
  } while (0)
25
25
  #define SafeGetPKCS7(obj, pkcs7) do { \
26
- OSSL_Check_Kind(obj, cPKCS7); \
27
- GetPKCS7(obj, pkcs7); \
26
+ OSSL_Check_Kind((obj), cPKCS7); \
27
+ GetPKCS7((obj), (pkcs7)); \
28
28
  } while (0)
29
29
 
30
30
  #define WrapPKCS7si(klass, obj, p7si) do { \
31
- if (!p7si) { \
31
+ if (!(p7si)) { \
32
32
  ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
33
33
  } \
34
- obj = Data_Wrap_Struct(klass, 0, PKCS7_SIGNER_INFO_free, p7si); \
34
+ (obj) = Data_Wrap_Struct((klass), 0, PKCS7_SIGNER_INFO_free, (p7si)); \
35
35
  } while (0)
36
36
  #define GetPKCS7si(obj, p7si) do { \
37
- Data_Get_Struct(obj, PKCS7_SIGNER_INFO, p7si); \
38
- if (!p7si) { \
37
+ Data_Get_Struct((obj), PKCS7_SIGNER_INFO, (p7si)); \
38
+ if (!(p7si)) { \
39
39
  ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
40
40
  } \
41
41
  } while (0)
42
42
  #define SafeGetPKCS7si(obj, p7si) do { \
43
- OSSL_Check_Kind(obj, cPKCS7Signer); \
44
- GetPKCS7si(obj, p7si); \
43
+ OSSL_Check_Kind((obj), cPKCS7Signer); \
44
+ GetPKCS7si((obj), (p7si)); \
45
45
  } while (0)
46
46
 
47
47
  #define WrapPKCS7ri(klass, obj, p7ri) do { \
48
- if (!p7ri) { \
48
+ if (!(p7ri)) { \
49
49
  ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
50
50
  } \
51
- obj = Data_Wrap_Struct(klass, 0, PKCS7_RECIP_INFO_free, p7ri); \
51
+ (obj) = Data_Wrap_Struct((klass), 0, PKCS7_RECIP_INFO_free, (p7ri)); \
52
52
  } while (0)
53
53
  #define GetPKCS7ri(obj, p7ri) do { \
54
- Data_Get_Struct(obj, PKCS7_RECIP_INFO, p7ri); \
55
- if (!p7ri) { \
54
+ Data_Get_Struct((obj), PKCS7_RECIP_INFO, (p7ri)); \
55
+ if (!(p7ri)) { \
56
56
  ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
57
57
  } \
58
58
  } while (0)
59
59
  #define SafeGetPKCS7ri(obj, p7ri) do { \
60
- OSSL_Check_Kind(obj, cPKCS7Recipient); \
61
- GetPKCS7ri(obj, p7ri); \
60
+ OSSL_Check_Kind((obj), cPKCS7Recipient); \
61
+ GetPKCS7ri((obj), (p7ri)); \
62
62
  } while (0)
63
63
 
64
- #define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
64
+ #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
65
65
 
66
66
  #define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v))
67
67
  #define ossl_pkcs7_get_data(o) rb_iv_get((o), "@data")
68
68
  #define ossl_pkcs7_set_err_string(o,v) rb_iv_set((o), "@error_string", (v))
69
69
  #define ossl_pkcs7_get_err_string(o) rb_iv_get((o), "@error_string")
70
70
 
71
- /*
71
+ /*
72
72
  * Classes
73
73
  */
74
74
  VALUE cPKCS7;
@@ -97,7 +97,7 @@ static PKCS7_SIGNER_INFO *
97
97
  DupPKCS7SignerPtr(VALUE obj)
98
98
  {
99
99
  PKCS7_SIGNER_INFO *p7si, *pkcs7;
100
-
100
+
101
101
  SafeGetPKCS7si(obj, p7si);
102
102
  if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) {
103
103
  ossl_raise(ePKCS7Error, NULL);
@@ -123,7 +123,7 @@ static PKCS7_RECIP_INFO *
123
123
  DupPKCS7RecipientPtr(VALUE obj)
124
124
  {
125
125
  PKCS7_RECIP_INFO *p7ri, *pkcs7;
126
-
126
+
127
127
  SafeGetPKCS7ri(obj, p7ri);
128
128
  if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) {
129
129
  ossl_raise(ePKCS7Error, NULL);
@@ -295,7 +295,7 @@ ossl_pkcs7_alloc(VALUE klass)
295
295
  ossl_raise(ePKCS7Error, NULL);
296
296
  }
297
297
  WrapPKCS7(klass, obj, pkcs7);
298
-
298
+
299
299
  return obj;
300
300
  }
301
301
 
@@ -309,7 +309,7 @@ ossl_pkcs7_alloc(VALUE klass)
309
309
  static VALUE
310
310
  ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
311
311
  {
312
- PKCS7 *p7;
312
+ PKCS7 *p7, *pkcs = DATA_PTR(self);
313
313
  BIO *in;
314
314
  VALUE arg;
315
315
 
@@ -317,11 +317,18 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
317
317
  return self;
318
318
  arg = ossl_to_der_if_possible(arg);
319
319
  in = ossl_obj2bio(arg);
320
- p7 = PEM_read_bio_PKCS7(in, (PKCS7 **)&DATA_PTR(self), NULL, NULL);
320
+ p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL);
321
321
  if (!p7) {
322
- BIO_reset(in);
323
- p7 = d2i_PKCS7_bio(in, (PKCS7 **)&DATA_PTR(self));
322
+ OSSL_BIO_reset(in);
323
+ p7 = d2i_PKCS7_bio(in, &pkcs);
324
+ if (!p7) {
325
+ BIO_free(in);
326
+ PKCS7_free(pkcs);
327
+ DATA_PTR(self) = NULL;
328
+ ossl_raise(rb_eArgError, "Could not parse the PKCS7");
329
+ }
324
330
  }
331
+ DATA_PTR(self) = pkcs;
325
332
  BIO_free(in);
326
333
  ossl_pkcs7_set_data(self, Qnil);
327
334
  ossl_pkcs7_set_err_string(self, Qnil);
@@ -493,7 +500,7 @@ ossl_pkcs7_get_signer(VALUE self)
493
500
  PKCS7_SIGNER_INFO *si;
494
501
  int num, i;
495
502
  VALUE ary;
496
-
503
+
497
504
  GetPKCS7(self, pkcs7);
498
505
  if (!(sk = PKCS7_get_signer_info(pkcs7))) {
499
506
  OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
@@ -535,7 +542,7 @@ ossl_pkcs7_get_recipient(VALUE self)
535
542
  PKCS7_RECIP_INFO *si;
536
543
  int num, i;
537
544
  VALUE ary;
538
-
545
+
539
546
  GetPKCS7(self, pkcs7);
540
547
  if (PKCS7_type_is_enveloped(pkcs7))
541
548
  sk = pkcs7->d.enveloped->recipientinfo;
@@ -775,7 +782,7 @@ ossl_pkcs7_add_data(VALUE self, VALUE data)
775
782
  }
776
783
  if(!PKCS7_dataFinal(pkcs7, out)) goto err;
777
784
  ossl_pkcs7_set_data(self, Qnil);
778
-
785
+
779
786
  err:
780
787
  BIO_free(out);
781
788
  BIO_free(in);
@@ -798,7 +805,7 @@ ossl_pkcs7_to_der(VALUE self)
798
805
  if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
799
806
  ossl_raise(ePKCS7Error, NULL);
800
807
  str = rb_str_new(0, len);
801
- p = RSTRING_PTR(str);
808
+ p = (unsigned char *)RSTRING_PTR(str);
802
809
  if(i2d_PKCS7(pkcs7, &p) <= 0)
803
810
  ossl_raise(ePKCS7Error, NULL);
804
811
  ossl_str_adjust(str, p);
@@ -812,7 +819,7 @@ ossl_pkcs7_to_pem(VALUE self)
812
819
  PKCS7 *pkcs7;
813
820
  BIO *out;
814
821
  VALUE str;
815
-
822
+
816
823
  GetPKCS7(self, pkcs7);
817
824
  if (!(out = BIO_new(BIO_s_mem()))) {
818
825
  ossl_raise(ePKCS7Error, NULL);
@@ -887,9 +894,9 @@ ossl_pkcs7si_get_signed_time(VALUE self)
887
894
  {
888
895
  PKCS7_SIGNER_INFO *p7si;
889
896
  ASN1_TYPE *asn1obj;
890
-
897
+
891
898
  GetPKCS7si(self, p7si);
892
-
899
+
893
900
  if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) {
894
901
  ossl_raise(ePKCS7Error, NULL);
895
902
  }
@@ -1019,10 +1026,10 @@ Init_ossl_pkcs7()
1019
1026
 
1020
1027
  cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject);
1021
1028
  rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
1022
- rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
1029
+ rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
1023
1030
  rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
1024
1031
  rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
1025
- rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
1032
+ rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
1026
1033
 
1027
1034
  #define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
1028
1035
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl_pkcs7.h 12496 2007-06-08 15:02:04Z technorama $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' project
4
4
  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
5
  * All rights reserved.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl_pkey.c 28004 2010-05-24 23:58:49Z shyouhei $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' project
4
4
  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
5
  * All rights reserved.
@@ -33,6 +33,42 @@ ossl_generate_cb(int p, int n, void *arg)
33
33
  rb_yield(ary);
34
34
  }
35
35
 
36
+ #if HAVE_BN_GENCB
37
+ /* OpenSSL 2nd version of GN generation callback */
38
+ int
39
+ ossl_generate_cb_2(int p, int n, BN_GENCB *cb)
40
+ {
41
+ VALUE ary;
42
+ struct ossl_generate_cb_arg *arg;
43
+ int state;
44
+
45
+ arg = (struct ossl_generate_cb_arg *)cb->arg;
46
+ if (arg->yield) {
47
+ ary = rb_ary_new2(2);
48
+ rb_ary_store(ary, 0, INT2NUM(p));
49
+ rb_ary_store(ary, 1, INT2NUM(n));
50
+
51
+ /*
52
+ * can be break by raising exception or 'break'
53
+ */
54
+ rb_protect(rb_yield, ary, &state);
55
+ if (state) {
56
+ arg->stop = 1;
57
+ arg->state = state;
58
+ }
59
+ }
60
+ if (arg->stop) return 0;
61
+ return 1;
62
+ }
63
+
64
+ void
65
+ ossl_generate_cb_stop(void *ptr)
66
+ {
67
+ struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr;
68
+ arg->stop = 1;
69
+ }
70
+ #endif
71
+
36
72
  /*
37
73
  * Public
38
74
  */
@@ -62,7 +98,8 @@ ossl_pkey_new(EVP_PKEY *pkey)
62
98
  default:
63
99
  ossl_raise(ePKeyError, "unsupported key type");
64
100
  }
65
- return Qnil; /* not reached */
101
+
102
+ UNREACHABLE;
66
103
  }
67
104
 
68
105
  VALUE
@@ -75,6 +112,7 @@ ossl_pkey_new_from_file(VALUE filename)
75
112
  if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
76
113
  ossl_raise(ePKeyError, "%s", strerror(errno));
77
114
  }
115
+ rb_update_max_fd(fileno(fp));
78
116
 
79
117
  pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
80
118
  fclose(fp);
@@ -85,6 +123,53 @@ ossl_pkey_new_from_file(VALUE filename)
85
123
  return ossl_pkey_new(pkey);
86
124
  }
87
125
 
126
+ /*
127
+ * call-seq:
128
+ * OpenSSL::PKey.read(string [, pwd ] ) -> PKey
129
+ * OpenSSL::PKey.read(file [, pwd ]) -> PKey
130
+ *
131
+ * === Parameters
132
+ * * +string+ is a DER- or PEM-encoded string containing an arbitrary private
133
+ * or public key.
134
+ * * +file+ is an instance of +File+ containing a DER- or PEM-encoded
135
+ * arbitrary private or public key.
136
+ * * +pwd+ is an optional password in case +string+ or +file+ is an encrypted
137
+ * PEM resource.
138
+ */
139
+ static VALUE
140
+ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
141
+ {
142
+ EVP_PKEY *pkey;
143
+ BIO *bio;
144
+ VALUE data, pass;
145
+ char *passwd = NULL;
146
+
147
+ rb_scan_args(argc, argv, "11", &data, &pass);
148
+
149
+ bio = ossl_obj2bio(data);
150
+ if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
151
+ OSSL_BIO_reset(bio);
152
+ if (!NIL_P(pass)) {
153
+ passwd = StringValuePtr(pass);
154
+ }
155
+ if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, passwd))) {
156
+ OSSL_BIO_reset(bio);
157
+ if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) {
158
+ OSSL_BIO_reset(bio);
159
+ if (!NIL_P(pass)) {
160
+ passwd = StringValuePtr(pass);
161
+ }
162
+ pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, passwd);
163
+ }
164
+ }
165
+ }
166
+
167
+ BIO_free(bio);
168
+ if (!pkey)
169
+ ossl_raise(rb_eArgError, "Could not parse PKey");
170
+ return ossl_pkey_new(pkey);
171
+ }
172
+
88
173
  EVP_PKEY *
89
174
  GetPKeyPtr(VALUE obj)
90
175
  {
@@ -99,7 +184,7 @@ EVP_PKEY *
99
184
  GetPrivPKeyPtr(VALUE obj)
100
185
  {
101
186
  EVP_PKEY *pkey;
102
-
187
+
103
188
  if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
104
189
  ossl_raise(rb_eArgError, "Private key is needed.");
105
190
  }
@@ -112,7 +197,7 @@ EVP_PKEY *
112
197
  DupPKeyPtr(VALUE obj)
113
198
  {
114
199
  EVP_PKEY *pkey;
115
-
200
+
116
201
  SafeGetPKey(obj, pkey);
117
202
  CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
118
203
 
@@ -123,7 +208,7 @@ EVP_PKEY *
123
208
  DupPrivPKeyPtr(VALUE obj)
124
209
  {
125
210
  EVP_PKEY *pkey;
126
-
211
+
127
212
  if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
128
213
  ossl_raise(rb_eArgError, "Private key is needed.");
129
214
  }
@@ -150,6 +235,13 @@ ossl_pkey_alloc(VALUE klass)
150
235
  return obj;
151
236
  }
152
237
 
238
+ /*
239
+ * call-seq:
240
+ * PKeyClass.new -> self
241
+ *
242
+ * Because PKey is an abstract class, actually calling this method explicitly
243
+ * will raise a +NotImplementedError+.
244
+ */
153
245
  static VALUE
154
246
  ossl_pkey_initialize(VALUE self)
155
247
  {
@@ -159,12 +251,29 @@ ossl_pkey_initialize(VALUE self)
159
251
  return self;
160
252
  }
161
253
 
254
+ /*
255
+ * call-seq:
256
+ * pkey.sign(digest, data) -> String
257
+ *
258
+ * To sign the +String+ +data+, +digest+, an instance of OpenSSL::Digest, must
259
+ * be provided. The return value is again a +String+ containing the signature.
260
+ * A PKeyError is raised should errors occur.
261
+ * Any previous state of the +Digest+ instance is irrelevant to the signature
262
+ * outcome, the digest instance is reset to its initial state during the
263
+ * operation.
264
+ *
265
+ * == Example
266
+ * data = 'Sign me!'
267
+ * digest = OpenSSL::Digest::SHA256.new
268
+ * pkey = OpenSSL::PKey::RSA.new(2048)
269
+ * signature = pkey.sign(digest, data)
270
+ */
162
271
  static VALUE
163
272
  ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
164
273
  {
165
274
  EVP_PKEY *pkey;
166
275
  EVP_MD_CTX ctx;
167
- int buf_len;
276
+ unsigned int buf_len;
168
277
  VALUE str;
169
278
 
170
279
  if (rb_funcall(self, id_private_q, 0, NULL) != Qtrue) {
@@ -175,7 +284,7 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
175
284
  StringValue(data);
176
285
  EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
177
286
  str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
178
- if (!EVP_SignFinal(&ctx, RSTRING_PTR(str), &buf_len, pkey))
287
+ if (!EVP_SignFinal(&ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey))
179
288
  ossl_raise(ePKeyError, NULL);
180
289
  assert((long)buf_len <= RSTRING_LEN(str));
181
290
  rb_str_set_len(str, buf_len);
@@ -183,6 +292,27 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
183
292
  return str;
184
293
  }
185
294
 
295
+ /*
296
+ * call-seq:
297
+ * pkey.verify(digest, signature, data) -> String
298
+ *
299
+ * To verify the +String+ +signature+, +digest+, an instance of
300
+ * OpenSSL::Digest, must be provided to re-compute the message digest of the
301
+ * original +data+, also a +String+. The return value is +true+ if the
302
+ * signature is valid, +false+ otherwise. A PKeyError is raised should errors
303
+ * occur.
304
+ * Any previous state of the +Digest+ instance is irrelevant to the validation
305
+ * outcome, the digest instance is reset to its initial state during the
306
+ * operation.
307
+ *
308
+ * == Example
309
+ * data = 'Sign me!'
310
+ * digest = OpenSSL::Digest::SHA256.new
311
+ * pkey = OpenSSL::PKey::RSA.new(2048)
312
+ * signature = pkey.sign(digest, data)
313
+ * pub_key = pkey.public_key
314
+ * puts pub_key.verify(digest, signature, data) # => true
315
+ */
186
316
  static VALUE
187
317
  ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
188
318
  {
@@ -194,7 +324,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
194
324
  StringValue(sig);
195
325
  StringValue(data);
196
326
  EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
197
- switch (EVP_VerifyFinal(&ctx, RSTRING_PTR(sig), RSTRING_LEN(sig), pkey)) {
327
+ switch (EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey)) {
198
328
  case 0:
199
329
  return Qfalse;
200
330
  case 1:
@@ -211,24 +341,90 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
211
341
  void
212
342
  Init_ossl_pkey()
213
343
  {
214
- #if 0 /* let rdoc know about mOSSL */
215
- mOSSL = rb_define_module("OpenSSL");
344
+ #if 0
345
+ mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
216
346
  #endif
217
-
347
+
348
+ /* Document-module: OpenSSL::PKey
349
+ *
350
+ * == Asymmetric Public Key Algorithms
351
+ *
352
+ * Asymmetric public key algorithms solve the problem of establishing and
353
+ * sharing secret keys to en-/decrypt messages. The key in such an
354
+ * algorithm consists of two parts: a public key that may be distributed
355
+ * to others and a private key that needs to remain secret.
356
+ *
357
+ * Messages encrypted with a public key can only be encrypted by
358
+ * recipients that are in possession of the associated private key.
359
+ * Since public key algorithms are considerably slower than symmetric
360
+ * key algorithms (cf. OpenSSL::Cipher) they are often used to establish
361
+ * a symmetric key shared between two parties that are in possession of
362
+ * each other's public key.
363
+ *
364
+ * Asymmetric algorithms offer a lot of nice features that are used in a
365
+ * lot of different areas. A very common application is the creation and
366
+ * validation of digital signatures. To sign a document, the signatory
367
+ * generally uses a message digest algorithm (cf. OpenSSL::Digest) to
368
+ * compute a digest of the document that is then encrypted (i.e. signed)
369
+ * using the private key. Anyone in possession of the public key may then
370
+ * verify the signature by computing the message digest of the original
371
+ * document on their own, decrypting the signature using the signatory's
372
+ * public key and comparing the result to the message digest they
373
+ * previously computed. The signature is valid if and only if the
374
+ * decrypted signature is equal to this message digest.
375
+ *
376
+ * The PKey module offers support for three popular public/private key
377
+ * algorithms:
378
+ * * RSA (OpenSSL::PKey::RSA)
379
+ * * DSA (OpenSSL::PKey::DSA)
380
+ * * Elliptic Curve Cryptography (OpenSSL::PKey::EC)
381
+ * Each of these implementations is in fact a sub-class of the abstract
382
+ * PKey class which offers the interface for supporting digital signatures
383
+ * in the form of PKey#sign and PKey#verify.
384
+ *
385
+ * == Diffie-Hellman Key Exchange
386
+ *
387
+ * Finally PKey also features OpenSSL::PKey::DH, an implementation of
388
+ * the Diffie-Hellman key exchange protocol based on discrete logarithms
389
+ * in finite fields, the same basis that DSA is built on.
390
+ * The Diffie-Hellman protocol can be used to exchange (symmetric) keys
391
+ * over insecure channels without needing any prior joint knowledge
392
+ * between the participating parties. As the security of DH demands
393
+ * relatively long "public keys" (i.e. the part that is overtly
394
+ * transmitted between participants) DH tends to be quite slow. If
395
+ * security or speed is your primary concern, OpenSSL::PKey::EC offers
396
+ * another implementation of the Diffie-Hellman protocol.
397
+ *
398
+ */
218
399
  mPKey = rb_define_module_under(mOSSL, "PKey");
219
-
400
+
401
+ /* Document-class: OpenSSL::PKey::PKeyError
402
+ *
403
+ *Raised when errors occur during PKey#sign or PKey#verify.
404
+ */
220
405
  ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
221
406
 
407
+ /* Document-class: OpenSSL::PKey::PKey
408
+ *
409
+ * An abstract class that bundles signature creation (PKey#sign) and
410
+ * validation (PKey#verify) that is common to all implementations except
411
+ * OpenSSL::PKey::DH
412
+ * * OpenSSL::PKey::RSA
413
+ * * OpenSSL::PKey::DSA
414
+ * * OpenSSL::PKey::EC
415
+ */
222
416
  cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
223
-
417
+
418
+ rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
419
+
224
420
  rb_define_alloc_func(cPKey, ossl_pkey_alloc);
225
421
  rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
226
422
 
227
423
  rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
228
424
  rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);
229
-
425
+
230
426
  id_private_q = rb_intern("private?");
231
-
427
+
232
428
  /*
233
429
  * INIT rsa, dsa, dh, ec
234
430
  */