ROOT logo
// $Id: GKeyRSA.cxx 2088 2008-11-23 20:26:46Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

//______________________________________________________________________
// GKeyRSA
//
// Example of trivial use:
//
//    GKeyRSA k1, k2;
//    TBufferFile b(TBuffer::kWrite);
//    try {
//       k1.ReadPubKey(PubKeyFile(mSaturnIdentity));
//       k1.GenerateSecret();
//       k1.SendSecret(b);
//
//       b.SetReadMode();
//       b.SetBufferOffset(0);
//
//       k2.ReadPrivKey(PrivKeyFile(mSaturnIdentity));
//       k2.ReceiveSecret(b);
//       if(k1.MatchSecrets(k2)) {
// 	cout <<"Secret comparison successful\n";
//       } else {
// 	cout <<"Secret comparison failed\n";
//       }
//     }
//     catch(Exc_t& exc) {
//       cout << "encode test failed: "<< exc << endl;
//     }
//

#include "GKeyRSA.h"
#include <Gled/GThread.h>

#include <TBuffer.h>
#include <TRandom2.h>

#include <openssl/ssl.h>
#include <openssl/err.h>

ClassImp(GKeyRSA);

/**************************************************************************/

bool    GKeyRSA::init_done = false;
GMutex* GKeyRSA::s_ssl_mutexen = 0;

void GKeyRSA::init_ssl()
{
  if(init_done) return;
  SSL_library_init();
  SSL_load_error_strings();

  int nl = CRYPTO_num_locks();
  //printf("GKeyRSA::init_ssl setting up %d locks\n", nl);
  s_ssl_mutexen = new GMutex[nl];

  CRYPTO_set_locking_callback(ssl_locker_foo);
  CRYPTO_set_id_callback(ssl_id_foo);

  init_done = true;
}

void GKeyRSA::ssl_locker_foo(int mode, int n, const char *file, int line)
{
  if(mode & CRYPTO_LOCK) {
    //printf("GKeyRSA::ssl_locker locking %d\n", n);
    s_ssl_mutexen[n].Lock();
  } else {
    //printf("GKeyRSA::ssl_locker unlocking %d\n", n);
    s_ssl_mutexen[n].Unlock();
  }
}

unsigned long GKeyRSA::ssl_id_foo()
{
  return (unsigned long) GThread::Self();
}

/**************************************************************************/
/**************************************************************************/

bool GKeyRSA::check_error()
{
  mSslError = ERR_get_error();
  return mSslError;
}

const char* GKeyRSA::error_string()
{
  return ERR_error_string(mSslError, 0);
}

/**************************************************************************/
/**************************************************************************/

GKeyRSA::GKeyRSA()
{
  mSecret = 0;
  mSecretLen = 0;

  bIsPrivate = false;
  pKey = 0;
  mSslError = 0;
}

GKeyRSA::~GKeyRSA()
{
  delete pKey;
  delete [] mSecret;
}

/**************************************************************************/

void GKeyRSA::ReadPubKey(const char* file)
{
  TString _eh("GKeyRSA::ReadPubKey ");

  if(pKey) { delete pKey; bIsPrivate = false; }
  FILE* fp = fopen(file, "r");
  if(!fp) throw(_eh + "file '" + file + "' not found");
  pKey = PEM_read_RSA_PUBKEY(fp, 0, 0, 0);
  fclose(fp);
  if(check_error()) {
    pKey = 0;
    throw(_eh + error_string());
  }
}

void GKeyRSA::ReadPrivKey(const char* file)
{
  TString _eh("GKeyRSA::ReadPrivKey ");

  if(pKey) { delete pKey; bIsPrivate = false; }
  FILE* fp = fopen(file, "r");
  if(!fp) throw(_eh + "file " + file + " not found");
  pKey = PEM_read_RSAPrivateKey(fp, 0, 0, 0);
  fclose(fp);
  if(check_error()) {
    pKey = 0;
    throw(_eh + error_string());
  }
  bIsPrivate = true;
}

/**************************************************************************/

void GKeyRSA::GenerateSecret()
{
  static TString _eh("GKeyRSA::GenerateSecret ");

  assert(pKey);

  UInt_t s;
  FILE* fp = fopen("/dev/random", "r");
  fread(&s, sizeof(UInt_t), 1, fp);
  fclose(fp);
  TRandom2 rnd(s);

  int modlen = RSA_size(pKey);
  mSecretLen = modlen - 41 - 1;
  if(mSecret) delete mSecret;
  mSecret    = new unsigned char[mSecretLen];
  for(int i=0; i<mSecretLen; ++i) {
    mSecret[i] = (unsigned char)(255.99*rnd.Rndm());
  }

}

void GKeyRSA::SendSecret(TBuffer& b)
{
  static TString _eh("GKeyRSA::SendSecret ");

  int modlen = RSA_size(pKey);
  unsigned char enc_secret[modlen];
  Int_t lenmsg = RSA_public_encrypt(mSecretLen, mSecret, enc_secret,
				    pKey, RSA_PKCS1_OAEP_PADDING);

  if(check_error())
    throw(_eh + error_string());

  b << lenmsg;
  b.WriteFastArray((char*)enc_secret, lenmsg);
}

void GKeyRSA::ReceiveSecret(TBuffer& b)
{
  static TString _eh("GKeyRSA::ReceiveSecret ");

  assert(pKey && bIsPrivate);

  Int_t lenmsg;
  b >> lenmsg;
  unsigned char enc_secret[lenmsg];
  unsigned char rec_secret[lenmsg];
  b.ReadFastArray((char*)enc_secret, lenmsg);
  mSecretLen = RSA_private_decrypt(lenmsg, enc_secret, rec_secret,
				   pKey, RSA_PKCS1_OAEP_PADDING);
  if(check_error())
    throw(_eh + error_string());

  if(mSecret) delete mSecret;
  mSecret    = new unsigned char[mSecretLen];
  for(int i=0; i<mSecretLen; ++i) mSecret[i] = rec_secret[i];
}

bool GKeyRSA::MatchSecrets(const GKeyRSA& a)
{
  if(mSecretLen != a.mSecretLen) return false;
  for(int i=0; i<mSecretLen; ++i) {
    if(mSecret[i] != a.mSecret[i]) return false;
  }
  return true;
}

/**************************************************************************/

void GKeyRSA::StreamPubKey(TBuffer& b)
{
  if(b.IsReading()) {

    if(pKey) delete pKey;
    pKey = RSA_new();
    bIsPrivate = false;

    Int_t ln, le;
    b >> ln >> le;

    char bn[ln], be[le];
    b.ReadFastArray(bn, ln);
    b.ReadFastArray(be, le);

    pKey->n = BN_mpi2bn((unsigned char *)bn, ln, 0);
    pKey->e = BN_mpi2bn((unsigned char *)be, le, 0);

  } else {

    Int_t ln, le;
    ln = BN_bn2mpi(pKey->n, NULL);
    le = BN_bn2mpi(pKey->e, NULL);
    b << ln << le;

    char bn[ln], be[le];
    BN_bn2mpi(pKey->n, (unsigned char*)bn);
    BN_bn2mpi(pKey->e, (unsigned char*)be);
    b.WriteFastArray(bn, ln);
    b.WriteFastArray(be, le);
  }
}
 GKeyRSA.cxx:1
 GKeyRSA.cxx:2
 GKeyRSA.cxx:3
 GKeyRSA.cxx:4
 GKeyRSA.cxx:5
 GKeyRSA.cxx:6
 GKeyRSA.cxx:7
 GKeyRSA.cxx:8
 GKeyRSA.cxx:9
 GKeyRSA.cxx:10
 GKeyRSA.cxx:11
 GKeyRSA.cxx:12
 GKeyRSA.cxx:13
 GKeyRSA.cxx:14
 GKeyRSA.cxx:15
 GKeyRSA.cxx:16
 GKeyRSA.cxx:17
 GKeyRSA.cxx:18
 GKeyRSA.cxx:19
 GKeyRSA.cxx:20
 GKeyRSA.cxx:21
 GKeyRSA.cxx:22
 GKeyRSA.cxx:23
 GKeyRSA.cxx:24
 GKeyRSA.cxx:25
 GKeyRSA.cxx:26
 GKeyRSA.cxx:27
 GKeyRSA.cxx:28
 GKeyRSA.cxx:29
 GKeyRSA.cxx:30
 GKeyRSA.cxx:31
 GKeyRSA.cxx:32
 GKeyRSA.cxx:33
 GKeyRSA.cxx:34
 GKeyRSA.cxx:35
 GKeyRSA.cxx:36
 GKeyRSA.cxx:37
 GKeyRSA.cxx:38
 GKeyRSA.cxx:39
 GKeyRSA.cxx:40
 GKeyRSA.cxx:41
 GKeyRSA.cxx:42
 GKeyRSA.cxx:43
 GKeyRSA.cxx:44
 GKeyRSA.cxx:45
 GKeyRSA.cxx:46
 GKeyRSA.cxx:47
 GKeyRSA.cxx:48
 GKeyRSA.cxx:49
 GKeyRSA.cxx:50
 GKeyRSA.cxx:51
 GKeyRSA.cxx:52
 GKeyRSA.cxx:53
 GKeyRSA.cxx:54
 GKeyRSA.cxx:55
 GKeyRSA.cxx:56
 GKeyRSA.cxx:57
 GKeyRSA.cxx:58
 GKeyRSA.cxx:59
 GKeyRSA.cxx:60
 GKeyRSA.cxx:61
 GKeyRSA.cxx:62
 GKeyRSA.cxx:63
 GKeyRSA.cxx:64
 GKeyRSA.cxx:65
 GKeyRSA.cxx:66
 GKeyRSA.cxx:67
 GKeyRSA.cxx:68
 GKeyRSA.cxx:69
 GKeyRSA.cxx:70
 GKeyRSA.cxx:71
 GKeyRSA.cxx:72
 GKeyRSA.cxx:73
 GKeyRSA.cxx:74
 GKeyRSA.cxx:75
 GKeyRSA.cxx:76
 GKeyRSA.cxx:77
 GKeyRSA.cxx:78
 GKeyRSA.cxx:79
 GKeyRSA.cxx:80
 GKeyRSA.cxx:81
 GKeyRSA.cxx:82
 GKeyRSA.cxx:83
 GKeyRSA.cxx:84
 GKeyRSA.cxx:85
 GKeyRSA.cxx:86
 GKeyRSA.cxx:87
 GKeyRSA.cxx:88
 GKeyRSA.cxx:89
 GKeyRSA.cxx:90
 GKeyRSA.cxx:91
 GKeyRSA.cxx:92
 GKeyRSA.cxx:93
 GKeyRSA.cxx:94
 GKeyRSA.cxx:95
 GKeyRSA.cxx:96
 GKeyRSA.cxx:97
 GKeyRSA.cxx:98
 GKeyRSA.cxx:99
 GKeyRSA.cxx:100
 GKeyRSA.cxx:101
 GKeyRSA.cxx:102
 GKeyRSA.cxx:103
 GKeyRSA.cxx:104
 GKeyRSA.cxx:105
 GKeyRSA.cxx:106
 GKeyRSA.cxx:107
 GKeyRSA.cxx:108
 GKeyRSA.cxx:109
 GKeyRSA.cxx:110
 GKeyRSA.cxx:111
 GKeyRSA.cxx:112
 GKeyRSA.cxx:113
 GKeyRSA.cxx:114
 GKeyRSA.cxx:115
 GKeyRSA.cxx:116
 GKeyRSA.cxx:117
 GKeyRSA.cxx:118
 GKeyRSA.cxx:119
 GKeyRSA.cxx:120
 GKeyRSA.cxx:121
 GKeyRSA.cxx:122
 GKeyRSA.cxx:123
 GKeyRSA.cxx:124
 GKeyRSA.cxx:125
 GKeyRSA.cxx:126
 GKeyRSA.cxx:127
 GKeyRSA.cxx:128
 GKeyRSA.cxx:129
 GKeyRSA.cxx:130
 GKeyRSA.cxx:131
 GKeyRSA.cxx:132
 GKeyRSA.cxx:133
 GKeyRSA.cxx:134
 GKeyRSA.cxx:135
 GKeyRSA.cxx:136
 GKeyRSA.cxx:137
 GKeyRSA.cxx:138
 GKeyRSA.cxx:139
 GKeyRSA.cxx:140
 GKeyRSA.cxx:141
 GKeyRSA.cxx:142
 GKeyRSA.cxx:143
 GKeyRSA.cxx:144
 GKeyRSA.cxx:145
 GKeyRSA.cxx:146
 GKeyRSA.cxx:147
 GKeyRSA.cxx:148
 GKeyRSA.cxx:149
 GKeyRSA.cxx:150
 GKeyRSA.cxx:151
 GKeyRSA.cxx:152
 GKeyRSA.cxx:153
 GKeyRSA.cxx:154
 GKeyRSA.cxx:155
 GKeyRSA.cxx:156
 GKeyRSA.cxx:157
 GKeyRSA.cxx:158
 GKeyRSA.cxx:159
 GKeyRSA.cxx:160
 GKeyRSA.cxx:161
 GKeyRSA.cxx:162
 GKeyRSA.cxx:163
 GKeyRSA.cxx:164
 GKeyRSA.cxx:165
 GKeyRSA.cxx:166
 GKeyRSA.cxx:167
 GKeyRSA.cxx:168
 GKeyRSA.cxx:169
 GKeyRSA.cxx:170
 GKeyRSA.cxx:171
 GKeyRSA.cxx:172
 GKeyRSA.cxx:173
 GKeyRSA.cxx:174
 GKeyRSA.cxx:175
 GKeyRSA.cxx:176
 GKeyRSA.cxx:177
 GKeyRSA.cxx:178
 GKeyRSA.cxx:179
 GKeyRSA.cxx:180
 GKeyRSA.cxx:181
 GKeyRSA.cxx:182
 GKeyRSA.cxx:183
 GKeyRSA.cxx:184
 GKeyRSA.cxx:185
 GKeyRSA.cxx:186
 GKeyRSA.cxx:187
 GKeyRSA.cxx:188
 GKeyRSA.cxx:189
 GKeyRSA.cxx:190
 GKeyRSA.cxx:191
 GKeyRSA.cxx:192
 GKeyRSA.cxx:193
 GKeyRSA.cxx:194
 GKeyRSA.cxx:195
 GKeyRSA.cxx:196
 GKeyRSA.cxx:197
 GKeyRSA.cxx:198
 GKeyRSA.cxx:199
 GKeyRSA.cxx:200
 GKeyRSA.cxx:201
 GKeyRSA.cxx:202
 GKeyRSA.cxx:203
 GKeyRSA.cxx:204
 GKeyRSA.cxx:205
 GKeyRSA.cxx:206
 GKeyRSA.cxx:207
 GKeyRSA.cxx:208
 GKeyRSA.cxx:209
 GKeyRSA.cxx:210
 GKeyRSA.cxx:211
 GKeyRSA.cxx:212
 GKeyRSA.cxx:213
 GKeyRSA.cxx:214
 GKeyRSA.cxx:215
 GKeyRSA.cxx:216
 GKeyRSA.cxx:217
 GKeyRSA.cxx:218
 GKeyRSA.cxx:219
 GKeyRSA.cxx:220
 GKeyRSA.cxx:221
 GKeyRSA.cxx:222
 GKeyRSA.cxx:223
 GKeyRSA.cxx:224
 GKeyRSA.cxx:225
 GKeyRSA.cxx:226
 GKeyRSA.cxx:227
 GKeyRSA.cxx:228
 GKeyRSA.cxx:229
 GKeyRSA.cxx:230
 GKeyRSA.cxx:231
 GKeyRSA.cxx:232
 GKeyRSA.cxx:233
 GKeyRSA.cxx:234
 GKeyRSA.cxx:235
 GKeyRSA.cxx:236
 GKeyRSA.cxx:237
 GKeyRSA.cxx:238
 GKeyRSA.cxx:239
 GKeyRSA.cxx:240
 GKeyRSA.cxx:241
 GKeyRSA.cxx:242
 GKeyRSA.cxx:243
 GKeyRSA.cxx:244
 GKeyRSA.cxx:245
 GKeyRSA.cxx:246
 GKeyRSA.cxx:247
 GKeyRSA.cxx:248
 GKeyRSA.cxx:249
 GKeyRSA.cxx:250
 GKeyRSA.cxx:251
 GKeyRSA.cxx:252