switch to IP that is in 192.0.2.0/24 range which is specifically reserved to be never...
[oweals/gnunet.git] / src / block / block.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 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 block/block.c
23  * @brief library for data block manipulation
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_signatures.h"
29 #include "gnunet_block_lib.h"
30
31 /**
32  * Check if the given KBlock is well-formed.
33  *
34  * @param kb the kblock data (or at least "dsize" bytes claiming to be one)
35  * @param dsize size of "kb" in bytes; check for < sizeof(struct KBlock)!
36  * @param query where to store the query that this block answers
37  * @return GNUNET_OK if this is actually a well-formed KBlock
38  */
39 static int
40 check_kblock (const struct KBlock *kb,
41               size_t dsize,
42               GNUNET_HashCode *query)
43 {
44   if (dsize < sizeof (struct KBlock))
45     {
46       GNUNET_break_op (0);
47       return GNUNET_SYSERR;
48     }
49   if (dsize - sizeof (struct KBlock) !=
50       ntohl (kb->purpose.size) 
51       - sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) 
52       - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) ) 
53     {
54       GNUNET_break_op (0);
55       return GNUNET_SYSERR;
56     }
57   if (GNUNET_OK !=
58       GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK,
59                                 &kb->purpose,
60                                 &kb->signature,
61                                 &kb->keyspace)) 
62     {
63       GNUNET_break_op (0);
64       return GNUNET_SYSERR;
65     }
66   if (query != NULL)
67     GNUNET_CRYPTO_hash (&kb->keyspace,
68                         sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
69                         query);
70   return GNUNET_OK;
71 }
72
73
74 /**
75  * Check if the given NBlock is well-formed.
76  *
77  * @param nb the nblock data (or at least "dsize" bytes claiming to be one)
78  * @param dsize size of "nb" in bytes; check for < sizeof(struct NBlock)!
79  * @param query where to store the query that this block answers
80  * @return GNUNET_OK if this is actually a well-formed NBlock
81  */
82 static int
83 check_nblock (const struct NBlock *nb,
84               size_t dsize,
85               GNUNET_HashCode *query)
86 {
87   if (dsize < sizeof (struct NBlock))
88     {
89       GNUNET_break_op (0);
90       return GNUNET_SYSERR;
91     }
92   if (dsize - sizeof (struct NBlock) !=
93       ntohl (nb->ns_purpose.size) 
94       - sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) 
95       - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) ) 
96     {
97       GNUNET_break_op (0);
98       return GNUNET_SYSERR;
99     }
100   if (dsize !=
101       ntohl (nb->ksk_purpose.size) + sizeof (struct GNUNET_CRYPTO_RsaSignature))
102     {
103       GNUNET_break_op (0);
104       return GNUNET_SYSERR;
105     }
106   if (GNUNET_OK !=
107       GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG,
108                                 &nb->ksk_purpose,
109                                 &nb->ksk_signature,
110                                 &nb->keyspace)) 
111     {
112       GNUNET_break_op (0);
113       return GNUNET_SYSERR;
114     }
115   if (GNUNET_OK !=
116       GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK,
117                                 &nb->ns_purpose,
118                                 &nb->ns_signature,
119                                 &nb->subspace)) 
120     {
121       GNUNET_break_op (0);
122       return GNUNET_SYSERR;
123     }
124   if (query != NULL)
125     GNUNET_CRYPTO_hash (&nb->keyspace,
126                         sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
127                         query);
128   return GNUNET_OK;
129 }
130
131
132 /**
133  * Check if the given SBlock is well-formed.
134  *
135  * @param sb the sblock data (or at least "dsize" bytes claiming to be one)
136  * @param dsize size of "kb" in bytes; check for < sizeof(struct SBlock)!
137  * @param query where to store the query that this block answers
138  * @return GNUNET_OK if this is actually a well-formed SBlock
139  */
140 static int
141 check_sblock (const struct SBlock *sb,
142               size_t dsize,
143               GNUNET_HashCode *query)
144 {
145   if (dsize < sizeof (struct SBlock))
146     {
147       GNUNET_break_op (0);
148       return GNUNET_SYSERR;
149     }
150   if (dsize !=
151       ntohl (sb->purpose.size) + sizeof (struct GNUNET_CRYPTO_RsaSignature))
152     {
153       GNUNET_break_op (0);
154       return GNUNET_SYSERR;
155     }
156   if (GNUNET_OK !=
157       GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK,
158                                 &sb->purpose,
159                                 &sb->signature,
160                                 &sb->subspace)) 
161     {
162       GNUNET_break_op (0);
163       return GNUNET_SYSERR;
164     }
165   if (query != NULL)
166     *query = sb->identifier;
167   return GNUNET_OK;
168 }
169
170
171 /**
172  * Check if the given block is well-formed (and of the given type).
173  *
174  * @param type type of the block
175  * @param block the block data (or at least "size" bytes claiming to be one)
176  * @param size size of "kb" in bytes; check that it is large enough
177  * @param query where to store the query that this block answers
178  * @return GNUNET_OK if this is actually a well-formed block,
179  *         GNUNET_NO if we could not determine the query,
180  *         GNUNET_SYSERR if the block is malformed
181  */
182 int
183 GNUNET_BLOCK_check_block (enum GNUNET_BLOCK_Type type,
184                           const void *block,
185                           size_t size,
186                           GNUNET_HashCode *query)
187 {
188   /* first, validate! */
189   switch (type)
190     {
191     case GNUNET_BLOCK_TYPE_DBLOCK:
192     case GNUNET_BLOCK_TYPE_IBLOCK:
193       GNUNET_CRYPTO_hash (block, size, query);
194       break;
195     case GNUNET_BLOCK_TYPE_KBLOCK:
196       if (GNUNET_OK !=
197           check_kblock (block,
198                         size,
199                         query))
200         return GNUNET_SYSERR;
201       break;
202     case GNUNET_BLOCK_TYPE_SBLOCK:
203       if (GNUNET_OK !=
204           check_sblock (block,
205                         size,
206                         query))
207         return GNUNET_SYSERR;
208       break;
209     case GNUNET_BLOCK_TYPE_NBLOCK:
210       if (GNUNET_OK !=
211           check_nblock (block,
212                         size,
213                         query))
214         return GNUNET_SYSERR;
215       return GNUNET_OK;
216     case GNUNET_BLOCK_TYPE_ONDEMAND:
217       if (size != sizeof (struct OnDemandBlock))
218         return GNUNET_SYSERR;
219       memset (query, 0, sizeof (GNUNET_HashCode));      
220       return GNUNET_NO;
221     default:
222       /* unknown block type */
223       GNUNET_break_op (0);
224       return GNUNET_SYSERR;
225     }
226   return GNUNET_OK;
227 }
228
229
230 /* end of block.c */