class Mongo::Crypt::Binding

A Ruby binding for the libmongocrypt C library

@api private

Public Class Methods

check_ctx_status(context) { || ... } click to toggle source

Raise a Mongo::Error::CryptError based on the status of the underlying mongocrypt_ctx_t object.

@return [ nil ] Always nil.

# File lib/mongo/crypt/binding.rb, line 1191
def self.check_ctx_status(context)
  if block_given?
    do_raise = !yield
  else
    do_raise = true
  end

  if do_raise
    status = Status.new

    mongocrypt_ctx_status(context.ctx_p, status.ref)
    status.raise_crypt_error
  end
end
check_kms_ctx_status(kms_context) { || ... } click to toggle source

If the provided block returns false, raise a CryptError with the status information from the provided KmsContext object.

@param [ Mongo::Crypt::KmsContext ] kms_context

@raise [ Mongo::Error::CryptError ] If the provided block returns false

# File lib/mongo/crypt/binding.rb, line 966
def self.check_kms_ctx_status(kms_context)
  unless yield
    status = Status.new

    mongocrypt_kms_ctx_status(kms_context.kms_ctx_p, status.ref)
    status.raise_crypt_error
  end
end
check_status(handle) { || ... } click to toggle source

Raise a Mongo::Error::CryptError based on the status of the underlying mongocrypt_t object.

@return [ nil ] Always nil.

# File lib/mongo/crypt/binding.rb, line 1178
def self.check_status(handle)
  unless yield
    status = Status.new

    mongocrypt_status(handle.ref, status.ref)
    status.raise_crypt_error
  end
end
ctx_datakey_init(context) click to toggle source

Initialize the Context to create a data key

@param [ Mongo::Crypt::Context ] context

@raise [ Mongo::Error::CryptError ] If initialization fails

# File lib/mongo/crypt/binding.rb, line 605
def self.ctx_datakey_init(context)
  check_ctx_status(context) do
    mongocrypt_ctx_datakey_init(context.ctx_p)
  end
end
ctx_decrypt_init(context, command) click to toggle source

Initialize the Context for auto-decryption

@param [ Mongo::Crypt::Context ] context @param [ BSON::Document ] command A BSON document to decrypt

@raise [ Mongo::Error::CryptError ] If initialization fails

# File lib/mongo/crypt/binding.rb, line 698
def self.ctx_decrypt_init(context, command)
  validate_document(command)
  data = command.to_bson.to_s
  Binary.wrap_string(data) do |data_p|
    check_ctx_status(context) do
      mongocrypt_ctx_decrypt_init(context.ctx_p, data_p)
    end
  end
end
ctx_encrypt_init(context, db_name, command) click to toggle source

Initialize the Context for auto-encryption

@param [ Mongo::Crypt::Context ] context @param [ String ] db_name The name of the database against which the

encrypted command is being performed

@param [ Hash ] command The command to be encrypted

@raise [ Mongo::Error::CryptError ] If initialization fails

# File lib/mongo/crypt/binding.rb, line 638
def self.ctx_encrypt_init(context, db_name, command)
  validate_document(command)
  data = command.to_bson.to_s
  Binary.wrap_string(data) do |data_p|
    check_ctx_status(context) do
      mongocrypt_ctx_encrypt_init(context.ctx_p, db_name, -1, data_p)
    end
  end
end
ctx_explicit_decrypt_init(context, doc) click to toggle source

Initialize the Context for explicit decryption

@param [ Mongo::Crypt::Context ] context @param [ Hash ] doc A BSON document to decrypt

@raise [ Mongo::Error::CryptError ] If initialization fails

# File lib/mongo/crypt/binding.rb, line 728
def self.ctx_explicit_decrypt_init(context, doc)
  validate_document(doc)
  data = doc.to_bson.to_s
  Binary.wrap_string(data) do |data_p|
    check_ctx_status(context) do
      mongocrypt_ctx_explicit_decrypt_init(context.ctx_p, data_p)
    end
  end
end
ctx_explicit_encrypt_init(context, doc) click to toggle source

Initialize the Context for explicit encryption

@param [ Mongo::Crypt::Context ] context @param [ Hash ] doc A BSON document to encrypt

@raise [ Mongo::Error::CryptError ] If initialization fails

# File lib/mongo/crypt/binding.rb, line 672
def self.ctx_explicit_encrypt_init(context, doc)
  validate_document(doc)
  data = doc.to_bson.to_s
  Binary.wrap_string(data) do |data_p|
    check_ctx_status(context) do
      mongocrypt_ctx_explicit_encrypt_init(context.ctx_p, data_p)
    end
  end
end
ctx_finalize(context) click to toggle source

Finalize the state machine represented by the Context

@param [ Mongo::Crypt::Context ] context

@raise [ Mongo::Error::CryptError ] If the state machine is not successfully

finalized
# File lib/mongo/crypt/binding.rb, line 1012
def self.ctx_finalize(context)
  binary = Binary.new

  check_ctx_status(context) do
    mongocrypt_ctx_finalize(context.ctx_p, binary.ref)
  end

  # TODO since the binary references a C pointer, and ByteBuffer is
  # written in C in MRI, we could omit a copy of the data by making
  # ByteBuffer reference the string that is owned by libmongocrypt.
  BSON::Document.from_bson(BSON::ByteBuffer.new(binary.to_s), mode: :bson)
end
ctx_kms_done(context) click to toggle source

Indicate to libmongocrypt that it will receive no more KMS replies.

@param [ Mongo::Crypt::Context ] context

@raise [ Mongo::Error::CryptError ] If the operation is unsuccessful

# File lib/mongo/crypt/binding.rb, line 989
def self.ctx_kms_done(context)
  check_ctx_status(context) do
    mongocrypt_ctx_kms_done(context.ctx_p)
  end
end
ctx_mongo_feed(context, doc) click to toggle source

Feed a response from the driver back to libmongocrypt

@param [ Mongo::Crypt::Context ] context @param [ BSON::Document ] doc The document representing the response

@raise [ Mongo::Error::CryptError ] If the response is not fed successfully

# File lib/mongo/crypt/binding.rb, line 808
def self.ctx_mongo_feed(context, doc)
  validate_document(doc)
  data = doc.to_bson.to_s
  Binary.wrap_string(data) do |data_p|
    check_ctx_status(context) do
      mongocrypt_ctx_mongo_feed(context.ctx_p, data_p)
    end
  end
end
ctx_mongo_op(context) click to toggle source

Returns a BSON::Document representing an operation that the driver must perform on behalf of libmongocrypt to get the information it needs in order to continue with encryption/decryption (for example, a filter for a key vault query).

@param [ Mongo::Crypt::Context ] context

@raise [ Mongo::Crypt ] If there is an error getting the operation @return [ BSON::Document ] The operation that the driver must perform

# File lib/mongo/crypt/binding.rb, line 779
def self.ctx_mongo_op(context)
  binary = Binary.new

  check_ctx_status(context) do
    mongocrypt_ctx_mongo_op(context.ctx_p, binary.ref)
  end

  # TODO since the binary references a C pointer, and ByteBuffer is
  # written in C in MRI, we could omit a copy of the data by making
  # ByteBuffer reference the string that is owned by libmongocrypt.
  BSON::Document.from_bson(BSON::ByteBuffer.new(binary.to_s), mode: :bson)
end
ctx_next_kms_ctx(context) click to toggle source

Return a new KmsContext object needed by a Context object.

@param [ Mongo::Crypt::Context ] context

@return [ Mongo::Crypt::KmsContext | nil ] The KmsContext needed to

fetch an AWS master key or nil, if no KmsContext is needed
# File lib/mongo/crypt/binding.rb, line 840
def self.ctx_next_kms_ctx(context)
  kms_ctx_p = mongocrypt_ctx_next_kms_ctx(context.ctx_p)

  if kms_ctx_p.null?
    nil
  else
    KmsContext.new(kms_ctx_p)
  end
end
ctx_setopt_algorithm(context, name) click to toggle source

Set the algorithm on the context

@param [ Mongo::Crypt::Context ] context @param [ String ] name The algorithm name. Valid values are:

- "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
- "AEAD_AES_256_CBC_HMAC_SHA_512-Random"

@raise [ Mongo::Error::CryptError ] If the operation failed

# File lib/mongo/crypt/binding.rb, line 490
def self.ctx_setopt_algorithm(context, name)
  check_ctx_status(context) do
    mongocrypt_ctx_setopt_algorithm(context.ctx_p, name, -1)
  end
end
ctx_setopt_key_alt_names(context, key_alt_names) click to toggle source

Set multiple alternate key names on data key creation

@param [ Mongo::Crypt::Context ] context A DataKeyContext @param [ Array ] key_alt_names An array of alternate key names as strings

@raise [ Mongo::Error::CryptError ] If any of the alternate names are

not valid UTF8 strings
# File lib/mongo/crypt/binding.rb, line 453
def self.ctx_setopt_key_alt_names(context, key_alt_names)
  key_alt_names.each do |key_alt_name|
    key_alt_name_bson = { :keyAltName => key_alt_name }.to_bson.to_s

    Binary.wrap_string(key_alt_name_bson) do |key_alt_name_p|
      check_ctx_status(context) do
        mongocrypt_ctx_setopt_key_alt_name(context.ctx_p, key_alt_name_p)
      end
    end
  end
end
ctx_setopt_key_id(context, key_id) click to toggle source

Sets the key id option on an explicit encryption context.

@param [ Mongo::Crypt::Context ] context Explicit encryption context @param [ String ] key_id The key id

@raise [ Mongo::Error::CryptError ] If the operation failed

# File lib/mongo/crypt/binding.rb, line 420
def self.ctx_setopt_key_id(context, key_id)
  Binary.wrap_string(key_id) do |key_id_p|
    check_ctx_status(context) do
      mongocrypt_ctx_setopt_key_id(context.ctx_p, key_id_p)
    end
  end
end
ctx_setopt_master_key_aws(context, region, arn) click to toggle source

Configure the Context object to take a master key from AWS

@param [ Mongo::Crypt::Context ] context @param [ String ] region The AWS region (e.g. “us-east-2”) @param [ String ] arn The master key Amazon Resource Name

@raise [ Mongo::Error::CryptError ] If the operation failed

# File lib/mongo/crypt/binding.rb, line 521
def self.ctx_setopt_master_key_aws(context, region, arn)
  check_ctx_status(context) do
    mongocrypt_ctx_setopt_masterkey_aws(
      context.ctx_p,
      region,
      -1,
      arn,
      -1
    )
  end
end
ctx_setopt_master_key_aws_endpoint(context, endpoint) click to toggle source

Configure the Context object to take a masterk ey from AWS

@param [ Mongo::Crypt::Context ] context @param [ String ] endpoint The custom AWS master key endpoint

@raise [ Mongo::Error::CryptError ] If the operation failed

# File lib/mongo/crypt/binding.rb, line 554
def self.ctx_setopt_master_key_aws_endpoint(context, endpoint)
  check_ctx_status(context) do
    mongocrypt_ctx_setopt_masterkey_aws_endpoint(
      context.ctx_p,
      endpoint,
      -1,
    )
  end
end
ctx_setopt_master_key_local(context) click to toggle source

Tell the Context object to read the master key from local KMS options

@param [ Mongo::Crypt::Context ] context

@raise [ Mongo::Error::CryptError ] If the operation failed

# File lib/mongo/crypt/binding.rb, line 582
def self.ctx_setopt_master_key_local(context)
  check_ctx_status(context) do
    mongocrypt_ctx_setopt_masterkey_local(context.ctx_p)
  end
end
init(handle) click to toggle source

Initialize the Mongo::Crypt::Handle object

@param [ Mongo::Crypt::Handle ] handle

@raise [ Mongo::Error::CryptError ] If initialization fails

# File lib/mongo/crypt/binding.rb, line 360
def self.init(handle)
  check_status(handle) do
    mongocrypt_init(handle.ref)
  end
end
kms_ctx_bytes_needed(kms_context) click to toggle source

Get the number of bytes needed by the KmsContext.

@param [ Mongo::Crypt::KmsContext ] kms_context

@return [ Integer ] The number of bytes needed

# File lib/mongo/crypt/binding.rb, line 922
def self.kms_ctx_bytes_needed(kms_context)
  mongocrypt_kms_ctx_bytes_needed(kms_context.kms_ctx_p)
end
kms_ctx_endpoint(kms_context) click to toggle source

Get the hostname with which to connect over TLS to get information about the AWS master key.

@param [ Mongo::Crypt::KmsContext ] kms_context

@raise [ Mongo::Error::CryptError ] If the response is not fed successfully

@return [ String | nil ] The hostname, or nil if none exists

# File lib/mongo/crypt/binding.rb, line 898
def self.kms_ctx_endpoint(kms_context)
  ptr = FFI::MemoryPointer.new(:pointer, 1)

  check_kms_ctx_status(kms_context) do
    mongocrypt_kms_ctx_endpoint(kms_context.kms_ctx_p, ptr)
  end

  str_ptr = ptr.read_pointer
  str_ptr.null? ? nil : str_ptr.read_string.force_encoding('UTF-8')
end
kms_ctx_feed(kms_context, bytes) click to toggle source

Feed replies from the KMS back to libmongocrypt.

@param [ Mongo::Crypt::KmsContext ] kms_context @param [ String ] bytes The data to feed to libmongocrypt

@raise [ Mongo::Error::CryptError ] If the response is not fed successfully

# File lib/mongo/crypt/binding.rb, line 942
def self.kms_ctx_feed(kms_context, bytes)
  check_kms_ctx_status(kms_context) do
    Binary.wrap_string(bytes) do |bytes_p|
      mongocrypt_kms_ctx_feed(kms_context.kms_ctx_p, bytes_p)
    end
  end
end
kms_ctx_message(kms_context) click to toggle source

Get the HTTP message needed to fetch the AWS KMS master key from a KmsContext object.

@param [ Mongo::Crypt::KmsContext ] kms_context

@raise [ Mongo::Error::CryptError ] If the response is not fed successfully

@return [ String ] The HTTP message

# File lib/mongo/crypt/binding.rb, line 869
def self.kms_ctx_message(kms_context)
  binary = Binary.new

  check_kms_ctx_status(kms_context) do
    mongocrypt_kms_ctx_message(kms_context.kms_ctx_p, binary.ref)
  end

  return binary.to_s
end
setopt_crypto_hooks(handle, aes_encrypt_cb, aes_decrypt_cb, random_cb, hmac_sha_512_cb, hmac_sha_256_cb, hmac_hash_cb ) click to toggle source

Set crypto callbacks on the Handle

@param [ Mongo::Crypt::Handle ] handle @param [ Method ] aes_encrypt_cb An AES encryption method @param [ Method ] aes_decrypt_cb A AES decryption method @param [ Method ] random_cb A method that returns a string of random bytes @param [ Method ] hmac_sha_512_cb A HMAC SHA-512 method @param [ Method ] hmac_sha_256_cb A HMAC SHA-256 method @param [ Method ] hmac_hash_cb A SHA-256 hash method

@raise [ Mongo::Error::CryptError ] If the callbacks aren’t set successfully

# File lib/mongo/crypt/binding.rb, line 1162
def self.setopt_crypto_hooks(handle,
  aes_encrypt_cb, aes_decrypt_cb, random_cb,
  hmac_sha_512_cb, hmac_sha_256_cb, hmac_hash_cb
)
  check_status(handle) do
    mongocrypt_setopt_crypto_hooks(handle.ref,
      aes_encrypt_cb, aes_decrypt_cb, random_cb,
      hmac_sha_512_cb, hmac_sha_256_cb, hmac_hash_cb, nil
    )
  end
end
setopt_kms_provider_aws(handle, aws_access_key, aws_secret_access_key ) click to toggle source

Configure the Handle object with AWS KMS provider options

@param [ Mongo::Crypt::Handle ] handle @param [ String ] aws_access_key The AWS access key @param [ String ] aws_secret_access_key The AWS secret access key

@raise [ Mongo::Error::CryptError ] If the option is not set successfully

# File lib/mongo/crypt/binding.rb, line 278
def self.setopt_kms_provider_aws(handle,
  aws_access_key, aws_secret_access_key
)
  check_status(handle) do
    mongocrypt_setopt_kms_provider_aws(
      handle.ref,
      aws_access_key,
      -1,
      aws_secret_access_key,
      -1
    )
  end
end
setopt_kms_provider_local(handle, master_key) click to toggle source

Set local KMS provider options on the Mongo::Crypt::Handle object

@param [ Mongo::Crypt::Handle ] handle @param [ String ] master_key The 96-byte local KMS master key

@raise [ Mongo::Error::CryptError ] If the option is not set successfully

# File lib/mongo/crypt/binding.rb, line 312
def self.setopt_kms_provider_local(handle, master_key)
  Binary.wrap_string(master_key) do |master_key_p|
    check_status(handle) do
      mongocrypt_setopt_kms_provider_local(handle.ref, master_key_p)
    end
  end
end
setopt_log_handler(handle, log_callback) click to toggle source

Set the logger callback function on the Mongo::Crypt::Handle object

@param [ Mongo::Crypt::Handle ] handle @param [ Method ] log_callback

@raise [ Mongo::Error::CryptError ] If the callback is not set successfully

# File lib/mongo/crypt/binding.rb, line 247
def self.setopt_log_handler(handle, log_callback)
  check_status(handle) do
    mongocrypt_setopt_log_handler(handle, log_callback, nil)
  end
end
setopt_schema_map(handle, schema_map_doc) click to toggle source

Set schema map on the Mongo::Crypt::Handle object

@param [ Mongo::Crypt::Handle ] handle @param [ BSON::Document ] schema_map_doc The schema map as a

BSON::Document object

@raise [ Mongo::Error::CryptError ] If the schema map is not set successfully

# File lib/mongo/crypt/binding.rb, line 337
def self.setopt_schema_map(handle, schema_map_doc)
  validate_document(schema_map_doc)
  data = schema_map_doc.to_bson.to_s
  Binary.wrap_string(data) do |data_p|
    check_status(handle) do
      mongocrypt_setopt_schema_map(handle.ref, data_p)
    end
  end
end
validate_document(data) click to toggle source

Checks that the specified data is a Hash before serializing it to BSON to prevent errors from libmongocrypt

@note All BSON::Document instances are also Hash instances

@param [ Object ] data The data to be passed to libmongocrypt

@raise [ Mongo::Error::CryptError ] If the data is not a Hash

# File lib/mongo/crypt/binding.rb, line 1214
def self.validate_document(data)
  return if data.is_a?(Hash)

  if data.nil?
    message = "Attempted to pass nil data to libmongocrypt. " +
      "Data must be a Hash"
  else
    message = "Attempted to pass invalid data to libmongocrypt: #{data} " +
      "Data must be a Hash"
  end

  raise Error::CryptError.new(message)
end