rubysl-openssl 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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);