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.
- checksums.yaml +4 -4
- data/.travis.yml +5 -6
- data/ext/rubysl/openssl/.gitignore +3 -0
- data/ext/rubysl/openssl/deprecation.rb +21 -0
- data/ext/rubysl/openssl/extconf.rb +45 -32
- data/ext/rubysl/openssl/openssl_missing.c +20 -7
- data/ext/rubysl/openssl/openssl_missing.h +22 -15
- data/ext/rubysl/openssl/ossl.c +610 -61
- data/ext/rubysl/openssl/ossl.h +31 -17
- data/ext/rubysl/openssl/ossl_asn1.c +974 -183
- data/ext/rubysl/openssl/ossl_asn1.h +3 -3
- data/ext/rubysl/openssl/ossl_bio.c +4 -3
- data/ext/rubysl/openssl/ossl_bio.h +1 -1
- data/ext/rubysl/openssl/ossl_bn.c +32 -28
- data/ext/rubysl/openssl/ossl_bn.h +1 -1
- data/ext/rubysl/openssl/ossl_cipher.c +494 -93
- data/ext/rubysl/openssl/ossl_cipher.h +1 -1
- data/ext/rubysl/openssl/ossl_config.c +4 -5
- data/ext/rubysl/openssl/ossl_config.h +1 -1
- data/ext/rubysl/openssl/ossl_digest.c +206 -24
- data/ext/rubysl/openssl/ossl_digest.h +1 -1
- data/ext/rubysl/openssl/ossl_engine.c +48 -26
- data/ext/rubysl/openssl/ossl_engine.h +1 -1
- data/ext/rubysl/openssl/ossl_hmac.c +40 -38
- data/ext/rubysl/openssl/ossl_hmac.h +1 -1
- data/ext/rubysl/openssl/ossl_ns_spki.c +157 -25
- data/ext/rubysl/openssl/ossl_ns_spki.h +1 -1
- data/ext/rubysl/openssl/ossl_ocsp.c +57 -40
- data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
- data/ext/rubysl/openssl/ossl_pkcs12.c +15 -13
- data/ext/rubysl/openssl/ossl_pkcs12.h +1 -1
- data/ext/rubysl/openssl/ossl_pkcs5.c +108 -18
- data/ext/rubysl/openssl/ossl_pkcs7.c +44 -37
- data/ext/rubysl/openssl/ossl_pkcs7.h +1 -1
- data/ext/rubysl/openssl/ossl_pkey.c +211 -15
- data/ext/rubysl/openssl/ossl_pkey.h +19 -9
- data/ext/rubysl/openssl/ossl_pkey_dh.c +180 -47
- data/ext/rubysl/openssl/ossl_pkey_dsa.c +184 -47
- data/ext/rubysl/openssl/ossl_pkey_ec.c +177 -93
- data/ext/rubysl/openssl/ossl_pkey_rsa.c +209 -102
- data/ext/rubysl/openssl/ossl_rand.c +15 -15
- data/ext/rubysl/openssl/ossl_rand.h +1 -1
- data/ext/rubysl/openssl/ossl_ssl.c +939 -192
- data/ext/rubysl/openssl/ossl_ssl.h +6 -6
- data/ext/rubysl/openssl/ossl_ssl_session.c +78 -62
- data/ext/rubysl/openssl/ossl_version.h +2 -2
- data/ext/rubysl/openssl/ossl_x509.c +1 -1
- data/ext/rubysl/openssl/ossl_x509.h +1 -1
- data/ext/rubysl/openssl/ossl_x509attr.c +20 -19
- data/ext/rubysl/openssl/ossl_x509cert.c +169 -67
- data/ext/rubysl/openssl/ossl_x509crl.c +41 -39
- data/ext/rubysl/openssl/ossl_x509ext.c +51 -38
- data/ext/rubysl/openssl/ossl_x509name.c +139 -29
- data/ext/rubysl/openssl/ossl_x509req.c +42 -40
- data/ext/rubysl/openssl/ossl_x509revoked.c +20 -20
- data/ext/rubysl/openssl/ossl_x509store.c +99 -47
- data/ext/rubysl/openssl/ruby_missing.h +3 -16
- data/lib/openssl/bn.rb +19 -19
- data/lib/openssl/buffering.rb +222 -14
- data/lib/openssl/cipher.rb +20 -20
- data/lib/openssl/config.rb +1 -4
- data/lib/openssl/digest.rb +47 -19
- data/lib/openssl/ssl.rb +197 -1
- data/lib/openssl/x509.rb +162 -1
- data/lib/rubysl/openssl.rb +4 -8
- data/lib/rubysl/openssl/version.rb +1 -1
- data/rubysl-openssl.gemspec +1 -2
- metadata +16 -34
- data/ext/rubysl/openssl/extconf.h +0 -50
- data/lib/openssl/net/ftptls.rb +0 -53
- data/lib/openssl/net/telnets.rb +0 -251
- data/lib/openssl/pkcs7.rb +0 -25
- data/lib/openssl/ssl-internal.rb +0 -187
- data/lib/openssl/x509-internal.rb +0 -153
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* $Id
|
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
|
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),
|
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
|
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
|
-
|
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),
|
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),
|
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
|
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?
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
81
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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("
|
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),
|
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
|
-
*
|
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
|
-
*
|
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/
|
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,
|
258
|
-
* with MD5 or SHA1.
|
259
|
-
* OpenSSL specific method.
|
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
|
-
|
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),
|
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 =
|
341
|
-
|
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 ->
|
379
|
+
* cipher.final -> string
|
363
380
|
*
|
364
|
-
* Returns the remaining data held in the cipher object.
|
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
|
-
*
|
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
|
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
|
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
|
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
|
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.
|
657
|
+
* cipher.key_len = integer -> integer
|
455
658
|
*
|
456
|
-
* Sets the key length of the cipher. If the cipher is a fixed length cipher
|
457
|
-
* length to any value other than the fixed
|
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.
|
717
|
+
* cipher.key_len -> integer
|
518
718
|
*
|
719
|
+
* Returns the key length in bytes of the Cipher.
|
519
720
|
*/
|
520
|
-
|
721
|
+
CIPHER_0ARG_INT(key_length)
|
521
722
|
/*
|
522
723
|
* call-seq:
|
523
|
-
* cipher.
|
724
|
+
* cipher.iv_len -> integer
|
524
725
|
*
|
726
|
+
* Returns the expected length in bytes for an IV for this Cipher.
|
525
727
|
*/
|
526
|
-
|
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
|
-
|
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
|
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);
|