16#ifndef AWS_CRYPTOSDK_CACHE_H
17#define AWS_CRYPTOSDK_CACHE_H
19#include <aws/common/clock.h>
21#include <aws/cryptosdk/exports.h>
23#include <aws/cryptosdk/vtable.h>
58#define AWS_CRYPTOSDK_CACHE_MAX_LIMIT_MESSAGES ((uint64_t)1 << 32)
63#ifdef AWS_CRYPTOSDK_DOXYGEN
64struct aws_cryptosdk_materials_cache;
66struct aws_cryptosdk_materials_cache {
67 struct aws_atomic_var refcount;
68 const struct aws_cryptosdk_materials_cache_vt *vt;
72#ifndef AWS_CRYPTOSDK_DOXYGEN
86struct aws_cryptosdk_materials_cache_entry;
88struct aws_cryptosdk_cache_usage_stats {
89 uint64_t bytes_encrypted, messages_encrypted;
92AWS_CRYPTOSDK_STATIC_INLINE
93void aws_cryptosdk_materials_cache_base_init(
94 struct aws_cryptosdk_materials_cache *cache,
const struct aws_cryptosdk_materials_cache_vt *vt) {
96 aws_atomic_init_int(&cache->refcount, 1);
99struct aws_cryptosdk_materials_cache_vt {
130 struct aws_cryptosdk_materials_cache *cache,
131 struct aws_cryptosdk_materials_cache_entry **entry,
133 const struct aws_byte_buf *cache_id);
153 int (*update_usage_stats)(
154 struct aws_cryptosdk_materials_cache *cache,
155 struct aws_cryptosdk_materials_cache_entry *entry,
156 struct aws_cryptosdk_cache_usage_stats *usage_stats);
173 int (*get_enc_materials)(
174 struct aws_cryptosdk_materials_cache *cache,
175 struct aws_allocator *allocator,
176 struct aws_cryptosdk_enc_materials **materials,
177 struct aws_hash_table *enc_ctx,
178 struct aws_cryptosdk_materials_cache_entry *entry);
191 int (*get_dec_materials)(
192 const struct aws_cryptosdk_materials_cache *cache,
193 struct aws_allocator *allocator,
194 struct aws_cryptosdk_dec_materials **materials,
195 const struct aws_cryptosdk_materials_cache_entry *entry);
215 void (*put_entry_for_encrypt)(
216 struct aws_cryptosdk_materials_cache *cache,
217 struct aws_cryptosdk_materials_cache_entry **entry,
218 const struct aws_cryptosdk_enc_materials *enc_materials,
219 struct aws_cryptosdk_cache_usage_stats initial_usage,
220 const struct aws_hash_table *enc_ctx,
221 const struct aws_byte_buf *cache_id);
237 void (*put_entry_for_decrypt)(
238 struct aws_cryptosdk_materials_cache *cache,
239 struct aws_cryptosdk_materials_cache_entry **entry,
240 const struct aws_cryptosdk_dec_materials *dec_materials,
241 const struct aws_byte_buf *cache_id);
249 void (*destroy)(
struct aws_cryptosdk_materials_cache *cache);
251 size_t (*entry_count)(
const struct aws_cryptosdk_materials_cache *cache);
258 void (*entry_release)(
259 struct aws_cryptosdk_materials_cache *cache,
260 struct aws_cryptosdk_materials_cache_entry *entry,
267 uint64_t (*entry_get_creation_time)(
268 const struct aws_cryptosdk_materials_cache *cache,
const struct aws_cryptosdk_materials_cache_entry *entry);
275 void (*entry_ttl_hint)(
276 struct aws_cryptosdk_materials_cache *cache,
277 struct aws_cryptosdk_materials_cache_entry *entry,
285 void (*clear)(
struct aws_cryptosdk_materials_cache *cache);
288AWS_CRYPTOSDK_STATIC_INLINE
289int aws_cryptosdk_materials_cache_find_entry(
290 struct aws_cryptosdk_materials_cache *cache,
291 struct aws_cryptosdk_materials_cache_entry **entry,
293 const struct aws_byte_buf *cache_id) {
295 struct aws_cryptosdk_materials_cache * cache,
296 struct aws_cryptosdk_materials_cache_entry * *entry,
298 const struct aws_byte_buf *cache_id) = AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, find_entry);
302 return find_entry(cache, entry, is_encrypt, cache_id);
305 return AWS_OP_SUCCESS;
308AWS_CRYPTOSDK_STATIC_INLINE
309int aws_cryptosdk_materials_cache_update_usage_stats(
310 struct aws_cryptosdk_materials_cache *cache,
311 struct aws_cryptosdk_materials_cache_entry *entry,
312 struct aws_cryptosdk_cache_usage_stats *usage_stats) {
313 int (*update_usage_stats)(
314 struct aws_cryptosdk_materials_cache * cache,
315 struct aws_cryptosdk_materials_cache_entry * entry,
316 struct aws_cryptosdk_cache_usage_stats * usage_stats) =
317 AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, update_usage_stats);
319 if (!update_usage_stats) {
320 return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION);
323 return update_usage_stats(cache, entry, usage_stats);
326AWS_CRYPTOSDK_STATIC_INLINE
327int aws_cryptosdk_materials_cache_get_enc_materials(
328 struct aws_cryptosdk_materials_cache *cache,
329 struct aws_allocator *allocator,
331 struct aws_hash_table *enc_ctx,
332 struct aws_cryptosdk_materials_cache_entry *entry) {
333 int (*get_enc_materials)(
334 struct aws_cryptosdk_materials_cache * cache,
335 struct aws_allocator * allocator,
337 struct aws_hash_table * enc_ctx,
338 struct aws_cryptosdk_materials_cache_entry * entry) =
339 AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, get_enc_materials);
342 if (!get_enc_materials) {
343 return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION);
346 return get_enc_materials(cache, allocator, materials, enc_ctx, entry);
349AWS_CRYPTOSDK_STATIC_INLINE
350int aws_cryptosdk_materials_cache_get_dec_materials(
351 const struct aws_cryptosdk_materials_cache *cache,
352 struct aws_allocator *allocator,
354 const struct aws_cryptosdk_materials_cache_entry *entry) {
355 int (*get_dec_materials)(
356 const struct aws_cryptosdk_materials_cache *cache,
357 struct aws_allocator *allocator,
359 const struct aws_cryptosdk_materials_cache_entry *entry) =
360 AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, get_dec_materials);
363 if (!get_dec_materials) {
364 return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION);
367 return get_dec_materials(cache, allocator, materials, entry);
370AWS_CRYPTOSDK_STATIC_INLINE
371void aws_cryptosdk_materials_cache_put_entry_for_encrypt(
372 struct aws_cryptosdk_materials_cache *cache,
373 struct aws_cryptosdk_materials_cache_entry **entry,
375 struct aws_cryptosdk_cache_usage_stats initial_usage,
376 const struct aws_hash_table *enc_ctx,
377 const struct aws_byte_buf *cache_id) {
378 void (*put_entry_for_encrypt)(
379 struct aws_cryptosdk_materials_cache * cache,
380 struct aws_cryptosdk_materials_cache_entry * *entry,
382 struct aws_cryptosdk_cache_usage_stats initial_usage,
383 const struct aws_hash_table *enc_ctx,
384 const struct aws_byte_buf *cache_id) = AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, put_entry_for_encrypt);
387 if (put_entry_for_encrypt) {
388 put_entry_for_encrypt(cache, entry, enc_materials, initial_usage, enc_ctx, cache_id);
392AWS_CRYPTOSDK_STATIC_INLINE
393void aws_cryptosdk_materials_cache_put_entry_for_decrypt(
394 struct aws_cryptosdk_materials_cache *cache,
395 struct aws_cryptosdk_materials_cache_entry **entry,
397 const struct aws_byte_buf *cache_id) {
398 void (*put_entry_for_decrypt)(
399 struct aws_cryptosdk_materials_cache * cache,
400 struct aws_cryptosdk_materials_cache_entry * *entry,
402 const struct aws_byte_buf *cache_id) = AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, put_entry_for_decrypt);
405 if (put_entry_for_decrypt) {
406 put_entry_for_decrypt(cache, entry, dec_materials, cache_id);
410AWS_CRYPTOSDK_STATIC_INLINE
411void aws_cryptosdk_materials_cache_entry_release(
412 struct aws_cryptosdk_materials_cache *cache,
struct aws_cryptosdk_materials_cache_entry *entry,
bool invalidate) {
413 void (*entry_release)(
414 struct aws_cryptosdk_materials_cache * cache,
415 struct aws_cryptosdk_materials_cache_entry * entry,
416 bool invalidate) = AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, entry_release);
419 entry_release(cache, entry, invalidate);
423AWS_CRYPTOSDK_STATIC_INLINE
424uint64_t aws_cryptosdk_materials_cache_entry_get_creation_time(
425 const struct aws_cryptosdk_materials_cache *cache,
const struct aws_cryptosdk_materials_cache_entry *entry) {
426 uint64_t (*entry_get_creation_time)(
427 const struct aws_cryptosdk_materials_cache *cache,
const struct aws_cryptosdk_materials_cache_entry *entry) =
428 AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, entry_get_creation_time);
430 if (entry_get_creation_time) {
431 return entry_get_creation_time(cache, entry);
437AWS_CRYPTOSDK_STATIC_INLINE
438void aws_cryptosdk_materials_cache_entry_ttl_hint(
439 struct aws_cryptosdk_materials_cache *cache,
struct aws_cryptosdk_materials_cache_entry *entry, uint64_t exp_time) {
440 void (*entry_ttl_hint)(
441 struct aws_cryptosdk_materials_cache * cache,
442 struct aws_cryptosdk_materials_cache_entry * entry,
443 uint64_t exp_time) = AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, entry_ttl_hint);
445 if (entry_ttl_hint) {
446 entry_ttl_hint(cache, entry, exp_time);
458 struct aws_allocator *alloc,
size_t capacity);
464AWS_CRYPTOSDK_STATIC_INLINE
466 size_t (*entry_count)(
const struct aws_cryptosdk_materials_cache *cache) =
467 AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, entry_count);
473 return entry_count(cache);
480AWS_CRYPTOSDK_STATIC_INLINE
482 void (*clear)(
struct aws_cryptosdk_materials_cache * cache) = AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(cache->vt, clear);
493 struct aws_cryptosdk_materials_cache *materials_cache) {
494 aws_cryptosdk_private_refcount_up(&materials_cache->refcount);
495 return materials_cache;
502 struct aws_cryptosdk_materials_cache *materials_cache) {
503 if (materials_cache && aws_cryptosdk_private_refcount_down(&materials_cache->refcount)) {
504 void (*destroy)(
struct aws_cryptosdk_materials_cache * cache) =
505 AWS_CRYPTOSDK_PRIVATE_VT_GET_NULL(materials_cache->vt, destroy);
511 destroy(materials_cache);
537 struct aws_allocator *alloc,
538 struct aws_cryptosdk_materials_cache *materials_cache,
540 const struct aws_byte_buf *partition_id,
541 uint64_t cache_limit_ttl,
542 enum aws_timestamp_unit cache_limit_ttl_units);
567 struct aws_allocator *alloc,
568 struct aws_cryptosdk_materials_cache *materials_cache,
570 const struct aws_byte_buf *partition_id,
571 uint64_t cache_limit_ttl,
572 enum aws_timestamp_unit cache_limit_ttl_units);
struct aws_cryptosdk_materials_cache * aws_cryptosdk_materials_cache_local_new(struct aws_allocator *alloc, size_t capacity)
int aws_cryptosdk_caching_cmm_set_ttl(struct aws_cryptosdk_cmm *cmm, uint64_t ttl, enum aws_timestamp_unit ttl_units)
size_t aws_cryptosdk_materials_cache_entry_count(const struct aws_cryptosdk_materials_cache *cache)
struct aws_cryptosdk_cmm * aws_cryptosdk_caching_cmm_new_from_cmm(struct aws_allocator *alloc, struct aws_cryptosdk_materials_cache *materials_cache, struct aws_cryptosdk_cmm *upstream, const struct aws_byte_buf *partition_id, uint64_t cache_limit_ttl, enum aws_timestamp_unit cache_limit_ttl_units)
void aws_cryptosdk_materials_cache_release(struct aws_cryptosdk_materials_cache *materials_cache)
struct aws_cryptosdk_cmm * aws_cryptosdk_caching_cmm_new_from_keyring(struct aws_allocator *alloc, struct aws_cryptosdk_materials_cache *materials_cache, struct aws_cryptosdk_keyring *keyring, const struct aws_byte_buf *partition_id, uint64_t cache_limit_ttl, enum aws_timestamp_unit cache_limit_ttl_units)
struct aws_cryptosdk_materials_cache * aws_cryptosdk_materials_cache_retain(struct aws_cryptosdk_materials_cache *materials_cache)
int aws_cryptosdk_caching_cmm_set_limit_bytes(struct aws_cryptosdk_cmm *cmm, uint64_t limit_bytes)
void aws_cryptosdk_materials_cache_clear(struct aws_cryptosdk_materials_cache *cache)
int aws_cryptosdk_caching_cmm_set_limit_messages(struct aws_cryptosdk_cmm *cmm, uint64_t limit_messages)