Tor  0.4.7.0-alpha-dev
crypto_dh_nss.c
Go to the documentation of this file.
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-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
7 /**
8  * \file crypto_dh_nss.c
9  *
10  * \brief NSS implementation of Diffie-Hellman over Z_p.
11  **/
12 
15 
16 #include "lib/encoding/binascii.h"
17 #include "lib/log/util_bug.h"
18 #include "lib/malloc/malloc.h"
19 
20 #include <cryptohi.h>
21 #include <keyhi.h>
22 #include <pk11pub.h>
23 
24 static int dh_initialized = 0;
25 static SECKEYDHParams tls_dh_param, circuit_dh_param;
26 static unsigned char tls_dh_prime_data[DH1024_KEY_LEN];
27 static unsigned char circuit_dh_prime_data[DH1024_KEY_LEN];
28 static unsigned char dh_generator_data[1];
29 
30 void
31 crypto_dh_init_nss(void)
32 {
33  if (dh_initialized)
34  return;
35 
36  int r;
37  r = base16_decode((char*)tls_dh_prime_data,
38  sizeof(tls_dh_prime_data),
39  TLS_DH_PRIME, strlen(TLS_DH_PRIME));
41  r = base16_decode((char*)circuit_dh_prime_data,
42  sizeof(circuit_dh_prime_data),
45  dh_generator_data[0] = DH_GENERATOR;
46 
47  tls_dh_param.prime.data = tls_dh_prime_data;
48  tls_dh_param.prime.len = DH1024_KEY_LEN;
49  tls_dh_param.base.data = dh_generator_data;
50  tls_dh_param.base.len = 1;
51 
52  circuit_dh_param.prime.data = circuit_dh_prime_data;
53  circuit_dh_param.prime.len = DH1024_KEY_LEN;
54  circuit_dh_param.base.data = dh_generator_data;
55  circuit_dh_param.base.len = 1;
56 
57  dh_initialized = 1;
58 }
59 
60 void
61 crypto_dh_free_all_nss(void)
62 {
63  dh_initialized = 0;
64 }
65 
66 struct crypto_dh_t {
67  int dh_type; // XXXX let's remove this later on.
68  SECKEYPrivateKey *seckey;
69  SECKEYPublicKey *pubkey;
70 };
71 
73 crypto_dh_new(int dh_type)
74 {
75  crypto_dh_t *r = tor_malloc_zero(sizeof(crypto_dh_t));
76  r->dh_type = dh_type;
77  return r;
78 }
79 
82 {
83  tor_assert(dh);
84  crypto_dh_t *r = crypto_dh_new(dh->dh_type);
85  if (dh->seckey)
86  r->seckey = SECKEY_CopyPrivateKey(dh->seckey);
87  if (dh->pubkey)
88  r->pubkey = SECKEY_CopyPublicKey(dh->pubkey);
89  return r;
90 }
91 
92 int
94 {
95  (void)dh;
96  return DH1024_KEY_LEN;
97 }
98 
99 int
101 {
102  tor_assert(dh);
103  SECKEYDHParams *p;
104  if (dh->dh_type == DH_TYPE_TLS)
105  p = &tls_dh_param;
106  else
107  p = &circuit_dh_param;
108 
109  dh->seckey = SECKEY_CreateDHPrivateKey(p, &dh->pubkey, NULL);
110  if (!dh->seckey || !dh->pubkey)
111  return -1;
112  else
113  return 0;
114 }
115 int
116 crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out,
117  size_t pubkey_out_len)
118 {
119  tor_assert(dh);
120  tor_assert(pubkey_out);
121  if (!dh->pubkey) {
122  if (crypto_dh_generate_public(dh) < 0)
123  return -1;
124  }
125 
126  const SECItem *item = &dh->pubkey->u.dh.publicValue;
127 
128  if (item->len > pubkey_out_len)
129  return -1;
130 
131  /* Left-pad the result with 0s. */
132  memset(pubkey_out, 0, pubkey_out_len);
133  memcpy(pubkey_out + pubkey_out_len - item->len,
134  item->data,
135  item->len);
136 
137  return 0;
138 }
139 
140 void
142 {
143  if (!dh)
144  return;
145  if (dh->seckey)
146  SECKEY_DestroyPrivateKey(dh->seckey);
147  if (dh->pubkey)
148  SECKEY_DestroyPublicKey(dh->pubkey);
149  tor_free(dh);
150 }
151 
152 ssize_t
154  const char *pubkey, size_t pubkey_len,
155  unsigned char *secret_out,
156  size_t secret_bytes_out)
157 {
158  tor_assert(dh);
159  if (pubkey_len > DH1024_KEY_LEN)
160  return -1;
161  if (!dh->pubkey || !dh->seckey)
162  return -1;
163  if (secret_bytes_out < DH1024_KEY_LEN)
164  return -1;
165 
166  SECKEYPublicKey peer_key;
167  memset(&peer_key, 0, sizeof(peer_key));
168  peer_key.keyType = dhKey;
169  peer_key.pkcs11ID = CK_INVALID_HANDLE;
170 
171  if (dh->dh_type == DH_TYPE_TLS)
172  peer_key.u.dh.prime.data = tls_dh_prime_data; // should never use this code
173  else
174  peer_key.u.dh.prime.data = circuit_dh_prime_data;
175  peer_key.u.dh.prime.len = DH1024_KEY_LEN;
176  peer_key.u.dh.base.data = dh_generator_data;
177  peer_key.u.dh.base.len = 1;
178  peer_key.u.dh.publicValue.data = (unsigned char *)pubkey;
179  peer_key.u.dh.publicValue.len = (int) pubkey_len;
180 
181  PK11SymKey *sym = PK11_PubDerive(dh->seckey, &peer_key,
182  PR_FALSE, NULL, NULL, CKM_DH_PKCS_DERIVE,
183  CKM_GENERIC_SECRET_KEY_GEN /* ??? */,
184  CKA_DERIVE, 0, NULL);
185  if (! sym) {
186  crypto_nss_log_errors(severity, "deriving a DH shared secret");
187  return -1;
188  }
189 
190  SECStatus s = PK11_ExtractKeyValue(sym);
191  if (s != SECSuccess) {
192  crypto_nss_log_errors(severity, "extracting a DH shared secret");
193  PK11_FreeSymKey(sym);
194  return -1;
195  }
196 
197  SECItem *result = PK11_GetKeyData(sym);
198  tor_assert(result); // This cannot fail.
199  if (BUG(result->len > secret_bytes_out)) {
200  PK11_FreeSymKey(sym);
201  return -1;
202  }
203 
204  ssize_t len = result->len;
205  memcpy(secret_out, result->data, len);
206  PK11_FreeSymKey(sym);
207 
208  return len;
209 }
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:506
Header for binascii.c.
const char OAKLEY_PRIME_2[]
Definition: crypto_dh.c:39
const char TLS_DH_PRIME[]
Definition: crypto_dh.c:28
const unsigned DH_GENERATOR
Definition: crypto_dh.c:23
Headers for crypto_dh.c.
int crypto_dh_generate_public(crypto_dh_t *dh)
crypto_dh_t * crypto_dh_dup(const crypto_dh_t *dh)
Definition: crypto_dh_nss.c:81
void crypto_dh_free_(crypto_dh_t *dh)
int crypto_dh_get_bytes(crypto_dh_t *dh)
Definition: crypto_dh_nss.c:93
crypto_dh_t * crypto_dh_new(int dh_type)
Definition: crypto_dh_nss.c:73
ssize_t crypto_dh_handshake(int severity, crypto_dh_t *dh, const char *pubkey, size_t pubkey_len, unsigned char *secret_out, size_t secret_bytes_out)
int crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out, size_t pubkey_out_len)
Headers for crypto_nss_mgt.c.
#define DH1024_KEY_LEN
Definition: dh_sizes.h:20
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:52
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:102