ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c in libmongocrypt-helper-1.8.0.0.1001 vs ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c in libmongocrypt-helper-1.11.0.0.1001
- old
+ new
@@ -12,14 +12,18 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "kms_message/kms_kmip_request.h"
#include "mongocrypt-binary-private.h"
#include "mongocrypt-buffer-private.h"
+#include "mongocrypt-crypto-private.h"
#include "mongocrypt-ctx-private.h"
+#include "mongocrypt-endpoint-private.h"
#include "mongocrypt-kms-ctx-private.h"
+#include "mongocrypt-log-private.h"
#include "mongocrypt-opts-private.h"
#include "mongocrypt-private.h"
#include "mongocrypt-status-private.h"
#include "mongocrypt-util-private.h"
#include "mongocrypt.h"
@@ -116,16 +120,21 @@
}
}
static bool is_kms(_kms_request_type_t kms_type) {
return kms_type == MONGOCRYPT_KMS_KMIP_REGISTER || kms_type == MONGOCRYPT_KMS_KMIP_ACTIVATE
- || kms_type == MONGOCRYPT_KMS_KMIP_GET;
+ || kms_type == MONGOCRYPT_KMS_KMIP_GET || kms_type == MONGOCRYPT_KMS_KMIP_ENCRYPT
+ || kms_type == MONGOCRYPT_KMS_KMIP_DECRYPT || kms_type == MONGOCRYPT_KMS_KMIP_CREATE;
}
-static void _init_common(mongocrypt_kms_ctx_t *kms, _mongocrypt_log_t *log, _kms_request_type_t kms_type) {
+static void
+_init_common(mongocrypt_kms_ctx_t *kms, _mongocrypt_log_t *log, _kms_request_type_t kms_type, const char *kmsid) {
BSON_ASSERT_PARAM(kms);
+ BSON_ASSERT_PARAM(kmsid);
+ kms->kmsid = bson_strdup(kmsid);
+
if (is_kms(kms_type)) {
kms->parser = kms_kmip_response_parser_new(NULL /* reserved */);
} else {
kms->parser = kms_response_parser_new();
}
@@ -136,23 +145,24 @@
}
bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms,
_mongocrypt_opts_kms_providers_t *kms_providers,
_mongocrypt_key_doc_t *key,
- _mongocrypt_log_t *log,
- _mongocrypt_crypto_t *crypto) {
+ _mongocrypt_crypto_t *crypto,
+ const char *kmsid,
+ _mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms);
BSON_ASSERT_PARAM(key);
BSON_ASSERT_PARAM(kms_providers);
BSON_ASSERT_PARAM(crypto);
kms_request_opt_t *opt;
mongocrypt_status_t *status;
ctx_with_status_t ctx_with_status;
bool ret = false;
- _init_common(kms, log, MONGOCRYPT_KMS_AWS_DECRYPT);
+ _init_common(kms, log, MONGOCRYPT_KMS_AWS_DECRYPT, kmsid);
status = kms->status;
ctx_with_status.ctx = crypto;
ctx_with_status.status = mongocrypt_status_new();
if (!key->kek.kms_provider) {
@@ -168,21 +178,23 @@
if (!key->kek.provider.aws.region) {
CLIENT_ERR("no key region provided");
goto done;
}
- if (0 == (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AWS)) {
- CLIENT_ERR("aws kms not configured");
+ mc_kms_creds_t kc;
+ if (!_mongocrypt_opts_kms_providers_lookup(kms_providers, key->kek.kmsid, &kc)) {
+ CLIENT_ERR("KMS provider `%s` is not configured", key->kek.kmsid);
goto done;
}
+ BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_AWS);
- if (!kms_providers->aws.access_key_id) {
+ if (!kc.value.aws.access_key_id) {
CLIENT_ERR("aws access key id not provided");
goto done;
}
- if (!kms_providers->aws.secret_access_key) {
+ if (!kc.value.aws.secret_access_key) {
CLIENT_ERR("aws secret access key not provided");
goto done;
}
/* create the KMS request. */
@@ -199,12 +211,12 @@
CLIENT_ERR("failed to set service: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
- if (kms_providers->aws.session_token) {
- if (!kms_request_add_header_field(kms->req, "X-Amz-Security-Token", kms_providers->aws.session_token)) {
+ if (kc.value.aws.session_token) {
+ if (!kms_request_add_header_field(kms->req, "X-Amz-Security-Token", kc.value.aws.session_token)) {
CLIENT_ERR("failed to set session token: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
}
@@ -228,16 +240,16 @@
CLIENT_ERR("failed to set region: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
- if (!kms_request_set_access_key_id(kms->req, kms_providers->aws.access_key_id)) {
+ if (!kms_request_set_access_key_id(kms->req, kc.value.aws.access_key_id)) {
CLIENT_ERR("failed to set aws access key id: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
- if (!kms_request_set_secret_key(kms->req, kms_providers->aws.secret_access_key)) {
+ if (!kms_request_set_secret_key(kms->req, kc.value.aws.secret_access_key)) {
CLIENT_ERR("failed to set aws secret access key: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
@@ -268,12 +280,13 @@
bool _mongocrypt_kms_ctx_init_aws_encrypt(mongocrypt_kms_ctx_t *kms,
_mongocrypt_opts_kms_providers_t *kms_providers,
_mongocrypt_ctx_opts_t *ctx_opts,
_mongocrypt_buffer_t *plaintext_key_material,
- _mongocrypt_log_t *log,
- _mongocrypt_crypto_t *crypto) {
+ _mongocrypt_crypto_t *crypto,
+ const char *kmsid,
+ _mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms);
BSON_ASSERT_PARAM(ctx_opts);
BSON_ASSERT_PARAM(kms_providers);
BSON_ASSERT_PARAM(crypto);
BSON_ASSERT_PARAM(plaintext_key_material);
@@ -281,11 +294,11 @@
kms_request_opt_t *opt;
mongocrypt_status_t *status;
ctx_with_status_t ctx_with_status;
bool ret = false;
- _init_common(kms, log, MONGOCRYPT_KMS_AWS_ENCRYPT);
+ _init_common(kms, log, MONGOCRYPT_KMS_AWS_ENCRYPT, kmsid);
status = kms->status;
ctx_with_status.ctx = crypto;
ctx_with_status.status = mongocrypt_status_new();
if (MONGOCRYPT_KMS_PROVIDER_AWS != ctx_opts->kek.kms_provider) {
@@ -301,21 +314,23 @@
if (!ctx_opts->kek.provider.aws.cmk) {
CLIENT_ERR("no aws cmk provided");
goto done;
}
- if (0 == (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AWS)) {
- CLIENT_ERR("aws kms not configured");
+ mc_kms_creds_t kc;
+ if (!_mongocrypt_opts_kms_providers_lookup(kms_providers, ctx_opts->kek.kmsid, &kc)) {
+ CLIENT_ERR("KMS provider `%s` is not configured", ctx_opts->kek.kmsid);
goto done;
}
+ BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_AWS);
- if (!kms_providers->aws.access_key_id) {
+ if (!kc.value.aws.access_key_id) {
CLIENT_ERR("aws access key id not provided");
goto done;
}
- if (!kms_providers->aws.secret_access_key) {
+ if (!kc.value.aws.secret_access_key) {
CLIENT_ERR("aws secret access key not provided");
goto done;
}
/* create the KMS request. */
@@ -335,12 +350,12 @@
CLIENT_ERR("failed to set service: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
- if (kms_providers->aws.session_token) {
- if (!kms_request_add_header_field(kms->req, "X-Amz-Security-Token", kms_providers->aws.session_token)) {
+ if (kc.value.aws.session_token) {
+ if (!kms_request_add_header_field(kms->req, "X-Amz-Security-Token", kc.value.aws.session_token)) {
CLIENT_ERR("failed to set session token: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
}
@@ -364,16 +379,16 @@
CLIENT_ERR("failed to set region: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
- if (!kms_request_set_access_key_id(kms->req, kms_providers->aws.access_key_id)) {
+ if (!kms_request_set_access_key_id(kms->req, kc.value.aws.access_key_id)) {
CLIENT_ERR("failed to set aws access key id: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
- if (!kms_request_set_secret_key(kms->req, kms_providers->aws.secret_access_key)) {
+ if (!kms_request_set_secret_key(kms->req, kc.value.aws.secret_access_key)) {
CLIENT_ERR("failed to set aws secret access key: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto done;
}
@@ -462,10 +477,14 @@
status = kms->status;
ret = false;
/* Parse out the {en|de}crypted result. */
http_status = kms_response_parser_status(kms->parser);
response = kms_response_parser_get_response(kms->parser);
+ if (!response) {
+ CLIENT_ERR("Failed to get response from parser: %s", kms_response_parser_error(kms->parser));
+ goto fail;
+ }
body = kms_response_get_body(response, &body_len);
if (http_status != 200) {
_handle_non200_http_status(http_status, body, body_len, status);
goto fail;
@@ -539,10 +558,14 @@
status = kms->status;
ret = false;
/* Parse out the oauth token result (or error). */
http_status = kms_response_parser_status(kms->parser);
response = kms_response_parser_get_response(kms->parser);
+ if (!response) {
+ CLIENT_ERR("Failed to get response from parser: %s", kms_response_parser_error(kms->parser));
+ goto fail;
+ }
body = kms_response_get_body(response, &body_len);
if (body_len == 0) {
CLIENT_ERR("Empty KMS response. HTTP status=%d", http_status);
goto fail;
@@ -612,10 +635,14 @@
status = kms->status;
ret = false;
/* Parse out the oauth token result (or error). */
http_status = kms_response_parser_status(kms->parser);
response = kms_response_parser_get_response(kms->parser);
+ if (!response) {
+ CLIENT_ERR("Failed to get response from parser: %s", kms_response_parser_error(kms->parser));
+ goto fail;
+ }
body = kms_response_get_body(response, &body_len);
if (body_len == 0) {
CLIENT_ERR("Empty KMS response. HTTP status=%d", http_status);
goto fail;
@@ -702,10 +729,14 @@
status = kms->status;
ret = false;
/* Parse out the {en|de}crypted result. */
http_status = kms_response_parser_status(kms->parser);
response = kms_response_parser_get_response(kms->parser);
+ if (!response) {
+ CLIENT_ERR("Failed to get response from parser: %s", kms_response_parser_error(kms->parser));
+ goto fail;
+ }
body = kms_response_get_body(response, &body_len);
if (http_status != 200) {
_handle_non200_http_status(http_status, body, body_len, status);
goto fail;
@@ -824,10 +855,148 @@
done:
kms_response_destroy(res);
return ret;
}
+static bool _ctx_done_kmip_create(mongocrypt_kms_ctx_t *kms_ctx) {
+ BSON_ASSERT_PARAM(kms_ctx);
+
+ kms_response_t *res = NULL;
+
+ mongocrypt_status_t *status = kms_ctx->status;
+ bool ret = false;
+ char *uid;
+
+ res = kms_response_parser_get_response(kms_ctx->parser);
+ if (!res) {
+ CLIENT_ERR("Error getting KMIP response: %s", kms_response_parser_error(kms_ctx->parser));
+ goto done;
+ }
+
+ uid = kms_kmip_response_get_unique_identifier(res);
+ if (!uid) {
+ CLIENT_ERR("Error getting UniqueIdentifer from KMIP Create response: %s", kms_response_get_error(res));
+ goto done;
+ }
+
+ if (!_mongocrypt_buffer_steal_from_string(&kms_ctx->result, uid)) {
+ CLIENT_ERR("Error storing KMS UniqueIdentifer result");
+ bson_free(uid);
+ goto done;
+ }
+ ret = true;
+
+done:
+ kms_response_destroy(res);
+ return ret;
+}
+
+static bool _ctx_done_kmip_encrypt(mongocrypt_kms_ctx_t *kms_ctx) {
+ BSON_ASSERT_PARAM(kms_ctx);
+
+ kms_response_t *res = NULL;
+
+ mongocrypt_status_t *status = kms_ctx->status;
+ bool ret = false;
+ uint8_t *ciphertext;
+ size_t ciphertext_len;
+ uint8_t *iv;
+ size_t iv_len;
+ _mongocrypt_buffer_t data_buf, iv_buf;
+ _mongocrypt_buffer_init(&data_buf);
+ _mongocrypt_buffer_init(&iv_buf);
+
+ res = kms_response_parser_get_response(kms_ctx->parser);
+ if (!res) {
+ CLIENT_ERR("Error getting KMIP response: %s", kms_response_parser_error(kms_ctx->parser));
+ goto done;
+ }
+
+ ciphertext = kms_kmip_response_get_data(res, &ciphertext_len);
+ if (!ciphertext) {
+ CLIENT_ERR("Error getting data from KMIP Encrypt response: %s", kms_response_get_error(res));
+ goto done;
+ }
+
+ iv = kms_kmip_response_get_iv(res, &iv_len);
+ if (!iv) {
+ CLIENT_ERR("Error getting IV from KMIP Encrypt response: %s", kms_response_get_error(res));
+ bson_free(ciphertext);
+ goto done;
+ }
+
+ if (iv_len != MONGOCRYPT_IV_LEN) {
+ CLIENT_ERR("KMIP IV response has unexpected length: %zu", iv_len);
+ bson_free(ciphertext);
+ bson_free(iv);
+ goto done;
+ }
+
+ if (!_mongocrypt_buffer_steal_from_data_and_size(&data_buf, ciphertext, ciphertext_len)) {
+ CLIENT_ERR("Error storing KMS Encrypt result");
+ bson_free(ciphertext);
+ bson_free(iv);
+ goto done;
+ }
+
+ if (!_mongocrypt_buffer_steal_from_data_and_size(&iv_buf, iv, iv_len)) {
+ CLIENT_ERR("Error storing KMS Encrypt IV");
+ bson_free(ciphertext);
+ bson_free(iv);
+ goto done;
+ }
+
+ const _mongocrypt_buffer_t results_buf[2] = {iv_buf, data_buf};
+ if (!_mongocrypt_buffer_concat(&kms_ctx->result, results_buf, 2)) {
+ CLIENT_ERR("Error concatenating IV and ciphertext");
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ kms_response_destroy(res);
+ _mongocrypt_buffer_cleanup(&iv_buf);
+ _mongocrypt_buffer_cleanup(&data_buf);
+ return ret;
+}
+
+static bool _ctx_done_kmip_decrypt(mongocrypt_kms_ctx_t *kms_ctx) {
+ BSON_ASSERT_PARAM(kms_ctx);
+
+ kms_response_t *res = NULL;
+
+ mongocrypt_status_t *status = kms_ctx->status;
+ bool ret = false;
+ uint8_t *ciphertext;
+ size_t ciphertext_len;
+
+ res = kms_response_parser_get_response(kms_ctx->parser);
+ if (!res) {
+ CLIENT_ERR("Error getting KMIP response: %s", kms_response_parser_error(kms_ctx->parser));
+ goto done;
+ }
+
+ ciphertext = kms_kmip_response_get_data(res, &ciphertext_len);
+ if (!ciphertext) {
+ CLIENT_ERR("Error getting data from KMIP Decrypt response: %s", kms_response_get_error(res));
+ goto done;
+ }
+
+ if (!_mongocrypt_buffer_steal_from_data_and_size(&kms_ctx->result, ciphertext, ciphertext_len)) {
+ CLIENT_ERR("Error storing KMS Decrypt result");
+ bson_free(ciphertext);
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ kms_response_destroy(res);
+ return ret;
+}
+
bool mongocrypt_kms_ctx_feed(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes) {
if (!kms) {
return false;
}
@@ -887,10 +1056,13 @@
case MONGOCRYPT_KMS_GCP_ENCRYPT: return _ctx_done_gcp(kms, "ciphertext");
case MONGOCRYPT_KMS_GCP_DECRYPT: return _ctx_done_gcp(kms, "plaintext");
case MONGOCRYPT_KMS_KMIP_REGISTER: return _ctx_done_kmip_register(kms);
case MONGOCRYPT_KMS_KMIP_ACTIVATE: return _ctx_done_kmip_activate(kms);
case MONGOCRYPT_KMS_KMIP_GET: return _ctx_done_kmip_get(kms);
+ case MONGOCRYPT_KMS_KMIP_ENCRYPT: return _ctx_done_kmip_encrypt(kms);
+ case MONGOCRYPT_KMS_KMIP_DECRYPT: return _ctx_done_kmip_decrypt(kms);
+ case MONGOCRYPT_KMS_KMIP_CREATE: return _ctx_done_kmip_create(kms);
}
}
return true;
}
@@ -946,10 +1118,11 @@
}
mongocrypt_status_destroy(kms->status);
_mongocrypt_buffer_cleanup(&kms->msg);
_mongocrypt_buffer_cleanup(&kms->result);
bson_free(kms->endpoint);
+ bson_free(kms->kmsid);
}
bool mongocrypt_kms_ctx_message(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *msg) {
if (!kms) {
return false;
@@ -977,29 +1150,32 @@
*endpoint = kms->endpoint;
return true;
}
bool _mongocrypt_kms_ctx_init_azure_auth(mongocrypt_kms_ctx_t *kms,
- _mongocrypt_log_t *log,
- _mongocrypt_opts_kms_providers_t *kms_providers,
- _mongocrypt_endpoint_t *key_vault_endpoint) {
+ const mc_kms_creds_t *kc,
+ _mongocrypt_endpoint_t *key_vault_endpoint,
+ const char *kmsid,
+ _mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms);
- BSON_ASSERT_PARAM(kms_providers);
+ BSON_ASSERT_PARAM(kc);
kms_request_opt_t *opt = NULL;
mongocrypt_status_t *status;
- _mongocrypt_endpoint_t *identity_platform_endpoint;
+ const _mongocrypt_endpoint_t *identity_platform_endpoint;
char *scope = NULL;
const char *hostname;
char *request_string;
bool ret = false;
- _init_common(kms, log, MONGOCRYPT_KMS_AZURE_OAUTH);
+ _init_common(kms, log, MONGOCRYPT_KMS_AZURE_OAUTH, kmsid);
status = kms->status;
- identity_platform_endpoint = kms_providers->azure.identity_platform_endpoint;
+ BSON_ASSERT(kc->type == MONGOCRYPT_KMS_PROVIDER_AZURE);
+ identity_platform_endpoint = kc->value.azure.identity_platform_endpoint;
+
if (identity_platform_endpoint) {
kms->endpoint = bson_strdup(identity_platform_endpoint->host_and_port);
hostname = identity_platform_endpoint->host;
} else {
kms->endpoint = bson_strdup("login.microsoftonline.com");
@@ -1020,13 +1196,13 @@
BSON_ASSERT(opt);
kms_request_opt_set_connection_close(opt, true);
kms_request_opt_set_provider(opt, KMS_REQUEST_PROVIDER_AZURE);
kms->req = kms_azure_request_oauth_new(hostname,
scope,
- kms_providers->azure.tenant_id,
- kms_providers->azure.client_id,
- kms_providers->azure.client_secret,
+ kc->value.azure.tenant_id,
+ kc->value.azure.client_id,
+ kc->value.azure.client_secret,
opt);
if (kms_request_get_error(kms->req)) {
CLIENT_ERR("error constructing KMS message: %s", kms_request_get_error(kms->req));
goto fail;
}
@@ -1047,15 +1223,16 @@
kms_request_opt_destroy(opt);
return ret;
}
bool _mongocrypt_kms_ctx_init_azure_wrapkey(mongocrypt_kms_ctx_t *kms,
- _mongocrypt_log_t *log,
_mongocrypt_opts_kms_providers_t *kms_providers,
struct __mongocrypt_ctx_opts_t *ctx_opts,
const char *access_token,
- _mongocrypt_buffer_t *plaintext_key_material) {
+ _mongocrypt_buffer_t *plaintext_key_material,
+ const char *kmsid,
+ _mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms);
BSON_ASSERT_PARAM(ctx_opts);
BSON_ASSERT_PARAM(plaintext_key_material);
kms_request_opt_t *opt = NULL;
@@ -1064,11 +1241,11 @@
char *payload = NULL;
const char *host;
char *request_string;
bool ret = false;
- _init_common(kms, log, MONGOCRYPT_KMS_AZURE_WRAPKEY);
+ _init_common(kms, log, MONGOCRYPT_KMS_AZURE_WRAPKEY, kmsid);
status = kms->status;
BSON_ASSERT(ctx_opts->kek.provider.azure.key_vault_endpoint);
kms->endpoint = bson_strdup(ctx_opts->kek.provider.azure.key_vault_endpoint->host_and_port);
@@ -1112,10 +1289,11 @@
bool _mongocrypt_kms_ctx_init_azure_unwrapkey(mongocrypt_kms_ctx_t *kms,
_mongocrypt_opts_kms_providers_t *kms_providers,
const char *access_token,
_mongocrypt_key_doc_t *key,
+ const char *kmsid,
_mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms);
BSON_ASSERT_PARAM(key);
kms_request_opt_t *opt = NULL;
@@ -1124,11 +1302,11 @@
char *payload = NULL;
const char *host;
char *request_string;
bool ret = false;
- _init_common(kms, log, MONGOCRYPT_KMS_AZURE_UNWRAPKEY);
+ _init_common(kms, log, MONGOCRYPT_KMS_AZURE_UNWRAPKEY, kmsid);
status = kms->status;
BSON_ASSERT(key->kek.provider.azure.key_vault_endpoint);
kms->endpoint = bson_strdup(key->kek.provider.azure.key_vault_endpoint->host_and_port);
@@ -1210,34 +1388,37 @@
ctx_with_status->status);
return ret;
}
bool _mongocrypt_kms_ctx_init_gcp_auth(mongocrypt_kms_ctx_t *kms,
- _mongocrypt_log_t *log,
_mongocrypt_opts_t *crypt_opts,
- _mongocrypt_opts_kms_providers_t *kms_providers,
- _mongocrypt_endpoint_t *kms_endpoint) {
+ const mc_kms_creds_t *kc,
+ _mongocrypt_endpoint_t *kms_endpoint,
+ const char *kmsid,
+ _mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms);
- BSON_ASSERT_PARAM(kms_providers);
+ BSON_ASSERT_PARAM(kc);
BSON_ASSERT_PARAM(crypt_opts);
kms_request_opt_t *opt = NULL;
mongocrypt_status_t *status;
- _mongocrypt_endpoint_t *auth_endpoint;
+ const _mongocrypt_endpoint_t *auth_endpoint;
char *scope = NULL;
char *audience = NULL;
const char *hostname;
char *request_string;
bool ret = false;
ctx_with_status_t ctx_with_status;
- _init_common(kms, log, MONGOCRYPT_KMS_GCP_OAUTH);
+ _init_common(kms, log, MONGOCRYPT_KMS_GCP_OAUTH, kmsid);
status = kms->status;
ctx_with_status.ctx = crypt_opts;
ctx_with_status.status = mongocrypt_status_new();
- auth_endpoint = kms_providers->gcp.endpoint;
+ BSON_ASSERT(kc->type == MONGOCRYPT_KMS_PROVIDER_GCP);
+
+ auth_endpoint = kc->value.gcp.endpoint;
if (auth_endpoint) {
kms->endpoint = bson_strdup(auth_endpoint->host_and_port);
hostname = auth_endpoint->host;
audience = bson_strdup_printf("https://%s/token", auth_endpoint->host);
} else {
@@ -1260,15 +1441,15 @@
kms_request_opt_set_provider(opt, KMS_REQUEST_PROVIDER_GCP);
if (crypt_opts->sign_rsaes_pkcs1_v1_5) {
kms_request_opt_set_crypto_hook_sign_rsaes_pkcs1_v1_5(opt, _sign_rsaes_pkcs1_v1_5_trampoline, &ctx_with_status);
}
kms->req = kms_gcp_request_oauth_new(hostname,
- kms_providers->gcp.email,
+ kc->value.gcp.email,
audience,
scope,
- (const char *)kms_providers->gcp.private_key.data,
- kms_providers->gcp.private_key.len,
+ (const char *)kc->value.gcp.private_key.data,
+ kc->value.gcp.private_key.len,
opt);
if (kms_request_get_error(kms->req)) {
CLIENT_ERR("error constructing KMS message: %s", kms_request_get_error(kms->req));
_mongocrypt_status_append(status, ctx_with_status.status);
goto fail;
@@ -1293,15 +1474,16 @@
mongocrypt_status_destroy(ctx_with_status.status);
return ret;
}
bool _mongocrypt_kms_ctx_init_gcp_encrypt(mongocrypt_kms_ctx_t *kms,
- _mongocrypt_log_t *log,
_mongocrypt_opts_kms_providers_t *kms_providers,
struct __mongocrypt_ctx_opts_t *ctx_opts,
const char *access_token,
- _mongocrypt_buffer_t *plaintext_key_material) {
+ _mongocrypt_buffer_t *plaintext_key_material,
+ const char *kmsid,
+ _mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms);
BSON_ASSERT_PARAM(ctx_opts);
BSON_ASSERT_PARAM(kms_providers);
BSON_ASSERT_PARAM(access_token);
BSON_ASSERT_PARAM(plaintext_key_material);
@@ -1312,11 +1494,11 @@
char *payload = NULL;
const char *hostname;
char *request_string;
bool ret = false;
- _init_common(kms, log, MONGOCRYPT_KMS_GCP_ENCRYPT);
+ _init_common(kms, log, MONGOCRYPT_KMS_GCP_ENCRYPT, kmsid);
status = kms->status;
if (ctx_opts->kek.provider.gcp.endpoint) {
kms->endpoint = bson_strdup(ctx_opts->kek.provider.gcp.endpoint->host_and_port);
hostname = ctx_opts->kek.provider.gcp.endpoint->host;
@@ -1366,10 +1548,11 @@
bool _mongocrypt_kms_ctx_init_gcp_decrypt(mongocrypt_kms_ctx_t *kms,
_mongocrypt_opts_kms_providers_t *kms_providers,
const char *access_token,
_mongocrypt_key_doc_t *key,
+ const char *kmsid,
_mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms);
BSON_ASSERT_PARAM(kms_providers);
BSON_ASSERT_PARAM(access_token);
BSON_ASSERT_PARAM(key);
@@ -1380,11 +1563,11 @@
char *payload = NULL;
const char *hostname;
char *request_string;
bool ret = false;
- _init_common(kms, log, MONGOCRYPT_KMS_GCP_DECRYPT);
+ _init_common(kms, log, MONGOCRYPT_KMS_GCP_DECRYPT, kmsid);
status = kms->status;
if (key->kek.provider.gcp.endpoint) {
kms->endpoint = bson_strdup(key->kek.provider.gcp.endpoint->host_and_port);
hostname = key->kek.provider.gcp.endpoint->host;
@@ -1433,21 +1616,22 @@
bool _mongocrypt_kms_ctx_init_kmip_register(mongocrypt_kms_ctx_t *kms_ctx,
const _mongocrypt_endpoint_t *endpoint,
const uint8_t *secretdata,
uint32_t secretdata_len,
+ const char *kmsid,
_mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms_ctx);
BSON_ASSERT_PARAM(endpoint);
BSON_ASSERT_PARAM(secretdata);
mongocrypt_status_t *status;
bool ret = false;
const uint8_t *reqdata;
size_t reqlen;
- _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_REGISTER);
+ _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_REGISTER, kmsid);
status = kms_ctx->status;
kms_ctx->endpoint = bson_strdup(endpoint->host_and_port);
_mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT);
kms_ctx->req = kms_kmip_request_register_secretdata_new(NULL /* reserved */, secretdata, secretdata_len);
@@ -1469,21 +1653,22 @@
}
bool _mongocrypt_kms_ctx_init_kmip_activate(mongocrypt_kms_ctx_t *kms_ctx,
const _mongocrypt_endpoint_t *endpoint,
const char *unique_identifier,
+ const char *kmsid,
_mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms_ctx);
BSON_ASSERT_PARAM(endpoint);
BSON_ASSERT_PARAM(unique_identifier);
mongocrypt_status_t *status;
bool ret = false;
size_t reqlen;
const uint8_t *reqdata;
- _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_ACTIVATE);
+ _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_ACTIVATE, kmsid);
status = kms_ctx->status;
kms_ctx->endpoint = bson_strdup(endpoint->host_and_port);
_mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT);
kms_ctx->req = kms_kmip_request_activate_new(NULL /* reserved */, unique_identifier);
@@ -1505,21 +1690,22 @@
}
bool _mongocrypt_kms_ctx_init_kmip_get(mongocrypt_kms_ctx_t *kms_ctx,
const _mongocrypt_endpoint_t *endpoint,
const char *unique_identifier,
+ const char *kmsid,
_mongocrypt_log_t *log) {
BSON_ASSERT_PARAM(kms_ctx);
BSON_ASSERT_PARAM(endpoint);
BSON_ASSERT_PARAM(unique_identifier);
mongocrypt_status_t *status;
bool ret = false;
size_t reqlen;
const uint8_t *reqdata;
- _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_GET);
+ _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_GET, kmsid);
status = kms_ctx->status;
kms_ctx->endpoint = bson_strdup(endpoint->host_and_port);
_mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT);
kms_ctx->req = kms_kmip_request_get_new(NULL /* reserved */, unique_identifier);
@@ -1538,10 +1724,133 @@
ret = true;
done:
return ret;
}
+bool _mongocrypt_kms_ctx_init_kmip_create(mongocrypt_kms_ctx_t *kms_ctx,
+ const _mongocrypt_endpoint_t *endpoint,
+ const char *kmsid,
+ _mongocrypt_log_t *log) {
+ BSON_ASSERT_PARAM(kms_ctx);
+ BSON_ASSERT_PARAM(endpoint);
+ bool ret = false;
+
+ _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_CREATE, kmsid);
+ mongocrypt_status_t *status = kms_ctx->status;
+ kms_ctx->endpoint = bson_strdup(endpoint->host_and_port);
+ _mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT);
+
+ kms_ctx->req = kms_kmip_request_create_new(NULL /* reserved */);
+
+ if (kms_request_get_error(kms_ctx->req)) {
+ CLIENT_ERR("Error creating KMIP create request: %s", kms_request_get_error(kms_ctx->req));
+ goto done;
+ }
+
+ size_t reqlen;
+ const uint8_t *reqdata = kms_request_to_bytes(kms_ctx->req, &reqlen);
+ if (!_mongocrypt_buffer_copy_from_data_and_size(&kms_ctx->msg, reqdata, reqlen)) {
+ CLIENT_ERR("Error storing KMS request payload");
+ goto done;
+ }
+
+ ret = true;
+done:
+ return ret;
+}
+
+bool _mongocrypt_kms_ctx_init_kmip_encrypt(mongocrypt_kms_ctx_t *kms_ctx,
+ const _mongocrypt_endpoint_t *endpoint,
+ const char *unique_identifier,
+ const char *kmsid,
+ _mongocrypt_buffer_t *plaintext,
+ _mongocrypt_log_t *log) {
+ BSON_ASSERT_PARAM(kms_ctx);
+ BSON_ASSERT_PARAM(endpoint);
+ BSON_ASSERT_PARAM(plaintext);
+ bool ret = false;
+
+ _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_ENCRYPT, kmsid);
+ mongocrypt_status_t *status = kms_ctx->status;
+ kms_ctx->endpoint = bson_strdup(endpoint->host_and_port);
+ _mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT);
+
+ kms_ctx->req =
+ kms_kmip_request_encrypt_new(NULL /* reserved */, unique_identifier, plaintext->data, plaintext->len);
+
+ if (kms_request_get_error(kms_ctx->req)) {
+ CLIENT_ERR("Error creating KMIP encrypt request: %s", kms_request_get_error(kms_ctx->req));
+ goto done;
+ }
+
+ size_t reqlen;
+ const uint8_t *reqdata = kms_request_to_bytes(kms_ctx->req, &reqlen);
+ if (!_mongocrypt_buffer_copy_from_data_and_size(&kms_ctx->msg, reqdata, reqlen)) {
+ CLIENT_ERR("Error storing KMS request payload");
+ goto done;
+ }
+
+ ret = true;
+done:
+ return ret;
+}
+
+bool _mongocrypt_kms_ctx_init_kmip_decrypt(mongocrypt_kms_ctx_t *kms_ctx,
+ const _mongocrypt_endpoint_t *endpoint,
+ const char *kmsid,
+ _mongocrypt_key_doc_t *key,
+ _mongocrypt_log_t *log) {
+ BSON_ASSERT_PARAM(kms_ctx);
+ BSON_ASSERT_PARAM(endpoint);
+ BSON_ASSERT_PARAM(key);
+ bool ret = false;
+
+ _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_DECRYPT, kmsid);
+ mongocrypt_status_t *status = kms_ctx->status;
+ kms_ctx->endpoint = bson_strdup(endpoint->host_and_port);
+ _mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT);
+
+ _mongocrypt_buffer_t iv;
+ if (!_mongocrypt_buffer_from_subrange(&iv, &key->key_material, 0, MONGOCRYPT_IV_LEN)) {
+ CLIENT_ERR("Error getting IV from key material");
+ goto done;
+ }
+ _mongocrypt_buffer_t ciphertext;
+ if (!_mongocrypt_buffer_from_subrange(&ciphertext,
+ &key->key_material,
+ MONGOCRYPT_IV_LEN,
+ key->key_material.len - MONGOCRYPT_IV_LEN)) {
+ CLIENT_ERR("Error getting ciphertext from key material");
+ goto done;
+ }
+
+ BSON_ASSERT(key->kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_KMIP);
+ BSON_ASSERT(key->kek.provider.kmip.delegated);
+ kms_ctx->req = kms_kmip_request_decrypt_new(NULL /* reserved */,
+ key->kek.provider.kmip.key_id,
+ ciphertext.data,
+ ciphertext.len,
+ iv.data,
+ iv.len);
+
+ if (kms_request_get_error(kms_ctx->req)) {
+ CLIENT_ERR("Error creating KMIP decrypt request: %s", kms_request_get_error(kms_ctx->req));
+ goto done;
+ }
+
+ size_t reqlen;
+ const uint8_t *reqdata = kms_request_to_bytes(kms_ctx->req, &reqlen);
+ if (!_mongocrypt_buffer_copy_from_data_and_size(&kms_ctx->msg, reqdata, reqlen)) {
+ CLIENT_ERR("Error storing KMS request payload");
+ goto done;
+ }
+
+ ret = true;
+done:
+ return ret;
+}
+
static const char *set_and_ret(const char *what, uint32_t *len) {
BSON_ASSERT_PARAM(what);
if (len) {
BSON_ASSERT(size_to_uint32(strlen(what), len));
@@ -1551,20 +1860,7 @@
const char *mongocrypt_kms_ctx_get_kms_provider(mongocrypt_kms_ctx_t *kms, uint32_t *len) {
BSON_ASSERT_PARAM(kms);
/* len is checked in set_and_ret () before it is used */
- switch (kms->req_type) {
- default: BSON_ASSERT(false && "unknown KMS request type");
- case MONGOCRYPT_KMS_AWS_ENCRYPT:
- case MONGOCRYPT_KMS_AWS_DECRYPT: return set_and_ret("aws", len);
- case MONGOCRYPT_KMS_AZURE_OAUTH:
- case MONGOCRYPT_KMS_AZURE_WRAPKEY:
- case MONGOCRYPT_KMS_AZURE_UNWRAPKEY: return set_and_ret("azure", len);
- case MONGOCRYPT_KMS_GCP_OAUTH:
- case MONGOCRYPT_KMS_GCP_ENCRYPT:
- case MONGOCRYPT_KMS_GCP_DECRYPT: return set_and_ret("gcp", len);
- case MONGOCRYPT_KMS_KMIP_REGISTER:
- case MONGOCRYPT_KMS_KMIP_ACTIVATE:
- case MONGOCRYPT_KMS_KMIP_GET: return set_and_ret("kmip", len);
- }
+ return set_and_ret(kms->kmsid, len);
}