first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / octopi / library / tentacles / encryption_infoton.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : encryption_infoton                                                *
4 *  Author : Chris Koeritz                                                     *
5 *                                                                             *
6 *******************************************************************************
7 * Copyright (c) 2004-$now By Author.  This program is free software; you can  *
8 * redistribute it and/or modify it under the terms of the GNU General Public  *
9 * License as published by the Free Software Foundation; either version 2 of   *
10 * the License or (at your option) any later version.  This is online at:      *
11 *     http://www.fsf.org/copyleft/gpl.html                                    *
12 * Please send any updates to: fred@gruntose.com                               *
13 \*****************************************************************************/
14
15 #include "encryption_infoton.h"
16
17 #include <basis/byte_array.h>
18
19 #include <basis/mutex.h>
20 #include <basis/functions.h>
21 #include <crypto/blowfish_crypto.h>
22 #include <crypto/rsa_crypto.h>
23 #include <octopus/tentacle.h>
24 #include <structures/static_memory_gremlin.h>
25 #include <textual/byte_formatter.h>
26
27 using namespace basis;
28 using namespace crypto;
29 using namespace octopi;
30 using namespace structures;
31 using namespace textual;
32
33 namespace octopi {
34
35 const int encryption_infoton::BLOWFISH_KEY_SIZE = 314;
36   // our key size is almost double the recommended key size (168 bits).
37   // this would take a very long time to crack using brute force.
38
39 const int encryption_infoton::RSA_KEY_SIZE = 1480;
40   // a little bit larger than the 1024 bit threshold.
41
42 #undef LOG
43 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s);
44
45 encryption_infoton::encryption_infoton(const byte_array &pub_key,
46     const byte_array &secret_blowfish)
47 : infoton(encryption_classifier()),
48   _public_key(pub_key),
49   _encrypted_blowfish_key(secret_blowfish),
50   _success(tentacle::NOT_FOUND)
51 {}
52
53 encryption_infoton::encryption_infoton(const encryption_infoton &to_copy)
54 : root_object(),
55   infoton(to_copy),
56   _public_key(to_copy._public_key),
57   _encrypted_blowfish_key(to_copy._encrypted_blowfish_key),
58   _success(to_copy._success)
59 {
60 }
61
62 encryption_infoton::~encryption_infoton() {}
63
64 clonable *encryption_infoton::clone() const
65 { return cloner<encryption_infoton>(*this); }
66
67 encryption_infoton &encryption_infoton::operator =
68     (const encryption_infoton &to_copy)
69 {
70   if (this == &to_copy) return *this;
71   _public_key = to_copy._public_key;
72   _encrypted_blowfish_key = to_copy._encrypted_blowfish_key;
73   _success = to_copy._success;
74   return *this;
75 }
76
77 const char *encryption_class_constant = "#octcod";
78
79 SAFE_STATIC_CONST(string_array, encryption_infoton::encryption_classifier,
80     (1, &encryption_class_constant))
81
82 int encryption_infoton::packed_size() const
83 {
84   return sizeof(int)  // packed outcome.
85       + _public_key.length() + sizeof(int)  // public key array.
86       + _encrypted_blowfish_key.length() + sizeof(int);  // secret key array.
87 }
88
89 void encryption_infoton::pack(byte_array &packed_form) const
90 {
91   structures::attach(packed_form, _success.value());
92   structures::attach(packed_form, _public_key);
93   structures::attach(packed_form, _encrypted_blowfish_key);
94 }
95
96 bool encryption_infoton::unpack(byte_array &packed_form)
97 {
98   int value;
99   if (!structures::detach(packed_form, value)) return false;
100   _success = outcome(value);
101   if (!structures::detach(packed_form, _public_key)) return false;
102   if (!structures::detach(packed_form, _encrypted_blowfish_key)) return false;
103   return true;
104 }
105
106 outcome encryption_infoton::prepare_blowfish_key(blowfish_crypto &new_key)
107 {
108 //  FUNCDEF("prepare_blowfish_key");
109   _encrypted_blowfish_key.reset();  // clean out stuff to create.
110   if (!_public_key.length()) {
111     // wrong type of request being seen or something.
112     _success = tentacle::BAD_INPUT;
113     return _success;
114   }
115
116   rsa_crypto pub(_public_key);  // suck in the provided key.
117   blowfish_crypto agreed_key(BLOWFISH_KEY_SIZE);  // random blowfish key.
118   new_key = agreed_key;
119
120   // now encrypt the new key for transit.
121   bool worked = pub.public_encrypt(agreed_key.get_key(),
122       _encrypted_blowfish_key);
123   if (!worked) _success = tentacle::GARBAGE;  // lacking a better description.
124   else _success = tentacle::OKAY;
125   return _success;
126 }
127
128 outcome encryption_infoton::prepare_both_keys(rsa_crypto &private_key)
129 {
130   rsa_crypto priv(RSA_KEY_SIZE);  // generate random key.
131   outcome to_return = prepare_public_key(priv);
132   if (to_return == tentacle::OKAY) private_key = priv;
133   return to_return;
134 }
135
136 outcome encryption_infoton::prepare_public_key(const rsa_crypto &private_key)
137 {
138   bool worked = private_key.public_key(_public_key);
139   if (!worked) return tentacle::DISALLOWED;  // why would that ever fail?
140   return tentacle::OKAY;
141 }
142
143 outcome encryption_infoton::extract_response(const rsa_crypto &private_key,
144     blowfish_crypto &new_key) const
145 {
146 //  FUNCDEF("extract_response");
147   if (_success != tentacle::OKAY) return _success;
148   byte_array decrypted;
149   bool worked = private_key.private_decrypt(_encrypted_blowfish_key, decrypted);
150   if (!worked) return tentacle::BAD_INPUT;  // that one we hope is accurate.
151   new_key.set_key(decrypted, BLOWFISH_KEY_SIZE);
152   return tentacle::OKAY;
153 }
154
155 } //namespace.
156