tor  0.4.1.0-alpha-dev
onion_tap.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-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
30 #include "core/or/or.h"
31 #include "app/config/config.h"
35 #include "core/crypto/onion_tap.h"
36 #include "feature/stats/rephist.h"
37 
38 /*----------------------------------------------------------------------*/
39 
52 int
54  crypto_dh_t **handshake_state_out,
55  char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */
56 {
57  char challenge[DH1024_KEY_LEN];
58  crypto_dh_t *dh = NULL;
59  int dhbytes, pkbytes;
60 
61  tor_assert(dest_router_key);
62  tor_assert(handshake_state_out);
63  tor_assert(onion_skin_out);
64  *handshake_state_out = NULL;
65  memset(onion_skin_out, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
66 
67  if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT)))
68  goto err;
69 
70  dhbytes = crypto_dh_get_bytes(dh);
71  pkbytes = (int) crypto_pk_keysize(dest_router_key);
72  tor_assert(dhbytes == 128);
73  tor_assert(pkbytes == 128);
74 
75  if (crypto_dh_get_public(dh, challenge, dhbytes))
76  goto err;
77 
78  /* set meeting point, meeting cookie, etc here. Leave zero for now. */
79  if (crypto_pk_obsolete_public_hybrid_encrypt(dest_router_key, onion_skin_out,
80  TAP_ONIONSKIN_CHALLENGE_LEN,
81  challenge, DH1024_KEY_LEN,
83  goto err;
84 
85  memwipe(challenge, 0, sizeof(challenge));
86  *handshake_state_out = dh;
87 
88  return 0;
89  err:
90  /* LCOV_EXCL_START
91  * We only get here if RSA encryption fails or DH keygen fails. Those
92  * shouldn't be possible. */
93  memwipe(challenge, 0, sizeof(challenge));
94  if (dh) crypto_dh_free(dh);
95  return -1;
96  /* LCOV_EXCL_STOP */
97 }
98 
104 int
106  /*TAP_ONIONSKIN_CHALLENGE_LEN*/
107  const char *onion_skin,
108  crypto_pk_t *private_key,
109  crypto_pk_t *prev_private_key,
110  /*TAP_ONIONSKIN_REPLY_LEN*/
111  char *handshake_reply_out,
112  char *key_out,
113  size_t key_out_len)
114 {
115  char challenge[TAP_ONIONSKIN_CHALLENGE_LEN];
116  crypto_dh_t *dh = NULL;
117  ssize_t len;
118  char *key_material=NULL;
119  size_t key_material_len=0;
120  int i;
121  crypto_pk_t *k;
122 
123  len = -1;
124  for (i=0;i<2;++i) {
125  k = i==0?private_key:prev_private_key;
126  if (!k)
127  break;
129  TAP_ONIONSKIN_CHALLENGE_LEN,
130  onion_skin,
131  TAP_ONIONSKIN_CHALLENGE_LEN,
133  if (len>0)
134  break;
135  }
136  if (len<0) {
137  log_info(LD_PROTOCOL,
138  "Couldn't decrypt onionskin: client may be using old onion key");
139  goto err;
140  } else if (len != DH1024_KEY_LEN) {
141  log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
142  "Unexpected onionskin length after decryption: %ld",
143  (long)len);
144  goto err;
145  }
146 
147  dh = crypto_dh_new(DH_TYPE_CIRCUIT);
148  if (!dh) {
149  /* LCOV_EXCL_START
150  * Failure to allocate a DH key should be impossible.
151  */
152  log_warn(LD_BUG, "Couldn't allocate DH key");
153  goto err;
154  /* LCOV_EXCL_STOP */
155  }
156  if (crypto_dh_get_public(dh, handshake_reply_out, DH1024_KEY_LEN)) {
157  /* LCOV_EXCL_START
158  * This can only fail if the length of the key we just allocated is too
159  * big. That should be impossible. */
160  log_info(LD_GENERAL, "crypto_dh_get_public failed.");
161  goto err;
162  /* LCOV_EXCL_STOP */
163  }
164 
165  key_material_len = DIGEST_LEN+key_out_len;
166  key_material = tor_malloc(key_material_len);
167  len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge,
168  DH1024_KEY_LEN, key_material,
169  key_material_len);
170  if (len < 0) {
171  log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
172  goto err;
173  }
174 
175  /* send back H(K|0) as proof that we learned K. */
176  memcpy(handshake_reply_out+DH1024_KEY_LEN, key_material, DIGEST_LEN);
177 
178  /* use the rest of the key material for our shared keys, digests, etc */
179  memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
180 
181  memwipe(challenge, 0, sizeof(challenge));
182  memwipe(key_material, 0, key_material_len);
183  tor_free(key_material);
184  crypto_dh_free(dh);
185  return 0;
186  err:
187  memwipe(challenge, 0, sizeof(challenge));
188  if (key_material) {
189  memwipe(key_material, 0, key_material_len);
190  tor_free(key_material);
191  }
192  if (dh) crypto_dh_free(dh);
193 
194  return -1;
195 }
196 
206 int
208  const char *handshake_reply, /* TAP_ONIONSKIN_REPLY_LEN bytes */
209  char *key_out,
210  size_t key_out_len,
211  const char **msg_out)
212 {
213  ssize_t len;
214  char *key_material=NULL;
215  size_t key_material_len;
216  tor_assert(crypto_dh_get_bytes(handshake_state) == DH1024_KEY_LEN);
217 
218  key_material_len = DIGEST_LEN + key_out_len;
219  key_material = tor_malloc(key_material_len);
220  len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state,
221  handshake_reply, DH1024_KEY_LEN, key_material,
222  key_material_len);
223  if (len < 0) {
224  if (msg_out)
225  *msg_out = "DH computation failed.";
226  goto err;
227  }
228 
229  if (tor_memneq(key_material, handshake_reply+DH1024_KEY_LEN, DIGEST_LEN)) {
230  /* H(K) does *not* match. Something fishy. */
231  if (msg_out)
232  *msg_out = "Digest DOES NOT MATCH on onion handshake. Bug or attack.";
233  goto err;
234  }
235 
236  /* use the rest of the key material for our shared keys, digests, etc */
237  memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
238 
239  memwipe(key_material, 0, key_material_len);
240  tor_free(key_material);
241  return 0;
242  err:
243  memwipe(key_material, 0, key_material_len);
244  tor_free(key_material);
245  return -1;
246 }
Common functions for using (pseudo-)random number generators.
Headers for crypto_dh.c.
#define LD_GENERAL
Definition: log.h:59
Header file for onion_tap.c.
int crypto_dh_get_public(crypto_dh_t *dh, char *pubkey_out, size_t pubkey_out_len)
Header file for config.c.
int onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state, const char *handshake_reply, char *key_out, size_t key_out_len, const char **msg_out)
Definition: onion_tap.c:207
#define tor_free(p)
Definition: malloc.h:52
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:57
int onion_skin_TAP_server_handshake(const char *onion_skin, crypto_pk_t *private_key, crypto_pk_t *prev_private_key, char *handshake_reply_out, char *key_out, size_t key_out_len)
Definition: onion_tap.c:105
Common functions for cryptographic routines.
tor_assert(buffer)
int crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env, char *to, size_t tolen, const char *from, size_t fromlen, int padding, int force)
Definition: crypto_rsa.c:94
#define DIGEST_LEN
Definition: digest_sizes.h:20
#define PK_PKCS1_OAEP_PADDING
Definition: crypto_rsa.h:27
Master header file for Tor-specific functionality.
Header file for rephist.c.
#define DH1024_KEY_LEN
Definition: dh_sizes.h:20
int onion_skin_TAP_create(crypto_pk_t *dest_router_key, crypto_dh_t **handshake_state_out, char *onion_skin_out)
Definition: onion_tap.c:53
crypto_dh_t * crypto_dh_new(int dh_type)
Definition: crypto_dh_nss.c:73
#define log_fn(severity, domain, args,...)
Definition: log.h:266
size_t crypto_pk_keysize(const crypto_pk_t *env)
int crypto_dh_get_bytes(crypto_dh_t *dh)
Definition: crypto_dh_nss.c:93
ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh, const char *pubkey, size_t pubkey_len, char *secret_out, size_t secret_bytes_out)
Definition: crypto_dh.c:79
int crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env, char *to, size_t tolen, const char *from, size_t fromlen, int padding, int warnOnFailure)
Definition: crypto_rsa.c:163
#define LD_PROTOCOL
Definition: log.h:69
#define LD_BUG
Definition: log.h:83