1 /*
2  * Copyright 2019-present MongoDB, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <bson/bson.h>
18 
19 #include "mongocrypt-ctx-private.h"
20 #include "mongocrypt-key-broker-private.h"
21 
22 #define ALGORITHM_DETERMINISTIC "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
23 #define ALGORITHM_DETERMINISTIC_LEN 43
24 #define ALGORITHM_RANDOM "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
25 #define ALGORITHM_RANDOM_LEN 36
26 
27 bool
_mongocrypt_ctx_fail_w_msg(mongocrypt_ctx_t * ctx,const char * msg)28 _mongocrypt_ctx_fail_w_msg (mongocrypt_ctx_t *ctx, const char *msg)
29 {
30    _mongocrypt_set_error (ctx->status,
31                           MONGOCRYPT_STATUS_ERROR_CLIENT,
32                           MONGOCRYPT_GENERIC_ERROR_CODE,
33                           "%s",
34                           msg);
35    return _mongocrypt_ctx_fail (ctx);
36 }
37 
38 /* A failure status has already been set. */
39 bool
_mongocrypt_ctx_fail(mongocrypt_ctx_t * ctx)40 _mongocrypt_ctx_fail (mongocrypt_ctx_t *ctx)
41 {
42    if (mongocrypt_status_ok (ctx->status)) {
43       return _mongocrypt_ctx_fail_w_msg (
44          ctx, "unexpected, failing but no error status set");
45    }
46    ctx->state = MONGOCRYPT_CTX_ERROR;
47    return false;
48 }
49 
50 
51 static bool
_set_binary_opt(mongocrypt_ctx_t * ctx,mongocrypt_binary_t * binary,_mongocrypt_buffer_t * buf,bson_subtype_t subtype)52 _set_binary_opt (mongocrypt_ctx_t *ctx,
53                  mongocrypt_binary_t *binary,
54                  _mongocrypt_buffer_t *buf,
55                  bson_subtype_t subtype)
56 {
57    BSON_ASSERT (ctx);
58 
59    if (ctx->state == MONGOCRYPT_CTX_ERROR) {
60       return false;
61    }
62 
63    if (!binary || !binary->data) {
64       return _mongocrypt_ctx_fail_w_msg (ctx, "option must be non-NULL");
65    }
66 
67    if (!_mongocrypt_buffer_empty (buf)) {
68       return _mongocrypt_ctx_fail_w_msg (ctx, "option already set");
69    }
70 
71    if (ctx->initialized) {
72       return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
73    }
74 
75    if (subtype == BSON_SUBTYPE_UUID && binary->len != 16) {
76       return _mongocrypt_ctx_fail_w_msg (ctx, "expected 16 byte UUID");
77    }
78 
79    _mongocrypt_buffer_copy_from_binary (buf, binary);
80    buf->subtype = subtype;
81 
82    return true;
83 }
84 
85 
86 bool
mongocrypt_ctx_setopt_key_id(mongocrypt_ctx_t * ctx,mongocrypt_binary_t * key_id)87 mongocrypt_ctx_setopt_key_id (mongocrypt_ctx_t *ctx,
88                               mongocrypt_binary_t *key_id)
89 {
90    if (!ctx) {
91       return false;
92    }
93 
94    if (ctx->crypt->log.trace_enabled && key_id && key_id->data) {
95       char *key_id_val;
96       key_id_val =
97          _mongocrypt_new_string_from_bytes (key_id->data, key_id->len);
98       _mongocrypt_log (&ctx->crypt->log,
99                        MONGOCRYPT_LOG_LEVEL_TRACE,
100                        "%s (%s=\"%s\")",
101                        BSON_FUNC,
102                        "key_id",
103                        key_id_val);
104       bson_free (key_id_val);
105    }
106 
107    return _set_binary_opt (ctx, key_id, &ctx->opts.key_id, BSON_SUBTYPE_UUID);
108 }
109 
110 
111 bool
mongocrypt_ctx_setopt_key_alt_name(mongocrypt_ctx_t * ctx,mongocrypt_binary_t * key_alt_name)112 mongocrypt_ctx_setopt_key_alt_name (mongocrypt_ctx_t *ctx,
113                                     mongocrypt_binary_t *key_alt_name)
114 {
115    bson_t as_bson;
116    bson_iter_t iter;
117    _mongocrypt_key_alt_name_t *new_key_alt_name;
118    const char *key;
119 
120    if (!ctx) {
121       return false;
122    }
123 
124    if (ctx->initialized) {
125       return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
126    }
127 
128    if (ctx->state == MONGOCRYPT_CTX_ERROR) {
129       return false;
130    }
131 
132    if (!key_alt_name || !key_alt_name->data) {
133       return _mongocrypt_ctx_fail_w_msg (ctx, "option must be non-NULL");
134    }
135 
136    if (!_mongocrypt_binary_to_bson (key_alt_name, &as_bson)) {
137       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid keyAltName bson object");
138    }
139 
140    if (!bson_iter_init (&iter, &as_bson) || !bson_iter_next (&iter)) {
141       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid bson");
142    }
143 
144    key = bson_iter_key (&iter);
145    BSON_ASSERT (key);
146    if (0 != strcmp (key, "keyAltName")) {
147       return _mongocrypt_ctx_fail_w_msg (
148          ctx, "keyAltName must have field 'keyAltName'");
149    }
150 
151    if (!BSON_ITER_HOLDS_UTF8 (&iter)) {
152       return _mongocrypt_ctx_fail_w_msg (ctx, "keyAltName expected to be UTF8");
153    }
154 
155    new_key_alt_name = _mongocrypt_key_alt_name_new (bson_iter_value (&iter));
156 
157    if (ctx->opts.key_alt_names &&
158        _mongocrypt_key_alt_name_intersects (ctx->opts.key_alt_names,
159                                             new_key_alt_name)) {
160       _mongocrypt_key_alt_name_destroy_all (new_key_alt_name);
161       return _mongocrypt_ctx_fail_w_msg (ctx, "duplicate keyAltNames found");
162    }
163    new_key_alt_name->next = ctx->opts.key_alt_names;
164    ctx->opts.key_alt_names = new_key_alt_name;
165 
166    if (bson_iter_next (&iter)) {
167       return _mongocrypt_ctx_fail_w_msg (
168          ctx, "unrecognized field, only keyAltName expected");
169    }
170 
171    return true;
172 }
173 
174 
175 bool
mongocrypt_ctx_setopt_algorithm(mongocrypt_ctx_t * ctx,const char * algorithm,int len)176 mongocrypt_ctx_setopt_algorithm (mongocrypt_ctx_t *ctx,
177                                  const char *algorithm,
178                                  int len)
179 {
180    size_t calculated_len;
181 
182    if (!ctx) {
183       return false;
184    }
185 
186    if (ctx->initialized) {
187       return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
188    }
189 
190    if (ctx->state == MONGOCRYPT_CTX_ERROR) {
191       return false;
192    }
193 
194    if (ctx->opts.algorithm != MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
195       return _mongocrypt_ctx_fail_w_msg (ctx, "already set algorithm");
196    }
197 
198    if (len < -1) {
199       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid algorithm length");
200    }
201 
202    if (!algorithm) {
203       return _mongocrypt_ctx_fail_w_msg (ctx, "passed null algorithm");
204    }
205 
206    calculated_len = len == -1 ? strlen (algorithm) : (size_t) len;
207    if (ctx->crypt->log.trace_enabled) {
208       _mongocrypt_log (&ctx->crypt->log,
209                        MONGOCRYPT_LOG_LEVEL_TRACE,
210                        "%s (%s=\"%.*s\")",
211                        BSON_FUNC,
212                        "algorithm",
213                        (int) calculated_len,
214                        algorithm);
215    }
216 
217    if (calculated_len == ALGORITHM_DETERMINISTIC_LEN &&
218        strncmp (algorithm,
219                 ALGORITHM_DETERMINISTIC,
220                 ALGORITHM_DETERMINISTIC_LEN) == 0) {
221       ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_DETERMINISTIC;
222       return true;
223    }
224 
225    if (calculated_len == ALGORITHM_RANDOM_LEN &&
226        strncmp (algorithm, ALGORITHM_RANDOM, ALGORITHM_RANDOM_LEN) == 0) {
227       ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM;
228       return true;
229    }
230 
231    return _mongocrypt_ctx_fail_w_msg (ctx, "unsupported algorithm");
232 }
233 
234 
235 mongocrypt_ctx_t *
mongocrypt_ctx_new(mongocrypt_t * crypt)236 mongocrypt_ctx_new (mongocrypt_t *crypt)
237 {
238    mongocrypt_ctx_t *ctx;
239    int ctx_size;
240 
241    if (!crypt) {
242       return NULL;
243    }
244    if (!crypt->initialized) {
245       mongocrypt_status_t *status;
246 
247       status = crypt->status;
248       CLIENT_ERR ("cannot create context from uninitialized crypt");
249       return NULL;
250    }
251    ctx_size = sizeof (_mongocrypt_ctx_encrypt_t);
252    if (sizeof (_mongocrypt_ctx_decrypt_t) > ctx_size) {
253       ctx_size = sizeof (_mongocrypt_ctx_decrypt_t);
254    }
255    if (sizeof (_mongocrypt_ctx_datakey_t) > ctx_size) {
256       ctx_size = sizeof (_mongocrypt_ctx_datakey_t);
257    }
258    ctx = bson_malloc0 (ctx_size);
259    BSON_ASSERT (ctx);
260 
261    ctx->crypt = crypt;
262    ctx->status = mongocrypt_status_new ();
263    ctx->opts.algorithm = MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE;
264    ctx->state = MONGOCRYPT_CTX_DONE;
265    return ctx;
266 }
267 
268 #define CHECK_AND_CALL(fn, ...)                                                \
269    do {                                                                        \
270       if (!ctx->vtable.fn) {                                                   \
271          return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context"); \
272       }                                                                        \
273       return ctx->vtable.fn (__VA_ARGS__);                                     \
274    } while (0)
275 
276 /* Common to both encrypt and decrypt context. */
277 static bool
_mongo_op_keys(mongocrypt_ctx_t * ctx,mongocrypt_binary_t * out)278 _mongo_op_keys (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
279 {
280    /* Construct the find filter to fetch keys. */
281    if (!_mongocrypt_key_broker_filter (&ctx->kb, out)) {
282       BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
283       return _mongocrypt_ctx_fail (ctx);
284    }
285    return true;
286 }
287 
288 
289 static bool
_mongo_feed_keys(mongocrypt_ctx_t * ctx,mongocrypt_binary_t * in)290 _mongo_feed_keys (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
291 {
292    _mongocrypt_buffer_t buf;
293 
294    _mongocrypt_buffer_from_binary (&buf, in);
295    if (!_mongocrypt_key_broker_add_doc (&ctx->kb, &buf)) {
296       BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
297       return _mongocrypt_ctx_fail (ctx);
298    }
299    return true;
300 }
301 
302 
303 static bool
_mongo_done_keys(mongocrypt_ctx_t * ctx)304 _mongo_done_keys (mongocrypt_ctx_t *ctx)
305 {
306    (void) _mongocrypt_key_broker_docs_done (&ctx->kb);
307    return _mongocrypt_ctx_state_from_key_broker (ctx);
308 }
309 
310 static mongocrypt_kms_ctx_t *
_next_kms_ctx(mongocrypt_ctx_t * ctx)311 _next_kms_ctx (mongocrypt_ctx_t *ctx)
312 {
313    return _mongocrypt_key_broker_next_kms (&ctx->kb);
314 }
315 
316 
317 static bool
_kms_done(mongocrypt_ctx_t * ctx)318 _kms_done (mongocrypt_ctx_t *ctx)
319 {
320    if (!_mongocrypt_key_broker_kms_done (&ctx->kb)) {
321       BSON_ASSERT (!_mongocrypt_key_broker_status (&ctx->kb, ctx->status));
322       return _mongocrypt_ctx_fail (ctx);
323    }
324    ctx->state = MONGOCRYPT_CTX_READY;
325    return true;
326 }
327 
328 
329 bool
mongocrypt_ctx_mongo_op(mongocrypt_ctx_t * ctx,mongocrypt_binary_t * out)330 mongocrypt_ctx_mongo_op (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
331 {
332    if (!ctx) {
333       return false;
334    }
335    if (!ctx->initialized) {
336       return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
337    }
338 
339    if (!out) {
340       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
341    }
342 
343    switch (ctx->state) {
344    case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
345       CHECK_AND_CALL (mongo_op_collinfo, ctx, out);
346    case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
347       CHECK_AND_CALL (mongo_op_markings, ctx, out);
348    case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
349       CHECK_AND_CALL (mongo_op_keys, ctx, out);
350    case MONGOCRYPT_CTX_ERROR:
351       return false;
352    default:
353       return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
354    }
355 }
356 
357 
358 bool
mongocrypt_ctx_mongo_feed(mongocrypt_ctx_t * ctx,mongocrypt_binary_t * in)359 mongocrypt_ctx_mongo_feed (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in)
360 {
361    if (!ctx) {
362       return false;
363    }
364    if (!ctx->initialized) {
365       return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
366    }
367 
368    if (!in) {
369       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
370    }
371 
372    if (ctx->crypt->log.trace_enabled) {
373       char *in_val;
374 
375       in_val = _mongocrypt_new_json_string_from_binary (in);
376       _mongocrypt_log (&ctx->crypt->log,
377                        MONGOCRYPT_LOG_LEVEL_TRACE,
378                        "%s (%s=\"%s\")",
379                        BSON_FUNC,
380                        "in",
381                        in_val);
382       bson_free (in_val);
383    }
384 
385    switch (ctx->state) {
386    case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
387       CHECK_AND_CALL (mongo_feed_collinfo, ctx, in);
388    case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
389       CHECK_AND_CALL (mongo_feed_markings, ctx, in);
390    case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
391       CHECK_AND_CALL (mongo_feed_keys, ctx, in);
392    case MONGOCRYPT_CTX_ERROR:
393       return false;
394    default:
395       return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
396    }
397 }
398 
399 
400 bool
mongocrypt_ctx_mongo_done(mongocrypt_ctx_t * ctx)401 mongocrypt_ctx_mongo_done (mongocrypt_ctx_t *ctx)
402 {
403    if (!ctx) {
404       return false;
405    }
406    if (!ctx->initialized) {
407       return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
408    }
409 
410    switch (ctx->state) {
411    case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO:
412       CHECK_AND_CALL (mongo_done_collinfo, ctx);
413    case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS:
414       CHECK_AND_CALL (mongo_done_markings, ctx);
415    case MONGOCRYPT_CTX_NEED_MONGO_KEYS:
416       CHECK_AND_CALL (mongo_done_keys, ctx);
417    case MONGOCRYPT_CTX_ERROR:
418       return false;
419    default:
420       return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
421    }
422 }
423 
424 
425 mongocrypt_ctx_state_t
mongocrypt_ctx_state(mongocrypt_ctx_t * ctx)426 mongocrypt_ctx_state (mongocrypt_ctx_t *ctx)
427 {
428    if (!ctx) {
429       return MONGOCRYPT_CTX_ERROR;
430    }
431    if (!ctx->initialized) {
432       _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
433       return MONGOCRYPT_CTX_ERROR;
434    }
435 
436    return ctx->state;
437 }
438 
439 
440 mongocrypt_kms_ctx_t *
mongocrypt_ctx_next_kms_ctx(mongocrypt_ctx_t * ctx)441 mongocrypt_ctx_next_kms_ctx (mongocrypt_ctx_t *ctx)
442 {
443    if (!ctx) {
444       return NULL;
445    }
446    if (!ctx->initialized) {
447       _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
448       return NULL;
449    }
450 
451    if (!ctx->vtable.next_kms_ctx) {
452       _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
453       return NULL;
454    }
455 
456    switch (ctx->state) {
457    case MONGOCRYPT_CTX_NEED_KMS:
458       return ctx->vtable.next_kms_ctx (ctx);
459    case MONGOCRYPT_CTX_ERROR:
460       return NULL;
461    default:
462       _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
463       return NULL;
464    }
465 }
466 
467 
468 bool
mongocrypt_ctx_kms_done(mongocrypt_ctx_t * ctx)469 mongocrypt_ctx_kms_done (mongocrypt_ctx_t *ctx)
470 {
471    if (!ctx) {
472       return false;
473    }
474    if (!ctx->initialized) {
475       return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
476    }
477 
478    if (!ctx->vtable.kms_done) {
479       return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
480    }
481 
482    switch (ctx->state) {
483    case MONGOCRYPT_CTX_NEED_KMS:
484       return ctx->vtable.kms_done (ctx);
485    case MONGOCRYPT_CTX_ERROR:
486       return false;
487    default:
488       return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
489    }
490 }
491 
492 
493 bool
mongocrypt_ctx_finalize(mongocrypt_ctx_t * ctx,mongocrypt_binary_t * out)494 mongocrypt_ctx_finalize (mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out)
495 {
496    if (!ctx) {
497       return false;
498    }
499    if (!ctx->initialized) {
500       return _mongocrypt_ctx_fail_w_msg (ctx, "ctx NULL or uninitialized");
501    }
502 
503    if (!out) {
504       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid NULL input");
505    }
506 
507    if (!ctx->vtable.finalize) {
508       return _mongocrypt_ctx_fail_w_msg (ctx, "not applicable to context");
509    }
510 
511    switch (ctx->state) {
512    case MONGOCRYPT_CTX_READY:
513       return ctx->vtable.finalize (ctx, out);
514    case MONGOCRYPT_CTX_ERROR:
515       return false;
516    default:
517       return _mongocrypt_ctx_fail_w_msg (ctx, "wrong state");
518    }
519 }
520 
521 bool
mongocrypt_ctx_status(mongocrypt_ctx_t * ctx,mongocrypt_status_t * out)522 mongocrypt_ctx_status (mongocrypt_ctx_t *ctx, mongocrypt_status_t *out)
523 {
524    if (!ctx) {
525       return false;
526    }
527 
528    if (!mongocrypt_status_ok (ctx->status)) {
529       _mongocrypt_status_copy_to (ctx->status, out);
530       return false;
531    }
532    _mongocrypt_status_reset (out);
533    return true;
534 }
535 
536 
537 void
mongocrypt_ctx_destroy(mongocrypt_ctx_t * ctx)538 mongocrypt_ctx_destroy (mongocrypt_ctx_t *ctx)
539 {
540    if (!ctx) {
541       return;
542    }
543 
544    if (ctx->vtable.cleanup) {
545       ctx->vtable.cleanup (ctx);
546    }
547 
548    bson_free (ctx->opts.masterkey_aws_region);
549    bson_free (ctx->opts.masterkey_aws_cmk);
550    bson_free (ctx->opts.masterkey_aws_endpoint);
551    mongocrypt_status_destroy (ctx->status);
552    _mongocrypt_key_broker_cleanup (&ctx->kb);
553    _mongocrypt_key_alt_name_destroy_all (ctx->opts.key_alt_names);
554    _mongocrypt_buffer_cleanup (&ctx->opts.key_id);
555    bson_free (ctx);
556    return;
557 }
558 
559 
560 bool
mongocrypt_ctx_setopt_masterkey_aws(mongocrypt_ctx_t * ctx,const char * region,int32_t region_len,const char * cmk,int32_t cmk_len)561 mongocrypt_ctx_setopt_masterkey_aws (mongocrypt_ctx_t *ctx,
562                                      const char *region,
563                                      int32_t region_len,
564                                      const char *cmk,
565                                      int32_t cmk_len)
566 {
567    if (!ctx) {
568       return false;
569    }
570    if (ctx->initialized) {
571       return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
572    }
573 
574    if (ctx->state == MONGOCRYPT_CTX_ERROR) {
575       return false;
576    }
577 
578    if (ctx->opts.masterkey_kms_provider) {
579       return _mongocrypt_ctx_fail_w_msg (ctx, "master key already set");
580    }
581 
582    if (!_mongocrypt_validate_and_copy_string (
583           region, region_len, &ctx->opts.masterkey_aws_region) ||
584        region_len == 0) {
585       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid region");
586    }
587 
588    if (!_mongocrypt_validate_and_copy_string (
589           cmk, cmk_len, &ctx->opts.masterkey_aws_cmk) ||
590        cmk_len == 0) {
591       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid cmk passed");
592    }
593 
594    if (ctx->crypt->log.trace_enabled) {
595       _mongocrypt_log (&ctx->crypt->log,
596                        MONGOCRYPT_LOG_LEVEL_TRACE,
597                        "%s (%s=\"%s\", %s=%d, %s=\"%s\", %s=%d)",
598                        BSON_FUNC,
599                        "region",
600                        ctx->opts.masterkey_aws_region,
601                        "region_len",
602                        region_len,
603                        "cmk",
604                        ctx->opts.masterkey_aws_cmk,
605                        "cmk_len",
606                        cmk_len);
607    }
608 
609    ctx->opts.masterkey_kms_provider = MONGOCRYPT_KMS_PROVIDER_AWS;
610    ctx->opts.masterkey_aws_region_len = region_len;
611    ctx->opts.masterkey_aws_cmk_len = cmk_len;
612    return true;
613 }
614 
615 
616 bool
mongocrypt_ctx_setopt_masterkey_local(mongocrypt_ctx_t * ctx)617 mongocrypt_ctx_setopt_masterkey_local (mongocrypt_ctx_t *ctx)
618 {
619    if (!ctx) {
620       return false;
621    }
622    if (ctx->initialized) {
623       return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
624    }
625 
626    if (ctx->state == MONGOCRYPT_CTX_ERROR) {
627       return false;
628    }
629 
630    if (ctx->opts.masterkey_kms_provider) {
631       return _mongocrypt_ctx_fail_w_msg (ctx, "master key already set");
632    }
633 
634    ctx->opts.masterkey_kms_provider = MONGOCRYPT_KMS_PROVIDER_LOCAL;
635    return true;
636 }
637 
638 
639 bool
_mongocrypt_ctx_init(mongocrypt_ctx_t * ctx,_mongocrypt_ctx_opts_spec_t * opts_spec)640 _mongocrypt_ctx_init (mongocrypt_ctx_t *ctx,
641                       _mongocrypt_ctx_opts_spec_t *opts_spec)
642 {
643    bool has_id = false, has_alt_name = false, has_multiple_alt_names = false;
644 
645    if (ctx->initialized) {
646       return _mongocrypt_ctx_fail_w_msg (ctx, "cannot double initialize");
647    }
648    ctx->initialized = true;
649 
650    if (ctx->state == MONGOCRYPT_CTX_ERROR) {
651       return false;
652    }
653    /* Set some default functions */
654    ctx->vtable.mongo_op_keys = _mongo_op_keys;
655    ctx->vtable.mongo_feed_keys = _mongo_feed_keys;
656    ctx->vtable.mongo_done_keys = _mongo_done_keys;
657    ctx->vtable.next_kms_ctx = _next_kms_ctx;
658    ctx->vtable.kms_done = _kms_done;
659 
660    /* Check that required options are included and prohibited options are
661     * not.
662     */
663 
664    if (opts_spec->masterkey == OPT_REQUIRED) {
665       if (!ctx->opts.masterkey_kms_provider) {
666          return _mongocrypt_ctx_fail_w_msg (ctx, "master key required");
667       }
668       if (!(ctx->opts.masterkey_kms_provider &
669             ctx->crypt->opts.kms_providers)) {
670          return _mongocrypt_ctx_fail_w_msg (
671             ctx, "requested kms provider not configured");
672       }
673    }
674 
675    if (opts_spec->masterkey == OPT_PROHIBITED &&
676        ctx->opts.masterkey_kms_provider) {
677       return _mongocrypt_ctx_fail_w_msg (ctx, "master key prohibited");
678    }
679 
680    /* Special case. key_descriptor applies to explicit encryption. It must be
681     * either a key id or *one* key alt name, but not both.
682     * key_alt_names applies to creating a data key. It may be one or multiple
683     * key alt names.
684     */
685    has_id = !_mongocrypt_buffer_empty (&ctx->opts.key_id);
686    has_alt_name = !!(ctx->opts.key_alt_names);
687    has_multiple_alt_names = has_alt_name && !!(ctx->opts.key_alt_names->next);
688 
689    if (opts_spec->key_descriptor == OPT_REQUIRED) {
690       if (!has_id && !has_alt_name) {
691          return _mongocrypt_ctx_fail_w_msg (
692             ctx, "either key id or key alt name required");
693       }
694 
695       if (has_id && has_alt_name) {
696          return _mongocrypt_ctx_fail_w_msg (
697             ctx, "cannot have both key id and key alt name");
698       }
699 
700       if (has_multiple_alt_names) {
701          return _mongocrypt_ctx_fail_w_msg (
702             ctx, "must not specify multiple key alt names");
703       }
704    }
705 
706    if (opts_spec->key_descriptor == OPT_PROHIBITED) {
707       /* still okay if key_alt_names are allowed and only alt names were
708        * specified. */
709       if ((opts_spec->key_alt_names == OPT_PROHIBITED && has_alt_name) ||
710           has_id) {
711          return _mongocrypt_ctx_fail_w_msg (ctx,
712                                             "key id and alt name prohibited");
713       }
714    }
715 
716    if (opts_spec->algorithm == OPT_REQUIRED &&
717        ctx->opts.algorithm == MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
718       return _mongocrypt_ctx_fail_w_msg (ctx, "algorithm required");
719    }
720 
721    if (opts_spec->algorithm == OPT_PROHIBITED &&
722        ctx->opts.algorithm != MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE) {
723       return _mongocrypt_ctx_fail_w_msg (ctx, "algorithm prohibited");
724    }
725 
726    if (opts_spec->endpoint == OPT_REQUIRED &&
727        !ctx->opts.masterkey_aws_endpoint) {
728       return _mongocrypt_ctx_fail_w_msg (ctx, "endpoint required");
729    }
730 
731    if (opts_spec->endpoint == OPT_PROHIBITED &&
732        ctx->opts.masterkey_aws_endpoint) {
733       return _mongocrypt_ctx_fail_w_msg (ctx, "endpoint prohibited");
734    }
735 
736    _mongocrypt_key_broker_init (&ctx->kb, ctx->crypt);
737    return true;
738 }
739 
740 bool
_mongocrypt_ctx_state_from_key_broker(mongocrypt_ctx_t * ctx)741 _mongocrypt_ctx_state_from_key_broker (mongocrypt_ctx_t *ctx)
742 {
743    _mongocrypt_key_broker_t *kb;
744    mongocrypt_status_t *status;
745    mongocrypt_ctx_state_t new_state = MONGOCRYPT_CTX_ERROR;
746    bool ret = false;
747 
748    status = ctx->status;
749    kb = &ctx->kb;
750 
751    if (ctx->state == MONGOCRYPT_CTX_ERROR) {
752       return false;
753    }
754 
755 
756    switch (kb->state) {
757    case KB_ERROR:
758       _mongocrypt_status_copy_to (kb->status, status);
759       new_state = MONGOCRYPT_CTX_ERROR;
760       ret = false;
761       break;
762    case KB_ADDING_DOCS:
763       /* Require key documents from driver. */
764       new_state = MONGOCRYPT_CTX_NEED_MONGO_KEYS;
765       ret = true;
766       break;
767    case KB_DECRYPTING_KEY_MATERIAL:
768       /* Encrypted keys need KMS. */
769       new_state = MONGOCRYPT_CTX_NEED_KMS;
770       ret = true;
771       break;
772    case KB_DONE:
773       new_state = MONGOCRYPT_CTX_READY;
774       if (kb->key_requests == NULL) {
775          /* No key requests were ever added. */
776          ctx->nothing_to_do = true; /* nothing to encrypt/decrypt */
777       }
778       ret = true;
779       break;
780    /* As currently implemented, we do not expect to ever be in KB_REQUESTING
781     * state when calling this function. */
782    case KB_REQUESTING:
783       CLIENT_ERR ("key broker in unexpected state");
784       new_state = MONGOCRYPT_CTX_ERROR;
785       ret = false;
786       break;
787    }
788 
789    if (new_state != ctx->state) {
790       ctx->state = new_state;
791    }
792 
793    return ret;
794 }
795 
796 
797 bool
mongocrypt_ctx_setopt_masterkey_aws_endpoint(mongocrypt_ctx_t * ctx,const char * endpoint,int32_t endpoint_len)798 mongocrypt_ctx_setopt_masterkey_aws_endpoint (mongocrypt_ctx_t *ctx,
799                                               const char *endpoint,
800                                               int32_t endpoint_len)
801 {
802    if (!ctx) {
803       return false;
804    }
805 
806    if (ctx->initialized) {
807       return _mongocrypt_ctx_fail_w_msg (ctx, "cannot set options after init");
808    }
809 
810    if (ctx->state == MONGOCRYPT_CTX_ERROR) {
811       return false;
812    }
813 
814    if (ctx->opts.masterkey_aws_endpoint) {
815       return _mongocrypt_ctx_fail_w_msg (ctx, "already set masterkey endpoint");
816    }
817 
818    if (!_mongocrypt_validate_and_copy_string (
819           endpoint, endpoint_len, &ctx->opts.masterkey_aws_endpoint)) {
820       return _mongocrypt_ctx_fail_w_msg (ctx, "invalid masterkey endpoint");
821    }
822    ctx->opts.masterkey_aws_endpoint_len = endpoint_len;
823    return true;
824 }