-
Notifications
You must be signed in to change notification settings - Fork 6
zpcprovider for sign/verify (ecdsa/eddsa) #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
holger-dengler
wants to merge
36
commits into
opencryptoki:main
Choose a base branch
from
holger-dengler:provider-sign
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
f8b76e0
libzpc: Harmonize length types in ecc API
holger-dengler d278e0c
cmake: Add cross-build architecture information
holger-dengler 7c9a4d8
cmake: Add test header comment
holger-dengler 2ca0af9
CONTRIBUTING: re-format
holger-dengler 911117c
cmake: Add OpenSSL package
holger-dengler f0d2895
provider: Add base provider
holger-dengler ccce480
cmake: Integrate base provider
holger-dengler 66ad25d
test: Add OpenSSL configuration template
holger-dengler 141e6fb
test: Add provider tests
holger-dengler f662444
cmake: Integrate provider test
holger-dengler 3d50465
provider: Add provider-specific key object
holger-dengler 1c3919f
cmake: Integrate provider-specific key object
holger-dengler e6af4b0
provider: Add hbkzpc-URI parser
holger-dengler 4ed730e
cmake: Integrate uri
holger-dengler ef6599c
provider: Add mapping helpers
holger-dengler 5871096
cmake: Integrate mapping helpers
holger-dengler 8e247be
provider: Add store-loader
holger-dengler 6f49dea
cmake: Integrate store-loader
holger-dengler 6b205d9
provider: Add asymmetric key management
holger-dengler 33f3dcb
cmake: Add zpc dependency for provider
holger-dengler 1aa12cf
cmake: Integrate asymmetric key management
holger-dengler 97b2a0c
test: Add provider test for store-loader
holger-dengler 01c4e9f
test: Add provider test for PKEY (store/keymgmt)
holger-dengler cbf1358
provider: Add signature algorithms
holger-dengler 767db62
cmake: Integrate signature algorithms
holger-dengler 2a6c319
test: Add provider test for signature algorithms
holger-dengler 7fd337b
provider: Add tls-property helpers
holger-dengler 4c8295c
cmake: Integrate tls-property helpers
holger-dengler 015a0a6
asn1: Add ASN.1 module (definition and functions)
holger-dengler bd4d772
cmake: ASN.1 module integration
holger-dengler 6ccf5ee
test: Add asn.1 tests
holger-dengler 1d2edc6
provider: Add decoders for hbkzpc-URI
holger-dengler f70038a
cmake: Integrate decoder implementation
holger-dengler 37affd1
test: Add decoder tests
holger-dengler d84e0c2
test: Add signature test (PEM)
holger-dengler ab5204e
WIP dbg: Add provider gdb-scripts
holger-dengler File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| // Copyright contributors to the libzpc project | ||
| #ifndef _OSSL_H | ||
| #define _OSSL_H | ||
|
|
||
| #include <openssl/types.h> | ||
|
|
||
| #define OSSL_RV_TRUE (1) | ||
| #define OSSL_RV_FALSE (0) | ||
| #define OSSL_RV_OK (1) | ||
| #define OSSL_RV_ERR (0) | ||
|
|
||
| #define ALGORITHM_DEFN(name, prop, fn, desc) { name, prop, fn, desc } | ||
| #define ALGORITHM_END { NULL, NULL, NULL, NULL } | ||
|
|
||
| #define DISPATCH_DEFN(MODULE, NAME, name) { OSSL_FUNC_##MODULE##_##NAME, (void (*)(void))name } | ||
| #define DISPATCH_END { 0, NULL } | ||
|
|
||
| #define DECL_DISPATCH_FUNC(MODULE, NAME, name) \ | ||
| static OSSL_FUNC_##MODULE##_##NAME##_fn name | ||
|
|
||
| #endif /* _OSSL_H */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,351 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| // Copyright contributors to the libzpc project | ||
| #include <string.h> | ||
| #include <openssl/core.h> | ||
| #include <openssl/core_dispatch.h> | ||
| #include <openssl/core_names.h> | ||
| #include <openssl/err.h> | ||
|
|
||
| #include <zpc/error.h> | ||
|
|
||
| #include "ossl.h" | ||
| #include "provider.h" | ||
|
|
||
| #define C(str) (void *)(str) | ||
| static const OSSL_ITEM reason_strings[] = { | ||
| { ZPC_ERROR_ARG1NULL, | ||
| C("argument 1 NULL") }, | ||
| { ZPC_ERROR_ARG2NULL, | ||
| C("argument 2 NULL") }, | ||
| { ZPC_ERROR_ARG3NULL, | ||
| C("argument 3 NULL") }, | ||
| { ZPC_ERROR_ARG4NULL, | ||
| C("argument 4 NULL") }, | ||
| { ZPC_ERROR_ARG5NULL, | ||
| C("argument 5 NULL") }, | ||
| { ZPC_ERROR_ARG6NULL, | ||
| C("argument 6 NULL") }, | ||
| { ZPC_ERROR_ARG7NULL, | ||
| C("argument 7 NULL") }, | ||
| { ZPC_ERROR_ARG8NULL, | ||
| C("argument 8 NULL") }, | ||
| { ZPC_ERROR_ARG1RANGE, | ||
| C("argument 1 out of range") }, | ||
| { ZPC_ERROR_ARG2RANGE, | ||
| C("argument 2 out of range") }, | ||
| { ZPC_ERROR_ARG3RANGE, | ||
| C("argument 3 out of range") }, | ||
| { ZPC_ERROR_ARG4RANGE, | ||
| C("argument 4 out of range") }, | ||
| { ZPC_ERROR_ARG5RANGE, | ||
| C("argument 5 out of range") }, | ||
| { ZPC_ERROR_ARG6RANGE, | ||
| C("argument 6 out of range") }, | ||
| { ZPC_ERROR_ARG7RANGE, | ||
| C("argument 7 out of range") }, | ||
| { ZPC_ERROR_ARG8RANGE, | ||
| C("argument 8 out of range") }, | ||
| { ZPC_ERROR_MALLOC, | ||
| C("malloc failed") }, | ||
| { ZPC_ERROR_KEYNOTSET, | ||
| C("no key is set") }, | ||
| { ZPC_ERROR_KEYSIZE, | ||
| C("invalid key size") }, | ||
| { ZPC_ERROR_IVNOTSET, | ||
| C("IV not set") }, | ||
| { ZPC_ERROR_IVSIZE, | ||
| C("invalid IV size") }, | ||
| { ZPC_ERROR_TAGSIZE, | ||
| C("invalid tag size") }, | ||
| { ZPC_ERROR_TAGMISMATCH, | ||
| C("tag mismatch") }, | ||
| { ZPC_ERROR_HWCAPS, | ||
| C("function not supported") }, | ||
| { ZPC_ERROR_SMALLOUTBUF, | ||
| C("output buffer too small") }, | ||
| { ZPC_ERROR_APQNSNOTSET, | ||
| C("APQNs not set") }, | ||
| { ZPC_ERROR_KEYTYPE, | ||
| C("invalid key type") }, | ||
| { ZPC_ERROR_KEYTYPENOTSET, | ||
| C("key type not set") }, | ||
| { ZPC_ERROR_IOCTLGENSECK2, | ||
| C("PKEY_GENSECK2 ioctl failed") }, | ||
| { ZPC_ERROR_IOCTLCLR2SECK2, | ||
| C("PKEY_CLR2SECK2 ioctl failed") }, | ||
| { ZPC_ERROR_IOCTLBLOB2PROTK2, | ||
| C("PKEY_BLOB2PROTK2 ioctl failed") }, | ||
| { ZPC_ERROR_WKVPMISMATCH, | ||
| C("wrapping key verification pattern mismatch") }, | ||
| { ZPC_ERROR_DEVPKEY, | ||
| C("opening /dev/pkey failed") }, | ||
| { ZPC_ERROR_CLEN, | ||
| C("ciphertext too long") }, | ||
| { ZPC_ERROR_MLEN, | ||
| C("message too long") }, | ||
| { ZPC_ERROR_AADLEN, | ||
| C("additional authenticated data too long") }, | ||
| { ZPC_ERROR_PARSE, | ||
| C("parse error") }, | ||
| { ZPC_ERROR_APQNNOTFOUND, | ||
| C("APQN not found in APQN list") }, | ||
| { ZPC_ERROR_MKVPLEN, | ||
| C("MKVP too long") }, | ||
| { ZPC_ERROR_INITLOCK, | ||
| C("initializing a lock failed") }, | ||
| { ZPC_ERROR_OBJINUSE, | ||
| C("object is in use") }, | ||
| { ZPC_ERROR_IOCTLAPQNS4KT, | ||
| C("PKEY_APQNS4KT ioctl failed") }, | ||
| { ZPC_ERROR_KEYSIZENOTSET, | ||
| C("key-size not set") }, | ||
| { ZPC_ERROR_IOCTLGENPROTK, | ||
| C("PKEY_GENPROTK ioctl failed") }, | ||
| { ZPC_ERROR_PROTKEYONLY, | ||
| C("protected-key only") }, | ||
| { ZPC_ERROR_KEYSEQUAL, | ||
| C("keys are equal") }, | ||
| { ZPC_ERROR_NOTSUP, | ||
| C("not supported") }, | ||
| { ZPC_ERROR_EC_INVALID_CURVE, | ||
| C("Invalid EC curve") }, | ||
| { ZPC_ERROR_EC_CURVE_NOTSET, | ||
| C("EC curve not set") }, | ||
| { ZPC_ERROR_EC_PRIVKEY_NOTSET, | ||
| C("EC private key not set") }, | ||
| { ZPC_ERROR_EC_PUBKEY_NOTSET, | ||
| C("EC public key not set") }, | ||
| { ZPC_ERROR_EC_NO_KEY_PARTS, | ||
| C("No EC key parts given") }, | ||
| { ZPC_ERROR_EC_SIGNATURE_INVALID, | ||
| C("signature invalid") }, | ||
| { ZPC_ERROR_IOCTLBLOB2PROTK3, | ||
| C("PKEY_BLOB2PROTK3 ioctl failed") }, | ||
| { ZPC_ERROR_IOCTLCLR2SECK3, | ||
| C("PKEY_CLR2SECK3 ioctl failed") }, | ||
| { ZPC_ERROR_APQNS_NOTSET, | ||
| C("No APQNs set for this key,but required for this operation") }, | ||
| { ZPC_ERROR_EC_SIGNATURE_LENGTH, | ||
| C("Signature length is invalid for this EC key") }, | ||
| { ZPC_ERROR_EC_KEY_PARTS_INCONSISTENT, | ||
| C("Given public/private key parts are inconsistent") }, | ||
| { ZPC_ERROR_CCA_HOST_LIB_NOT_AVAILABLE, | ||
| C("CCA host library not available,but required for this operation") }, | ||
| { ZPC_ERROR_EP11_HOST_LIB_NOT_AVAILABLE, | ||
| C("EP11 host library not available,but required for this operation") }, | ||
| { ZPC_ERROR_EC_PUBKEY_LENGTH, | ||
| C("The given EC public key length is invalid") }, | ||
| { ZPC_ERROR_EC_PRIVKEY_LENGTH, | ||
| C("The given EC private key length is invalid") }, | ||
| { ZPC_ERROR_EC_NO_CCA_SECUREKEY_TOKEN, | ||
| C("The given buffer does not contain a valid CCA secure key token") }, | ||
| { ZPC_ERROR_EC_NO_EP11_SECUREKEY_TOKEN, | ||
| C("The given buffer does not contain a valid EP11 secure key token") }, | ||
| { ZPC_ERROR_EC_EP11_SPKI_INVALID_LENGTH, | ||
| C("The imported buffer contains an EP11 SPKI with an invalid length") }, | ||
| { ZPC_ERROR_EC_EP11_SPKI_INVALID_CURVE, | ||
| C("The imported buffer contains an EP11 SPKI with an invalid EC curve") }, | ||
| { ZPC_ERROR_EC_EP11_SPKI_INVALID_PUBKEY, | ||
| C("The imported buffer contains an EP11 SPKI with an invalid public key") }, | ||
| { ZPC_ERROR_EC_EP11_SPKI_INVALID_MKVP, | ||
| C("The imported buffer contains an EP11 MACed SPKI with an invalid MKVP") }, | ||
| { ZPC_ERROR_BLOB_NOT_PKEY_EXTRACTABLE, | ||
| C("The imported buffer contains a key blob that cannot be transformed into a protected key.") }, | ||
| { ZPC_ERROR_APQNS_INVALID_VERSION, | ||
| C("At least one APQN version is invalid for this function.") }, | ||
| { ZPC_ERROR_AES_NO_EP11_SECUREKEY_TOKEN, | ||
| C("The given buffer does not contain a valid EP11 AES secure key token.") }, | ||
| { ZPC_ERROR_AES_NO_CCA_DATAKEY_TOKEN, | ||
| C("The given buffer does not contain a valid CCA datakey token") }, | ||
| { ZPC_ERROR_AES_NO_CCA_CIPHERKEY_TOKEN, | ||
| C("The given buffer does not contain a valid CCA cipherkey token") }, | ||
| { ZPC_ERROR_RNDGEN, | ||
| C("Error creating random bytes") }, | ||
| { ZPC_ERROR_GCM_IV_CREATED_INTERNALLY, | ||
| C("Invalid usage of a gcm context with an internally created iv") }, | ||
| { ZPC_ERROR_UV_PVSECRETS_NOT_AVAILABLE, | ||
| C("Support for UV retrievable secrets is not available,but required for this function.") }, | ||
| { ZPC_ERROR_PVSECRET_TYPE_NOT_SUPPORTED, | ||
| C("The given pvsecret type is not supported by libzpc.") }, | ||
| { ZPC_ERROR_PVSECRET_ID_NOT_FOUND_IN_UV_OR_INVALID_TYPE, | ||
| C("The given pvsecret ID does either not exist or belongs to a different secret type.") }, | ||
| { ZPC_ERROR_IOCTLVERIFYKEY2, | ||
| C("PKEY_VERIFYKEY2 ioctl failed.") }, | ||
| { ZPC_ERROR_HMAC_HASH_FUNCTION_NOTSET, | ||
| C("HMAC hash function not set.") }, | ||
| { ZPC_ERROR_HMAC_HASH_FUNCTION_INVALID, | ||
| C("HMAC hash function invalid.") }, | ||
| { ZPC_ERROR_HMAC_KEYGEN_VIA_SYSFS, | ||
| C("HMAC key generation via sysfs attributes failed.") }, | ||
| { ZPC_ERROR_CREATE_BLOCKSIZED_KEY, | ||
| C("Creating a block-sized HMAC key failed.") }, | ||
| { ZPC_ERROR_XTS_KEYGEN_VIA_SYSFS, | ||
| C("Creating a full-xts key via sysfs attributes failed") }, | ||
| { 0, NULL }, | ||
| }; | ||
| #undef C | ||
|
|
||
| static const OSSL_PARAM prov_param_types[] = { | ||
| OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0), | ||
| OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0), | ||
| OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0), | ||
| OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0), | ||
| OSSL_PARAM_END, | ||
| }; | ||
|
|
||
| static int prov_ctx_init(struct provider_ctx *pctx, const OSSL_CORE_HANDLE *handle, | ||
| const OSSL_DISPATCH *in) | ||
| { | ||
| const OSSL_DISPATCH *iter_in; | ||
| OSSL_LIB_CTX *libctx; | ||
|
|
||
| if (!pctx) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| libctx = OSSL_LIB_CTX_new_from_dispatch(handle, in); | ||
| if (!libctx) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| pctx->libctx = libctx; | ||
| pctx->handle = handle; | ||
| pctx->state = PROVIDER_INITIALIZED; | ||
|
|
||
| for (iter_in = in; iter_in->function_id != 0; iter_in++) { | ||
| switch (iter_in->function_id) { | ||
| case OSSL_FUNC_CORE_NEW_ERROR: | ||
| pctx->core_new_error = OSSL_FUNC_core_new_error(iter_in); | ||
| break; | ||
| case OSSL_FUNC_CORE_SET_ERROR_DEBUG: | ||
| pctx->core_set_error_debug = OSSL_FUNC_core_set_error_debug(iter_in); | ||
| break; | ||
| case OSSL_FUNC_CORE_VSET_ERROR: | ||
| pctx->core_vset_error = OSSL_FUNC_core_vset_error(iter_in); | ||
| break; | ||
| default: | ||
| continue; | ||
| } | ||
| } | ||
| return OSSL_RV_OK; | ||
| } | ||
|
|
||
| static void prov_teardown(void *vpctx) | ||
| { | ||
| OPENSSL_free(vpctx); | ||
| } | ||
|
|
||
| static const OSSL_PARAM *prov_gettable_params(void *vpctx __unused) | ||
| { | ||
| return prov_param_types; | ||
| } | ||
|
|
||
| static int prov_get_params(void *vpctx, OSSL_PARAM params[]) | ||
| { | ||
| struct provider_ctx *pctx = vpctx; | ||
| OSSL_PARAM *p; | ||
|
|
||
| if (!pctx) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME); | ||
| if (p && (OSSL_PARAM_set_utf8_ptr(p, PROV_NAME) != OSSL_RV_OK)) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION); | ||
| if (p && (OSSL_PARAM_set_utf8_ptr(p, PROV_VERSION) != OSSL_RV_OK)) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO); | ||
| if (p && (OSSL_PARAM_set_utf8_ptr(p, PROV_VERSION) != OSSL_RV_OK)) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS); | ||
| if (p && (OSSL_PARAM_set_int(p, pctx->state) != OSSL_RV_OK)) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| return OSSL_RV_OK; | ||
| } | ||
|
|
||
| static const OSSL_ALGORITHM *prov_query_operation(void *vpctx, int operation_id, int *no_cache) | ||
| { | ||
| struct provider_ctx *pctx = vpctx; | ||
| const OSSL_ALGORITHM *ops; | ||
|
|
||
| if (!pctx || pctx->state == PROVIDER_UNINITIALIZED) | ||
| return NULL; | ||
|
|
||
| switch (operation_id) { | ||
| default: | ||
| ops = NULL; | ||
| break; | ||
| } | ||
|
|
||
| *no_cache = 1; | ||
| return ops; | ||
| } | ||
|
|
||
| static const OSSL_ITEM *prov_get_reason_strings(void *vpctx __unused) | ||
| { | ||
| return reason_strings; | ||
| } | ||
|
|
||
| static const OSSL_DISPATCH provider_dispatch_table[] = { | ||
| #define FUNC(func) (void (*)(void))(func) | ||
| { OSSL_FUNC_PROVIDER_TEARDOWN, FUNC(prov_teardown) }, | ||
| { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, FUNC(prov_gettable_params) }, | ||
| { OSSL_FUNC_PROVIDER_GET_PARAMS, FUNC(prov_get_params) }, | ||
| { OSSL_FUNC_PROVIDER_QUERY_OPERATION, FUNC(prov_query_operation) }, | ||
| { OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, FUNC(prov_get_reason_strings) }, | ||
| { 0, NULL } | ||
| #undef FUNC | ||
| }; | ||
|
|
||
| static int prov_init(const OSSL_CORE_HANDLE *handle, | ||
| const OSSL_DISPATCH *in, | ||
| const OSSL_DISPATCH **out, | ||
| void **vpctx) | ||
| { | ||
| struct provider_ctx *pctx; | ||
| int rv = OSSL_RV_ERR; | ||
|
|
||
| if (!handle || !in || !out || !vpctx) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| pctx = OPENSSL_zalloc(sizeof(*pctx)); | ||
| if (!pctx) | ||
| return OSSL_RV_ERR; | ||
|
|
||
| if (!prov_ctx_init(pctx, handle, in)) | ||
| goto err; | ||
|
|
||
| *vpctx = pctx; | ||
| *out = provider_dispatch_table; | ||
| return OSSL_RV_OK; | ||
|
|
||
| err: | ||
| OPENSSL_free(pctx); | ||
| return rv; | ||
| } | ||
|
|
||
| void prov_err_raise(struct provider_ctx *pctx, const char *file, int line, | ||
| const char *func, int reason, const char *fmt, ...) | ||
| { | ||
| va_list args; | ||
|
|
||
| if (!pctx || !pctx->core_new_error || | ||
| !pctx->core_set_error_debug || !pctx->core_vset_error) | ||
| return ERR_raise(ERR_LIB_PROV, reason); | ||
|
|
||
| va_start(args, fmt); | ||
| pctx->core_new_error(pctx->handle); | ||
| pctx->core_set_error_debug(pctx->handle, file, line, func); | ||
| pctx->core_vset_error(pctx->handle, reason, fmt, args); | ||
| va_end(args); | ||
| } | ||
|
|
||
| int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, | ||
| const OSSL_DISPATCH *in, | ||
| const OSSL_DISPATCH **out, | ||
| void **provctx) | ||
| { | ||
| return prov_init(handle, in, out, provctx); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason for setting no_cache to 1? Why can't these queries be cached ?
OK, there are no algos anyway as of now, but eben once there are, why can't it be cached?