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