encryption_tentacle.cpp

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

Generated on Thu Nov 20 04:29:06 2008 for HOOPLE Libraries by  doxygen 1.5.1