CryptDh.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /** @file
  2. Diffie-Hellman Wrapper Implementation over OpenSSL.
  3. Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "InternalCryptLib.h"
  7. #include <openssl/bn.h>
  8. #include <openssl/dh.h>
  9. /**
  10. Allocates and Initializes one Diffie-Hellman Context for subsequent use.
  11. @return Pointer to the Diffie-Hellman Context that has been initialized.
  12. If the allocations fails, DhNew() returns NULL.
  13. **/
  14. VOID *
  15. EFIAPI
  16. DhNew (
  17. VOID
  18. )
  19. {
  20. //
  21. // Allocates & Initializes DH Context by OpenSSL DH_new()
  22. //
  23. return (VOID *) DH_new ();
  24. }
  25. /**
  26. Release the specified DH context.
  27. If DhContext is NULL, then return FALSE.
  28. @param[in] DhContext Pointer to the DH context to be released.
  29. **/
  30. VOID
  31. EFIAPI
  32. DhFree (
  33. IN VOID *DhContext
  34. )
  35. {
  36. //
  37. // Free OpenSSL DH Context
  38. //
  39. DH_free ((DH *) DhContext);
  40. }
  41. /**
  42. Generates DH parameter.
  43. Given generator g, and length of prime number p in bits, this function generates p,
  44. and sets DH context according to value of g and p.
  45. Before this function can be invoked, pseudorandom number generator must be correctly
  46. initialized by RandomSeed().
  47. If DhContext is NULL, then return FALSE.
  48. If Prime is NULL, then return FALSE.
  49. @param[in, out] DhContext Pointer to the DH context.
  50. @param[in] Generator Value of generator.
  51. @param[in] PrimeLength Length in bits of prime to be generated.
  52. @param[out] Prime Pointer to the buffer to receive the generated prime number.
  53. @retval TRUE DH parameter generation succeeded.
  54. @retval FALSE Value of Generator is not supported.
  55. @retval FALSE PRNG fails to generate random prime number with PrimeLength.
  56. **/
  57. BOOLEAN
  58. EFIAPI
  59. DhGenerateParameter (
  60. IN OUT VOID *DhContext,
  61. IN UINTN Generator,
  62. IN UINTN PrimeLength,
  63. OUT UINT8 *Prime
  64. )
  65. {
  66. BOOLEAN RetVal;
  67. BIGNUM *BnP;
  68. //
  69. // Check input parameters.
  70. //
  71. if (DhContext == NULL || Prime == NULL || PrimeLength > INT_MAX) {
  72. return FALSE;
  73. }
  74. if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) {
  75. return FALSE;
  76. }
  77. RetVal = (BOOLEAN) DH_generate_parameters_ex (DhContext, (UINT32) PrimeLength, (UINT32) Generator, NULL);
  78. if (!RetVal) {
  79. return FALSE;
  80. }
  81. DH_get0_pqg (DhContext, (const BIGNUM **)&BnP, NULL, NULL);
  82. BN_bn2bin (BnP, Prime);
  83. return TRUE;
  84. }
  85. /**
  86. Sets generator and prime parameters for DH.
  87. Given generator g, and prime number p, this function and sets DH
  88. context accordingly.
  89. If DhContext is NULL, then return FALSE.
  90. If Prime is NULL, then return FALSE.
  91. @param[in, out] DhContext Pointer to the DH context.
  92. @param[in] Generator Value of generator.
  93. @param[in] PrimeLength Length in bits of prime to be generated.
  94. @param[in] Prime Pointer to the prime number.
  95. @retval TRUE DH parameter setting succeeded.
  96. @retval FALSE Value of Generator is not supported.
  97. @retval FALSE Value of Generator is not suitable for the Prime.
  98. @retval FALSE Value of Prime is not a prime number.
  99. @retval FALSE Value of Prime is not a safe prime number.
  100. **/
  101. BOOLEAN
  102. EFIAPI
  103. DhSetParameter (
  104. IN OUT VOID *DhContext,
  105. IN UINTN Generator,
  106. IN UINTN PrimeLength,
  107. IN CONST UINT8 *Prime
  108. )
  109. {
  110. DH *Dh;
  111. BIGNUM *BnP;
  112. BIGNUM *BnG;
  113. //
  114. // Check input parameters.
  115. //
  116. if (DhContext == NULL || Prime == NULL || PrimeLength > INT_MAX) {
  117. return FALSE;
  118. }
  119. if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) {
  120. return FALSE;
  121. }
  122. //
  123. // Set the generator and prime parameters for DH object.
  124. //
  125. Dh = (DH *)DhContext;
  126. BnP = BN_bin2bn ((const unsigned char *)Prime, (int)(PrimeLength / 8), NULL);
  127. BnG = BN_bin2bn ((const unsigned char *)&Generator, 1, NULL);
  128. if ((BnP == NULL) || (BnG == NULL) || !DH_set0_pqg (Dh, BnP, NULL, BnG)) {
  129. goto Error;
  130. }
  131. return TRUE;
  132. Error:
  133. BN_free (BnP);
  134. BN_free (BnG);
  135. return FALSE;
  136. }
  137. /**
  138. Generates DH public key.
  139. This function generates random secret exponent, and computes the public key, which is
  140. returned via parameter PublicKey and PublicKeySize. DH context is updated accordingly.
  141. If the PublicKey buffer is too small to hold the public key, FALSE is returned and
  142. PublicKeySize is set to the required buffer size to obtain the public key.
  143. If DhContext is NULL, then return FALSE.
  144. If PublicKeySize is NULL, then return FALSE.
  145. If PublicKeySize is large enough but PublicKey is NULL, then return FALSE.
  146. @param[in, out] DhContext Pointer to the DH context.
  147. @param[out] PublicKey Pointer to the buffer to receive generated public key.
  148. @param[in, out] PublicKeySize On input, the size of PublicKey buffer in bytes.
  149. On output, the size of data returned in PublicKey buffer in bytes.
  150. @retval TRUE DH public key generation succeeded.
  151. @retval FALSE DH public key generation failed.
  152. @retval FALSE PublicKeySize is not large enough.
  153. **/
  154. BOOLEAN
  155. EFIAPI
  156. DhGenerateKey (
  157. IN OUT VOID *DhContext,
  158. OUT UINT8 *PublicKey,
  159. IN OUT UINTN *PublicKeySize
  160. )
  161. {
  162. BOOLEAN RetVal;
  163. DH *Dh;
  164. BIGNUM *DhPubKey;
  165. INTN Size;
  166. //
  167. // Check input parameters.
  168. //
  169. if (DhContext == NULL || PublicKeySize == NULL) {
  170. return FALSE;
  171. }
  172. if (PublicKey == NULL && *PublicKeySize != 0) {
  173. return FALSE;
  174. }
  175. Dh = (DH *) DhContext;
  176. RetVal = (BOOLEAN) DH_generate_key (DhContext);
  177. if (RetVal) {
  178. DH_get0_key (Dh, (const BIGNUM **)&DhPubKey, NULL);
  179. Size = BN_num_bytes (DhPubKey);
  180. if ((Size > 0) && (*PublicKeySize < (UINTN) Size)) {
  181. *PublicKeySize = Size;
  182. return FALSE;
  183. }
  184. if (PublicKey != NULL) {
  185. BN_bn2bin (DhPubKey, PublicKey);
  186. }
  187. *PublicKeySize = Size;
  188. }
  189. return RetVal;
  190. }
  191. /**
  192. Computes exchanged common key.
  193. Given peer's public key, this function computes the exchanged common key, based on its own
  194. context including value of prime modulus and random secret exponent.
  195. If DhContext is NULL, then return FALSE.
  196. If PeerPublicKey is NULL, then return FALSE.
  197. If KeySize is NULL, then return FALSE.
  198. If Key is NULL, then return FALSE.
  199. If KeySize is not large enough, then return FALSE.
  200. @param[in, out] DhContext Pointer to the DH context.
  201. @param[in] PeerPublicKey Pointer to the peer's public key.
  202. @param[in] PeerPublicKeySize Size of peer's public key in bytes.
  203. @param[out] Key Pointer to the buffer to receive generated key.
  204. @param[in, out] KeySize On input, the size of Key buffer in bytes.
  205. On output, the size of data returned in Key buffer in bytes.
  206. @retval TRUE DH exchanged key generation succeeded.
  207. @retval FALSE DH exchanged key generation failed.
  208. @retval FALSE KeySize is not large enough.
  209. **/
  210. BOOLEAN
  211. EFIAPI
  212. DhComputeKey (
  213. IN OUT VOID *DhContext,
  214. IN CONST UINT8 *PeerPublicKey,
  215. IN UINTN PeerPublicKeySize,
  216. OUT UINT8 *Key,
  217. IN OUT UINTN *KeySize
  218. )
  219. {
  220. BIGNUM *Bn;
  221. INTN Size;
  222. //
  223. // Check input parameters.
  224. //
  225. if (DhContext == NULL || PeerPublicKey == NULL || KeySize == NULL || Key == NULL) {
  226. return FALSE;
  227. }
  228. if (PeerPublicKeySize > INT_MAX) {
  229. return FALSE;
  230. }
  231. Bn = BN_bin2bn (PeerPublicKey, (UINT32) PeerPublicKeySize, NULL);
  232. if (Bn == NULL) {
  233. return FALSE;
  234. }
  235. Size = DH_compute_key (Key, Bn, DhContext);
  236. if (Size < 0) {
  237. BN_free (Bn);
  238. return FALSE;
  239. }
  240. if (*KeySize < (UINTN) Size) {
  241. *KeySize = Size;
  242. BN_free (Bn);
  243. return FALSE;
  244. }
  245. *KeySize = Size;
  246. BN_free (Bn);
  247. return TRUE;
  248. }