12#define NewCipher(klass) \
13 TypedData_Wrap_Struct((klass), &ossl_cipher_type, 0)
14#define AllocCipher(obj, ctx) do { \
15 (ctx) = EVP_CIPHER_CTX_new(); \
17 ossl_raise(rb_eRuntimeError, NULL); \
18 RTYPEDDATA_DATA(obj) = (ctx); \
20#define GetCipherInit(obj, ctx) do { \
21 TypedData_Get_Struct((obj), EVP_CIPHER_CTX, &ossl_cipher_type, (ctx)); \
23#define GetCipher(obj, ctx) do { \
24 GetCipherInit((obj), (ctx)); \
26 ossl_raise(rb_eRuntimeError, "Cipher not initialized!"); \
35static ID id_auth_tag_len, id_key_set;
38static void ossl_cipher_free(
void *
ptr);
59 return EVP_CIPHER_CTX_cipher(ctx);
62 const EVP_CIPHER *cipher;
68 "unsupported cipher algorithm: %"PRIsVALUE, obj);
80 ret = ossl_cipher_alloc(
cCipher);
82 if (EVP_CipherInit_ex(ctx, cipher,
NULL,
NULL,
NULL, -1) != 1)
92ossl_cipher_free(
void *
ptr)
94 EVP_CIPHER_CTX_free(
ptr);
98ossl_cipher_alloc(
VALUE klass)
115 const EVP_CIPHER *cipher;
124 if (!(cipher = EVP_get_cipherbyname(
name))) {
127 if (EVP_CipherInit_ex(ctx, cipher,
NULL,
NULL,
NULL, -1) != 1)
136 EVP_CIPHER_CTX *ctx1, *ctx2;
139 if (self == other)
return self;
146 if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1)
153add_cipher_name_to_ary(
const OBJ_NAME *
name,
VALUE ary)
166ossl_s_ciphers(
VALUE self)
171 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
172 (
void(*)(
const OBJ_NAME*,
void*))add_cipher_name_to_ary,
188ossl_cipher_reset(
VALUE self)
203 unsigned char key[EVP_MAX_KEY_LENGTH], *p_key =
NULL;
204 unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv =
NULL;
215 "use %"PRIsVALUE"#pkcs5_keyivgen to derive key and IV",
216 cname, cname, cname);
219 if (
NIL_P(init_v))
memcpy(iv,
"OpenSSL for Ruby rulez!",
sizeof(iv));
223 memset(iv, 0, EVP_MAX_IV_LENGTH);
228 EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
236 if (EVP_CipherInit_ex(ctx,
NULL,
NULL, p_key, p_iv,
mode) != 1) {
260 return ossl_cipher_init(
argc,
argv, self, 1);
278 return ossl_cipher_init(
argc,
argv, self, 0);
305 const EVP_MD *digest;
306 VALUE vpass, vsalt, viter, vdigest;
307 unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt =
NULL;
323 EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
324 (
unsigned char *)
RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter,
key, iv);
325 if (EVP_CipherInit_ex(ctx,
NULL,
NULL,
key, iv, -1) != 1)
327 OPENSSL_cleanse(
key,
sizeof key);
328 OPENSSL_cleanse(iv,
sizeof iv);
336ossl_cipher_update_long(EVP_CIPHER_CTX *ctx,
unsigned char *
out,
long *out_len_ptr,
337 const unsigned char *
in,
long in_len)
340 int limit = INT_MAX / 2 + 1;
344 int in_part_len = in_len > limit ? limit : (
int)in_len;
346 if (!EVP_CipherUpdate(ctx,
out ? (
out + out_len) : 0,
347 &out_part_len,
in, in_part_len))
350 out_len += out_part_len;
352 }
while ((in_len -= limit) > 0);
355 *out_len_ptr = out_len;
377 long in_len, out_len;
390 out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
393 "data too big to make output buffer: %ld bytes", in_len);
403 if (!ossl_cipher_update_long(ctx, (
unsigned char *)
RSTRING_PTR(
str), &out_len,
in, in_len))
426ossl_cipher_final(
VALUE self)
434 if (!EVP_CipherFinal_ex(ctx, (
unsigned char *)
RSTRING_PTR(
str), &out_len))
450ossl_cipher_name(
VALUE self)
456 return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx)));
479 key_len = EVP_CIPHER_CTX_key_length(ctx);
512 if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)
513 iv_len = (
int)(
VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
515 iv_len = EVP_CIPHER_CTX_iv_length(ctx);
533ossl_cipher_is_authenticated(
VALUE self)
539 return (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) ?
Qtrue :
Qfalse;
561ossl_cipher_set_auth_data(
VALUE self,
VALUE data)
565 long in_len, out_len;
573 if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
576 if (!ossl_cipher_update_long(ctx,
NULL, &out_len,
in, in_len))
607 if (!
NIL_P(vtag_len))
612 if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
636ossl_cipher_set_auth_tag(
VALUE self,
VALUE vtag)
644 tag_len = RSTRING_LENINT(vtag);
647 if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
668ossl_cipher_set_auth_tag_len(
VALUE self,
VALUE vlen)
674 if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
695ossl_cipher_set_iv_length(
VALUE self,
VALUE iv_length)
701 if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
711 EVP_CIPHER_CTX_set_app_data(ctx, (
void *)(
VALUE)
len);
729ossl_cipher_set_key_length(
VALUE self,
VALUE key_length)
735 if (EVP_CIPHER_CTX_set_key_length(ctx,
len) != 1)
752ossl_cipher_set_padding(
VALUE self,
VALUE padding)
758 if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1)
770ossl_cipher_key_length(
VALUE self)
776 return INT2NUM(EVP_CIPHER_CTX_key_length(ctx));
786ossl_cipher_iv_length(
VALUE self)
792 if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)
793 len = (
int)(
VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
795 len = EVP_CIPHER_CTX_iv_length(ctx);
807ossl_cipher_block_size(
VALUE self)
813 return INT2NUM(EVP_CIPHER_CTX_block_size(ctx));
827ossl_cipher_set_ccm_data_len(
VALUE self,
VALUE data_len)
835 if (EVP_CipherUpdate(ctx,
NULL, &out_len,
NULL, in_len) != 1)
1073 id_auth_tag_len = rb_intern_const(
"auth_tag_len");
1074 id_key_set = rb_intern_const(
"key_set");
VALUE rb_ary_push(VALUE ary, VALUE item)
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_module_function(klass, mid, func, arity)
Defines klass#mid and makes it a module function.
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module(const char *name)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_warn(const char *fmt,...)
VALUE rb_cObject
Object class.
VALUE rb_obj_class(VALUE)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
unsigned in(void *in_desc, z_const unsigned char **buf)
VALUE rb_str_resize(VALUE, long)
#define rb_str_new(str, len)
void rb_str_set_len(VALUE, long)
VALUE rb_class_path(VALUE)
VALUE rb_attr_get(VALUE, ID)
VALUE rb_ivar_set(VALUE, ID, VALUE)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define EVP_CTRL_AEAD_SET_IVLEN
#define EVP_CTRL_AEAD_GET_TAG
#define EVP_CTRL_AEAD_SET_TAG
void ossl_raise(VALUE exc, const char *fmt,...)
#define AllocCipher(obj, ctx)
const EVP_CIPHER * ossl_evp_get_cipherbyname(VALUE obj)
void Init_ossl_cipher(void)
VALUE ossl_cipher_new(const EVP_CIPHER *cipher)
#define GetCipherInit(obj, ctx)
#define GetCipher(obj, ctx)
const EVP_MD * ossl_evp_get_digestbyname(VALUE obj)
#define StringValueCStr(v)
@ RUBY_TYPED_FREE_IMMEDIATELY