static VALUE ossl_asn1data_to_der(VALUE self) { VALUE value, der, inf_length; int tag, tag_class, is_cons = 0, tmp_cons = 1; long length; unsigned char *p; value = ossl_asn1_get_value(self); if(rb_obj_is_kind_of(value, rb_cArray)){ is_cons = 1; value = join_der(value); } StringValue(value); tag = ossl_asn1_tag(self); tag_class = ossl_asn1_tag_class(self); inf_length = ossl_asn1_get_infinite_length(self); if (inf_length == Qtrue) { is_cons = 2; tmp_cons = 2; } if((length = ASN1_object_size(tmp_cons, RSTRING_LENINT(value), tag)) <= 0) ossl_raise(eASN1Error, NULL); der = rb_str_new(0, length); p = (unsigned char *)RSTRING_PTR(der); ASN1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class); memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); p += RSTRING_LEN(value); ossl_str_adjust(der, p); return der; }
/* * call-seq: * basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent * * send _mesg_ via _basicsocket_. * * _mesg_ should be a string. * * _flags_ should be a bitwise OR of Socket::MSG_* constants. * * _dest_sockaddr_ should be a packed sockaddr string or an addrinfo. * * TCPSocket.open("localhost", 80) {|s| * s.send "GET / HTTP/1.0\r\n\r\n", 0 * p s.read * } */ VALUE rsock_bsock_send(int argc, VALUE *argv, VALUE sock) { struct rsock_send_arg arg; VALUE flags, to; rb_io_t *fptr; int n; rb_blocking_function_t *func; rb_secure(4); rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to); StringValue(arg.mesg); if (!NIL_P(to)) { SockAddrStringValue(to); to = rb_str_new4(to); arg.to = (struct sockaddr *)RSTRING_PTR(to); arg.tolen = (socklen_t)RSTRING_LENINT(to); func = rsock_sendto_blocking; } else { func = rsock_send_blocking; } GetOpenFile(sock, fptr); arg.fd = fptr->fd; arg.flags = NUM2INT(flags); while (rb_thread_fd_writable(arg.fd), (n = (int)BLOCKING_REGION_FD(func, &arg)) < 0) { if (rb_io_wait_writable(arg.fd)) { continue; } rb_sys_fail("send(2)"); } return INT2FIX(n); }
BIO * ossl_obj2bio(VALUE obj) { BIO *bio; if (RB_TYPE_P(obj, T_FILE)) { rb_io_t *fptr; FILE *fp; int fd; GetOpenFile(obj, fptr); rb_io_check_readable(fptr); if ((fd = rb_cloexec_dup(FPTR_TO_FD(fptr))) < 0){ rb_sys_fail(0); } rb_update_max_fd(fd); if (!(fp = fdopen(fd, "r"))){ int e = errno; close(fd); rb_syserr_fail(e, 0); } if (!(bio = BIO_new_fp(fp, BIO_CLOSE))){ fclose(fp); ossl_raise(eOSSLError, NULL); } } else { StringValue(obj); bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj)); if (!bio) ossl_raise(eOSSLError, NULL); } return bio; }
int ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd) { int len, status = 0; VALUE rflag, pass; if (pwd || !rb_block_given_p()) return PEM_def_callback(buf, max_len, flag, pwd); while (1) { /* * when the flag is nonzero, this passphrase * will be used to perform encryption; otherwise it will * be used to perform decryption. */ rflag = flag ? Qtrue : Qfalse; pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status); if (status) return -1; /* exception was raised. */ len = RSTRING_LENINT(pass); if (len < 4) { /* 4 is OpenSSL hardcoded limit */ rb_warning("password must be longer than 4 bytes"); continue; } if (len > max_len) { rb_warning("password must be shorter then %d bytes", max_len-1); continue; } memcpy(buf, RSTRING_PTR(pass), len); break; } return len; }
/* * call-seq: * cipher.update(data [, buffer]) -> string or buffer * * Encrypts data in a streaming fashion. Hand consecutive blocks of data * to the +update+ method in order to encrypt it. Returns the encrypted * data chunk. When done, the output of Cipher#final should be additionally * added to the result. * * === Parameters * +data+ is a nonempty string. * +buffer+ is an optional string to store the result. */ static VALUE ossl_cipher_update(int argc, VALUE *argv, VALUE self) { EVP_CIPHER_CTX *ctx; unsigned char *in; int in_len, out_len; VALUE data, str; rb_scan_args(argc, argv, "11", &data, &str); StringValue(data); in = (unsigned char *)RSTRING_PTR(data); if ((in_len = RSTRING_LENINT(data)) == 0) ossl_raise(rb_eArgError, "data must not be empty"); GetCipher(self, ctx); out_len = in_len+EVP_CIPHER_CTX_block_size(ctx); if (NIL_P(str)) { str = rb_str_new(0, out_len); } else { StringValue(str); rb_str_resize(str, out_len); } if (!EVP_CipherUpdate(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len)) ossl_raise(eCipherError, NULL); assert(out_len < RSTRING_LEN(str)); rb_str_set_len(str, out_len); return str; }
/* * call-seq: * cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> nil * * Generates and sets the key/IV based on a password. * * WARNING: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40, * or DES with MD5 or SHA1. Using anything else (like AES) will generate the * key/iv using an OpenSSL specific method. This method is deprecated and * should no longer be used. Use a PKCS5 v2 key generation method from * OpenSSL::PKCS5 instead. * * === Parameters * +salt+ must be an 8 byte string if provided. * +iterations+ is a integer with a default of 2048. * +digest+ is a Digest object that defaults to 'MD5' * * A minimum of 1000 iterations is recommended. * */ static VALUE ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self) { EVP_CIPHER_CTX *ctx; const EVP_MD *digest; VALUE vpass, vsalt, viter, vdigest; unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL; int iter; rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest); StringValue(vpass); if(!NIL_P(vsalt)){ StringValue(vsalt); if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN) ossl_raise(eCipherError, "salt must be an 8-octet string"); salt = (unsigned char *)RSTRING_PTR(vsalt); } iter = NIL_P(viter) ? 2048 : NUM2INT(viter); digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest); GetCipher(self, ctx); EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt, (unsigned char *)RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter, key, iv); if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1) ossl_raise(eCipherError, NULL); OPENSSL_cleanse(key, sizeof key); OPENSSL_cleanse(iv, sizeof iv); return Qnil; }
static VALUE t_set_sock_opt (VALUE self, VALUE signature, VALUE lev, VALUE optname, VALUE optval) { int fd = evma_get_file_descriptor (NUM2ULONG (signature)); int level = NUM2INT(lev), option = NUM2INT(optname); int i; const void *v; socklen_t len; switch (TYPE(optval)) { case T_FIXNUM: i = FIX2INT(optval); goto numval; case T_FALSE: i = 0; goto numval; case T_TRUE: i = 1; numval: v = (void*)&i; len = sizeof(i); break; default: StringValue(optval); v = RSTRING_PTR(optval); len = RSTRING_LENINT(optval); break; } if (setsockopt(fd, level, option, (char *)v, len) < 0) rb_sys_fail("setsockopt"); return INT2FIX(0); }
/* * call-seq: * add(str, entropy) -> self * * Mixes the bytes from +str+ into the Pseudo Random Number Generator(PRNG) * state. * * Thus, if the data from +str+ are unpredictable to an adversary, this * increases the uncertainty about the state and makes the PRNG output less * predictable. * * The +entropy+ argument is (the lower bound of) an estimate of how much * randomness is contained in +str+, measured in bytes. * * Example: * * pid = $$ * now = Time.now * ary = [now.to_i, now.nsec, 1000, pid] * OpenSSL::Random.add(ary.join("").to_s, 0.0) * OpenSSL::Random.seed(ary.join("").to_s) */ static VALUE ossl_rand_add(VALUE self, VALUE str, VALUE entropy) { StringValue(str); RAND_add(RSTRING_PTR(str), RSTRING_LENINT(str), NUM2DBL(entropy)); return self; }
/* * call-seq: * seed(str) -> str * * ::seed is equivalent to ::add where +entropy+ is length of +str+. */ static VALUE ossl_rand_seed(VALUE self, VALUE str) { StringValue(str); RAND_seed(RSTRING_PTR(str), RSTRING_LENINT(str)); return str; }
static VALUE gl_LoadProgramNV(VALUE obj,VALUE arg1,VALUE arg2,VALUE arg3) { LOAD_GL_FUNC(glLoadProgramNV, "GL_NV_vertex_program"); Check_Type(arg3,T_STRING); fptr_glLoadProgramNV((GLenum)NUM2INT(arg1),(GLuint)NUM2UINT(arg2),(GLsizei)RSTRING_LENINT(arg3),(GLubyte *)RSTRING_PTR(arg3)); CHECK_GLERROR_FROM("glLoadProgramNV"); return Qnil; }
static VALUE gl_ProgramStringARB(VALUE obj,VALUE arg1,VALUE arg2,VALUE arg3) { LOAD_GL_FUNC(glProgramStringARB, "GL_ARB_vertex_program"); Check_Type(arg3,T_STRING); fptr_glProgramStringARB((GLenum)NUM2INT(arg1),(GLenum)NUM2INT(arg2),(GLsizei)RSTRING_LENINT(arg3),RSTRING_PTR(arg3)); CHECK_GLERROR_FROM("glProgramStringARB"); return Qnil; }
/* * call-seq: * PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string * * === Parameters * * +pass+ - string * * +salt+ - string * * +iter+ - integer - should be greater than 1000. 2000 is better. * * +keylen+ - integer * * This method is available almost any version OpenSSL. * * Conforms to rfc2898. */ static VALUE ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen) { VALUE str; int len = NUM2INT(keylen); StringValue(pass); StringValue(salt); str = rb_str_new(0, len); if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LENINT(pass), (const unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt), NUM2INT(iter), len, (unsigned char *)RSTRING_PTR(str)) != 1) ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1"); return str; }
static VALUE method_deserialize(VALUE self, VALUE bson) { const char* buffer = RSTRING_PTR(bson); int remaining = RSTRING_LENINT(bson); // NOTE we just swallow the size and end byte here buffer += 4; remaining -= 5; return elements_to_hash(buffer, remaining); }
/* * call-seq: * PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string * * === Parameters * * +pass+ - string * * +salt+ - string - should be at least 8 bytes long. * * +iter+ - integer - should be greater than 1000. 20000 is better. * * +keylen+ - integer * * +digest+ - a string or OpenSSL::Digest object. * * Available in OpenSSL 0.9.4. * * Digests other than SHA1 may not be supported by other cryptography libraries. */ static VALUE ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest) { VALUE str; const EVP_MD *md; int len = NUM2INT(keylen); StringValue(pass); StringValue(salt); md = GetDigestPtr(digest); str = rb_str_new(0, len); if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass), (unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt), NUM2INT(iter), md, len, (unsigned char *)RSTRING_PTR(str)) != 1) ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC"); return str; }
/* * Document-method: setsockopt * call-seq: * setsockopt(level, optname, optval) * setsockopt(socketoption) * * Sets a socket option. These are protocol and system specific, see your * local system documentation for details. * * === Parameters * * +level+ is an integer, usually one of the SOL_ constants such as * Socket::SOL_SOCKET, or a protocol level. * A string or symbol of the name, possibly without prefix, is also * accepted. * * +optname+ is an integer, usually one of the SO_ constants, such * as Socket::SO_REUSEADDR. * A string or symbol of the name, possibly without prefix, is also * accepted. * * +optval+ is the value of the option, it is passed to the underlying * setsockopt() as a pointer to a certain number of bytes. How this is * done depends on the type: * - Fixnum: value is assigned to an int, and a pointer to the int is * passed, with length of sizeof(int). * - true or false: 1 or 0 (respectively) is assigned to an int, and the * int is passed as for a Fixnum. Note that +false+ must be passed, * not +nil+. * - String: the string's data and length is passed to the socket. * * +socketoption+ is an instance of Socket::Option * * === Examples * * Some socket options are integers with boolean values, in this case * #setsockopt could be called like this: * sock.setsockopt(:SOCKET, :REUSEADDR, true) * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true) * sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true)) * * Some socket options are integers with numeric values, in this case * #setsockopt could be called like this: * sock.setsockopt(:IP, :TTL, 255) * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255) * sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255)) * * Option values may be structs. Passing them can be complex as it involves * examining your system headers to determine the correct definition. An * example is an +ip_mreq+, which may be defined in your system headers as: * struct ip_mreq { * struct in_addr imr_multiaddr; * struct in_addr imr_interface; * }; * * In this case #setsockopt could be called like this: * optval = IPAddr.new("224.0.0.251").hton + * IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval) * */ static VALUE bsock_setsockopt(int argc, VALUE *argv, VALUE sock) { UNRUBBY_SOCKET_HACK; VALUE lev, optname, val; int family, level, option; rb_io_t *fptr; int i; char *v; int vlen; if (argc == 1) { lev = rb_funcall(argv[0], rb_intern("level"), 0); optname = rb_funcall(argv[0], rb_intern("optname"), 0); val = rb_funcall(argv[0], rb_intern("data"), 0); } else { rb_scan_args(argc, argv, "30", &lev, &optname, &val); } rb_secure(2); GetOpenFile(sock, fptr); family = rsock_getfamily(fptr->fd); level = rsock_level_arg(family, lev); option = rsock_optname_arg(family, level, optname); switch (TYPE(val)) { case T_FIXNUM: i = FIX2INT(val); goto numval; case T_FALSE: i = 0; goto numval; case T_TRUE: i = 1; numval: v = (char*)&i; vlen = (int)sizeof(i); break; default: StringValue(val); v = RSTRING_PTR(val); vlen = RSTRING_LENINT(val); break; } #define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path)) rb_io_check_closed(fptr); if (setsockopt(fptr->fd, level, option, v, vlen) < 0) rb_sys_fail_path(fptr->pathv); return INT2FIX(0); }
/* * call-seq: * HMAC.new(key, digest) -> hmac * * Returns an instance of OpenSSL::HMAC set with the key and digest * algorithm to be used. The instance represents the initial state of * the message authentication code before any data has been processed. * To process data with it, use the instance method #update with your * data as an argument. * * === Example * * key = 'key' * digest = OpenSSL::Digest.new('sha1') * instance = OpenSSL::HMAC.new(key, digest) * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * instance.class * #=> OpenSSL::HMAC * * === A note about comparisons * * Two instances won't be equal when they're compared, even if they have the * same value. Use #to_s or #hexdigest to return the authentication code that * the instance represents. For example: * * other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1')) * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * instance * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * instance == other_instance * #=> false * instance.to_s == other_instance.to_s * #=> true * */ static VALUE ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) { HMAC_CTX *ctx; StringValue(key); GetHMAC(self, ctx); HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key), ossl_evp_get_digestbyname(digest), NULL); return self; }
static ASN1_STRING* obj_to_asn1str(VALUE obj) { ASN1_STRING *str; StringValue(obj); if(!(str = ASN1_STRING_new())) ossl_raise(eASN1Error, NULL); ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LENINT(obj)); return str; }
/* * call-seq: * HMAC.new(key, digest) -> hmac * * Returns an instance of OpenSSL::HMAC set with the key and digest * algorithm to be used. The instance represents the initial state of * the message authentication code before any data has been processed. * To process data with it, use the instance method #update with your * data as an argument. * * === Example * * key = 'key' * digest = OpenSSL::Digest.new('sha1') * instance = OpenSSL::HMAC.new(key, digest) * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * instance.class * #=> OpenSSL::HMAC * * === A note about comparisons * * Two instances won't be equal when they're compared, even if they have the * same value. Use #to_s or #hexdigest to return the authentication code that * the instance represents. For example: * * other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1')) * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * instance * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f * instance == other_instance * #=> false * instance.to_s == other_instance.to_s * #=> true * */ static VALUE ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) { HMAC_CTX *ctx; StringValue(key); GetHMAC(self, ctx); HMAC_Init(ctx, RSTRING_PTR(key), RSTRING_LENINT(key), GetDigestPtr(digest)); return self; }
static ASN1_STRING* obj_to_asn1derstr(VALUE obj) { ASN1_STRING *a1str; VALUE str; str = ossl_to_der(obj); if(!(a1str = ASN1_STRING_new())) ossl_raise(eASN1Error, NULL); ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LENINT(str)); return a1str; }
/* * call-seq: * spki.challenge = str => string * * === Parameters * * +str+ - the challenge string to be set for this instance * * Sets the challenge to be associated with the SPKI. May be used by the * server, e.g. to prevent replay. */ static VALUE ossl_spki_set_challenge(VALUE self, VALUE str) { NETSCAPE_SPKI *spki; StringValue(str); GetSPKI(self, spki); if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str), RSTRING_LENINT(str))) { ossl_raise(eSPKIError, NULL); } return str; }
static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format) { EC_KEY *ec; BIO *out; int i = -1; int private = 0; char *password = NULL; VALUE str; Require_EC_KEY(self, ec); if (EC_KEY_get0_public_key(ec) == NULL) ossl_raise(eECError, "can't export - no public key set"); if (EC_KEY_check_key(ec) != 1) ossl_raise(eECError, "can't export - EC_KEY_check_key failed"); if (EC_KEY_get0_private_key(ec)) private = 1; if (!(out = BIO_new(BIO_s_mem()))) ossl_raise(eECError, "BIO_new(BIO_s_mem())"); switch(format) { case EXPORT_PEM: if (private) { const EVP_CIPHER *cipher; if (!NIL_P(ciph)) { cipher = GetCipherPtr(ciph); if (!NIL_P(pass)) { StringValue(pass); if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN) ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long"); password = RSTRING_PTR(pass); } } else { cipher = NULL; } i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password); } else { i = PEM_write_bio_EC_PUBKEY(out, ec); } break; case EXPORT_DER: if (private) { i = i2d_ECPrivateKey_bio(out, ec); } else {
static ASN1_BIT_STRING* obj_to_asn1bstr(VALUE obj, long unused_bits) { ASN1_BIT_STRING *bstr; if(unused_bits < 0) unused_bits = 0; StringValue(obj); if(!(bstr = ASN1_BIT_STRING_new())) ossl_raise(eASN1Error, NULL); ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj)); bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */ bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07); return bstr; }
BIO * ossl_obj2bio(volatile VALUE *pobj) { VALUE obj = *pobj; BIO *bio; if (RB_TYPE_P(obj, T_FILE)) obj = rb_funcallv(obj, rb_intern("read"), 0, NULL); StringValue(obj); bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj)); if (!bio) ossl_raise(eOSSLError, "BIO_new_mem_buf"); *pobj = obj; return bio; }
static VALUE mWBXML2_convert(VALUE self, VALUE input, void *conv, mWBXML2_run_conv run_conv) { WBXMLError code = WBXML_OK; WB_UTINY *output_buf_ptr = NULL; WB_ULONG output_len = 0; VALUE retval = Qnil; if (WBXML_OK != (code = run_conv(conv, (WB_UTINY*)StringValuePtr(input), RSTRING_LENINT(input), &output_buf_ptr, &output_len))) { rb_raise(rb_eRuntimeError, "conversion error: %s.", wbxml_errors_string(code)); } retval = rb_str_new((char*)output_buf_ptr, output_len); free(output_buf_ptr); return retval; }
static VALUE method_deserialize(VALUE self, VALUE bson, VALUE opts) { const char* buffer = RSTRING_PTR(bson); int remaining = RSTRING_LENINT(bson); struct deserialize_opts deserialize_opts; deserialize_opts.compile_regex = 1; if (rb_funcall(opts, rb_intern("has_key?"), 1, ID2SYM(rb_intern("compile_regex"))) == Qtrue && rb_hash_aref(opts, ID2SYM(rb_intern("compile_regex"))) == Qfalse) { deserialize_opts.compile_regex = 0; } // NOTE we just swallow the size and end byte here buffer += 4; remaining -= 5; return elements_to_hash(buffer, remaining, &deserialize_opts); }
static VALUE ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) { EVP_CIPHER_CTX *ctx; unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL; unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL; VALUE pass, init_v; if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){ /* * oops. this code mistakes salt for IV. * We deprecated the arguments for this method, but we decided * keeping this behaviour for backward compatibility. */ VALUE cname = rb_class_path(rb_obj_class(self)); rb_warn("arguments for %"PRIsVALUE"#encrypt and %"PRIsVALUE"#decrypt were deprecated; " "use %"PRIsVALUE"#pkcs5_keyivgen to derive key and IV", cname, cname, cname); StringValue(pass); GetCipher(self, ctx); if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv)); else{ StringValue(init_v); if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) { memset(iv, 0, EVP_MAX_IV_LENGTH); memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v)); } else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv)); } EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv, (unsigned char *)RSTRING_PTR(pass), RSTRING_LENINT(pass), 1, key, NULL); p_key = key; p_iv = iv; } else { GetCipher(self, ctx); } if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) { ossl_raise(eCipherError, NULL); } return self; }
/* * call-seq: * cipher.auth_data = string -> string * * Sets the cipher's additional authenticated data. This field must be * set when using AEAD cipher modes such as GCM or CCM. If no associated * data shall be used, this method must *still* be called with a value of "". * The contents of this field should be non-sensitive data which will be * added to the ciphertext to generate the authentication tag which validates * the contents of the ciphertext. * * The AAD must be set prior to encryption or decryption. In encryption mode, * it must be set after calling Cipher#encrypt and setting Cipher#key= and * Cipher#iv=. When decrypting, the authenticated data must be set after key, * iv and especially *after* the authentication tag has been set. I.e. set it * only after calling Cipher#decrypt, Cipher#key=, Cipher#iv= and * Cipher#auth_tag= first. */ static VALUE ossl_cipher_set_auth_data(VALUE self, VALUE data) { EVP_CIPHER_CTX *ctx; unsigned char *in; int in_len; int out_len; StringValue(data); in = (unsigned char *) RSTRING_PTR(data); in_len = RSTRING_LENINT(data); GetCipher(self, ctx); if (!EVP_CipherUpdate(ctx, NULL, &out_len, in, in_len)) ossl_raise(eCipherError, "couldn't set additional authenticated data"); return data; }
/* * call-seq: * sdbm.key(value) -> key * * Returns the +key+ associated with the given +value+. If more than one * +key+ corresponds to the given +value+, then the first key to be found * will be returned. If no keys are found, +nil+ will be returned. */ static VALUE fsdbm_key(VALUE obj, VALUE valstr) { datum key, val; struct dbmdata *dbmp; DBM *dbm; ExportStringValue(valstr); val.dptr = RSTRING_PTR(valstr); val.dsize = RSTRING_LENINT(valstr); GetDBM2(obj, dbmp, dbm); for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) { val = sdbm_fetch(dbm, key); if (val.dsize == RSTRING_LEN(valstr) && memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) return rb_external_str_new(key.dptr, key.dsize); } return Qnil; }
static VALUE fsdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone) { datum key, value; struct dbmdata *dbmp; DBM *dbm; ExportStringValue(keystr); key.dptr = RSTRING_PTR(keystr); key.dsize = RSTRING_LENINT(keystr); GetDBM2(obj, dbmp, dbm); value = sdbm_fetch(dbm, key); if (value.dptr == 0) { if (ifnone == Qnil && rb_block_given_p()) return rb_yield(rb_external_str_new(key.dptr, key.dsize)); return ifnone; } return rb_external_str_new(value.dptr, value.dsize); }
static VALUE ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self) { OCSP_BASICRESP *bs; VALUE val; int ret; rb_scan_args(argc, argv, "01", &val); if(NIL_P(val)) { GetOCSPBasicRes(self, bs); ret = OCSP_basic_add1_nonce(bs, NULL, -1); } else{ StringValue(val); GetOCSPBasicRes(self, bs); ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val)); } if(!ret) ossl_raise(eOCSPError, NULL); return self; }