aboutsummaryrefslogtreecommitdiff
path: root/src/gnsrecord/gnsrecord_crypto.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-16 20:14:02 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-16 20:14:02 +0000
commit3d670727232e79b7e49a1df7ba9260db4e5798a0 (patch)
tree093f7b5aec28134dc6c5fe34cd2d8bfb1e1445ad /src/gnsrecord/gnsrecord_crypto.c
parent2de26776993a5e591e487321a5dc1d62b86d9cd4 (diff)
downloadgnunet-3d670727232e79b7e49a1df7ba9260db4e5798a0.tar.gz
gnunet-3d670727232e79b7e49a1df7ba9260db4e5798a0.zip
-moving namestore_common functions to gnsrecord library
Diffstat (limited to 'src/gnsrecord/gnsrecord_crypto.c')
-rw-r--r--src/gnsrecord/gnsrecord_crypto.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/src/gnsrecord/gnsrecord_crypto.c b/src/gnsrecord/gnsrecord_crypto.c
new file mode 100644
index 000000000..823ffcae3
--- /dev/null
+++ b/src/gnsrecord/gnsrecord_crypto.c
@@ -0,0 +1,263 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file gnsrecord/gnsrecord_crypto.c
23 * @brief API for GNS record-related crypto
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_signatures.h"
32#include "gnunet_arm_service.h"
33#include "gnunet_gnsrecord_lib.h"
34#include "gnunet_dnsparser_lib.h"
35#include "gnunet_tun_lib.h"
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
39
40
41/**
42 * Derive session key and iv from label and public key.
43 *
44 * @param iv initialization vector to initialize
45 * @param skey session key to initialize
46 * @param label label to use for KDF
47 * @param pub public key to use for KDF
48 */
49static void
50derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
51 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
52 const char *label,
53 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
54{
55 static const char ctx_key[] = "gns-aes-ctx-key";
56 static const char ctx_iv[] = "gns-aes-ctx-iv";
57
58 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
59 pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
60 label, strlen (label),
61 ctx_key, strlen (ctx_key),
62 NULL, 0);
63 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
64 pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
65 label, strlen (label),
66 ctx_iv, strlen (ctx_iv),
67 NULL, 0);
68}
69
70
71/**
72 * Sign name and records
73 *
74 * @param key the private key
75 * @param expire block expiration
76 * @param label the name for the records
77 * @param rd record data
78 * @param rd_count number of records
79 * @return NULL on error (block too large)
80 */
81struct GNUNET_NAMESTORE_Block *
82GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
83 struct GNUNET_TIME_Absolute expire,
84 const char *label,
85 const struct GNUNET_NAMESTORE_RecordData *rd,
86 unsigned int rd_count)
87{
88 size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
89 char payload[sizeof (uint32_t) + payload_len];
90 struct GNUNET_NAMESTORE_Block *block;
91 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
92 struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey;
93 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
94 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
95 uint32_t rd_count_nbo;
96
97 if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE)
98 return NULL;
99 rd_count_nbo = htonl (rd_count);
100 memcpy (payload, &rd_count_nbo, sizeof (uint32_t));
101 GNUNET_assert (payload_len ==
102 GNUNET_NAMESTORE_records_serialize (rd_count, rd,
103 payload_len, &payload[sizeof (uint32_t)]));
104 block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) +
105 sizeof (uint32_t) + payload_len);
106 block->purpose.size = htonl (sizeof (uint32_t) + payload_len +
107 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
108 sizeof (struct GNUNET_TIME_AbsoluteNBO));
109 block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
110 block->expiration_time = GNUNET_TIME_absolute_hton (expire);
111 dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key,
112 label,
113 "gns");
114 GNUNET_CRYPTO_ecdsa_key_get_public (dkey,
115 &block->derived_key);
116 GNUNET_CRYPTO_ecdsa_key_get_public (key,
117 &pkey);
118 derive_block_aes_key (&iv, &skey, label, &pkey);
119 GNUNET_break (payload_len + sizeof (uint32_t) ==
120 GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len + sizeof (uint32_t),
121 &skey, &iv,
122 &block[1]));
123 if (GNUNET_OK !=
124 GNUNET_CRYPTO_ecdsa_sign (dkey,
125 &block->purpose,
126 &block->signature))
127 {
128 GNUNET_break (0);
129 GNUNET_free (dkey);
130 GNUNET_free (block);
131 return NULL;
132 }
133 GNUNET_free (dkey);
134 return block;
135}
136
137
138/**
139 * Check if a signature is valid. This API is used by the GNS Block
140 * to validate signatures received from the network.
141 *
142 * @param block block to verify
143 * @return #GNUNET_OK if the signature is valid
144 */
145int
146GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block)
147{
148 return GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
149 &block->purpose,
150 &block->signature,
151 &block->derived_key);
152}
153
154
155/**
156 * Decrypt block.
157 *
158 * @param block block to decrypt
159 * @param zone_key public key of the zone
160 * @param label the name for the records
161 * @param proc function to call with the result
162 * @param proc_cls closure for proc
163 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
164 * not well-formed
165 */
166int
167GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
168 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
169 const char *label,
170 GNUNET_NAMESTORE_RecordCallback proc,
171 void *proc_cls)
172{
173 size_t payload_len = ntohl (block->purpose.size) -
174 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
175 sizeof (struct GNUNET_TIME_AbsoluteNBO);
176 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
177 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
178
179 if (ntohl (block->purpose.size) <
180 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
181 sizeof (struct GNUNET_TIME_AbsoluteNBO))
182 {
183 GNUNET_break_op (0);
184 return GNUNET_SYSERR;
185 }
186 derive_block_aes_key (&iv, &skey, label, zone_key);
187 {
188 char payload[payload_len];
189 uint32_t rd_count;
190
191 GNUNET_break (payload_len ==
192 GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len,
193 &skey, &iv,
194 payload));
195 memcpy (&rd_count,
196 payload,
197 sizeof (uint32_t));
198 rd_count = ntohl (rd_count);
199 if (rd_count > 2048)
200 {
201 /* limit to sane value */
202 GNUNET_break_op (0);
203 return GNUNET_SYSERR;
204 }
205 {
206 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
207
208 if (GNUNET_OK !=
209 GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t),
210 &payload[sizeof (uint32_t)],
211 rd_count,
212 rd))
213 {
214 GNUNET_break_op (0);
215 return GNUNET_SYSERR;
216 }
217 if (NULL != proc)
218 proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL);
219 }
220 }
221 return GNUNET_OK;
222}
223
224
225/**
226 * Calculate the DHT query for a given @a label in a given @a zone.
227 *
228 * @param zone private key of the zone
229 * @param label label of the record
230 * @param query hash to use for the query
231 */
232void
233GNUNET_NAMESTORE_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
234 const char *label,
235 struct GNUNET_HashCode *query)
236{
237 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
238
239 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub);
240 GNUNET_NAMESTORE_query_from_public_key (&pub, label, query);
241}
242
243
244/**
245 * Calculate the DHT query for a given @a label in a given @a zone.
246 *
247 * @param pub public key of the zone
248 * @param label label of the record
249 * @param query hash to use for the query
250 */
251void
252GNUNET_NAMESTORE_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
253 const char *label,
254 struct GNUNET_HashCode *query)
255{
256 struct GNUNET_CRYPTO_EcdsaPublicKey pd;
257
258 GNUNET_CRYPTO_ecdsa_public_key_derive (pub, label, "gns", &pd);
259 GNUNET_CRYPTO_hash (&pd, sizeof (pd), query);
260}
261
262
263/* end of gnsrecord_crypto.c */