⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ecrs_core.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
字号:
/*     This file is part of GNUnet     (C) 2001, 2002, 2003, 2004, 2005, 2008 Christian Grothoff (and other contributing authors)     GNUnet is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published     by the Free Software Foundation; either version 2, or (at your     option) any later version.     GNUnet is distributed in the hope that it will be useful, but     WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     General Public License for more details.     You should have received a copy of the GNU General Public License     along with GNUnet; see the file COPYING.  If not, write to the     Free Software Foundation, Inc., 59 Temple Place - Suite 330,     Boston, MA 02111-1307, USA.*//** * @file applications/fs/module/ecrs_core.c * @brief support for ECRS encoding of files * @author Christian Grothoff */#include "platform.h"#include "gnunet_protocols.h"#include "ecrs_core.h"/** * Perform on-demand content encoding. * * @param data the data to encode * @param len the length of the data * @param query the query that was used to query *  for the content (verified that it matches *  data) * @param value the encoded data (set); *        the anonymity_level is to be set to 0 *        (caller should have checked before calling *        this method). * @return GNUNET_OK on success, GNUNET_SYSERR if data does not *  match the query */intGNUNET_EC_file_block_encode (const GNUNET_EC_DBlock * data,                             unsigned int len,                             const GNUNET_HashCode * query,                             GNUNET_DatastoreValue ** value){  GNUNET_HashCode hc;  GNUNET_AES_SessionKey skey;  GNUNET_AES_InitializationVector iv;   /* initial value */  GNUNET_DatastoreValue *val;  GNUNET_EC_DBlock *db;  GNUNET_GE_ASSERT (NULL, len >= sizeof (GNUNET_EC_DBlock));  GNUNET_GE_ASSERT (NULL, (data != NULL) && (query != NULL));  GNUNET_hash (&data[1], len - sizeof (GNUNET_EC_DBlock), &hc);  GNUNET_hash_to_AES_key (&hc, &skey, &iv);  val = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + len);  val->size = htonl (sizeof (GNUNET_DatastoreValue) + len);  val->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);  val->priority = htonl (0);  val->anonymity_level = htonl (0);  val->expiration_time = GNUNET_htonll (0);  db = (GNUNET_EC_DBlock *) & val[1];  db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);  GNUNET_GE_ASSERT (NULL,                    len - sizeof (GNUNET_EC_DBlock) < GNUNET_MAX_BUFFER_SIZE);  GNUNET_GE_ASSERT (NULL,                    len - sizeof (GNUNET_EC_DBlock) ==                    GNUNET_AES_encrypt (&data[1],                                        len - sizeof (GNUNET_EC_DBlock),                                        &skey, &iv, &db[1]));  GNUNET_hash (&db[1], len - sizeof (GNUNET_EC_DBlock), &hc);  if (0 != memcmp (query, &hc, sizeof (GNUNET_HashCode)))    {      GNUNET_free (val);      *value = NULL;      return GNUNET_SYSERR;    }  *value = val;  return GNUNET_OK;}/** * Get the key that will be used to decrypt * a certain block of data. */voidGNUNET_EC_file_block_get_key (const GNUNET_EC_DBlock * data, unsigned int len,                              GNUNET_HashCode * key){  GNUNET_GE_ASSERT (NULL, len >= sizeof (GNUNET_EC_DBlock));  GNUNET_hash (&data[1], len - sizeof (GNUNET_EC_DBlock), key);}/** * Get the query that will be used to query for * a certain block of data. * * @param db the block in plaintext */voidGNUNET_EC_file_block_get_query (const GNUNET_EC_DBlock * db, unsigned int len,                                GNUNET_HashCode * query){  char *tmp;  const char *data;  GNUNET_HashCode hc;  GNUNET_AES_SessionKey skey;  GNUNET_AES_InitializationVector iv;  GNUNET_GE_ASSERT (NULL, len >= sizeof (GNUNET_EC_DBlock));  data = (const char *) &db[1];  len -= sizeof (GNUNET_EC_DBlock);  GNUNET_GE_ASSERT (NULL, len < GNUNET_MAX_BUFFER_SIZE);  GNUNET_hash (data, len, &hc);  GNUNET_hash_to_AES_key (&hc, &skey, &iv);  tmp = GNUNET_malloc (len);  GNUNET_GE_ASSERT (NULL,                    len == GNUNET_AES_encrypt (data, len, &skey, &iv, tmp));  GNUNET_hash (tmp, len, query);  GNUNET_free (tmp);}unsigned intGNUNET_EC_file_block_get_type (unsigned int size,                               const GNUNET_EC_DBlock * data){  if (size <= 4)    {      GNUNET_GE_BREAK (NULL, 0);      return GNUNET_ECRS_BLOCKTYPE_ANY; /* signal error */    }  return ntohl (*((const unsigned int *) data));}/** * What is the main query (the one that is used in routing and for the * DB lookup) for the given content and block type? * * @param data the content (encoded) * @param query set to the query for the content * @return GNUNET_SYSERR if the content is invalid or *   the content type is not known */intGNUNET_EC_file_block_check_and_get_query (unsigned int size,                                          const GNUNET_EC_DBlock * data,                                          int verify, GNUNET_HashCode * query){  unsigned int type;  type = GNUNET_EC_file_block_get_type (size, data);  if (type == GNUNET_ECRS_BLOCKTYPE_ANY)    {      GNUNET_GE_BREAK (NULL, 0);      return GNUNET_SYSERR;    }  switch (type)    {    case GNUNET_ECRS_BLOCKTYPE_DATA:      /* GNUNET_EC_ContentHashKey: GNUNET_hash of content == query */      GNUNET_hash (&data[1], size - sizeof (GNUNET_EC_DBlock), query);      return GNUNET_OK;    case GNUNET_ECRS_BLOCKTYPE_SIGNED:      {        const GNUNET_EC_SBlock *sb;        if (size < sizeof (GNUNET_EC_SBlock))          {            GNUNET_GE_BREAK (NULL, 0);            return GNUNET_SYSERR;          }        sb = (const GNUNET_EC_SBlock *) data;        if ((verify == GNUNET_YES) &&            (GNUNET_OK != GNUNET_RSA_verify (&sb->identifier,                                             size                                             - sizeof (GNUNET_RSA_Signature)                                             - sizeof (GNUNET_RSA_PublicKey)                                             - sizeof (unsigned int),                                             &sb->signature, &sb->subspace)))          {            GNUNET_GE_BREAK (NULL, 0);            return GNUNET_SYSERR;          }        *query = sb->identifier;        return GNUNET_OK;      }    case GNUNET_ECRS_BLOCKTYPE_KEYWORD:      {        const GNUNET_EC_KBlock *kb;        if (size < sizeof (GNUNET_EC_KBlock))          {            GNUNET_GE_BREAK (NULL, 0);            return GNUNET_SYSERR;          }        kb = (const GNUNET_EC_KBlock *) data;        if ((verify == GNUNET_YES) &&            ((GNUNET_OK != GNUNET_RSA_verify (&kb[1],                                              size -                                              sizeof (GNUNET_EC_KBlock),                                              &kb->signature,                                              &kb->keyspace))))          {            GNUNET_GE_BREAK (NULL, 0);            return GNUNET_SYSERR;          }        GNUNET_hash (&kb->keyspace, sizeof (GNUNET_RSA_PublicKey), query);        return GNUNET_OK;      }    case GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED:      {        const GNUNET_EC_KSBlock *ks;        if (size < sizeof (GNUNET_EC_KSBlock))          {            GNUNET_GE_BREAK (NULL, 0);            return GNUNET_SYSERR;          }        ks = (const GNUNET_EC_KSBlock *) data;        if ((verify == GNUNET_YES) &&            ((GNUNET_OK != GNUNET_RSA_verify (&ks->sblock,                                              size                                              - sizeof (GNUNET_EC_KBlock)                                              - sizeof (unsigned int),                                              &ks->kblock.signature,                                              &ks->kblock.keyspace))))          {            GNUNET_GE_BREAK (NULL, 0);            return GNUNET_SYSERR;          }        GNUNET_hash (&ks->kblock.keyspace, sizeof (GNUNET_RSA_PublicKey),                     query);        return GNUNET_OK;      }    case GNUNET_ECRS_BLOCKTYPE_ONDEMAND:      {        GNUNET_GE_BREAK_OP (NULL, 0);   /* should never be used here! */        return GNUNET_SYSERR;      }    default:      {        GNUNET_GE_BREAK_OP (NULL, 0);   /* unknown block type */        return GNUNET_SYSERR;      }    }                           /* end switch */}/** * Verify that the given Datum is a valid response * to a given query. * * @param type the type of the query * @param size the size of the data * @param data the encoded data * @param hc result of GNUNET_EC_file_block_check_and_get_query * @param keyCount the number of keys in the query, *        use 0 to match only primary key * @param keys the keys of the query * @return GNUNET_YES if this data matches the query, otherwise *         GNUNET_NO; GNUNET_SYSERR if the keyCount does not match the *         query type */intGNUNET_EC_is_block_applicable_for_query (unsigned int type,                                         unsigned int size,                                         const GNUNET_EC_DBlock * data,                                         const GNUNET_HashCode * hc,                                         unsigned int keyCount,                                         const GNUNET_HashCode * keys){  GNUNET_HashCode h;  if (type != GNUNET_EC_file_block_get_type (size, data))    {      GNUNET_GE_BREAK (NULL, 0);      return GNUNET_SYSERR;     /* type mismatch */    }  if (0 != memcmp (hc, &keys[0], sizeof (GNUNET_HashCode)))    {      GNUNET_GE_BREAK (NULL, 0);        /* mismatch between primary queries,                                           we should not even see those here. */      return GNUNET_SYSERR;    }  if (keyCount == 0)    return GNUNET_YES;          /* request was to match only primary key */  switch (type)    {    case GNUNET_ECRS_BLOCKTYPE_SIGNED:      if (keyCount != 2)        return GNUNET_SYSERR;   /* no match */      GNUNET_hash (&((const GNUNET_EC_SBlock *) data)->subspace,                   sizeof (GNUNET_RSA_PublicKey), &h);      if (0 == memcmp (&keys[1], &h, sizeof (GNUNET_HashCode)))        return GNUNET_OK;      return GNUNET_SYSERR;    case GNUNET_ECRS_BLOCKTYPE_DATA:    case GNUNET_ECRS_BLOCKTYPE_KEYWORD:    case GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED:      if (keyCount != 1)        GNUNET_GE_BREAK (NULL, 0);      /* keyCount should be 1 */      return GNUNET_OK;         /* if query matches, everything matches! */    case GNUNET_ECRS_BLOCKTYPE_ANY:      GNUNET_GE_BREAK (NULL, 0);        /* block type should be known */      return GNUNET_SYSERR;    default:      GNUNET_GE_BREAK (NULL, 0);        /* unknown block type */      return GNUNET_SYSERR;    }}/* end of ecrs_core.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -