s2n_dhe.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License").
  5. * You may not use this file except in compliance with the License.
  6. * A copy of the License is located at
  7. *
  8. * http://aws.amazon.com/apache2.0
  9. *
  10. * or in the "license" file accompanying this file. This file is distributed
  11. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  12. * express or implied. See the License for the specific language governing
  13. * permissions and limitations under the License.
  14. */
  15. #include "crypto/s2n_dhe.h"
  16. #include <openssl/bn.h>
  17. #include <openssl/dh.h>
  18. #include <openssl/evp.h>
  19. #include <stdint.h>
  20. #include "crypto/s2n_openssl.h"
  21. #include "error/s2n_errno.h"
  22. #include "stuffer/s2n_stuffer.h"
  23. #include "utils/s2n_blob.h"
  24. #include "utils/s2n_mem.h"
  25. #include "utils/s2n_safety.h"
  26. #define S2N_MIN_DH_PRIME_SIZE_BYTES (2048 / 8)
  27. /* Caller is not responsible for freeing values returned by these accessors
  28. * Per https://www.openssl.org/docs/man1.1.0/crypto/DH_get0_pqg.html
  29. */
  30. static const BIGNUM *s2n_get_Ys_dh_param(struct s2n_dh_params *dh_params)
  31. {
  32. const BIGNUM *Ys;
  33. /* DH made opaque in Openssl 1.1.0 */
  34. #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
  35. DH_get0_key(dh_params->dh, &Ys, NULL);
  36. #else
  37. Ys = dh_params->dh->pub_key;
  38. #endif
  39. return Ys;
  40. }
  41. static const BIGNUM *s2n_get_p_dh_param(struct s2n_dh_params *dh_params)
  42. {
  43. const BIGNUM *p;
  44. #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
  45. DH_get0_pqg(dh_params->dh, &p, NULL, NULL);
  46. #else
  47. p = dh_params->dh->p;
  48. #endif
  49. return p;
  50. }
  51. static const BIGNUM *s2n_get_g_dh_param(struct s2n_dh_params *dh_params)
  52. {
  53. const BIGNUM *g;
  54. #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
  55. DH_get0_pqg(dh_params->dh, NULL, NULL, &g);
  56. #else
  57. g = dh_params->dh->g;
  58. #endif
  59. return g;
  60. }
  61. static int s2n_check_p_g_dh_params(struct s2n_dh_params *dh_params)
  62. {
  63. POSIX_ENSURE_REF(dh_params);
  64. POSIX_ENSURE_REF(dh_params->dh);
  65. const BIGNUM *p = s2n_get_p_dh_param(dh_params);
  66. const BIGNUM *g = s2n_get_g_dh_param(dh_params);
  67. POSIX_ENSURE_REF(g);
  68. POSIX_ENSURE_REF(p);
  69. S2N_ERROR_IF(DH_size(dh_params->dh) < S2N_MIN_DH_PRIME_SIZE_BYTES, S2N_ERR_DH_PARAMS_CREATE);
  70. S2N_ERROR_IF(BN_is_zero(g), S2N_ERR_DH_PARAMS_CREATE);
  71. S2N_ERROR_IF(BN_is_zero(p), S2N_ERR_DH_PARAMS_CREATE);
  72. return S2N_SUCCESS;
  73. }
  74. static int s2n_check_pub_key_dh_params(struct s2n_dh_params *dh_params)
  75. {
  76. const BIGNUM *pub_key = s2n_get_Ys_dh_param(dh_params);
  77. POSIX_ENSURE_REF(pub_key);
  78. S2N_ERROR_IF(BN_is_zero(pub_key), S2N_ERR_DH_PARAMS_CREATE);
  79. return S2N_SUCCESS;
  80. }
  81. static int s2n_set_p_g_Ys_dh_params(struct s2n_dh_params *dh_params, struct s2n_blob *p, struct s2n_blob *g,
  82. struct s2n_blob *Ys)
  83. {
  84. POSIX_ENSURE(p->size <= INT_MAX, S2N_ERR_INTEGER_OVERFLOW);
  85. POSIX_ENSURE(g->size <= INT_MAX, S2N_ERR_INTEGER_OVERFLOW);
  86. POSIX_ENSURE(Ys->size <= INT_MAX, S2N_ERR_INTEGER_OVERFLOW);
  87. BIGNUM *bn_p = BN_bin2bn((const unsigned char *) p->data, p->size, NULL);
  88. BIGNUM *bn_g = BN_bin2bn((const unsigned char *) g->data, g->size, NULL);
  89. BIGNUM *bn_Ys = BN_bin2bn((const unsigned char *) Ys->data, Ys->size, NULL);
  90. #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
  91. /* Per https://www.openssl.org/docs/man1.1.0/crypto/DH_get0_pqg.html:
  92. * values that have been passed in should not be freed directly after this function has been called
  93. */
  94. POSIX_GUARD_OSSL(DH_set0_pqg(dh_params->dh, bn_p, NULL, bn_g), S2N_ERR_DH_PARAMS_CREATE);
  95. /* Same as DH_set0_pqg */
  96. POSIX_GUARD_OSSL(DH_set0_key(dh_params->dh, bn_Ys, NULL), S2N_ERR_DH_PARAMS_CREATE);
  97. #else
  98. dh_params->dh->p = bn_p;
  99. dh_params->dh->g = bn_g;
  100. dh_params->dh->pub_key = bn_Ys;
  101. #endif
  102. return S2N_SUCCESS;
  103. }
  104. int s2n_check_all_dh_params(struct s2n_dh_params *dh_params)
  105. {
  106. POSIX_GUARD(s2n_check_p_g_dh_params(dh_params));
  107. POSIX_GUARD(s2n_check_pub_key_dh_params(dh_params));
  108. return S2N_SUCCESS;
  109. }
  110. int s2n_pkcs3_to_dh_params(struct s2n_dh_params *dh_params, struct s2n_blob *pkcs3)
  111. {
  112. POSIX_ENSURE_REF(dh_params);
  113. POSIX_PRECONDITION(s2n_blob_validate(pkcs3));
  114. DEFER_CLEANUP(struct s2n_dh_params temp_dh_params = { 0 }, s2n_dh_params_free);
  115. uint8_t *original_ptr = pkcs3->data;
  116. temp_dh_params.dh = d2i_DHparams(NULL, (const unsigned char **) (void *) &pkcs3->data, pkcs3->size);
  117. POSIX_GUARD(s2n_check_p_g_dh_params(&temp_dh_params));
  118. if (pkcs3->data) {
  119. POSIX_ENSURE_GTE(pkcs3->data, original_ptr);
  120. POSIX_ENSURE((uint32_t) (pkcs3->data - original_ptr) == pkcs3->size, S2N_ERR_INVALID_PKCS3);
  121. }
  122. pkcs3->data = original_ptr;
  123. /* Require at least 2048 bits for the DH size */
  124. POSIX_ENSURE(DH_size(temp_dh_params.dh) >= S2N_MIN_DH_PRIME_SIZE_BYTES, S2N_ERR_DH_TOO_SMALL);
  125. /* Check the generator and prime */
  126. POSIX_GUARD(s2n_dh_params_check(&temp_dh_params));
  127. dh_params->dh = temp_dh_params.dh;
  128. ZERO_TO_DISABLE_DEFER_CLEANUP(temp_dh_params);
  129. return S2N_SUCCESS;
  130. }
  131. int s2n_dh_p_g_Ys_to_dh_params(struct s2n_dh_params *server_dh_params, struct s2n_blob *p, struct s2n_blob *g,
  132. struct s2n_blob *Ys)
  133. {
  134. POSIX_ENSURE_REF(server_dh_params);
  135. POSIX_PRECONDITION(s2n_blob_validate(p));
  136. POSIX_PRECONDITION(s2n_blob_validate(g));
  137. POSIX_PRECONDITION(s2n_blob_validate(Ys));
  138. server_dh_params->dh = DH_new();
  139. POSIX_ENSURE(server_dh_params->dh != NULL, S2N_ERR_DH_PARAMS_CREATE);
  140. POSIX_GUARD(s2n_set_p_g_Ys_dh_params(server_dh_params, p, g, Ys));
  141. POSIX_GUARD(s2n_check_all_dh_params(server_dh_params));
  142. return S2N_SUCCESS;
  143. }
  144. int s2n_dh_params_to_p_g_Ys(struct s2n_dh_params *server_dh_params, struct s2n_stuffer *out, struct s2n_blob *output)
  145. {
  146. POSIX_GUARD(s2n_check_all_dh_params(server_dh_params));
  147. POSIX_PRECONDITION(s2n_stuffer_validate(out));
  148. POSIX_PRECONDITION(s2n_blob_validate(output));
  149. const BIGNUM *bn_p = s2n_get_p_dh_param(server_dh_params);
  150. const BIGNUM *bn_g = s2n_get_g_dh_param(server_dh_params);
  151. const BIGNUM *bn_Ys = s2n_get_Ys_dh_param(server_dh_params);
  152. uint16_t p_size = BN_num_bytes(bn_p);
  153. uint16_t g_size = BN_num_bytes(bn_g);
  154. uint16_t Ys_size = BN_num_bytes(bn_Ys);
  155. uint8_t *p = NULL;
  156. uint8_t *g = NULL;
  157. uint8_t *Ys = NULL;
  158. output->data = s2n_stuffer_raw_write(out, 0);
  159. POSIX_ENSURE_REF(output->data);
  160. POSIX_GUARD(s2n_stuffer_write_uint16(out, p_size));
  161. p = s2n_stuffer_raw_write(out, p_size);
  162. POSIX_ENSURE_REF(p);
  163. POSIX_ENSURE(BN_bn2bin(bn_p, p) == p_size, S2N_ERR_DH_SERIALIZING);
  164. POSIX_GUARD(s2n_stuffer_write_uint16(out, g_size));
  165. g = s2n_stuffer_raw_write(out, g_size);
  166. POSIX_ENSURE_REF(g);
  167. POSIX_ENSURE(BN_bn2bin(bn_g, g) == g_size, S2N_ERR_DH_SERIALIZING);
  168. POSIX_GUARD(s2n_stuffer_write_uint16(out, Ys_size));
  169. Ys = s2n_stuffer_raw_write(out, Ys_size);
  170. POSIX_ENSURE_REF(Ys);
  171. POSIX_ENSURE(BN_bn2bin(bn_Ys, Ys) == Ys_size, S2N_ERR_DH_SERIALIZING);
  172. output->size = p_size + 2 + g_size + 2 + Ys_size + 2;
  173. return S2N_SUCCESS;
  174. }
  175. int s2n_dh_compute_shared_secret_as_client(struct s2n_dh_params *server_dh_params, struct s2n_stuffer *Yc_out,
  176. struct s2n_blob *shared_key)
  177. {
  178. struct s2n_dh_params client_params = { 0 };
  179. uint8_t *client_pub_key = NULL;
  180. uint16_t client_pub_key_size = 0;
  181. int shared_key_size = 0;
  182. POSIX_GUARD(s2n_dh_params_check(server_dh_params));
  183. POSIX_GUARD(s2n_dh_params_copy(server_dh_params, &client_params));
  184. POSIX_GUARD(s2n_dh_generate_ephemeral_key(&client_params));
  185. POSIX_GUARD(s2n_alloc(shared_key, DH_size(server_dh_params->dh)));
  186. const BIGNUM *client_pub_key_bn = s2n_get_Ys_dh_param(&client_params);
  187. POSIX_ENSURE_REF(client_pub_key_bn);
  188. client_pub_key_size = BN_num_bytes(client_pub_key_bn);
  189. POSIX_GUARD(s2n_stuffer_write_uint16(Yc_out, client_pub_key_size));
  190. client_pub_key = s2n_stuffer_raw_write(Yc_out, client_pub_key_size);
  191. if (client_pub_key == NULL) {
  192. POSIX_GUARD(s2n_free(shared_key));
  193. POSIX_GUARD(s2n_dh_params_free(&client_params));
  194. POSIX_BAIL(S2N_ERR_DH_WRITING_PUBLIC_KEY);
  195. }
  196. if (BN_bn2bin(client_pub_key_bn, client_pub_key) != client_pub_key_size) {
  197. POSIX_GUARD(s2n_free(shared_key));
  198. POSIX_GUARD(s2n_dh_params_free(&client_params));
  199. POSIX_BAIL(S2N_ERR_DH_COPYING_PUBLIC_KEY);
  200. }
  201. /* server_dh_params already validated */
  202. const BIGNUM *server_pub_key_bn = s2n_get_Ys_dh_param(server_dh_params);
  203. shared_key_size = DH_compute_key(shared_key->data, server_pub_key_bn, client_params.dh);
  204. if (shared_key_size < 0) {
  205. POSIX_GUARD(s2n_free(shared_key));
  206. POSIX_GUARD(s2n_dh_params_free(&client_params));
  207. POSIX_BAIL(S2N_ERR_DH_SHARED_SECRET);
  208. }
  209. shared_key->size = shared_key_size;
  210. POSIX_GUARD(s2n_dh_params_free(&client_params));
  211. return S2N_SUCCESS;
  212. }
  213. int s2n_dh_compute_shared_secret_as_server(struct s2n_dh_params *server_dh_params, struct s2n_stuffer *Yc_in,
  214. struct s2n_blob *shared_key)
  215. {
  216. uint16_t Yc_length = 0;
  217. struct s2n_blob Yc = { 0 };
  218. int shared_key_size = 0;
  219. BIGNUM *pub_key = NULL;
  220. POSIX_GUARD(s2n_check_all_dh_params(server_dh_params));
  221. POSIX_GUARD(s2n_stuffer_read_uint16(Yc_in, &Yc_length));
  222. Yc.size = Yc_length;
  223. Yc.data = s2n_stuffer_raw_read(Yc_in, Yc.size);
  224. POSIX_ENSURE_REF(Yc.data);
  225. pub_key = BN_bin2bn((const unsigned char *) Yc.data, Yc.size, NULL);
  226. POSIX_ENSURE_REF(pub_key);
  227. int server_dh_params_size = DH_size(server_dh_params->dh);
  228. POSIX_ENSURE(server_dh_params_size <= INT32_MAX, S2N_ERR_INTEGER_OVERFLOW);
  229. POSIX_GUARD(s2n_alloc(shared_key, server_dh_params_size));
  230. shared_key_size = DH_compute_key(shared_key->data, pub_key, server_dh_params->dh);
  231. if (shared_key_size <= 0) {
  232. BN_free(pub_key);
  233. POSIX_BAIL(S2N_ERR_DH_SHARED_SECRET);
  234. }
  235. shared_key->size = shared_key_size;
  236. BN_free(pub_key);
  237. return S2N_SUCCESS;
  238. }
  239. int s2n_dh_params_check(struct s2n_dh_params *dh_params)
  240. {
  241. POSIX_ENSURE_REF(dh_params);
  242. POSIX_ENSURE_REF(dh_params->dh);
  243. int codes = 0;
  244. POSIX_GUARD_OSSL(DH_check(dh_params->dh, &codes), S2N_ERR_DH_PARAMETER_CHECK);
  245. POSIX_ENSURE(codes == 0, S2N_ERR_DH_PARAMETER_CHECK);
  246. return S2N_SUCCESS;
  247. }
  248. int s2n_dh_params_copy(struct s2n_dh_params *from, struct s2n_dh_params *to)
  249. {
  250. POSIX_GUARD(s2n_check_p_g_dh_params(from));
  251. POSIX_ENSURE_REF(to);
  252. to->dh = DHparams_dup(from->dh);
  253. POSIX_ENSURE(to->dh != NULL, S2N_ERR_DH_COPYING_PARAMETERS);
  254. return S2N_SUCCESS;
  255. }
  256. int s2n_dh_generate_ephemeral_key(struct s2n_dh_params *dh_params)
  257. {
  258. POSIX_GUARD(s2n_check_p_g_dh_params(dh_params));
  259. POSIX_GUARD_OSSL(DH_generate_key(dh_params->dh), S2N_ERR_DH_GENERATING_PARAMETERS);
  260. return S2N_SUCCESS;
  261. }
  262. int s2n_dh_params_free(struct s2n_dh_params *dh_params)
  263. {
  264. POSIX_ENSURE_REF(dh_params);
  265. DH_free(dh_params->dh);
  266. dh_params->dh = NULL;
  267. return S2N_SUCCESS;
  268. }