summaryrefslogtreecommitdiff
path: root/usr/src/lib/libkmsagent/common/KMSAgentLoadBalancer.h
diff options
context:
space:
mode:
authorWyllys Ingersoll <Wyllys.Ingersoll@Sun.COM>2010-06-28 16:04:11 -0700
committerWyllys Ingersoll <Wyllys.Ingersoll@Sun.COM>2010-06-28 16:04:11 -0700
commit4f14b0f29aa144cc03efdde5508ae126ae197acf (patch)
tree5292d99c7ec8374d412d58116e7bbc7279e72067 /usr/src/lib/libkmsagent/common/KMSAgentLoadBalancer.h
parent1e49577a7fcde812700ded04431b49d67cc57d6d (diff)
downloadillumos-joyent-4f14b0f29aa144cc03efdde5508ae126ae197acf.tar.gz
PSARC 2010/195 PKCS11 KMS Provider
6944296 Solaris needs a PKCS#11 provider to allow access to KMS keystore functionality
Diffstat (limited to 'usr/src/lib/libkmsagent/common/KMSAgentLoadBalancer.h')
-rw-r--r--usr/src/lib/libkmsagent/common/KMSAgentLoadBalancer.h339
1 files changed, 339 insertions, 0 deletions
diff --git a/usr/src/lib/libkmsagent/common/KMSAgentLoadBalancer.h b/usr/src/lib/libkmsagent/common/KMSAgentLoadBalancer.h
new file mode 100644
index 0000000000..b4237e6be1
--- /dev/null
+++ b/usr/src/lib/libkmsagent/common/KMSAgentLoadBalancer.h
@@ -0,0 +1,339 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/**
+ * \file KMSAgentLoadBalancer.h
+ */
+
+#ifndef KMS_AGENT_LOAD_BALANCER_H
+#define KMS_AGENT_LOAD_BALANCER_H
+typedef char UTF8_KEYID[2*KMS_KWK_KEY_ID_SIZE+1];
+
+class CAgentLoadBalancer
+{
+public:
+
+ /**
+ * the load balancer retains a pointer to the specified profile
+ */
+ CAgentLoadBalancer(
+ KMSClientProfile * const i_pProfile );
+
+ ~CAgentLoadBalancer ();
+
+ /**
+ * This method must be called at the top of each agent library transaction.
+ * Responsibilities:
+ * <ul>
+ * <li>clear profile failover attempts
+ * <li>sets transaction start time
+ * <li>performs discovery at the frequency specified in the profile
+ * <li>maintains the status of KMAs within the cluster
+ * </ul>
+ * @return a random KMA from the "available" KMAs within the agent's site
+ * or a random KMA from any of the "available" KMA's if none are available
+ * within the agent's site.
+ * When operating in FIPS mode then only KMAs that are
+ * FIPS compatible will be selected, see <code>FIPScompatibleKMA</code>.
+ * Available KMAs
+ * are KMAs that are enabled and responding. If no FIPS compatible KMAs
+ * are available then <code>NO_FIPS_KMA_AVAILABLE</code> is returned.
+ * When <code>m_iClusterDiscoveryFrequency</code> is set to 0 in the profile
+ * then load balancing and automatic discovery
+ * are disabled so the default KMA is returned.
+ */
+ int Balance();
+
+ /**
+ * @return a KMA from the cache that has affinity with the specified DataUnitID,
+ * if possible, otherwise return a KMA from <code>Balance</code>. See
+ * <code>Balance</code> for <code>FIPS_MODE</code> behavior and disabled load balancing.
+ */
+ int BalanceByDataUnitID(
+ const unsigned char * const i_pDataUnitID,
+ int i_iDataUnitIDMaxLen );
+
+ /**
+ * @return a KMA from the cache that has affinity with the specified DataUnitKeyID,
+ * if possible, otherwise return a KMA from <code>Balance</code>. See
+ * <code>Balance</code> for <code>FIPS_MODE</code> behavior and disabled load balancing.
+ */
+ int BalanceByDataUnitKeyID(
+ const unsigned char * const i_pDataUnitKeyID,
+ int i_iDataUnitKeyIDMaxLen );
+
+ enum ERRORS
+ {
+ CLIENT_SIDE_ERROR = -1,
+ NO_KMA_AVAILABLE = -2,
+ AES_KEY_UNWRAP_ERROR = -3,
+ AES_KEY_WRAP_SETUP_ERROR = -4,
+ NO_FIPS_KMA_AVAILABLE = -5,
+ KWK_NOT_REGISTERED = -6
+ };
+
+ /**
+ * Makes a failover determination based upon soap error information and profile settings.
+ * Responsibilities:
+ * <ul>
+ * <li>updates the status of the failed KMA within the profile's cluster array
+ * <li>Client Faults - no failover, same KMA will be returned if a Server Busy error
+ * occurred and
+ * either the transaction timeout has not been exceeded or failover limit has not been exceeded
+ * <li>Server Faults - a failover KMA is chosen if the limit specified set in the profile
+ * has not been exceed
+ * <li>For <code>CLIENT_ERROR_AGENT_KWK_NOT_REGISTERED</code> the KWK is deleted and
+ * i_iFailedApplianceIndex is returned. The caller should re-regsiter the
+ * KWK with this appliance.
+ * </ul>
+ * If all KMAs are disabled or non-responding then give up.
+ * <li>increments profile failover attempts
+ * </ul>
+ * @param i_iFailedApplianceIndex the index within the profile's cluster array of the failed KMA
+ * @param i_pstSoap the gSoap runtime from which error information can be analyzed
+ * @return index of KMA in cluster to failover to, <code>CLIENT_SIDE_ERROR</code> to give up due to client side error,
+ * <code>NO_KMA_AVAILABLE</code> or <code>NO_FIPS_KMA_AVAILABLE</code> if running in FIPS_MODE
+ * if server error but no KMA to failover to
+ */
+ int FailOver(
+ int i_iFailedApplianceIndex,
+ struct soap *i_pstSoap );
+
+ /**
+ * Updates the response status for the specified KMA to responding.
+ */
+ void UpdateResponseStatus(int i_iIndex);
+
+ /**
+ * @return HTTPS protocol URL for the KMA referenced by the specified index entry within this
+ * object's cluster array and the specified web service port.
+ */
+ char* GetHTTPSURL(
+ int i_iIndex,
+ int i_iPort );
+ /**
+ * @return HTTP protocol URL for the KMA referenced by the specified index entry within this
+ * object's cluster array and the specified web service port.
+ */
+ char* GetHTTPURL(
+ int i_iIndex,
+ int i_iPort );
+
+ /**
+ * @return the KMA IP address for the specified index entry within this object's cluster
+ * array.
+ */
+ char* GetApplianceNetworkAddress(
+ int i_iIndex );
+
+ /**
+ * @return the KMA ID for the specified index entry within this
+ * object's cluster. Returns -1 if an invalid
+ * index is provided
+ */
+ Long64 GetKMAID(
+ int i_iIndex );
+
+ /**
+ * retrieves the KWKID for a specified KMA in the cluster.
+ * @param i_Index element in this object's KMS cluster as returned by
+ * one of the Balance methods or the Failover method.
+ * @param i_lKMAID the KMAID for which a KWK is desired
+ * @param i_pstSoap non-NULL pointer to an initialized gSoap runtime to be
+ * used, if necessary, for KWK registration with the KMA.
+ * @param o_pKWKID pointer to UTF8 hex character string to receive the KWKID
+ * for the specified KMA in the cluster.
+ * @param o_pbClientAESKeyWrapSetupError this arg gets set to true if an
+ * error occurs that is client side related and pertaining to establishment
+ * of the AES Key Wrapping Keys.
+ * If the KMS cluster does not support AES KeyWrap o_pKWKID is set to
+ * a zero-length string. A new KWK may be registered with the KMA if a value
+ * has not yet been registered for this instance of CAgentLoadBalancer.
+ * @return TRUE if successful and FALSE otherwise with soap fault available
+ * in the gSoap runtime provided by the caller and io_pIndex set to
+ * AES_KEY_WRAP_SETUP_ERROR. Use ServerError() to
+ * determine if failover is appropriate.
+ */
+ int GetKWKID(
+ int i_Index,
+ Long64 i_lKMAID,
+ struct soap * const i_pstSoap,
+ UTF8_KEYID o_pKWKID,
+ bool * const o_pbClientAESKeyWrapSetupError);
+
+ /**
+ * performs AES Key unwrapping according to RFC3394.
+ * @param io_pIndex Cluster index for KMA that wrapped the key. On error
+ * the cluster index is set to AES_KEY_UNWRAP_ERROR
+ * @param i_pAESWrappedKey pointer to the wrapped key
+ * @param o_pPlainTextKey point to buffer to receive unwrapped key
+ * @return true for success, false otherwise and sets *io_pIndex to
+ * AES_KEY_UNWRAP_ERROR
+ */
+ bool AESKeyUnwrap (
+ int * const io_pIndex,
+ const WRAPPED_KEY i_pAESWrappedKey,
+ KEY o_pPlainTextKey );
+
+ /**
+ * @return true if the KMA referenced by the specified cluster
+ * index supports AES key wrap
+ */
+ bool AESKeyWrapSupported (
+ int i_iIndex);
+
+protected:
+ /**
+ * @return the cluster array index of the KMA with the specified IP address
+ * or CLIENT_SIDE_ERROR if the KMA is not responding or not enabled
+ */
+ int FindIndexByNetworkAddress (
+ char* i_wsApplianceNetworkAddress);
+
+private:
+
+ /**
+ * Sorts the cluster array ascending by load.
+ * Before sorting, the other site's KMAs' load are added by 0x10000000000 and
+ * the disabled/non-responding/locked KMAs are added by 0x1000000000000 and KMAs
+ * not matching the agent's FIPS setting the load is bumped by 0x100000000000000.
+ * This ensures that KMAs
+ * in the current site are sorted before KMAs in other sites and
+ * disabled/non-responding/locked KMAs are after those enabled KMAs. When the agent is
+ * in FIPS mode the non-FIPS KMAs are sorted last.
+ */
+ void KMSClient_SortClusterArray (
+ KMSClientProfile * const i_pProfile);
+
+ static const int MAX_RSA_PUB_KEY_LENGTH = 256;
+ int m_iClusterNum;
+
+ /**
+ * this array is reinitialized from the profile's Cluster array each time Balance() is called.
+ * Failover() will resort the profile's Cluster array so this array may not
+ * match the sort order in the profile
+ */
+ KMSClusterEntry m_aCluster[KMS_MAX_CLUSTER_NUM];
+ KMSClientProfile *m_pProfile;
+ char m_sURL[KMS_MAX_URL+1];
+ unsigned int m_iTransactionStartTimeInMilliseconds;
+ bool m_bFIPS;
+
+ /**
+ * number of elements in KWKEntries
+ */
+ int m_iKWKEntryNum;
+
+ /**
+ * in a failover scenario, if all KMAs are not responding this
+ * member variable tracks the index into m_aCluster of the last KMA attempted.
+ */
+ int m_iLastAttemptedWhenNoneResponding;
+
+ /**
+ * @return true if the failover limit has been exceeded. If failover
+ * limit of -1 is specified in the profile then always return false.
+ */
+ bool FailOverLimit(void);
+
+ /**
+ * \struct for each KMA used in a profile session there will be
+ * a KWKEntry in KWKEntries. These values do not persist
+ * beyond a profile session
+ */
+ struct KWKEntry
+ {
+ /**
+ * The KMA associated with this KWK. This KMA
+ * receives the KWK via the KMS_Agent__RegisterAgentKWK()
+ * agent service which returns the KMA assigned value for
+ * m_acKWKID
+ */
+ Long64 m_lKMAID;
+
+ /**
+ * the KeyID for this KWK, provided by the KMA
+ */
+ UTF8_KEYID m_acKWKID;
+
+ /**
+ * the plaintext value of the AES KWK
+ */
+ KEY m_acKWK;
+ };
+
+ /**
+ * set of KWKEntry ptrs for KMAs used in this profile session.
+ */
+ struct KWKEntry * m_aKWKEntries[KMS_MAX_CLUSTER_NUM];
+
+ /**
+ * retrieve the Key Wrapping Key for a KMA
+ * @param i_lKMAID KMA identifier, must not be equal to -1
+ * @return pointer to the KWKEntry for the specified KMAID, NULL
+ * if the entry does not exist
+ */
+ struct KWKEntry *GetKWK(
+ Long64 i_lKMAID );
+
+ /**
+ * creates a new KWKEntry on the heap and store a ptr to it in an
+ * unused slot in <code>m_aKWKEntries</code>.
+ * @return NULL on error, otherwise a pointer to the newly
+ * created KWKEntry
+ */
+ struct KWKEntry *CreateKWK(
+ Long64 i_lKMAID,
+ struct soap * const i_pstSoap,
+ const char * const i_sURL,
+ bool * const o_pbClientAESKeyWrapSetupError);
+
+ /**
+ * free the <code>KWKEntry</code> corresponding to the specified KMA ID
+ * and set the slot it occupied in <code>m_aKWKEntries</code> to NULL.
+ */
+ void DeleteKWKEntry(Long64 i_lKMAID);
+
+ /**
+ * retrieve the RSA public key to be used for wrapping a KWK
+ */
+ int GetKWKWrappingKey(
+ struct soap * const i_pstSoap,
+ const char * const i_sURL,
+ CPublicKey * const o_opPublicKEK );
+
+ /**
+ * register the KWK with a specified KMA and return the KWK ID
+ */
+ int RegisterKWK(
+ int i_iWrappedKWKSize,
+ const unsigned char * const i_acWrappedKWK,
+ struct soap * const i_pstSoap,
+ const char * const i_sURL,
+ UTF8_KEYID o_acUTF8KeyID );
+
+};
+
+#endif //KMS_AGENT_LOAD_BALANCER_H