encryption_tentacle.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : encryption_tentacle                                               *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *******************************************************************************
00007 * Copyright (c) 2004-$now By Author.  This program is free software; you can  *
00008 * redistribute it and/or modify it under the terms of the GNU General Public  *
00009 * License as published by the Free Software Foundation; either version 2 of   *
00010 * the License or (at your option) any later version.  This is online at:      *
00011 *     http://www.fsf.org/copyleft/gpl.html                                    *
00012 * Please send any updates to: fred@gruntose.com                               *
00013 \*****************************************************************************/
00014 
00015 #include "encryption_tentacle.h"
00016 #include "encryption_wrapper.h"
00017 #include "key_repository.h"
00018 
00019 #include <crypto/blowfish_crypto.h>
00020 #include <crypto/rsa_crypto.h>
00021 #include <loggers/program_wide_logger.h>
00022 #include <structures/symbol_table.h>
00023 #include <textual/byte_formatter.h>
00024 
00025 using namespace basis;
00026 using namespace crypto;
00027 using namespace loggers;
00028 using namespace structures;
00029 using namespace textual;
00030 
00031 namespace octopi {
00032 
00033 #undef LOG
00034 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
00035 
00036 #define DEBUG_ENCRYPTION_TENTACLE
00037   // uncomment for noisier code.
00038 
00040 
00041 encryption_tentacle::encryption_tentacle()
00042 : tentacle_helper<encryption_infoton>
00043     (encryption_infoton::encryption_classifier(), false),
00044   _server_side(true),
00045   _keys(new key_repository),
00046   _rsa_private(NIL)
00047 {
00048 }
00049 
00050 encryption_tentacle::encryption_tentacle(const byte_array &private_key)
00051 : tentacle_helper<encryption_infoton>
00052     (encryption_infoton::encryption_classifier(), false),
00053   _server_side(false),
00054   _keys(new key_repository),
00055   _rsa_private(new rsa_crypto(private_key))
00056 {
00057 }
00058 
00059 encryption_tentacle::encryption_tentacle(int key_size)
00060 : tentacle_helper<encryption_infoton>
00061     (encryption_infoton::encryption_classifier(), false),
00062   _server_side(false),
00063   _keys(new key_repository),
00064   _rsa_private(new rsa_crypto(key_size))
00065 {
00066 }
00067 
00068 encryption_tentacle::~encryption_tentacle()
00069 {
00070   WHACK(_rsa_private);
00071   WHACK(_keys);
00072 }
00073 
00074 key_repository &encryption_tentacle::keys() const { return *_keys; }
00075 
00076 const rsa_crypto &encryption_tentacle::private_key() const
00077 { return *_rsa_private; }
00078 
00079 outcome encryption_tentacle::reconstitute(const string_array &classifier,
00080     byte_array &packed_form, infoton * &reformed)
00081 {
00082   if (classifier != encryption_infoton::encryption_classifier()) 
00083     return NO_HANDLER;
00084 
00085   return reconstituter(classifier, packed_form, reformed,
00086       (encryption_infoton *)NIL);
00087 }
00088 
00089 void encryption_tentacle::expunge(const octopus_entity &formal(to_remove))
00090 {
00092 //we need a better approach.  it seems there are places where an entity
00093 //can get reused and it still expects its key to be present.
00094 }
00095 
00096 outcome encryption_tentacle::consume(infoton &to_chow,
00097     const octopus_request_id &item_id, byte_array &transformed)
00098 {
00099   FUNCDEF("consume");
00100   transformed.reset();
00101   encryption_infoton *inf = dynamic_cast<encryption_infoton *>(&to_chow);
00102   if (!inf) {
00103     // this package is not explicitly an encryption infoton.  we need to
00104     // decrypt it using what we already know.
00105 
00106     encryption_wrapper *wrap = dynamic_cast<encryption_wrapper *>(&to_chow);
00107     if (!wrap) {
00108 #ifdef DEBUG_ENCRYPTION_TENTACLE
00109 //      LOG(astring("got a stray infoton that was not encrypted: ")
00110 //          + to_chow.text_form());
00111 #endif
00112       // this signals that we were expecting an encrypted package.
00113       return ENCRYPTION_MISMATCH;
00114     }
00115 
00116     octenc_key_record record;
00117     octenc_key_record *rec = _keys->lock(item_id._entity);
00118     if (!rec) {
00119 #ifdef DEBUG_ENCRYPTION_TENTACLE
00120       LOG(astring("no key stored for entity ")
00121           + item_id._entity.mangled_form()
00122           + "; rejecting packet.");
00123 #endif
00124       return DISALLOWED;
00125     }
00126     record = *rec;
00127     _keys->unlock(rec);
00128 
00129     byte_array decro;
00130     bool decrypts_properly = record._key.decrypt(wrap->_wrapped, decro);
00131     if (decrypts_properly) {
00132       // this package seems to be intact.  we need to reconstitute the
00133       // original infoton.
00134       transformed = decro;  // set the decrypted blob.
00135       return PARTIAL;
00136     }
00137 
00138 #ifdef DEBUG_ENCRYPTION_TENTACLE
00139     LOG(astring("denying client ") + item_id._entity.mangled_form()
00140         + " due to erroneous decryption");
00141 #endif
00142 
00143     // the infoton's client is not authorized; it needs to be dropped.
00144     return DISALLOWED;
00145   }
00146 
00147   // reaching here means this is explicitly an encryption startup request.
00148 
00149   if (!_server_side) {
00150     // client's side must track the key we were given for decryption.  we'll
00151     // use that from now on.
00152     blowfish_crypto new_key(blowfish_crypto::minimum_key_size());  // bogus.
00153     outcome ret = inf->extract_response(*_rsa_private, new_key);
00154     if (ret != OKAY) {
00155 #ifdef DEBUG_ENCRYPTION_TENTACLE
00156       LOG(astring("client failed to process encrypted blowfish key for ")
00157           + item_id._entity.mangled_form());
00158 #endif
00159     } else {
00160       _keys->add(item_id._entity, new_key);  // add our key for this guy.
00161     }
00162     // we do not store a copy of the infoton; it's just done now.
00163     return ret;
00164   } else {
00165     // server's side need to process a key request and send it back using
00166     // the public key the requester provided.
00167     blowfish_crypto agreed_key(blowfish_crypto::minimum_key_size());
00168       // initialized with junk.
00169     outcome worked = inf->prepare_blowfish_key(agreed_key);
00170     if (worked != OKAY) {
00171 #ifdef DEBUG_ENCRYPTION_TENTACLE
00172       LOG(astring("server failed to encrypt blowfish key for ")
00173           + item_id._entity.mangled_form());
00174 #endif
00175     } else {
00176       _keys->add(item_id._entity, agreed_key);  // add our key for this guy.
00177     }
00178   }
00179 
00180   if (!store_product(dynamic_cast<infoton *>(inf->clone()), item_id))
00181     return NO_SPACE;
00182   return OKAY;
00183 }
00184 
00185 } //namespace.
00186 
Generated on Sat Jan 28 04:22:49 2012 for hoople2 project by  doxygen 1.6.3