diff options
Diffstat (limited to '')
-rw-r--r-- | src/tpm2/AsymmetricCommands.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/src/tpm2/AsymmetricCommands.c b/src/tpm2/AsymmetricCommands.c new file mode 100644 index 0000000..885087b --- /dev/null +++ b/src/tpm2/AsymmetricCommands.c @@ -0,0 +1,299 @@ +/********************************************************************************/ +/* */ +/* Asymmetric Commands */ +/* Written by Ken Goldman */ +/* IBM Thomas J. Watson Research Center */ +/* $Id: AsymmetricCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ +/* */ +/* 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. and others, 2016 - 2019 */ +/* */ +/********************************************************************************/ + +#include "Tpm.h" +#include "RSA_Encrypt_fp.h" +#if CC_RSA_Encrypt // Conditional expansion of this file +TPM_RC +TPM2_RSA_Encrypt( + RSA_Encrypt_In *in, // IN: input parameter list + RSA_Encrypt_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *rsaKey; + TPMT_RSA_DECRYPT *scheme; + // Input Validation + rsaKey = HandleToObject(in->keyHandle); + // selected key must be an RSA key + if(rsaKey->publicArea.type != TPM_ALG_RSA) + return TPM_RCS_KEY + RC_RSA_Encrypt_keyHandle; + // selected key must have the decryption attribute + if(!IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_RSA_Encrypt_keyHandle; + // Is there a label? + if(!IsLabelProperlyFormatted(&in->label.b)) + return TPM_RCS_VALUE + RC_RSA_Encrypt_label; + // Command Output + // Select a scheme for encryption + scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); + if(scheme == NULL) + return TPM_RCS_SCHEME + RC_RSA_Encrypt_inScheme; + // Encryption. TPM_RC_VALUE, or TPM_RC_SCHEME errors my be returned buy + // CryptEncyptRSA. + out->outData.t.size = sizeof(out->outData.t.buffer); + result = CryptRsaEncrypt(&out->outData, &in->message.b, rsaKey, scheme, + &in->label.b, NULL); + return result; +} +#endif // CC_RSA_Encrypt +#include "Tpm.h" +#include "RSA_Decrypt_fp.h" +#if CC_RSA_Decrypt // Conditional expansion of this file +TPM_RC +TPM2_RSA_Decrypt( + RSA_Decrypt_In *in, // IN: input parameter list + RSA_Decrypt_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *rsaKey; + TPMT_RSA_DECRYPT *scheme; + // Input Validation + rsaKey = HandleToObject(in->keyHandle); + // The selected key must be an RSA key + if(rsaKey->publicArea.type != TPM_ALG_RSA) + return TPM_RCS_KEY + RC_RSA_Decrypt_keyHandle; + // The selected key must be an unrestricted decryption key + if(IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_RSA_Decrypt_keyHandle; + // NOTE: Proper operation of this command requires that the sensitive area + // of the key is loaded. This is assured because authorization is required + // to use the sensitive area of the key. In order to check the authorization, + // the sensitive area has to be loaded, even if authorization is with policy. + // If label is present, make sure that it is a NULL-terminated string + if(!IsLabelProperlyFormatted(&in->label.b)) + return TPM_RCS_VALUE + RC_RSA_Decrypt_label; + // Command Output + // Select a scheme for decrypt. + scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); + if(scheme == NULL) + return TPM_RCS_SCHEME + RC_RSA_Decrypt_inScheme; + // Decryption. TPM_RC_VALUE, TPM_RC_SIZE, and TPM_RC_KEY error may be + // returned by CryptRsaDecrypt. + // NOTE: CryptRsaDecrypt can also return TPM_RC_ATTRIBUTES or TPM_RC_BINDING + // when the key is not a decryption key but that was checked above. + out->message.t.size = sizeof(out->message.t.buffer); + result = CryptRsaDecrypt(&out->message.b, &in->cipherText.b, rsaKey, + scheme, &in->label.b); + return result; +} +#endif // CC_RSA_Decrypt +#include "Tpm.h" +#include "ECDH_KeyGen_fp.h" +#if CC_ECDH_KeyGen // Conditional expansion of this file +TPM_RC +TPM2_ECDH_KeyGen( + ECDH_KeyGen_In *in, // IN: input parameter list + ECDH_KeyGen_Out *out // OUT: output parameter list + ) +{ + OBJECT *eccKey; + TPM2B_ECC_PARAMETER sensitive; + TPM_RC result; + // Input Validation + eccKey = HandleToObject(in->keyHandle); + // Referenced key must be an ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; + // Command Output + do + { + TPMT_PUBLIC *keyPublic = &eccKey->publicArea; + // Create ephemeral ECC key + result = CryptEccNewKeyPair(&out->pubPoint.point, &sensitive, + keyPublic->parameters.eccDetail.curveID); + if(result == TPM_RC_SUCCESS) + { + // Compute Z + result = CryptEccPointMultiply(&out->zPoint.point, + keyPublic->parameters.eccDetail.curveID, + &keyPublic->unique.ecc, + &sensitive, + NULL, NULL); + // The point in the key is not on the curve. Indicate + // that the key is bad. + if(result == TPM_RC_ECC_POINT) + return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; + // The other possible error from CryptEccPointMultiply is + // TPM_RC_NO_RESULT indicating that the multiplication resulted in + // the point at infinity, so get a new random key and start over + // BTW, this never happens. + } + } while(result == TPM_RC_NO_RESULT); + return result; +} +#endif // CC_ECDH_KeyGen +#include "Tpm.h" +#include "ECDH_ZGen_fp.h" +#if CC_ECDH_ZGen // Conditional expansion of this file +TPM_RC +TPM2_ECDH_ZGen( + ECDH_ZGen_In *in, // IN: input parameter list + ECDH_ZGen_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *eccKey; + // Input Validation + eccKey = HandleToObject(in->keyHandle); + // Selected key must be a non-restricted, decrypt ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ECDH_ZGen_keyHandle; + // Selected key needs to be unrestricted with the 'decrypt' attribute + if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_ECDH_ZGen_keyHandle; + // Make sure the scheme allows this use + if(eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_ECDH + && eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME + RC_ECDH_ZGen_keyHandle; + // Command Output + // Compute Z. TPM_RC_ECC_POINT or TPM_RC_NO_RESULT may be returned here. + result = CryptEccPointMultiply(&out->outPoint.point, + eccKey->publicArea.parameters.eccDetail.curveID, + &in->inPoint.point, + &eccKey->sensitive.sensitive.ecc, + NULL, NULL); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_ECDH_ZGen_inPoint); + return result; +} +#endif // CC_ECDH_ZGen +#include "Tpm.h" +#include "ECC_Parameters_fp.h" +#if CC_ECC_Parameters // Conditional expansion of this file +TPM_RC +TPM2_ECC_Parameters( + ECC_Parameters_In *in, // IN: input parameter list + ECC_Parameters_Out *out // OUT: output parameter list + ) +{ + // Command Output + // Get ECC curve parameters + if(CryptEccGetParameters(in->curveID, &out->parameters)) + return TPM_RC_SUCCESS; + else + return TPM_RCS_VALUE + RC_ECC_Parameters_curveID; +} +#endif // CC_ECC_Parameters +#include "Tpm.h" +#include "ZGen_2Phase_fp.h" +#if CC_ZGen_2Phase // Conditional expansion of this file +TPM_RC +TPM2_ZGen_2Phase( + ZGen_2Phase_In *in, // IN: input parameter list + ZGen_2Phase_Out *out // OUT: output parameter list + ) +{ + TPM_RC result; + OBJECT *eccKey; + TPM2B_ECC_PARAMETER r; + TPM_ALG_ID scheme; + // Input Validation + eccKey = HandleToObject(in->keyA); + // keyA must be an ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ZGen_2Phase_keyA; + // keyA must not be restricted and must be a decrypt key + if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_ZGen_2Phase_keyA; + // if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise + // the input scheme must be the same as the scheme of keyA + scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme; + if(scheme != TPM_ALG_NULL) + { + if(scheme != in->inScheme) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + } + else + scheme = in->inScheme; + if(scheme == TPM_ALG_NULL) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + // Input points must be on the curve of keyA + if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, + &in->inQsB.point)) + return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQsB; + if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, + &in->inQeB.point)) + return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQeB; + if(!CryptGenerateR(&r, &in->counter, + eccKey->publicArea.parameters.eccDetail.curveID, + NULL)) + return TPM_RCS_VALUE + RC_ZGen_2Phase_counter; + // Command Output + result = CryptEcc2PhaseKeyExchange(&out->outZ1.point, + &out->outZ2.point, + eccKey->publicArea.parameters.eccDetail.curveID, + scheme, + &eccKey->sensitive.sensitive.ecc, + &r, + &in->inQsB.point, + &in->inQeB.point); + if(result == TPM_RC_SCHEME) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + if(result == TPM_RC_SUCCESS) + CryptEndCommit(in->counter); + return result; +} +#endif // CC_ZGen_2Phase |