crypto_dh_nss.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /* Copyright (c) 2001, Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * \file crypto_dh_nss.h
  8. *
  9. * \brief NSS implementation of Diffie-Hellman over Z_p.
  10. **/
  11. #include "lib/crypt_ops/crypto_dh.h"
  12. #include "lib/crypt_ops/crypto_nss_mgt.h"
  13. #include "lib/encoding/binascii.h"
  14. #include "lib/log/util_bug.h"
  15. #include "lib/malloc/malloc.h"
  16. #include <cryptohi.h>
  17. #include <keyhi.h>
  18. #include <pk11pub.h>
  19. static int dh_initialized = 0;
  20. static SECKEYDHParams tls_dh_param, circuit_dh_param;
  21. static unsigned char tls_dh_prime_data[DH1024_KEY_LEN];
  22. static unsigned char circuit_dh_prime_data[DH1024_KEY_LEN];
  23. static unsigned char dh_generator_data[1];
  24. void
  25. crypto_dh_init_nss(void)
  26. {
  27. if (dh_initialized)
  28. return;
  29. int r;
  30. r = base16_decode((char*)tls_dh_prime_data,
  31. sizeof(tls_dh_prime_data),
  32. TLS_DH_PRIME, strlen(TLS_DH_PRIME));
  33. tor_assert(r == DH1024_KEY_LEN);
  34. r = base16_decode((char*)circuit_dh_prime_data,
  35. sizeof(circuit_dh_prime_data),
  36. OAKLEY_PRIME_2, strlen(OAKLEY_PRIME_2));
  37. tor_assert(r == DH1024_KEY_LEN);
  38. dh_generator_data[0] = DH_GENERATOR;
  39. tls_dh_param.prime.data = tls_dh_prime_data;
  40. tls_dh_param.prime.len = DH1024_KEY_LEN;
  41. tls_dh_param.base.data = dh_generator_data;
  42. tls_dh_param.base.len = 1;
  43. circuit_dh_param.prime.data = circuit_dh_prime_data;
  44. circuit_dh_param.prime.len = DH1024_KEY_LEN;
  45. circuit_dh_param.base.data = dh_generator_data;
  46. circuit_dh_param.base.len = 1;
  47. }
  48. void
  49. crypto_dh_free_all_nss(void)
  50. {
  51. dh_initialized = 0;
  52. }
  53. struct crypto_dh_t {
  54. int dh_type; // XXXX let's remove this later on.
  55. SECKEYPrivateKey *seckey;
  56. SECKEYPublicKey *pubkey;
  57. };
  58. crypto_dh_t *
  59. crypto_dh_new(int dh_type)
  60. {
  61. crypto_dh_t *r = tor_malloc_zero(sizeof(crypto_dh_t));
  62. r->dh_type = dh_type;
  63. return r;
  64. }
  65. crypto_dh_t *
  66. crypto_dh_dup(const crypto_dh_t *dh)
  67. {
  68. tor_assert(dh);
  69. crypto_dh_t *r = crypto_dh_new(dh->dh_type);
  70. if (dh->seckey)
  71. r->seckey = SECKEY_CopyPrivateKey(dh->seckey);
  72. if (dh->pubkey)
  73. r->pubkey = SECKEY_CopyPublicKey(dh->pubkey);
  74. return r;
  75. }
  76. int
  77. crypto_dh_get_bytes(crypto_dh_t *dh)
  78. {
  79. (void)dh;
  80. return DH1024_KEY_LEN;
  81. }
  82. int
  83. crypto_dh_generate_public(crypto_dh_t *dh)
  84. {
  85. tor_assert(dh);
  86. SECKEYDHParams *p;
  87. if (dh->dh_type == DH_TYPE_TLS)
  88. p = &tls_dh_param;
  89. else
  90. p = &circuit_dh_param;
  91. dh->seckey = SECKEY_CreateDHPrivateKey(p, &dh->pubkey, NULL);
  92. if (!dh->seckey || !dh->pubkey)
  93. return -1;
  94. else
  95. return 0;
  96. }
  97. int
  98. crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out,
  99. size_t pubkey_out_len)
  100. {
  101. tor_assert(dh);
  102. tor_assert(pubkey_out);
  103. if (!dh->pubkey) {
  104. if (crypto_dh_generate_public(dh) < 0)
  105. return -1;
  106. }
  107. const SECItem *item = &dh->pubkey->u.dh.publicValue;
  108. if (item->len > pubkey_out_len)
  109. return -1;
  110. /* Left-pad the result with 0s. */
  111. memset(pubkey_out, 0, pubkey_out_len);
  112. memcpy(pubkey_out + pubkey_out_len - item->len,
  113. item->data,
  114. item->len);
  115. return 0;
  116. }
  117. void
  118. crypto_dh_free_(crypto_dh_t *dh)
  119. {
  120. if (!dh)
  121. return;
  122. if (dh->seckey)
  123. SECKEY_DestroyPrivateKey(dh->seckey);
  124. if (dh->pubkey)
  125. SECKEY_DestroyPublicKey(dh->pubkey);
  126. tor_free(dh);
  127. }
  128. ssize_t
  129. crypto_dh_handshake(int severity, crypto_dh_t *dh,
  130. const char *pubkey, size_t pubkey_len,
  131. unsigned char *secret_out,
  132. size_t secret_bytes_out)
  133. {
  134. tor_assert(dh);
  135. if (pubkey_len > DH1024_KEY_LEN)
  136. return -1;
  137. if (!dh->pubkey || !dh->seckey)
  138. return -1;
  139. if (secret_bytes_out < DH1024_KEY_LEN)
  140. return -1;
  141. SECKEYPublicKey peer_key;
  142. memset(&peer_key, 0, sizeof(peer_key));
  143. peer_key.keyType = dhKey;
  144. peer_key.pkcs11ID = CK_INVALID_HANDLE;
  145. if (dh->dh_type == DH_TYPE_TLS)
  146. peer_key.u.dh.prime.data = tls_dh_prime_data; // should never use this code
  147. else
  148. peer_key.u.dh.prime.data = circuit_dh_prime_data;
  149. peer_key.u.dh.prime.len = DH1024_KEY_LEN;
  150. peer_key.u.dh.base.data = dh_generator_data;
  151. peer_key.u.dh.base.len = 1;
  152. peer_key.u.dh.publicValue.data = (unsigned char *)pubkey;
  153. peer_key.u.dh.publicValue.len = (int) pubkey_len;
  154. PK11SymKey *sym = PK11_PubDerive(dh->seckey, &peer_key,
  155. PR_FALSE, NULL, NULL, CKM_DH_PKCS_DERIVE,
  156. CKM_GENERIC_SECRET_KEY_GEN /* ??? */,
  157. CKA_DERIVE, 0, NULL);
  158. if (! sym) {
  159. crypto_nss_log_errors(severity, "deriving a DH shared secret");
  160. return -1;
  161. }
  162. SECStatus s = PK11_ExtractKeyValue(sym);
  163. if (s != SECSuccess) {
  164. crypto_nss_log_errors(severity, "extracting a DH shared secret");
  165. PK11_FreeSymKey(sym);
  166. return -1;
  167. }
  168. SECItem *result = PK11_GetKeyData(sym);
  169. tor_assert(result); // This cannot fail.
  170. if (BUG(result->len > secret_bytes_out)) {
  171. PK11_FreeSymKey(sym);
  172. return -1;
  173. }
  174. ssize_t len = result->len;
  175. memcpy(secret_out, result->data, len);
  176. PK11_FreeSymKey(sym);
  177. return len;
  178. }