static VALUE ossl_cipher_update(VALUE self, VALUE data) { EVP_CIPHER_CTX *ctx; char *in; int in_len, out_len; VALUE str; StringValue(data); in = RSTRING(data)->ptr; if ((in_len = RSTRING(data)->len) == 0) rb_raise(rb_eArgError, "data must not be empty"); GetCipher(self, ctx); str = rb_str_new(0, in_len+EVP_CIPHER_CTX_block_size(ctx)); if (!EVP_CipherUpdate(ctx, RSTRING(str)->ptr, &out_len, in, in_len)) ossl_raise(eCipherError, NULL); assert(out_len < RSTRING(str)->len); RSTRING(str)->len = out_len; RSTRING(str)->ptr[out_len] = 0; return str; }
/* * call-seq: * cipher.auth_tag([ tag_len ] -> string * * Gets the authentication tag generated by Authenticated Encryption Cipher * modes (GCM for example). This tag may be stored along with the ciphertext, * then set on the decryption cipher to authenticate the contents of the * ciphertext against changes. If the optional integer parameter +tag_len+ is * given, the returned tag will be +tag_len+ bytes long. If the parameter is * omitted, the maximum length of 16 bytes will be returned. For maximum * security, the default of 16 bytes should be chosen. * * The tag may only be retrieved after calling Cipher#final. */ static VALUE ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self) { VALUE vtag_len; EVP_CIPHER_CTX *ctx; int nid, tag_len; if (rb_scan_args(argc, argv, "01", &vtag_len) == 0) { tag_len = 16; } else { tag_len = NUM2INT(vtag_len); } GetCipher(self, ctx); nid = EVP_CIPHER_CTX_nid(ctx); if (ossl_is_gcm(nid)) { return ossl_get_gcm_auth_tag(ctx, tag_len); } else { ossl_raise(eCipherError, "authentication tag not supported by this cipher"); return Qnil; /* dummy */ } }
/* * call-seq: * cipher.auth_tag = string -> string * * Sets the authentication tag to verify the contents of the * ciphertext. The tag must be set after calling Cipher#decrypt, * Cipher#key= and Cipher#iv=, but before assigning the associated * authenticated data using Cipher#auth_data= and of course, before * decrypting any of the ciphertext. After all decryption is * performed, the tag is verified automatically in the call to * Cipher#final. */ static VALUE ossl_cipher_set_auth_tag(VALUE self, VALUE vtag) { EVP_CIPHER_CTX *ctx; int nid; unsigned char *tag; int tag_len; StringValue(vtag); tag = (unsigned char *) RSTRING_PTR(vtag); tag_len = RSTRING_LENINT(vtag); GetCipher(self, ctx); nid = EVP_CIPHER_CTX_nid(ctx); if (ossl_is_gcm(nid)) { ossl_set_gcm_auth_tag(ctx, tag, tag_len); } else { ossl_raise(eCipherError, "authentication tag not supported by this cipher"); } return vtag; }
static VALUE ossl_cipher_set_tag(VALUE self, VALUE data) { EVP_CIPHER_CTX *ctx; char *in = NULL; int in_len = 0; StringValue(data); in = (unsigned char *) RSTRING_PTR(data); in_len = RSTRING_LEN(data); GetCipher(self, ctx); #ifndef EVP_CTRL_GCM_SET_TAG ossl_raise(eCipherError, "your version of OpenSSL doesn't support GCM"); #else if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, in_len, in)) ossl_raise(eCipherError, NULL); #endif return data; }