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_asn1.h 11708 2007-02-12 23:01:19Z shyouhei $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' team members
4
4
  * Copyright (C) 2003
5
5
  * All rights reserved.
@@ -32,12 +32,12 @@ ASN1_INTEGER *num_to_asn1integer(VALUE, ASN1_INTEGER *);
32
32
  * ASN1 module
33
33
  */
34
34
  extern VALUE mASN1;
35
- extern VALUE eASN1Error;
35
+ extern VALUE eASN1Error;
36
36
 
37
37
  extern VALUE cASN1Data;
38
38
  extern VALUE cASN1Primitive;
39
39
  extern VALUE cASN1Constructive;
40
-
40
+
41
41
  extern VALUE cASN1Boolean; /* BOOLEAN */
42
42
  extern VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
43
43
  extern VALUE cASN1BitString; /* BIT STRING */
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl_bio.c 12496 2007-06-08 15:02:04Z technorama $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' team members
4
4
  * Copyright (C) 2003
5
5
  * All rights reserved.
@@ -28,6 +28,7 @@ ossl_obj2bio(VALUE obj)
28
28
  if ((fd = dup(FPTR_TO_FD(fptr))) < 0){
29
29
  rb_sys_fail(0);
30
30
  }
31
+ rb_update_max_fd(fd);
31
32
  if (!(fp = fdopen(fd, "r"))){
32
33
  close(fd);
33
34
  rb_sys_fail(0);
@@ -39,7 +40,7 @@ ossl_obj2bio(VALUE obj)
39
40
  }
40
41
  else {
41
42
  StringValue(obj);
42
- bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LEN(obj));
43
+ bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj));
43
44
  if (!bio) ossl_raise(eOSSLError, NULL);
44
45
  }
45
46
 
@@ -72,7 +73,7 @@ ossl_protect_membio2str(BIO *bio, int *status)
72
73
  return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str0, (VALUE)bio, status);
73
74
  }
74
75
 
75
- VALUE
76
+ VALUE
76
77
  ossl_membio2str(BIO *bio)
77
78
  {
78
79
  VALUE ret;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl_bio.h 11708 2007-02-12 23:01:19Z shyouhei $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' team members
4
4
  * Copyright (C) 2003
5
5
  * All rights reserved.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl_bn.c 31657 2011-05-20 22:25:35Z shyouhei $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' project
4
4
  * Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net>
5
5
  * All rights reserved.
@@ -12,22 +12,22 @@
12
12
  #include "ossl.h"
13
13
 
14
14
  #define WrapBN(klass, obj, bn) do { \
15
- if (!bn) { \
15
+ if (!(bn)) { \
16
16
  ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
17
17
  } \
18
- obj = Data_Wrap_Struct(klass, 0, BN_clear_free, bn); \
18
+ (obj) = Data_Wrap_Struct((klass), 0, BN_clear_free, (bn)); \
19
19
  } while (0)
20
20
 
21
21
  #define GetBN(obj, bn) do { \
22
- Data_Get_Struct(obj, BIGNUM, bn); \
23
- if (!bn) { \
22
+ Data_Get_Struct((obj), BIGNUM, (bn)); \
23
+ if (!(bn)) { \
24
24
  ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
25
25
  } \
26
26
  } while (0)
27
27
 
28
28
  #define SafeGetBN(obj, bn) do { \
29
- OSSL_Check_Kind(obj, cBN); \
30
- GetBN(obj, bn); \
29
+ OSSL_Check_Kind((obj), cBN); \
30
+ GetBN((obj), (bn)); \
31
31
  } while (0)
32
32
 
33
33
  /*
@@ -70,6 +70,8 @@ GetBNPtr(VALUE obj)
70
70
  }
71
71
  WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */
72
72
  break;
73
+ case T_NIL:
74
+ break;
73
75
  default:
74
76
  ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
75
77
  }
@@ -91,7 +93,7 @@ ossl_bn_alloc(VALUE klass)
91
93
  {
92
94
  BIGNUM *bn;
93
95
  VALUE obj;
94
-
96
+
95
97
  if (!(bn = BN_new())) {
96
98
  ossl_raise(eBNError, NULL);
97
99
  }
@@ -117,11 +119,11 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
117
119
  if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) {
118
120
  base = NUM2INT(bs);
119
121
  }
120
- StringValue(str);
121
- GetBN(self, bn);
122
+
122
123
  if (RTEST(rb_obj_is_kind_of(str, cBN))) {
123
124
  BIGNUM *other;
124
125
 
126
+ GetBN(self, bn);
125
127
  GetBN(str, other); /* Safe - we checked kind_of? above */
126
128
  if (!BN_copy(bn, other)) {
127
129
  ossl_raise(eBNError, NULL);
@@ -129,14 +131,16 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
129
131
  return self;
130
132
  }
131
133
 
134
+ StringValue(str);
135
+ GetBN(self, bn);
132
136
  switch (base) {
133
137
  case 0:
134
- if (!BN_mpi2bn(RSTRING_PTR(str), RSTRING_LEN(str), bn)) {
138
+ if (!BN_mpi2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) {
135
139
  ossl_raise(eBNError, NULL);
136
140
  }
137
141
  break;
138
142
  case 2:
139
- if (!BN_bin2bn(RSTRING_PTR(str), RSTRING_LEN(str), bn)) {
143
+ if (!BN_bin2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) {
140
144
  ossl_raise(eBNError, NULL);
141
145
  }
142
146
  break;
@@ -185,22 +189,22 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
185
189
  case 0:
186
190
  len = BN_bn2mpi(bn, NULL);
187
191
  str = rb_str_new(0, len);
188
- if (BN_bn2mpi(bn, RSTRING_PTR(str)) != len)
192
+ if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len)
189
193
  ossl_raise(eBNError, NULL);
190
194
  break;
191
195
  case 2:
192
196
  len = BN_num_bytes(bn);
193
197
  str = rb_str_new(0, len);
194
- if (BN_bn2bin(bn, RSTRING_PTR(str)) != len)
198
+ if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len)
195
199
  ossl_raise(eBNError, NULL);
196
200
  break;
197
201
  case 10:
198
202
  if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL);
199
- str = ossl_buf2str(buf, strlen(buf));
203
+ str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
200
204
  break;
201
205
  case 16:
202
206
  if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL);
203
- str = ossl_buf2str(buf, strlen(buf));
207
+ str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
204
208
  break;
205
209
  default:
206
210
  ossl_raise(rb_eArgError, "invalid radix %d", base);
@@ -380,7 +384,7 @@ ossl_bn_div(VALUE self, VALUE other)
380
384
  }
381
385
  WrapBN(CLASS_OF(self), obj1, r1);
382
386
  WrapBN(CLASS_OF(self), obj2, r2);
383
-
387
+
384
388
  return rb_ary_new3(2, obj1, obj2);
385
389
  }
386
390
 
@@ -573,7 +577,7 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
573
577
  VALUE vnum, vsafe, vadd, vrem, obj;
574
578
 
575
579
  rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem);
576
-
580
+
577
581
  num = NUM2INT(vnum);
578
582
 
579
583
  if (vsafe == Qfalse) {
@@ -591,7 +595,7 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
591
595
  ossl_raise(eBNError, NULL);
592
596
  }
593
597
  WrapBN(klass, obj, result);
594
-
598
+
595
599
  return obj;
596
600
  }
597
601
 
@@ -615,14 +619,14 @@ static VALUE
615
619
  ossl_bn_copy(VALUE self, VALUE other)
616
620
  {
617
621
  BIGNUM *bn1, *bn2;
618
-
622
+
619
623
  rb_check_frozen(self);
620
-
624
+
621
625
  if (self == other) return self;
622
-
626
+
623
627
  GetBN(self, bn1);
624
628
  bn2 = GetBNPtr(other);
625
-
629
+
626
630
  if (!BN_copy(bn1, bn2)) {
627
631
  ossl_raise(eBNError, NULL);
628
632
  }
@@ -731,8 +735,8 @@ ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
731
735
  void
732
736
  Init_ossl_bn()
733
737
  {
734
- #if 0 /* let rdoc know about mOSSL */
735
- mOSSL = rb_define_module("OpenSSL");
738
+ #if 0
739
+ mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
736
740
  #endif
737
741
 
738
742
  if (!(ossl_bn_ctx = BN_CTX_new())) {
@@ -745,7 +749,7 @@ Init_ossl_bn()
745
749
 
746
750
  rb_define_alloc_func(cBN, ossl_bn_alloc);
747
751
  rb_define_method(cBN, "initialize", ossl_bn_initialize, -1);
748
-
752
+
749
753
  rb_define_copy_func(cBN, ossl_bn_copy);
750
754
  rb_define_method(cBN, "copy", ossl_bn_copy, 1);
751
755
 
@@ -793,7 +797,7 @@ Init_ossl_bn()
793
797
  * value_one - DON'T IMPL.
794
798
  * set_word
795
799
  * get_word */
796
-
800
+
797
801
  rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1);
798
802
  rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1);
799
803
  rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1);
@@ -830,7 +834,7 @@ Init_ossl_bn()
830
834
  rb_define_alias(cBN, "to_int", "to_i");
831
835
  rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0);
832
836
  rb_define_method(cBN, "coerce", ossl_bn_coerce, 1);
833
-
837
+
834
838
  /*
835
839
  * TODO:
836
840
  * But how to: from_bin, from_mpi? PACK?
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl_bn.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.
@@ -10,17 +10,24 @@
10
10
  */
11
11
  #include "ossl.h"
12
12
 
13
+ #define WrapCipher(obj, klass, ctx) \
14
+ (obj) = Data_Wrap_Struct((klass), 0, ossl_cipher_free, (ctx))
13
15
  #define MakeCipher(obj, klass, ctx) \
14
- obj = Data_Make_Struct(klass, EVP_CIPHER_CTX, 0, ossl_cipher_free, ctx)
16
+ (obj) = Data_Make_Struct((klass), EVP_CIPHER_CTX, 0, ossl_cipher_free, (ctx))
17
+ #define AllocCipher(obj, ctx) \
18
+ memset(DATA_PTR(obj) = (ctx) = ALLOC(EVP_CIPHER_CTX), 0, sizeof(EVP_CIPHER_CTX))
19
+ #define GetCipherInit(obj, ctx) do { \
20
+ Data_Get_Struct((obj), EVP_CIPHER_CTX, (ctx)); \
21
+ } while (0)
15
22
  #define GetCipher(obj, ctx) do { \
16
- Data_Get_Struct(obj, EVP_CIPHER_CTX, ctx); \
17
- if (!ctx) { \
23
+ GetCipherInit((obj), (ctx)); \
24
+ if (!(ctx)) { \
18
25
  ossl_raise(rb_eRuntimeError, "Cipher not inititalized!"); \
19
26
  } \
20
27
  } while (0)
21
28
  #define SafeGetCipher(obj, ctx) do { \
22
- OSSL_Check_Kind(obj, cCipher); \
23
- GetCipher(obj, ctx); \
29
+ OSSL_Check_Kind((obj), cCipher); \
30
+ GetCipher((obj), (ctx)); \
24
31
  } while (0)
25
32
 
26
33
  /*
@@ -51,7 +58,7 @@ ossl_cipher_new(const EVP_CIPHER *cipher)
51
58
  EVP_CIPHER_CTX *ctx;
52
59
 
53
60
  ret = ossl_cipher_alloc(cCipher);
54
- GetCipher(ret, ctx);
61
+ AllocCipher(ret, ctx);
55
62
  EVP_CIPHER_CTX_init(ctx);
56
63
  if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
57
64
  ossl_raise(eCipherError, NULL);
@@ -67,19 +74,17 @@ ossl_cipher_free(EVP_CIPHER_CTX *ctx)
67
74
  {
68
75
  if (ctx) {
69
76
  EVP_CIPHER_CTX_cleanup(ctx);
70
- ruby_xfree(ctx);
77
+ ruby_xfree(ctx);
71
78
  }
72
79
  }
73
80
 
74
81
  static VALUE
75
82
  ossl_cipher_alloc(VALUE klass)
76
83
  {
77
- EVP_CIPHER_CTX *ctx;
78
84
  VALUE obj;
79
85
 
80
- MakeCipher(obj, klass, ctx);
81
- EVP_CIPHER_CTX_init(ctx);
82
-
86
+ WrapCipher(obj, klass, 0);
87
+
83
88
  return obj;
84
89
  }
85
90
 
@@ -97,26 +102,43 @@ ossl_cipher_initialize(VALUE self, VALUE str)
97
102
  EVP_CIPHER_CTX *ctx;
98
103
  const EVP_CIPHER *cipher;
99
104
  char *name;
105
+ unsigned char key[EVP_MAX_KEY_LENGTH];
100
106
 
101
107
  name = StringValuePtr(str);
102
- GetCipher(self, ctx);
108
+ GetCipherInit(self, ctx);
109
+ if (ctx) {
110
+ ossl_raise(rb_eRuntimeError, "Cipher already inititalized!");
111
+ }
112
+ AllocCipher(self, ctx);
113
+ EVP_CIPHER_CTX_init(ctx);
103
114
  if (!(cipher = EVP_get_cipherbyname(name))) {
104
115
  ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name);
105
116
  }
106
- if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
117
+ /*
118
+ * The EVP which has EVP_CIPH_RAND_KEY flag (such as DES3) allows
119
+ * uninitialized key, but other EVPs (such as AES) does not allow it.
120
+ * Calling EVP_CipherUpdate() without initializing key causes SEGV so we
121
+ * set the data filled with "\0" as the key by default.
122
+ */
123
+ memset(key, 0, EVP_MAX_KEY_LENGTH);
124
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, -1) != 1)
107
125
  ossl_raise(eCipherError, NULL);
108
126
 
109
127
  return self;
110
128
  }
129
+
111
130
  static VALUE
112
131
  ossl_cipher_copy(VALUE self, VALUE other)
113
132
  {
114
133
  EVP_CIPHER_CTX *ctx1, *ctx2;
115
-
134
+
116
135
  rb_check_frozen(self);
117
136
  if (self == other) return self;
118
137
 
119
- GetCipher(self, ctx1);
138
+ GetCipherInit(self, ctx1);
139
+ if (!ctx1) {
140
+ AllocCipher(self, ctx1);
141
+ }
120
142
  SafeGetCipher(other, ctx2);
121
143
  if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1)
122
144
  ossl_raise(eCipherError, NULL);
@@ -133,6 +155,7 @@ add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
133
155
  }
134
156
  #endif
135
157
 
158
+ #ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
136
159
  /*
137
160
  * call-seq:
138
161
  * Cipher.ciphers -> array[string...]
@@ -142,7 +165,6 @@ add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
142
165
  static VALUE
143
166
  ossl_s_ciphers(VALUE self)
144
167
  {
145
- #ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
146
168
  VALUE ary;
147
169
 
148
170
  ary = rb_ary_new();
@@ -151,15 +173,18 @@ ossl_s_ciphers(VALUE self)
151
173
  (void*)ary);
152
174
 
153
175
  return ary;
176
+ }
154
177
  #else
155
- rb_notimplement();
178
+ #define ossl_s_ciphers rb_f_notimplement
156
179
  #endif
157
- }
158
180
 
159
181
  /*
160
182
  * call-seq:
161
183
  * cipher.reset -> self
162
184
  *
185
+ * Fully resets the internal state of the Cipher. By using this, the same
186
+ * Cipher instance may be used several times for en- or decryption tasks.
187
+ *
163
188
  * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
164
189
  */
165
190
  static VALUE
@@ -170,7 +195,7 @@ ossl_cipher_reset(VALUE self)
170
195
  GetCipher(self, ctx);
171
196
  if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1)
172
197
  ossl_raise(eCipherError, NULL);
173
-
198
+
174
199
  return self;
175
200
  }
176
201
 
@@ -189,7 +214,7 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
189
214
  * keeping this behaviour for backward compatibility.
190
215
  */
191
216
  const char *cname = rb_class2name(rb_obj_class(self));
192
- rb_warn("argumtents for %s#encrypt and %s#decrypt were deprecated; "
217
+ rb_warn("arguments for %s#encrypt and %s#decrypt were deprecated; "
193
218
  "use %s#pkcs5_keyivgen to derive key and IV",
194
219
  cname, cname, cname);
195
220
  StringValue(pass);
@@ -204,7 +229,7 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
204
229
  else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv));
205
230
  }
206
231
  EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
207
- RSTRING_PTR(pass), RSTRING_LEN(pass), 1, key, NULL);
232
+ (unsigned char *)RSTRING_PTR(pass), RSTRING_LENINT(pass), 1, key, NULL);
208
233
  p_key = key;
209
234
  p_iv = iv;
210
235
  }
@@ -222,7 +247,10 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
222
247
  * call-seq:
223
248
  * cipher.encrypt -> self
224
249
  *
225
- * Make sure to call .encrypt or .decrypt before using any of the following methods:
250
+ * Initializes the Cipher for encryption.
251
+ *
252
+ * Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the
253
+ * following methods:
226
254
  * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
227
255
  *
228
256
  * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
@@ -237,7 +265,10 @@ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
237
265
  * call-seq:
238
266
  * cipher.decrypt -> self
239
267
  *
240
- * Make sure to call .encrypt or .decrypt before using any of the following methods:
268
+ * Initializes the Cipher for decryption.
269
+ *
270
+ * Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the
271
+ * following methods:
241
272
  * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
242
273
  *
243
274
  * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
@@ -252,11 +283,13 @@ ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
252
283
  * call-seq:
253
284
  * cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> nil
254
285
  *
255
- * Generates and sets the key/iv based on a password.
286
+ * Generates and sets the key/IV based on a password.
256
287
  *
257
- * WARNING: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40, or DES
258
- * with MD5 or SHA1. Using anything else (like AES) will generate the key/iv using an
259
- * OpenSSL specific method. Use a PKCS5 v2 key generation method instead.
288
+ * WARNING: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40,
289
+ * or DES with MD5 or SHA1. Using anything else (like AES) will generate the
290
+ * key/iv using an OpenSSL specific method. This method is deprecated and
291
+ * should no longer be used. Use a PKCS5 v2 key generation method from
292
+ * OpenSSL::PKCS5 instead.
260
293
  *
261
294
  * === Parameters
262
295
  * +salt+ must be an 8 byte string if provided.
@@ -280,14 +313,14 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
280
313
  if(!NIL_P(vsalt)){
281
314
  StringValue(vsalt);
282
315
  if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
283
- rb_raise(eCipherError, "salt must be an 8-octet string");
284
- salt = RSTRING_PTR(vsalt);
316
+ ossl_raise(eCipherError, "salt must be an 8-octet string");
317
+ salt = (unsigned char *)RSTRING_PTR(vsalt);
285
318
  }
286
319
  iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
287
320
  digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest);
288
321
  GetCipher(self, ctx);
289
322
  EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
290
- RSTRING_PTR(vpass), RSTRING_LEN(vpass), iter, key, iv);
323
+ (unsigned char *)RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter, key, iv);
291
324
  if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
292
325
  ossl_raise(eCipherError, NULL);
293
326
  OPENSSL_cleanse(key, sizeof key);
@@ -296,49 +329,33 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
296
329
  return Qnil;
297
330
  }
298
331
 
299
-
300
- /*
301
- * call-seq:
302
- * cipher << data -> string
303
- *
304
- * === Parameters
305
- * +data+ is a nonempty string.
306
- *
307
- * This method is deprecated and not available in 1.9.x or later.
308
- */
309
- static VALUE
310
- ossl_cipher_update_deprecated(VALUE self, VALUE data)
311
- {
312
- const char *cname;
313
-
314
- cname = rb_class2name(rb_obj_class(self));
315
- rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname);
316
- return rb_funcall(self, rb_intern("update"), 1, data);
317
- }
318
-
319
-
320
332
  /*
321
333
  * call-seq:
322
334
  * cipher.update(data [, buffer]) -> string or buffer
323
335
  *
336
+ * Encrypts data in a streaming fashion. Hand consecutive blocks of data
337
+ * to the +update+ method in order to encrypt it. Returns the encrypted
338
+ * data chunk. When done, the output of Cipher#final should be additionally
339
+ * added to the result.
340
+ *
324
341
  * === Parameters
325
342
  * +data+ is a nonempty string.
326
343
  * +buffer+ is an optional string to store the result.
327
344
  */
328
- static VALUE
345
+ static VALUE
329
346
  ossl_cipher_update(int argc, VALUE *argv, VALUE self)
330
347
  {
331
348
  EVP_CIPHER_CTX *ctx;
332
- char *in;
349
+ unsigned char *in;
333
350
  int in_len, out_len;
334
351
  VALUE data, str;
335
352
 
336
353
  rb_scan_args(argc, argv, "11", &data, &str);
337
354
 
338
355
  StringValue(data);
339
- in = RSTRING_PTR(data);
340
- if ((in_len = RSTRING_LEN(data)) == 0)
341
- rb_raise(rb_eArgError, "data must not be empty");
356
+ in = (unsigned char *)RSTRING_PTR(data);
357
+ if ((in_len = RSTRING_LENINT(data)) == 0)
358
+ ossl_raise(rb_eArgError, "data must not be empty");
342
359
  GetCipher(self, ctx);
343
360
  out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
344
361
 
@@ -349,7 +366,7 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
349
366
  rb_str_resize(str, out_len);
350
367
  }
351
368
 
352
- if (!EVP_CipherUpdate(ctx, RSTRING_PTR(str), &out_len, in, in_len))
369
+ if (!EVP_CipherUpdate(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
353
370
  ossl_raise(eCipherError, NULL);
354
371
  assert(out_len < RSTRING_LEN(str));
355
372
  rb_str_set_len(str, out_len);
@@ -359,13 +376,19 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
359
376
 
360
377
  /*
361
378
  * call-seq:
362
- * cipher.final -> aString
379
+ * cipher.final -> string
363
380
  *
364
- * Returns the remaining data held in the cipher object. Further calls to update() or final() will return garbage.
381
+ * Returns the remaining data held in the cipher object. Further calls to
382
+ * Cipher#update or Cipher#final will return garbage. This call should always
383
+ * be made as the last call of an encryption or decryption operation, after
384
+ * after having fed the entire plaintext or ciphertext to the Cipher instance.
365
385
  *
366
- * See EVP_CipherFinal_ex for further information.
386
+ * If an authenticated cipher was used, a CipherError is raised if the tag
387
+ * could not be authenticated successfully. Only call this method after
388
+ * setting the authentication tag and passing the entire contents of the
389
+ * ciphertext into the cipher.
367
390
  */
368
- static VALUE
391
+ static VALUE
369
392
  ossl_cipher_final(VALUE self)
370
393
  {
371
394
  EVP_CIPHER_CTX *ctx;
@@ -374,7 +397,7 @@ ossl_cipher_final(VALUE self)
374
397
 
375
398
  GetCipher(self, ctx);
376
399
  str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
377
- if (!EVP_CipherFinal_ex(ctx, RSTRING_PTR(str), &out_len))
400
+ if (!EVP_CipherFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), &out_len))
378
401
  ossl_raise(eCipherError, NULL);
379
402
  assert(out_len <= RSTRING_LEN(str));
380
403
  rb_str_set_len(str, out_len);
@@ -386,7 +409,8 @@ ossl_cipher_final(VALUE self)
386
409
  * call-seq:
387
410
  * cipher.name -> string
388
411
  *
389
- * Returns the name of the cipher which may differ slightly from the original name provided.
412
+ * Returns the name of the cipher which may differ slightly from the original
413
+ * name provided.
390
414
  */
391
415
  static VALUE
392
416
  ossl_cipher_name(VALUE self)
@@ -402,9 +426,12 @@ ossl_cipher_name(VALUE self)
402
426
  * call-seq:
403
427
  * cipher.key = string -> string
404
428
  *
405
- * Sets the cipher key.
429
+ * Sets the cipher key. To generate a key, you should either use a secure
430
+ * random byte string or, if the key is to be derived from a password, you
431
+ * should rely on PBKDF2 functionality provided by OpenSSL::PKCS5. To
432
+ * generate a secure random-based key, Cipher#random_key may be used.
406
433
  *
407
- * Only call this method after calling cipher.encrypt or cipher.decrypt.
434
+ * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
408
435
  */
409
436
  static VALUE
410
437
  ossl_cipher_set_key(VALUE self, VALUE key)
@@ -417,7 +444,7 @@ ossl_cipher_set_key(VALUE self, VALUE key)
417
444
  if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx))
418
445
  ossl_raise(eCipherError, "key length too short");
419
446
 
420
- if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING_PTR(key), NULL, -1) != 1)
447
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1)
421
448
  ossl_raise(eCipherError, NULL);
422
449
 
423
450
  return key;
@@ -427,9 +454,16 @@ ossl_cipher_set_key(VALUE self, VALUE key)
427
454
  * call-seq:
428
455
  * cipher.iv = string -> string
429
456
  *
430
- * Sets the cipher iv.
457
+ * Sets the cipher IV. Please note that since you should never be using ECB
458
+ * mode, an IV is always explicitly required and should be set prior to
459
+ * encryption. The IV itself can be safely transmitted in public, but it
460
+ * should be unpredictable to prevent certain kinds of attacks. You may use
461
+ * Cipher#random_iv to create a secure random IV.
431
462
  *
432
- * Only call this method after calling cipher.encrypt or cipher.decrypt.
463
+ * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
464
+ *
465
+ * If not explicitly set, the OpenSSL default of an all-zeroes ("\\0") IV is
466
+ * used.
433
467
  */
434
468
  static VALUE
435
469
  ossl_cipher_set_iv(VALUE self, VALUE iv)
@@ -442,19 +476,189 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
442
476
  if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx))
443
477
  ossl_raise(eCipherError, "iv length too short");
444
478
 
445
- if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING_PTR(iv), -1) != 1)
479
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (unsigned char *)RSTRING_PTR(iv), -1) != 1)
446
480
  ossl_raise(eCipherError, NULL);
447
481
 
448
482
  return iv;
449
483
  }
450
484
 
485
+ #ifdef HAVE_AUTHENTICATED_ENCRYPTION
486
+ /*
487
+ * call-seq:
488
+ * cipher.auth_data = string -> string
489
+ *
490
+ * Sets the cipher's additional authenticated data. This field must be
491
+ * set when using AEAD cipher modes such as GCM or CCM. If no associated
492
+ * data shall be used, this method must *still* be called with a value of "".
493
+ * The contents of this field should be non-sensitive data which will be
494
+ * added to the ciphertext to generate the authentication tag which validates
495
+ * the contents of the ciphertext.
496
+ *
497
+ * The AAD must be set prior to encryption or decryption. In encryption mode,
498
+ * it must be set after calling Cipher#encrypt and setting Cipher#key= and
499
+ * Cipher#iv=. When decrypting, the authenticated data must be set after key,
500
+ * iv and especially *after* the authentication tag has been set. I.e. set it
501
+ * only after calling Cipher#decrypt, Cipher#key=, Cipher#iv= and
502
+ * Cipher#auth_tag= first.
503
+ */
504
+ static VALUE
505
+ ossl_cipher_set_auth_data(VALUE self, VALUE data)
506
+ {
507
+ EVP_CIPHER_CTX *ctx;
508
+ unsigned char *in;
509
+ int in_len;
510
+ int out_len;
511
+
512
+ StringValue(data);
513
+
514
+ in = (unsigned char *) RSTRING_PTR(data);
515
+ in_len = RSTRING_LENINT(data);
516
+
517
+ GetCipher(self, ctx);
518
+
519
+ if (!EVP_CipherUpdate(ctx, NULL, &out_len, in, in_len))
520
+ ossl_raise(eCipherError, "couldn't set additional authenticated data");
521
+
522
+ return data;
523
+ }
524
+
525
+ #define ossl_is_gcm(nid) (nid) == NID_aes_128_gcm || \
526
+ (nid) == NID_aes_192_gcm || \
527
+ (nid) == NID_aes_256_gcm
528
+
529
+ static VALUE
530
+ ossl_get_gcm_auth_tag(EVP_CIPHER_CTX *ctx, int len)
531
+ {
532
+ unsigned char *tag;
533
+ VALUE ret;
534
+
535
+ tag = ALLOC_N(unsigned char, len);
536
+
537
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, len, tag))
538
+ ossl_raise(eCipherError, "retrieving the authentication tag failed");
539
+
540
+ ret = rb_str_new((const char *) tag, len);
541
+ xfree(tag);
542
+ return ret;
543
+ }
544
+
545
+ /*
546
+ * call-seq:
547
+ * cipher.auth_tag([ tag_len ] -> string
548
+ *
549
+ * Gets the authentication tag generated by Authenticated Encryption Cipher
550
+ * modes (GCM for example). This tag may be stored along with the ciphertext,
551
+ * then set on the decryption cipher to authenticate the contents of the
552
+ * ciphertext against changes. If the optional integer parameter +tag_len+ is
553
+ * given, the returned tag will be +tag_len+ bytes long. If the parameter is
554
+ * omitted, the maximum length of 16 bytes will be returned. For maximum
555
+ * security, the default of 16 bytes should be chosen.
556
+ *
557
+ * The tag may only be retrieved after calling Cipher#final.
558
+ */
559
+ static VALUE
560
+ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
561
+ {
562
+ VALUE vtag_len;
563
+ EVP_CIPHER_CTX *ctx;
564
+ int nid, tag_len;
565
+
566
+ if (rb_scan_args(argc, argv, "01", &vtag_len) == 0) {
567
+ tag_len = 16;
568
+ } else {
569
+ tag_len = NUM2INT(vtag_len);
570
+ }
571
+
572
+ GetCipher(self, ctx);
573
+ nid = EVP_CIPHER_CTX_nid(ctx);
574
+
575
+ if (ossl_is_gcm(nid)) {
576
+ return ossl_get_gcm_auth_tag(ctx, tag_len);
577
+ } else {
578
+ ossl_raise(eCipherError, "authentication tag not supported by this cipher");
579
+ return Qnil; /* dummy */
580
+ }
581
+ }
582
+
583
+ static inline void
584
+ ossl_set_gcm_auth_tag(EVP_CIPHER_CTX *ctx, unsigned char *tag, int tag_len)
585
+ {
586
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_len, tag))
587
+ ossl_raise(eCipherError, "unable to set GCM tag");
588
+ }
589
+
590
+ /*
591
+ * call-seq:
592
+ * cipher.auth_tag = string -> string
593
+ *
594
+ * Sets the authentication tag to verify the contents of the
595
+ * ciphertext. The tag must be set after calling Cipher#decrypt,
596
+ * Cipher#key= and Cipher#iv=, but before assigning the associated
597
+ * authenticated data using Cipher#auth_data= and of course, before
598
+ * decrypting any of the ciphertext. After all decryption is
599
+ * performed, the tag is verified automatically in the call to
600
+ * Cipher#final.
601
+ */
602
+ static VALUE
603
+ ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
604
+ {
605
+ EVP_CIPHER_CTX *ctx;
606
+ int nid;
607
+ unsigned char *tag;
608
+ int tag_len;
609
+
610
+ StringValue(vtag);
611
+ tag = (unsigned char *) RSTRING_PTR(vtag);
612
+ tag_len = RSTRING_LENINT(vtag);
613
+
614
+ GetCipher(self, ctx);
615
+ nid = EVP_CIPHER_CTX_nid(ctx);
616
+
617
+ if (ossl_is_gcm(nid)) {
618
+ ossl_set_gcm_auth_tag(ctx, tag, tag_len);
619
+ } else {
620
+ ossl_raise(eCipherError, "authentication tag not supported by this cipher");
621
+ }
622
+
623
+ return vtag;
624
+ }
625
+
626
+ /*
627
+ * call-seq:
628
+ * cipher.authenticated? -> boolean
629
+ *
630
+ * Indicated whether this Cipher instance uses an Authenticated Encryption
631
+ * mode.
632
+ */
633
+ static VALUE
634
+ ossl_cipher_is_authenticated(VALUE self)
635
+ {
636
+ EVP_CIPHER_CTX *ctx;
637
+ int nid;
638
+
639
+ GetCipher(self, ctx);
640
+ nid = EVP_CIPHER_CTX_nid(ctx);
641
+
642
+ if (ossl_is_gcm(nid)) {
643
+ return Qtrue;
644
+ } else {
645
+ return Qfalse;
646
+ }
647
+ }
648
+ #else
649
+ #define ossl_cipher_set_auth_data rb_f_notimplement
650
+ #define ossl_cipher_get_auth_tag rb_f_notimplement
651
+ #define ossl_cipher_set_auth_tag rb_f_notimplement
652
+ #define ossl_cipher_is_authenticated rb_f_notimplement
653
+ #endif
451
654
 
452
655
  /*
453
656
  * call-seq:
454
- * cipher.key_length = integer -> integer
657
+ * cipher.key_len = integer -> integer
455
658
  *
456
- * Sets the key length of the cipher. If the cipher is a fixed length cipher then attempting to set the key
457
- * length to any value other than the fixed value is an error.
659
+ * Sets the key length of the cipher. If the cipher is a fixed length cipher
660
+ * then attempting to set the key length to any value other than the fixed
661
+ * value is an error.
458
662
  *
459
663
  * Under normal circumstances you do not need to call this method (and probably shouldn't).
460
664
  *
@@ -465,7 +669,7 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
465
669
  {
466
670
  int len = NUM2INT(key_length);
467
671
  EVP_CIPHER_CTX *ctx;
468
-
672
+
469
673
  GetCipher(self, ctx);
470
674
  if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
471
675
  ossl_raise(eCipherError, NULL);
@@ -473,6 +677,7 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
473
677
  return key_length;
474
678
  }
475
679
 
680
+ #if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING)
476
681
  /*
477
682
  * call-seq:
478
683
  * cipher.padding = integer -> integer
@@ -486,18 +691,17 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
486
691
  static VALUE
487
692
  ossl_cipher_set_padding(VALUE self, VALUE padding)
488
693
  {
489
- #if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING)
490
694
  EVP_CIPHER_CTX *ctx;
491
695
  int pad = NUM2INT(padding);
492
696
 
493
697
  GetCipher(self, ctx);
494
698
  if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1)
495
699
  ossl_raise(eCipherError, NULL);
496
- #else
497
- rb_notimplement();
498
- #endif
499
700
  return padding;
500
701
  }
702
+ #else
703
+ #define ossl_cipher_set_padding rb_f_notimplement
704
+ #endif
501
705
 
502
706
  #define CIPHER_0ARG_INT(func) \
503
707
  static VALUE \
@@ -507,40 +711,236 @@ ossl_cipher_set_padding(VALUE self, VALUE padding)
507
711
  GetCipher(self, ctx); \
508
712
  return INT2NUM(EVP_CIPHER_##func(EVP_CIPHER_CTX_cipher(ctx))); \
509
713
  }
510
- CIPHER_0ARG_INT(key_length)
511
- CIPHER_0ARG_INT(iv_length)
512
- CIPHER_0ARG_INT(block_size)
513
714
 
514
- #if 0
515
715
  /*
516
716
  * call-seq:
517
- * cipher.key_length -> integer
717
+ * cipher.key_len -> integer
518
718
  *
719
+ * Returns the key length in bytes of the Cipher.
519
720
  */
520
- static VALUE ossl_cipher_key_length() { }
721
+ CIPHER_0ARG_INT(key_length)
521
722
  /*
522
723
  * call-seq:
523
- * cipher.iv_length -> integer
724
+ * cipher.iv_len -> integer
524
725
  *
726
+ * Returns the expected length in bytes for an IV for this Cipher.
525
727
  */
526
- static VALUE ossl_cipher_iv_length() { }
728
+ CIPHER_0ARG_INT(iv_length)
527
729
  /*
528
730
  * call-seq:
529
731
  * cipher.block_size -> integer
530
732
  *
733
+ * Returns the size in bytes of the blocks on which this Cipher operates on.
531
734
  */
532
- static VALUE ossl_cipher_block_size() { }
533
- #endif
735
+ CIPHER_0ARG_INT(block_size)
534
736
 
535
737
  /*
536
738
  * INIT
537
739
  */
538
- void
740
+ void
539
741
  Init_ossl_cipher(void)
540
742
  {
541
- #if 0 /* let rdoc know about mOSSL */
542
- mOSSL = rb_define_module("OpenSSL");
743
+ #if 0
744
+ mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
543
745
  #endif
746
+
747
+ /* Document-class: OpenSSL::Cipher
748
+ *
749
+ * Provides symmetric algorithms for encryption and decryption. The
750
+ * algorithms that are available depend on the particular version
751
+ * of OpenSSL that is installed.
752
+ *
753
+ * === Listing all supported algorithms
754
+ *
755
+ * A list of supported algorithms can be obtained by
756
+ *
757
+ * puts OpenSSL::Cipher.ciphers
758
+ *
759
+ * === Instantiating a Cipher
760
+ *
761
+ * There are several ways to create a Cipher instance. Generally, a
762
+ * Cipher algorithm is categorized by its name, the key length in bits
763
+ * and the cipher mode to be used. The most generic way to create a
764
+ * Cipher is the following
765
+ *
766
+ * cipher = OpenSSL::Cipher.new('<name>-<key length>-<mode>')
767
+ *
768
+ * That is, a string consisting of the hyphenated concatenation of the
769
+ * individual components name, key length and mode. Either all uppercase
770
+ * or all lowercase strings may be used, for example:
771
+ *
772
+ * cipher = OpenSSL::Cipher.new('AES-128-CBC')
773
+ *
774
+ * For each algorithm supported, there is a class defined under the
775
+ * Cipher class that goes by the name of the cipher, e.g. to obtain an
776
+ * instance of AES, you could also use
777
+ *
778
+ * # these are equivalent
779
+ * cipher = OpenSSL::Cipher::AES.new(128, :CBC)
780
+ * cipher = OpenSSL::Cipher::AES.new(128, 'CBC')
781
+ * cipher = OpenSSL::Cipher::AES.new('128-CBC')
782
+ *
783
+ * Finally, due to its wide-spread use, there are also extra classes
784
+ * defined for the different key sizes of AES
785
+ *
786
+ * cipher = OpenSSL::Cipher::AES128.new(:CBC)
787
+ * cipher = OpenSSL::Cipher::AES192.new(:CBC)
788
+ * cipher = OpenSSL::Cipher::AES256.new(:CBC)
789
+ *
790
+ * === Choosing either encryption or decryption mode
791
+ *
792
+ * Encryption and decryption are often very similar operations for
793
+ * symmetric algorithms, this is reflected by not having to choose
794
+ * different classes for either operation, both can be done using the
795
+ * same class. Still, after obtaining a Cipher instance, we need to
796
+ * tell the instance what it is that we intend to do with it, so we
797
+ * need to call either
798
+ *
799
+ * cipher.encrypt
800
+ *
801
+ * or
802
+ *
803
+ * cipher.decrypt
804
+ *
805
+ * on the Cipher instance. This should be the first call after creating
806
+ * the instance, otherwise configuration that has already been set could
807
+ * get lost in the process.
808
+ *
809
+ * === Choosing a key
810
+ *
811
+ * Symmetric encryption requires a key that is the same for the encrypting
812
+ * and for the decrypting party and after initial key establishment should
813
+ * be kept as private information. There are a lot of ways to create
814
+ * insecure keys, the most notable is to simply take a password as the key
815
+ * without processing the password further. A simple and secure way to
816
+ * create a key for a particular Cipher is
817
+ *
818
+ * cipher = OpenSSL::AES256.new(:CFB)
819
+ * cipher.encrypt
820
+ * key = cipher.random_key # also sets the generated key on the Cipher
821
+ *
822
+ * If you absolutely need to use passwords as encryption keys, you
823
+ * should use Password-Based Key Derivation Function 2 (PBKDF2) by
824
+ * generating the key with the help of the functionality provided by
825
+ * OpenSSL::PKCS5.pbkdf2_hmac_sha1 or OpenSSL::PKCS5.pbkdf2_hmac.
826
+ *
827
+ * Although there is Cipher#pkcs5_keyivgen, its use is deprecated and
828
+ * it should only be used in legacy applications because it does not use
829
+ * the newer PKCS#5 v2 algorithms.
830
+ *
831
+ * === Choosing an IV
832
+ *
833
+ * The cipher modes CBC, CFB, OFB and CTR all need an "initialization
834
+ * vector", or short, IV. ECB mode is the only mode that does not require
835
+ * an IV, but there is almost no legitimate use case for this mode
836
+ * because of the fact that it does not sufficiently hide plaintext
837
+ * patterns. Therefore
838
+ *
839
+ * <b>You should never use ECB mode unless you are absolutely sure that
840
+ * you absolutely need it</b>
841
+ *
842
+ * Because of this, you will end up with a mode that explicitly requires
843
+ * an IV in any case. Note that for backwards compatibility reasons,
844
+ * setting an IV is not explicitly mandated by the Cipher API. If not
845
+ * set, OpenSSL itself defaults to an all-zeroes IV ("\\0", not the
846
+ * character). Although the IV can be seen as public information, i.e.
847
+ * it may be transmitted in public once generated, it should still stay
848
+ * unpredictable to prevent certain kinds of attacks. Therefore, ideally
849
+ *
850
+ * <b>Always create a secure random IV for every encryption of your
851
+ * Cipher</b>
852
+ *
853
+ * A new, random IV should be created for every encryption of data. Think
854
+ * of the IV as a nonce (number used once) - it's public but random and
855
+ * unpredictable. A secure random IV can be created as follows
856
+ *
857
+ * cipher = ...
858
+ * cipher.encrypt
859
+ * key = cipher.random_key
860
+ * iv = cipher.random_iv # also sets the generated IV on the Cipher
861
+ *
862
+ * Although the key is generally a random value, too, it is a bad choice
863
+ * as an IV. There are elaborate ways how an attacker can take advantage
864
+ * of such an IV. As a general rule of thumb, exposing the key directly
865
+ * or indirectly should be avoided at all cost and exceptions only be
866
+ * made with good reason.
867
+ *
868
+ * === Calling Cipher#final
869
+ *
870
+ * ECB (which should not be used) and CBC are both block-based modes.
871
+ * This means that unlike for the other streaming-based modes, they
872
+ * operate on fixed-size blocks of data, and therefore they require a
873
+ * "finalization" step to produce or correctly decrypt the last block of
874
+ * data by appropriately handling some form of padding. Therefore it is
875
+ * essential to add the output of OpenSSL::Cipher#final to your
876
+ * encryption/decryption buffer or you will end up with decryption errors
877
+ * or truncated data.
878
+ *
879
+ * Although this is not really necessary for streaming-mode ciphers, it is
880
+ * still recommended to apply the same pattern of adding the output of
881
+ * Cipher#final there as well - it also enables you to switch between
882
+ * modes more easily in the future.
883
+ *
884
+ * === Encrypting and decrypting some data
885
+ *
886
+ * data = "Very, very confidential data"
887
+ *
888
+ * cipher = OpenSSL::Cipher::AES.new(128, :CBC)
889
+ * cipher.encrypt
890
+ * key = cipher.random_key
891
+ * iv = cipher.random_iv
892
+ *
893
+ * encrypted = cipher.update(data) + cipher.final
894
+ * ...
895
+ * decipher = OpenSSL::Cipher::AES.new(128, :CBC)
896
+ * decipher.decrypt
897
+ * decipher.key = key
898
+ * decipher.iv = iv
899
+ *
900
+ * plain = decipher.update(encrypted) + decipher.final
901
+ *
902
+ * puts data == plain #=> true
903
+ *
904
+ * === Authenticated Encryption and Associated Data (AEAD)
905
+ *
906
+ * If the OpenSSL version used supports it, an Authenticated Encryption
907
+ * mode (such as GCM or CCM) should always be preferred over any
908
+ * unauthenticated mode. Currently, OpenSSL supports AE only in combination
909
+ * with Associated Data (AEAD) where additional associated data is included
910
+ * in the encryption process to compute a tag at the end of the encryption.
911
+ * This tag will also be used in the decryption process and by verifying
912
+ * its validity, the authenticity of a given ciphertext is established.
913
+ *
914
+ * This is superior to unauthenticated modes in that it allows to detect
915
+ * if somebody effectively changed the ciphertext after it had been
916
+ * encrypted. This prevents malicious modifications of the ciphertext that
917
+ * could otherwise be exploited to modify ciphertexts in ways beneficial to
918
+ * potential attackers.
919
+ *
920
+ * If no associated data is needed for encryption and later decryption,
921
+ * the OpenSSL library still requires a value to be set - "" may be used in
922
+ * case none is available. An example using the GCM (Galois Counter Mode):
923
+ *
924
+ * cipher = OpenSSL::Cipher::AES.new(128, :GCM)
925
+ * cipher.encrypt
926
+ * key = cipher.random_key
927
+ * iv = cipher.random_iv
928
+ * cipher.auth_data = ""
929
+ *
930
+ * encrypted = cipher.update(data) + cipher.final
931
+ * tag = cipher.auth_tag
932
+ *
933
+ * decipher = OpenSSL::Cipher::AES.new(128, :GCM)
934
+ * decipher.decrypt
935
+ * decipher.key = key
936
+ * decipher.iv = iv
937
+ * decipher.auth_tag = tag
938
+ * decipher.auth_data = ""
939
+ *
940
+ * plain = decipher.update(encrypted) + decipher.final
941
+ *
942
+ * puts data == plain #=> true
943
+ */
544
944
  cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
545
945
  eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
546
946
 
@@ -553,12 +953,13 @@ Init_ossl_cipher(void)
553
953
  rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
554
954
  rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
555
955
  rb_define_method(cCipher, "update", ossl_cipher_update, -1);
556
- #if RUBY_VERSION_CODE < 190
557
- rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1);
558
- #endif
559
956
  rb_define_method(cCipher, "final", ossl_cipher_final, 0);
560
957
  rb_define_method(cCipher, "name", ossl_cipher_name, 0);
561
958
  rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1);
959
+ rb_define_method(cCipher, "auth_data=", ossl_cipher_set_auth_data, 1);
960
+ rb_define_method(cCipher, "auth_tag=", ossl_cipher_set_auth_tag, 1);
961
+ rb_define_method(cCipher, "auth_tag", ossl_cipher_get_auth_tag, -1);
962
+ rb_define_method(cCipher, "authenticated?", ossl_cipher_is_authenticated, 0);
562
963
  rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1);
563
964
  rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0);
564
965
  rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1);