rubysl-openssl 0.0.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/ext/rubysl/openssl/extconf.h +50 -0
  7. data/ext/rubysl/openssl/extconf.rb +144 -0
  8. data/ext/rubysl/openssl/openssl_missing.c +343 -0
  9. data/ext/rubysl/openssl/openssl_missing.h +191 -0
  10. data/ext/rubysl/openssl/ossl.c +552 -0
  11. data/ext/rubysl/openssl/ossl.h +233 -0
  12. data/ext/rubysl/openssl/ossl_asn1.c +1160 -0
  13. data/ext/rubysl/openssl/ossl_asn1.h +59 -0
  14. data/ext/rubysl/openssl/ossl_bio.c +86 -0
  15. data/ext/rubysl/openssl/ossl_bio.h +21 -0
  16. data/ext/rubysl/openssl/ossl_bn.c +852 -0
  17. data/ext/rubysl/openssl/ossl_bn.h +25 -0
  18. data/ext/rubysl/openssl/ossl_cipher.c +569 -0
  19. data/ext/rubysl/openssl/ossl_cipher.h +22 -0
  20. data/ext/rubysl/openssl/ossl_config.c +75 -0
  21. data/ext/rubysl/openssl/ossl_config.h +22 -0
  22. data/ext/rubysl/openssl/ossl_digest.c +259 -0
  23. data/ext/rubysl/openssl/ossl_digest.h +22 -0
  24. data/ext/rubysl/openssl/ossl_engine.c +411 -0
  25. data/ext/rubysl/openssl/ossl_engine.h +20 -0
  26. data/ext/rubysl/openssl/ossl_hmac.c +268 -0
  27. data/ext/rubysl/openssl/ossl_hmac.h +19 -0
  28. data/ext/rubysl/openssl/ossl_ns_spki.c +257 -0
  29. data/ext/rubysl/openssl/ossl_ns_spki.h +21 -0
  30. data/ext/rubysl/openssl/ossl_ocsp.c +769 -0
  31. data/ext/rubysl/openssl/ossl_ocsp.h +24 -0
  32. data/ext/rubysl/openssl/ossl_pkcs12.c +210 -0
  33. data/ext/rubysl/openssl/ossl_pkcs12.h +15 -0
  34. data/ext/rubysl/openssl/ossl_pkcs5.c +99 -0
  35. data/ext/rubysl/openssl/ossl_pkcs5.h +6 -0
  36. data/ext/rubysl/openssl/ossl_pkcs7.c +1039 -0
  37. data/ext/rubysl/openssl/ossl_pkcs7.h +22 -0
  38. data/ext/rubysl/openssl/ossl_pkey.c +240 -0
  39. data/ext/rubysl/openssl/ossl_pkey.h +141 -0
  40. data/ext/rubysl/openssl/ossl_pkey_dh.c +532 -0
  41. data/ext/rubysl/openssl/ossl_pkey_dsa.c +484 -0
  42. data/ext/rubysl/openssl/ossl_pkey_ec.c +1593 -0
  43. data/ext/rubysl/openssl/ossl_pkey_rsa.c +593 -0
  44. data/ext/rubysl/openssl/ossl_rand.c +202 -0
  45. data/ext/rubysl/openssl/ossl_rand.h +20 -0
  46. data/ext/rubysl/openssl/ossl_ssl.c +1484 -0
  47. data/ext/rubysl/openssl/ossl_ssl.h +36 -0
  48. data/ext/rubysl/openssl/ossl_ssl_session.c +307 -0
  49. data/ext/rubysl/openssl/ossl_version.h +16 -0
  50. data/ext/rubysl/openssl/ossl_x509.c +104 -0
  51. data/ext/rubysl/openssl/ossl_x509.h +114 -0
  52. data/ext/rubysl/openssl/ossl_x509attr.c +274 -0
  53. data/ext/rubysl/openssl/ossl_x509cert.c +764 -0
  54. data/ext/rubysl/openssl/ossl_x509crl.c +535 -0
  55. data/ext/rubysl/openssl/ossl_x509ext.c +458 -0
  56. data/ext/rubysl/openssl/ossl_x509name.c +399 -0
  57. data/ext/rubysl/openssl/ossl_x509req.c +466 -0
  58. data/ext/rubysl/openssl/ossl_x509revoked.c +229 -0
  59. data/ext/rubysl/openssl/ossl_x509store.c +625 -0
  60. data/ext/rubysl/openssl/ruby_missing.h +41 -0
  61. data/lib/openssl.rb +1 -0
  62. data/lib/openssl/bn.rb +35 -0
  63. data/lib/openssl/buffering.rb +241 -0
  64. data/lib/openssl/cipher.rb +65 -0
  65. data/lib/openssl/config.rb +316 -0
  66. data/lib/openssl/digest.rb +61 -0
  67. data/lib/openssl/net/ftptls.rb +53 -0
  68. data/lib/openssl/net/telnets.rb +251 -0
  69. data/lib/openssl/pkcs7.rb +25 -0
  70. data/lib/openssl/ssl-internal.rb +187 -0
  71. data/lib/openssl/ssl.rb +1 -0
  72. data/lib/openssl/x509-internal.rb +153 -0
  73. data/lib/openssl/x509.rb +1 -0
  74. data/lib/rubysl/openssl.rb +28 -0
  75. data/lib/rubysl/openssl/version.rb +5 -0
  76. data/rubysl-openssl.gemspec +19 -18
  77. data/spec/cipher_spec.rb +16 -0
  78. data/spec/config/freeze_spec.rb +17 -0
  79. data/spec/hmac/digest_spec.rb +15 -0
  80. data/spec/hmac/hexdigest_spec.rb +15 -0
  81. data/spec/random/pseudo_bytes_spec.rb +5 -0
  82. data/spec/random/random_bytes_spec.rb +5 -0
  83. data/spec/random/shared/random_bytes.rb +28 -0
  84. data/spec/shared/constants.rb +11 -0
  85. data/spec/x509/name/parse_spec.rb +47 -0
  86. metadata +153 -89
  87. data/lib/rubysl-openssl.rb +0 -7
  88. data/lib/rubysl-openssl/version.rb +0 -5
@@ -0,0 +1,25 @@
1
+ /*
2
+ * $Id: ossl_bn.h 12496 2007-06-08 15:02:04Z technorama $
3
+ * 'OpenSSL for Ruby' project
4
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
+ * All rights reserved.
6
+ */
7
+ /*
8
+ * This program is licenced under the same licence as Ruby.
9
+ * (See the file 'LICENCE'.)
10
+ */
11
+ #if !defined(_OSSL_BN_H_)
12
+ #define _OSSL_BN_H_
13
+
14
+ extern VALUE cBN;
15
+ extern VALUE eBNError;
16
+
17
+ extern BN_CTX *ossl_bn_ctx;
18
+
19
+ VALUE ossl_bn_new(const BIGNUM *);
20
+ BIGNUM *GetBNPtr(VALUE);
21
+ void Init_ossl_bn(void);
22
+
23
+
24
+ #endif /* _OSS_BN_H_ */
25
+
@@ -0,0 +1,569 @@
1
+ /*
2
+ * $Id$
3
+ * 'OpenSSL for Ruby' project
4
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
+ * All rights reserved.
6
+ */
7
+ /*
8
+ * This program is licenced under the same licence as Ruby.
9
+ * (See the file 'LICENCE'.)
10
+ */
11
+ #include "ossl.h"
12
+
13
+ #define MakeCipher(obj, klass, ctx) \
14
+ obj = Data_Make_Struct(klass, EVP_CIPHER_CTX, 0, ossl_cipher_free, ctx)
15
+ #define GetCipher(obj, ctx) do { \
16
+ Data_Get_Struct(obj, EVP_CIPHER_CTX, ctx); \
17
+ if (!ctx) { \
18
+ ossl_raise(rb_eRuntimeError, "Cipher not inititalized!"); \
19
+ } \
20
+ } while (0)
21
+ #define SafeGetCipher(obj, ctx) do { \
22
+ OSSL_Check_Kind(obj, cCipher); \
23
+ GetCipher(obj, ctx); \
24
+ } while (0)
25
+
26
+ /*
27
+ * Classes
28
+ */
29
+ VALUE cCipher;
30
+ VALUE eCipherError;
31
+
32
+ static VALUE ossl_cipher_alloc(VALUE klass);
33
+
34
+ /*
35
+ * PUBLIC
36
+ */
37
+ const EVP_CIPHER *
38
+ GetCipherPtr(VALUE obj)
39
+ {
40
+ EVP_CIPHER_CTX *ctx;
41
+
42
+ SafeGetCipher(obj, ctx);
43
+
44
+ return EVP_CIPHER_CTX_cipher(ctx);
45
+ }
46
+
47
+ VALUE
48
+ ossl_cipher_new(const EVP_CIPHER *cipher)
49
+ {
50
+ VALUE ret;
51
+ EVP_CIPHER_CTX *ctx;
52
+
53
+ ret = ossl_cipher_alloc(cCipher);
54
+ GetCipher(ret, ctx);
55
+ EVP_CIPHER_CTX_init(ctx);
56
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
57
+ ossl_raise(eCipherError, NULL);
58
+
59
+ return ret;
60
+ }
61
+
62
+ /*
63
+ * PRIVATE
64
+ */
65
+ static void
66
+ ossl_cipher_free(EVP_CIPHER_CTX *ctx)
67
+ {
68
+ if (ctx) {
69
+ EVP_CIPHER_CTX_cleanup(ctx);
70
+ ruby_xfree(ctx);
71
+ }
72
+ }
73
+
74
+ static VALUE
75
+ ossl_cipher_alloc(VALUE klass)
76
+ {
77
+ EVP_CIPHER_CTX *ctx;
78
+ VALUE obj;
79
+
80
+ MakeCipher(obj, klass, ctx);
81
+ EVP_CIPHER_CTX_init(ctx);
82
+
83
+ return obj;
84
+ }
85
+
86
+ /*
87
+ * call-seq:
88
+ * Cipher.new(string) -> cipher
89
+ *
90
+ * The string must contain a valid cipher name like "AES-128-CBC" or "3DES".
91
+ *
92
+ * A list of cipher names is available by calling OpenSSL::Cipher.ciphers.
93
+ */
94
+ static VALUE
95
+ ossl_cipher_initialize(VALUE self, VALUE str)
96
+ {
97
+ EVP_CIPHER_CTX *ctx;
98
+ const EVP_CIPHER *cipher;
99
+ char *name;
100
+
101
+ name = StringValuePtr(str);
102
+ GetCipher(self, ctx);
103
+ if (!(cipher = EVP_get_cipherbyname(name))) {
104
+ ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name);
105
+ }
106
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
107
+ ossl_raise(eCipherError, NULL);
108
+
109
+ return self;
110
+ }
111
+ static VALUE
112
+ ossl_cipher_copy(VALUE self, VALUE other)
113
+ {
114
+ EVP_CIPHER_CTX *ctx1, *ctx2;
115
+
116
+ rb_check_frozen(self);
117
+ if (self == other) return self;
118
+
119
+ GetCipher(self, ctx1);
120
+ SafeGetCipher(other, ctx2);
121
+ if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1)
122
+ ossl_raise(eCipherError, NULL);
123
+
124
+ return self;
125
+ }
126
+
127
+ #ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
128
+ static void*
129
+ add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
130
+ {
131
+ rb_ary_push(ary, rb_str_new2(name->name));
132
+ return NULL;
133
+ }
134
+ #endif
135
+
136
+ /*
137
+ * call-seq:
138
+ * Cipher.ciphers -> array[string...]
139
+ *
140
+ * Returns the names of all available ciphers in an array.
141
+ */
142
+ static VALUE
143
+ ossl_s_ciphers(VALUE self)
144
+ {
145
+ #ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
146
+ VALUE ary;
147
+
148
+ ary = rb_ary_new();
149
+ OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
150
+ (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary,
151
+ (void*)ary);
152
+
153
+ return ary;
154
+ #else
155
+ rb_notimplement();
156
+ #endif
157
+ }
158
+
159
+ /*
160
+ * call-seq:
161
+ * cipher.reset -> self
162
+ *
163
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
164
+ */
165
+ static VALUE
166
+ ossl_cipher_reset(VALUE self)
167
+ {
168
+ EVP_CIPHER_CTX *ctx;
169
+
170
+ GetCipher(self, ctx);
171
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1)
172
+ ossl_raise(eCipherError, NULL);
173
+
174
+ return self;
175
+ }
176
+
177
+ static VALUE
178
+ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
179
+ {
180
+ EVP_CIPHER_CTX *ctx;
181
+ unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL;
182
+ unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL;
183
+ VALUE pass, init_v;
184
+
185
+ if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){
186
+ /*
187
+ * oops. this code mistakes salt for IV.
188
+ * We deprecated the arguments for this method, but we decided
189
+ * keeping this behaviour for backward compatibility.
190
+ */
191
+ const char *cname = rb_class2name(rb_obj_class(self));
192
+ rb_warn("argumtents for %s#encrypt and %s#decrypt were deprecated; "
193
+ "use %s#pkcs5_keyivgen to derive key and IV",
194
+ cname, cname, cname);
195
+ StringValue(pass);
196
+ GetCipher(self, ctx);
197
+ if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
198
+ else{
199
+ StringValue(init_v);
200
+ if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) {
201
+ memset(iv, 0, EVP_MAX_IV_LENGTH);
202
+ memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v));
203
+ }
204
+ else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv));
205
+ }
206
+ EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
207
+ RSTRING_PTR(pass), RSTRING_LEN(pass), 1, key, NULL);
208
+ p_key = key;
209
+ p_iv = iv;
210
+ }
211
+ else {
212
+ GetCipher(self, ctx);
213
+ }
214
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) {
215
+ ossl_raise(eCipherError, NULL);
216
+ }
217
+
218
+ return self;
219
+ }
220
+
221
+ /*
222
+ * call-seq:
223
+ * cipher.encrypt -> self
224
+ *
225
+ * Make sure to call .encrypt or .decrypt before using any of the following methods:
226
+ * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
227
+ *
228
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
229
+ */
230
+ static VALUE
231
+ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
232
+ {
233
+ return ossl_cipher_init(argc, argv, self, 1);
234
+ }
235
+
236
+ /*
237
+ * call-seq:
238
+ * cipher.decrypt -> self
239
+ *
240
+ * Make sure to call .encrypt or .decrypt before using any of the following methods:
241
+ * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
242
+ *
243
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
244
+ */
245
+ static VALUE
246
+ ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
247
+ {
248
+ return ossl_cipher_init(argc, argv, self, 0);
249
+ }
250
+
251
+ /*
252
+ * call-seq:
253
+ * cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> nil
254
+ *
255
+ * Generates and sets the key/iv based on a password.
256
+ *
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.
260
+ *
261
+ * === Parameters
262
+ * +salt+ must be an 8 byte string if provided.
263
+ * +iterations+ is a integer with a default of 2048.
264
+ * +digest+ is a Digest object that defaults to 'MD5'
265
+ *
266
+ * A minimum of 1000 iterations is recommended.
267
+ *
268
+ */
269
+ static VALUE
270
+ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
271
+ {
272
+ EVP_CIPHER_CTX *ctx;
273
+ const EVP_MD *digest;
274
+ VALUE vpass, vsalt, viter, vdigest;
275
+ unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL;
276
+ int iter;
277
+
278
+ rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest);
279
+ StringValue(vpass);
280
+ if(!NIL_P(vsalt)){
281
+ StringValue(vsalt);
282
+ if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
283
+ rb_raise(eCipherError, "salt must be an 8-octet string");
284
+ salt = RSTRING_PTR(vsalt);
285
+ }
286
+ iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
287
+ digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest);
288
+ GetCipher(self, ctx);
289
+ EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
290
+ RSTRING_PTR(vpass), RSTRING_LEN(vpass), iter, key, iv);
291
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
292
+ ossl_raise(eCipherError, NULL);
293
+ OPENSSL_cleanse(key, sizeof key);
294
+ OPENSSL_cleanse(iv, sizeof iv);
295
+
296
+ return Qnil;
297
+ }
298
+
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
+ /*
321
+ * call-seq:
322
+ * cipher.update(data [, buffer]) -> string or buffer
323
+ *
324
+ * === Parameters
325
+ * +data+ is a nonempty string.
326
+ * +buffer+ is an optional string to store the result.
327
+ */
328
+ static VALUE
329
+ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
330
+ {
331
+ EVP_CIPHER_CTX *ctx;
332
+ char *in;
333
+ int in_len, out_len;
334
+ VALUE data, str;
335
+
336
+ rb_scan_args(argc, argv, "11", &data, &str);
337
+
338
+ 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");
342
+ GetCipher(self, ctx);
343
+ out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
344
+
345
+ if (NIL_P(str)) {
346
+ str = rb_str_new(0, out_len);
347
+ } else {
348
+ StringValue(str);
349
+ rb_str_resize(str, out_len);
350
+ }
351
+
352
+ if (!EVP_CipherUpdate(ctx, RSTRING_PTR(str), &out_len, in, in_len))
353
+ ossl_raise(eCipherError, NULL);
354
+ assert(out_len < RSTRING_LEN(str));
355
+ rb_str_set_len(str, out_len);
356
+
357
+ return str;
358
+ }
359
+
360
+ /*
361
+ * call-seq:
362
+ * cipher.final -> aString
363
+ *
364
+ * Returns the remaining data held in the cipher object. Further calls to update() or final() will return garbage.
365
+ *
366
+ * See EVP_CipherFinal_ex for further information.
367
+ */
368
+ static VALUE
369
+ ossl_cipher_final(VALUE self)
370
+ {
371
+ EVP_CIPHER_CTX *ctx;
372
+ int out_len;
373
+ VALUE str;
374
+
375
+ GetCipher(self, ctx);
376
+ str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
377
+ if (!EVP_CipherFinal_ex(ctx, RSTRING_PTR(str), &out_len))
378
+ ossl_raise(eCipherError, NULL);
379
+ assert(out_len <= RSTRING_LEN(str));
380
+ rb_str_set_len(str, out_len);
381
+
382
+ return str;
383
+ }
384
+
385
+ /*
386
+ * call-seq:
387
+ * cipher.name -> string
388
+ *
389
+ * Returns the name of the cipher which may differ slightly from the original name provided.
390
+ */
391
+ static VALUE
392
+ ossl_cipher_name(VALUE self)
393
+ {
394
+ EVP_CIPHER_CTX *ctx;
395
+
396
+ GetCipher(self, ctx);
397
+
398
+ return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx)));
399
+ }
400
+
401
+ /*
402
+ * call-seq:
403
+ * cipher.key = string -> string
404
+ *
405
+ * Sets the cipher key.
406
+ *
407
+ * Only call this method after calling cipher.encrypt or cipher.decrypt.
408
+ */
409
+ static VALUE
410
+ ossl_cipher_set_key(VALUE self, VALUE key)
411
+ {
412
+ EVP_CIPHER_CTX *ctx;
413
+
414
+ StringValue(key);
415
+ GetCipher(self, ctx);
416
+
417
+ if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx))
418
+ ossl_raise(eCipherError, "key length too short");
419
+
420
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING_PTR(key), NULL, -1) != 1)
421
+ ossl_raise(eCipherError, NULL);
422
+
423
+ return key;
424
+ }
425
+
426
+ /*
427
+ * call-seq:
428
+ * cipher.iv = string -> string
429
+ *
430
+ * Sets the cipher iv.
431
+ *
432
+ * Only call this method after calling cipher.encrypt or cipher.decrypt.
433
+ */
434
+ static VALUE
435
+ ossl_cipher_set_iv(VALUE self, VALUE iv)
436
+ {
437
+ EVP_CIPHER_CTX *ctx;
438
+
439
+ StringValue(iv);
440
+ GetCipher(self, ctx);
441
+
442
+ if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx))
443
+ ossl_raise(eCipherError, "iv length too short");
444
+
445
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING_PTR(iv), -1) != 1)
446
+ ossl_raise(eCipherError, NULL);
447
+
448
+ return iv;
449
+ }
450
+
451
+
452
+ /*
453
+ * call-seq:
454
+ * cipher.key_length = integer -> integer
455
+ *
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.
458
+ *
459
+ * Under normal circumstances you do not need to call this method (and probably shouldn't).
460
+ *
461
+ * See EVP_CIPHER_CTX_set_key_length for further information.
462
+ */
463
+ static VALUE
464
+ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
465
+ {
466
+ int len = NUM2INT(key_length);
467
+ EVP_CIPHER_CTX *ctx;
468
+
469
+ GetCipher(self, ctx);
470
+ if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
471
+ ossl_raise(eCipherError, NULL);
472
+
473
+ return key_length;
474
+ }
475
+
476
+ /*
477
+ * call-seq:
478
+ * cipher.padding = integer -> integer
479
+ *
480
+ * Enables or disables padding. By default encryption operations are padded using standard block padding and the
481
+ * padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the
482
+ * total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur.
483
+ *
484
+ * See EVP_CIPHER_CTX_set_padding for further information.
485
+ */
486
+ static VALUE
487
+ ossl_cipher_set_padding(VALUE self, VALUE padding)
488
+ {
489
+ #if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING)
490
+ EVP_CIPHER_CTX *ctx;
491
+ int pad = NUM2INT(padding);
492
+
493
+ GetCipher(self, ctx);
494
+ if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1)
495
+ ossl_raise(eCipherError, NULL);
496
+ #else
497
+ rb_notimplement();
498
+ #endif
499
+ return padding;
500
+ }
501
+
502
+ #define CIPHER_0ARG_INT(func) \
503
+ static VALUE \
504
+ ossl_cipher_##func(VALUE self) \
505
+ { \
506
+ EVP_CIPHER_CTX *ctx; \
507
+ GetCipher(self, ctx); \
508
+ return INT2NUM(EVP_CIPHER_##func(EVP_CIPHER_CTX_cipher(ctx))); \
509
+ }
510
+ CIPHER_0ARG_INT(key_length)
511
+ CIPHER_0ARG_INT(iv_length)
512
+ CIPHER_0ARG_INT(block_size)
513
+
514
+ #if 0
515
+ /*
516
+ * call-seq:
517
+ * cipher.key_length -> integer
518
+ *
519
+ */
520
+ static VALUE ossl_cipher_key_length() { }
521
+ /*
522
+ * call-seq:
523
+ * cipher.iv_length -> integer
524
+ *
525
+ */
526
+ static VALUE ossl_cipher_iv_length() { }
527
+ /*
528
+ * call-seq:
529
+ * cipher.block_size -> integer
530
+ *
531
+ */
532
+ static VALUE ossl_cipher_block_size() { }
533
+ #endif
534
+
535
+ /*
536
+ * INIT
537
+ */
538
+ void
539
+ Init_ossl_cipher(void)
540
+ {
541
+ #if 0 /* let rdoc know about mOSSL */
542
+ mOSSL = rb_define_module("OpenSSL");
543
+ #endif
544
+ cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
545
+ eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
546
+
547
+ rb_define_alloc_func(cCipher, ossl_cipher_alloc);
548
+ rb_define_copy_func(cCipher, ossl_cipher_copy);
549
+ rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0);
550
+ rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
551
+ rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
552
+ rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);
553
+ rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
554
+ rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
555
+ 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
+ rb_define_method(cCipher, "final", ossl_cipher_final, 0);
560
+ rb_define_method(cCipher, "name", ossl_cipher_name, 0);
561
+ rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1);
562
+ rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1);
563
+ rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0);
564
+ rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1);
565
+ rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
566
+ rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
567
+ rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
568
+ }
569
+