diff options
Diffstat (limited to '')
-rw-r--r-- | src/tpm2/crypto/openssl/ExpDCache.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/tpm2/crypto/openssl/ExpDCache.c b/src/tpm2/crypto/openssl/ExpDCache.c new file mode 100644 index 0000000..5aeaf14 --- /dev/null +++ b/src/tpm2/crypto/openssl/ExpDCache.c @@ -0,0 +1,200 @@ +/********************************************************************************/ +/* */ +/* Private Exponent D cache functions */ +/* Written by Stefan Berger */ +/* IBM Thomas J. Watson Research Center */ +/* */ +/* Licenses and Notices */ +/* */ +/* 1. Copyright Licenses: */ +/* */ +/* - Trusted Computing Group (TCG) grants to the user of the source code in */ +/* this specification (the "Source Code") a worldwide, irrevocable, */ +/* nonexclusive, royalty free, copyright license to reproduce, create */ +/* derivative works, distribute, display and perform the Source Code and */ +/* derivative works thereof, and to grant others the rights granted herein. */ +/* */ +/* - The TCG grants to the user of the other parts of the specification */ +/* (other than the Source Code) the rights to reproduce, distribute, */ +/* display, and perform the specification solely for the purpose of */ +/* developing products based on such documents. */ +/* */ +/* 2. Source Code Distribution Conditions: */ +/* */ +/* - Redistributions of Source Code must retain the above copyright licenses, */ +/* this list of conditions and the following disclaimers. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright */ +/* licenses, this list of conditions and the following disclaimers in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* 3. Disclaimers: */ +/* */ +/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ +/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ +/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ +/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ +/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ +/* information on specification licensing rights available through TCG */ +/* membership agreements. */ +/* */ +/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ +/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ +/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ +/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ +/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ +/* */ +/* - Without limitation, TCG and its members and licensors disclaim all */ +/* liability, including liability for infringement of any proprietary */ +/* rights, relating to use of information in this specification and to the */ +/* implementation of this specification, and TCG disclaims all liability for */ +/* cost of procurement of substitute goods or services, lost profits, loss */ +/* of use, loss of data or any incidental, consequential, direct, indirect, */ +/* or special damages, whether under contract, tort, warranty or otherwise, */ +/* arising in any way out of use or reliance upon this specification or any */ +/* information herein. */ +/* */ +/* (c) Copyright IBM Corp., 2021 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "ExpDCache_fp.h" + +/* Implement a cache for the private exponent D so it doesn't need to be + * recalculated every time from P, Q, E and N (modulus). The cache has a + * number of entries that cache D and use P, Q, and E for lookup. + * A least-recently-used cache eviction strategy is implemented that evicts + * the oldest cache entry in case space is needed. An entry is young once + * it is added or made young when it was found via lookup. All other entries + * age by '1' when an entry is added or accessed. + */ + +struct ExpDCacheEntry { + /* The age of the entry; the higher the number the more likely it + * will be evicted soon + */ + unsigned int age; + BIGNUM *P; /* input */ + BIGNUM *N; /* input */ + BIGNUM *E; /* input */ + BIGNUM *Q; /* cached */ + BIGNUM *D; /* cached */ +}; + +#define DCACHE_NUM_ENTRIES 64 + +static struct ExpDCacheEntry ExpDCache[DCACHE_NUM_ENTRIES]; + +/* Increment the age of all cache entries that have a current age <= maxage */ +static void ExpDCacheIncrementAge(unsigned maxage) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { + if (ExpDCache[i].age <= maxage && ExpDCache[i].D != NULL) + ExpDCache[i].age++; + } +} + +/* Free the data associated with a ExpDCacheEntry and initialize it */ +static void ExpDCacheEntryFree(struct ExpDCacheEntry *dce) +{ + BN_clear_free(dce->P); + BN_free(dce->N); + BN_free(dce->E); + BN_clear_free(dce->Q); + BN_clear_free(dce->D); + memset(dce, 0, sizeof(*dce)); +} + +void ExpDCacheFree(void) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) + ExpDCacheEntryFree(&ExpDCache[i]); +} + +/* Get a ExpDCacheEntry by finding either an unused entry or evicting the oldest + * entry. The returned entry will have all NULL pointers and age 0. + */ +static struct ExpDCacheEntry *ExpDCacheEntryGet(void) +{ + size_t i, use_i = 0; + unsigned oldest_age = 0; + struct ExpDCacheEntry *dce; + + for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { + if (ExpDCache[i].D == NULL) { + /* use this free entry */ + use_i = i; + break; + } + if (ExpDCache[i].age > oldest_age) { + /* this one is currently the oldest */ + use_i = i; + oldest_age = ExpDCache[i].age; + } + } + dce = &ExpDCache[use_i]; + + ExpDCacheEntryFree(dce); + + return dce; +} + +/* Add 'D' to the ExpDCache. This function does not check for duplicates */ +void ExpDCacheAdd(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, + const BIGNUM *Q, const BIGNUM *D) +{ + struct ExpDCacheEntry *dce = ExpDCacheEntryGet(); + + /* age of 'dce' is '0' */ + dce->P = BN_dup(P); + dce->N = BN_dup(N); + dce->E = BN_dup(E); + dce->Q = BN_dup(Q); + dce->D = BN_dup(D); + + if (!dce->P || !dce->N || !dce->E || !dce->Q || !dce->D) + ExpDCacheEntryFree(dce); + else + ExpDCacheIncrementAge(~0); +} + +BIGNUM *ExpDCacheFind(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, BIGNUM **Q) +{ + size_t i; + unsigned myage; + BIGNUM *D; + + for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { + if (BN_cmp(ExpDCache[i].P, P) == 0 && BN_cmp(ExpDCache[i].N, N) == 0 && + BN_cmp(ExpDCache[i].E, E) == 0) { + /* entry found */ + myage = ExpDCache[i].age; + /* mark this entry as most recently used */ + ExpDCache[i].age = 0; + /* Increment everyone who is <= 'myage'. + * The age of this entry will be '1' after that. + */ + ExpDCacheIncrementAge(myage); + + *Q = BN_dup(ExpDCache[i].Q); + if (*Q == NULL) + return NULL; + D = BN_dup(ExpDCache[i].D); + if (D == NULL) { + BN_clear_free(*Q); + *Q = NULL; + return NULL; + } + BN_set_flags(*Q, BN_FLG_CONSTTIME); + BN_set_flags(D, BN_FLG_CONSTTIME); + return D; + } + } + + return NULL; +} |