CryptEccCrypt.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /********************************************************************************/
  2. /* */
  3. /* Asymmetric ECC Commands */
  4. /* Written by Ken Goldman */
  5. /* IBM Thomas J. Watson Research Center */
  6. /* $Id$ */
  7. /* */
  8. /* Licenses and Notices */
  9. /* */
  10. /* 1. Copyright Licenses: */
  11. /* */
  12. /* - Trusted Computing Group (TCG) grants to the user of the source code in */
  13. /* this specification (the "Source Code") a worldwide, irrevocable, */
  14. /* nonexclusive, royalty free, copyright license to reproduce, create */
  15. /* derivative works, distribute, display and perform the Source Code and */
  16. /* derivative works thereof, and to grant others the rights granted herein. */
  17. /* */
  18. /* - The TCG grants to the user of the other parts of the specification */
  19. /* (other than the Source Code) the rights to reproduce, distribute, */
  20. /* display, and perform the specification solely for the purpose of */
  21. /* developing products based on such documents. */
  22. /* */
  23. /* 2. Source Code Distribution Conditions: */
  24. /* */
  25. /* - Redistributions of Source Code must retain the above copyright licenses, */
  26. /* this list of conditions and the following disclaimers. */
  27. /* */
  28. /* - Redistributions in binary form must reproduce the above copyright */
  29. /* licenses, this list of conditions and the following disclaimers in the */
  30. /* documentation and/or other materials provided with the distribution. */
  31. /* */
  32. /* 3. Disclaimers: */
  33. /* */
  34. /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
  35. /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
  36. /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
  37. /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
  38. /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
  39. /* information on specification licensing rights available through TCG */
  40. /* membership agreements. */
  41. /* */
  42. /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
  43. /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
  44. /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
  45. /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
  46. /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
  47. /* */
  48. /* - Without limitation, TCG and its members and licensors disclaim all */
  49. /* liability, including liability for infringement of any proprietary */
  50. /* rights, relating to use of information in this specification and to the */
  51. /* implementation of this specification, and TCG disclaims all liability for */
  52. /* cost of procurement of substitute goods or services, lost profits, loss */
  53. /* of use, loss of data or any incidental, consequential, direct, indirect, */
  54. /* or special damages, whether under contract, tort, warranty or otherwise, */
  55. /* arising in any way out of use or reliance upon this specification or any */
  56. /* information herein. */
  57. /* */
  58. /* (c) Copyright IBM Corp. and others, 2022 */
  59. /* */
  60. /********************************************************************************/
  61. /* 10.2.28.1 Includes and Defines */
  62. #include "Tpm.h"
  63. #if CC_ECC_Encrypt || CC_ECC_Encrypt
  64. /* 10.2.28.2 Functions */
  65. /* 10.2.28.2.1 CryptEccSelectScheme() */
  66. /* This function is used by TPM2_ECC_Decrypt and TPM2_ECC_Encrypt. It sets scheme either the input
  67. scheme or the key scheme. If they key scheme is not TPM_ALG_NULL then the input scheme must be
  68. TPM_ALG_NULL or the same as the key scheme. If not, then the function returns FALSE. */
  69. /* Return Value Meaning */
  70. /* TRUE scheme is set */
  71. /* FALSE scheme is not valid (it may have been changed). */
  72. BOOL
  73. CryptEccSelectScheme(
  74. OBJECT *key, //IN: key containing default scheme
  75. TPMT_KDF_SCHEME *scheme // IN: a decrypt scheme
  76. )
  77. {
  78. TPMT_KDF_SCHEME *keyScheme = &key->publicArea.parameters.eccDetail.kdf;
  79. // Get sign object pointer
  80. if(scheme->scheme == TPM_ALG_NULL)
  81. *scheme = *keyScheme;
  82. if(keyScheme->scheme == TPM_ALG_NULL)
  83. keyScheme = scheme;
  84. return (scheme->scheme != TPM_ALG_NULL &&
  85. (keyScheme->scheme == scheme->scheme
  86. && keyScheme->details.anyKdf.hashAlg == scheme->details.anyKdf.hashAlg));
  87. }
  88. /* 10.2.28.2.2 CryptEccEncrypt() */
  89. /* This function performs ECC-based data obfuscation. The only scheme that is currently supported is
  90. MGF1 based. See Part 1, Annex D for details. */
  91. /* Error Return Meaning */
  92. /* TPM_RC_CURVE unsupported curve */
  93. /* TPM_RC_HASH hash not allowed */
  94. /* TPM_RC_SCHEME scheme is not supported */
  95. /* TPM_RC_NO_RESULT internal error in big number processing */
  96. LIB_EXPORT TPM_RC
  97. CryptEccEncrypt(
  98. OBJECT *key, // IN: public key of recipient
  99. TPMT_KDF_SCHEME *scheme, // IN: scheme to use.
  100. TPM2B_MAX_BUFFER *plainText, // IN: the text to obfuscate
  101. TPMS_ECC_POINT *c1, // OUT: public ephemeral key
  102. TPM2B_MAX_BUFFER *c2, // OUT: obfuscated text
  103. TPM2B_DIGEST *c3 // OUT: digest of ephemeral key
  104. // and plainText
  105. )
  106. {
  107. CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID);
  108. POINT_INITIALIZED(PB, &key->publicArea.unique.ecc);
  109. POINT_VAR(Px, MAX_ECC_KEY_BITS);
  110. TPMS_ECC_POINT p2;
  111. ECC_NUM(D);
  112. TPM2B_TYPE(2ECC, MAX_ECC_KEY_BYTES * 2);
  113. TPM2B_2ECC z;
  114. int i;
  115. HASH_STATE hashState;
  116. TPM_RC retVal = TPM_RC_SUCCESS;
  117. //
  118. #if defined DEBUG_ECC_ENCRYPT && DEBUG_ECC_ENCRYPT == YES
  119. RND_DEBUG dbg;
  120. // This value is one less than the value from the reference so that it
  121. // will become the correct value after having one added
  122. TPM2B_ECC_PARAMETER k = {24, {
  123. 0x38, 0x4F, 0x30, 0x35, 0x30, 0x73, 0xAE, 0xEC,
  124. 0xE7, 0xA1, 0x65, 0x43, 0x30, 0xA9, 0x62, 0x04,
  125. 0xD3, 0x79, 0x82, 0xA3, 0xE1, 0x5B, 0x2C, 0xB4}};
  126. RND_DEBUG_Instantiate(&dbg, &k.b);
  127. # define RANDOM (RAND_STATE *)&dbg
  128. #else
  129. # define RANDOM NULL
  130. #endif
  131. if (E == NULL)
  132. ERROR_RETURN(TPM_RC_CURVE);
  133. if (TPM_ALG_KDF2 != scheme->scheme)
  134. ERROR_RETURN(TPM_RC_SCHEME);
  135. // generate an ephemeral key from a random k
  136. if (!BnEccGenerateKeyPair(D, Px, E, RANDOM)
  137. // C1 is the public part of the ephemeral key
  138. || !BnPointTo2B(c1, Px, E)
  139. // Compute P2
  140. || (BnPointMult(Px, PB, D, NULL, NULL, E) != TPM_RC_SUCCESS)
  141. || !BnPointTo2B(&p2, Px, E))
  142. ERROR_RETURN(TPM_RC_NO_RESULT);
  143. //Compute the C3 value hash(x2 || M || y2)
  144. if (0 == CryptHashStart(&hashState, scheme->details.mgf1.hashAlg))
  145. ERROR_RETURN(TPM_RC_HASH);
  146. CryptDigestUpdate2B(&hashState, &p2.x.b);
  147. CryptDigestUpdate2B(&hashState, &plainText->b);
  148. CryptDigestUpdate2B(&hashState, &p2.y.b);
  149. c3->t.size = CryptHashEnd(&hashState, sizeof(c3->t.buffer), c3->t.buffer);
  150. MemoryCopy2B(&z.b, &p2.x.b, sizeof(z.t.buffer));
  151. MemoryConcat2B(&z.b, &p2.y.b, sizeof(z.t.buffer));
  152. // Generate the mask value from MGF1 and put it in the return buffer
  153. c2->t.size = CryptMGF_KDF(plainText->t.size, c2->t.buffer,
  154. scheme->details.mgf1.hashAlg, z.t.size, z.t.buffer, 1);
  155. // XOR the plainText into the generated mask to create the obfuscated data
  156. for (i = 0; i < plainText->t.size; i++)
  157. c2->t.buffer[i] ^= plainText->t.buffer[i];
  158. Exit:
  159. CURVE_FREE(E);
  160. return retVal;
  161. }
  162. /* 10.2.28.2.3 CryptEccDecrypt() */
  163. /* This function performs ECC decryption and integrity check of the input data. */
  164. /* Error Return Meaning */
  165. /* TPM_RC_CURVE unsupported curve */
  166. /* TPM_RC_HASH hash not allowed */
  167. /* TPM_RC_SCHEME scheme is not supported */
  168. /* TPM_RC_NO_RESULT internal error in big number processing */
  169. /* TPM_RC_VALUE C3 did not match hash of recovered data */
  170. LIB_EXPORT TPM_RC
  171. CryptEccDecrypt(
  172. OBJECT *key, // IN: key used for data recovery
  173. TPMT_KDF_SCHEME *scheme, // IN: scheme to use.
  174. TPM2B_MAX_BUFFER *plainText, // OUT: the recovered text
  175. TPMS_ECC_POINT *c1, // IN: public ephemeral key
  176. TPM2B_MAX_BUFFER *c2, // IN: obfuscated text
  177. TPM2B_DIGEST *c3 // IN: digest of ephemeral key
  178. // and plainText
  179. )
  180. {
  181. CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID);
  182. ECC_INITIALIZED(D, &key->sensitive.sensitive.ecc.b);
  183. POINT_INITIALIZED(C1, c1);
  184. TPMS_ECC_POINT p2;
  185. TPM2B_TYPE(2ECC, MAX_ECC_KEY_BYTES * 2);
  186. TPM2B_DIGEST check;
  187. TPM2B_2ECC z;
  188. int i;
  189. HASH_STATE hashState;
  190. TPM_RC retVal = TPM_RC_SUCCESS;
  191. //
  192. if (E == NULL)
  193. ERROR_RETURN(TPM_RC_CURVE);
  194. if (TPM_ALG_KDF2 != scheme->scheme)
  195. ERROR_RETURN(TPM_RC_SCHEME);
  196. // Generate the Z value
  197. BnPointMult(C1, C1, D, NULL, NULL, E);
  198. BnPointTo2B(&p2, C1, E);
  199. // Start the hash to check the algorithm
  200. if (0 == CryptHashStart(&hashState, scheme->details.mgf1.hashAlg))
  201. ERROR_RETURN(TPM_RC_HASH);
  202. CryptDigestUpdate2B(&hashState, &p2.x.b);
  203. MemoryCopy2B(&z.b, &p2.x.b, sizeof(z.t.buffer));
  204. MemoryConcat2B(&z.b, &p2.y.b, sizeof(z.t.buffer));
  205. // Generate the mask
  206. plainText->t.size = CryptMGF_KDF(c2->t.size, plainText->t.buffer,
  207. scheme->details.mgf1.hashAlg, z.t.size,
  208. z.t.buffer, 1);
  209. // XOR the obfuscated data into the generated mask to create the plainText data
  210. for (i = 0; i < plainText->t.size; i++)
  211. plainText->t.buffer[i] ^= c2->t.buffer[i];
  212. // Complete the hash and verify the data
  213. CryptDigestUpdate2B(&hashState, &plainText->b);
  214. CryptDigestUpdate2B(&hashState, &p2.y.b);
  215. check.t.size = CryptHashEnd(&hashState, sizeof(check.t.buffer), check.t.buffer);
  216. if (!MemoryEqual2B(&check.b, &c3->b))
  217. ERROR_RETURN(TPM_RC_VALUE);
  218. Exit:
  219. CURVE_FREE(E);
  220. return retVal;
  221. }
  222. #endif // CC_ECC_Encrypt ||