Skip to content

Commit 4d7b35e

Browse files
committed
PHPC-1499: Implement ClientEncryption::encrypt
1 parent e65a933 commit 4d7b35e

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

php_phongo.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3104,6 +3104,93 @@ void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clien
31043104
mongoc_client_encryption_datakey_opts_destroy(opts);
31053105
}
31063106
} /* }}} */
3107+
3108+
static mongoc_client_encryption_encrypt_opts_t* phongo_clientencryption_encrypt_opts_from_zval(zval* options TSRMLS_DC) /* {{{ */
3109+
{
3110+
mongoc_client_encryption_encrypt_opts_t* opts;
3111+
3112+
opts = mongoc_client_encryption_encrypt_opts_new();
3113+
3114+
if (!options || Z_TYPE_P(options) != IS_ARRAY) {
3115+
return opts;
3116+
}
3117+
3118+
if (php_array_existsc(options, "keyId")) {
3119+
bson_value_t keyid;
3120+
3121+
php_phongo_zval_to_bson_value(php_array_fetchc(options, "keyId"), PHONGO_BSON_NONE, &keyid TSRMLS_CC);
3122+
if (EG(exception)) {
3123+
goto cleanup;
3124+
}
3125+
3126+
mongoc_client_encryption_encrypt_opts_set_keyid(opts, &keyid);
3127+
}
3128+
3129+
if (php_array_existsc(options, "keyAltName")) {
3130+
char* keyaltname;
3131+
int plen;
3132+
zend_bool pfree;
3133+
3134+
keyaltname = php_array_fetch_string(options, "keyAltName", &plen, &pfree);
3135+
mongoc_client_encryption_encrypt_opts_set_keyaltname(opts, keyaltname);
3136+
3137+
if (pfree) {
3138+
str_efree(keyaltname);
3139+
}
3140+
}
3141+
3142+
if (php_array_existsc(options, "algorithm")) {
3143+
char* algorithm;
3144+
int plen;
3145+
zend_bool pfree;
3146+
3147+
algorithm = php_array_fetch_string(options, "algorithm", &plen, &pfree);
3148+
mongoc_client_encryption_encrypt_opts_set_algorithm(opts, algorithm);
3149+
3150+
if (pfree) {
3151+
str_efree(algorithm);
3152+
}
3153+
}
3154+
3155+
return opts;
3156+
3157+
cleanup:
3158+
if (opts) {
3159+
mongoc_client_encryption_encrypt_opts_destroy(opts);
3160+
}
3161+
3162+
return NULL;
3163+
} /* }}} */
3164+
3165+
void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options TSRMLS_DC) /* {{{ */
3166+
{
3167+
mongoc_client_encryption_encrypt_opts_t* opts;
3168+
bson_value_t ciphertext, value;
3169+
bson_error_t error = { 0 };
3170+
3171+
php_phongo_zval_to_bson_value(zvalue, PHONGO_BSON_NONE, &value TSRMLS_CC);
3172+
3173+
opts = phongo_clientencryption_encrypt_opts_from_zval(options TSRMLS_CC);
3174+
if (!opts) {
3175+
/* Exception already thrown */
3176+
goto cleanup;
3177+
}
3178+
3179+
if (!mongoc_client_encryption_encrypt(clientencryption->client_encryption, &value, opts, &ciphertext, &error)) {
3180+
phongo_throw_exception_from_bson_error_t(&error TSRMLS_CC);
3181+
goto cleanup;
3182+
}
3183+
3184+
if (!php_phongo_bson_value_to_zval(&ciphertext, zciphertext)) {
3185+
/* Exception already thrown */
3186+
goto cleanup;
3187+
}
3188+
3189+
cleanup:
3190+
if (opts) {
3191+
mongoc_client_encryption_encrypt_opts_destroy(opts);
3192+
}
3193+
} /* }}} */
31073194
#else /* MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION */
31083195
static void phongo_throw_exception_no_cse(php_phongo_error_domain_t domain, const char* message TSRMLS_DC) /* {{{ */
31093196
{
@@ -3134,6 +3221,12 @@ void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clien
31343221
phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot create encryption key." TSRMLS_CC);
31353222
}
31363223
/* }}} */
3224+
3225+
void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options TSRMLS_DC) /* {{{ */
3226+
{
3227+
phongo_throw_exception_no_cse(PHONGO_ERROR_RUNTIME, "Cannot encrypt value." TSRMLS_CC);
3228+
}
3229+
/* }}} */
31373230
#endif
31383231

31393232
void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string, zval* options, zval* driverOptions TSRMLS_DC) /* {{{ */

php_phongo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ int php_phongo_set_monitoring_callbacks(mongoc_client_t* client);
168168
bool php_phongo_parse_int64(int64_t* retval, const char* data, phongo_zpp_char_len data_len);
169169

170170
void phongo_clientencryption_create_datakey(php_phongo_clientencryption_t* clientencryption, zval* return_value, char* kms_provider, zval* options TSRMLS_DC);
171+
void phongo_clientencryption_encrypt(php_phongo_clientencryption_t* clientencryption, zval* zvalue, zval* zciphertext, zval* options TSRMLS_DC);
171172

172173
zend_bool phongo_writeerror_init(zval* return_value, bson_t* bson TSRMLS_DC);
173174
zend_bool phongo_writeconcernerror_init(zval* return_value, bson_t* bson TSRMLS_DC);

src/MongoDB/ClientEncryption.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,45 @@ static PHP_METHOD(ClientEncryption, createDataKey)
4949
phongo_clientencryption_create_datakey(intern, return_value, kms_provider, options TSRMLS_CC);
5050
} /* }}} */
5151

52+
/* {{{ proto MongoDB\BSON\Binary MongoDB\Driver\ClientEncryption::encrypt(mixed $value[, array $options])
53+
Encrypts a value with a given key and algorithm */
54+
static PHP_METHOD(ClientEncryption, encrypt)
55+
{
56+
zval* value = NULL;
57+
zval* options = NULL;
58+
zend_error_handling error_handling;
59+
php_phongo_clientencryption_t* intern;
60+
61+
intern = Z_CLIENTENCRYPTION_OBJ_P(getThis());
62+
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
63+
64+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a!", &value, &options) == FAILURE) {
65+
zend_restore_error_handling(&error_handling TSRMLS_CC);
66+
return;
67+
}
68+
69+
zend_restore_error_handling(&error_handling TSRMLS_CC);
70+
71+
phongo_clientencryption_encrypt(intern, value, return_value, options TSRMLS_CC);
72+
} /* }}} */
73+
5274
ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_createDataKey, 0, 0, 1)
5375
ZEND_ARG_INFO(0, kmsProvider)
5476
ZEND_ARG_ARRAY_INFO(0, options, 1)
5577
ZEND_END_ARG_INFO()
5678

79+
ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_encrypt, 0, 0, 1)
80+
ZEND_ARG_INFO(0, value)
81+
ZEND_ARG_ARRAY_INFO(0, options, 1)
82+
ZEND_END_ARG_INFO()
83+
5784
ZEND_BEGIN_ARG_INFO_EX(ai_ClientEncryption_void, 0, 0, 0)
5885
ZEND_END_ARG_INFO()
5986

6087
static zend_function_entry php_phongo_clientencryption_me[] = {
6188
/* clang-format off */
6289
PHP_ME(ClientEncryption, createDataKey, ai_ClientEncryption_createDataKey, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
90+
PHP_ME(ClientEncryption, encrypt, ai_ClientEncryption_encrypt, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
6391
ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_ClientEncryption_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
6492
ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_ClientEncryption_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
6593
PHP_FE_END
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
MongoDB\Driver\ClientEncryption::encrypt()
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_libmongocrypt(); ?>
6+
<?php skip_if_not_live(); ?>
7+
<?php skip_if_server_version('<', '3.6'); ?>
8+
--FILE--
9+
<?php
10+
require_once __DIR__ . "/../utils/basic.inc";
11+
12+
$key = base64_decode('Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk');
13+
14+
$manager = new MongoDB\Driver\Manager(URI);
15+
$clientEncryption = $manager->createClientEncryption(['keyVaultNamespace' => 'default.keys', 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary($key, 0)]]]);
16+
17+
$key = $clientEncryption->createDataKey('local');
18+
19+
var_dump($clientEncryption->encrypt('top-secret', ['keyId' => $key, 'algorithm' => 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic']));
20+
21+
?>
22+
===DONE===
23+
<?php exit(0); ?>
24+
--EXPECTF--
25+
object(MongoDB\BSON\Binary)#%d (%d) {
26+
["data"]=>
27+
string(82) "%a"
28+
["type"]=>
29+
int(6)
30+
}
31+
===DONE===

0 commit comments

Comments
 (0)