00001
00002
00003 const char *XrdCryptosslRSACVSID = "$Id: XrdCryptosslRSA.cc 30949 2009-11-02 16:37:58Z ganis $";
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <XrdSut/XrdSutRndm.hh>
00021 #include <XrdCrypto/XrdCryptosslTrace.hh>
00022 #include <XrdCrypto/XrdCryptosslRSA.hh>
00023
00024 #include <string.h>
00025
00026 #include <openssl/bio.h>
00027 #include <openssl/err.h>
00028 #include <openssl/pem.h>
00029
00030
00031 XrdCryptosslRSA::XrdCryptosslRSA(int bits, int exp)
00032 {
00033
00034
00035
00036
00037 EPNAME("RSA::XrdCryptosslRSA");
00038
00039 publen = -1;
00040 prilen = -1;
00041
00042
00043 if (!(fEVP = EVP_PKEY_new())) {
00044 DEBUG("cannot allocate new public key container");
00045 return;
00046 }
00047
00048
00049 bits = (bits >= XrdCryptoMinRSABits) ? bits : XrdCryptoMinRSABits;
00050
00051
00052 if (!(exp & 1<<1))
00053 exp = XrdCryptoDefRSAExp;
00054
00055 DEBUG("bits: "<<bits<<", exp:"<<exp);
00056
00057
00058 RSA *fRSA = RSA_generate_key(bits,exp,0,0);
00059
00060
00061 if (fRSA) {
00062 if (RSA_check_key(fRSA) != 0) {
00063 status = kComplete;
00064 DEBUG("basic length: "<<RSA_size(fRSA)<<" bytes");
00065
00066 EVP_PKEY_set1_RSA(fEVP, fRSA);
00067 } else {
00068 DEBUG("WARNING: generated key is invalid");
00069
00070 RSA_free(fRSA);
00071 }
00072 }
00073 }
00074
00075
00076 XrdCryptosslRSA::XrdCryptosslRSA(const char *pub, int lpub)
00077 {
00078
00079
00080
00081
00082
00083
00084 fEVP = 0;
00085 publen = -1;
00086 prilen = -1;
00087
00088
00089 ImportPublic(pub,lpub);
00090 }
00091
00092
00093 XrdCryptosslRSA::XrdCryptosslRSA(EVP_PKEY *key, bool check)
00094 {
00095
00096 EPNAME("RSA::XrdCryptosslRSA_key");
00097
00098 fEVP = 0;
00099 publen = -1;
00100 prilen = -1;
00101
00102
00103 if (!key) {
00104 DEBUG("no input key");
00105 return;
00106 }
00107
00108 if (check) {
00109
00110 if (RSA_check_key(key->pkey.rsa) != 0) {
00111 fEVP = key;
00112
00113 status = kComplete;
00114 } else {
00115 DEBUG("key contains inconsistent information");
00116 }
00117 } else {
00118
00119 fEVP = key;
00120
00121 status = kPublic;
00122 }
00123 }
00124
00125
00126
00127 XrdCryptosslRSA::XrdCryptosslRSA(const XrdCryptosslRSA &r)
00128 {
00129
00130 EPNAME("RSA::XrdCryptosslRSA_copy");
00131
00132 fEVP = 0;
00133 publen = -1;
00134 prilen = -1;
00135
00136 if (!r.fEVP) {
00137 DEBUG("input key is empty");
00138 return;
00139 }
00140
00141
00142 bool publiconly = (r.fEVP->pkey.rsa->d == 0);
00143
00144
00145 BIO *bcpy = BIO_new(BIO_s_mem());
00146 if (bcpy) {
00147
00148 if (PEM_write_bio_PUBKEY(bcpy, r.fEVP)) {
00149 bool ok = (publiconly) ? 1 :
00150
00151 (PEM_write_bio_PrivateKey(bcpy,r.fEVP,0,0,0,0,0) != 0);
00152 if (ok) {
00153
00154 if ((fEVP = PEM_read_bio_PUBKEY(bcpy, 0, 0, 0))) {
00155
00156 status = kPublic;
00157 ok = (publiconly) ? 1 :
00158
00159 (PEM_read_bio_PrivateKey(bcpy,&fEVP,0,0) != 0);
00160 if (ok) {
00161
00162 if (!publiconly && RSA_check_key(fEVP->pkey.rsa) != 0) {
00163
00164 status = kComplete;
00165 }
00166 }
00167 }
00168 }
00169 }
00170
00171 BIO_free(bcpy);
00172 }
00173 }
00174
00175
00176 XrdCryptosslRSA::~XrdCryptosslRSA()
00177 {
00178
00179
00180
00181 if (fEVP)
00182 EVP_PKEY_free(fEVP);
00183 fEVP = 0;
00184 }
00185
00186
00187 int XrdCryptosslRSA::GetOutlen(int lin)
00188 {
00189
00190
00191 int lcmax = RSA_size(fEVP->pkey.rsa) - 42;
00192
00193 return ((lin / lcmax) + 1) * RSA_size(fEVP->pkey.rsa);
00194 }
00195
00196
00197 int XrdCryptosslRSA::ImportPublic(const char *pub, int lpub)
00198 {
00199
00200
00201
00202
00203
00204
00205
00206 if (fEVP)
00207 EVP_PKEY_free(fEVP);
00208 fEVP = 0;
00209 publen = -1;
00210 prilen = -1;
00211
00212
00213 EVP_PKEY *keytmp = 0;
00214
00215
00216 BIO *bpub = BIO_new(BIO_s_mem());
00217
00218
00219 lpub = (lpub <= 0) ? strlen(pub) : lpub;
00220
00221
00222 BIO_write(bpub,(void *)pub,lpub);
00223
00224
00225 if ((keytmp = PEM_read_bio_PUBKEY(bpub, 0, 0, 0))) {
00226 fEVP = keytmp;
00227
00228 status = kPublic;
00229 return 0;
00230 }
00231 return -1;
00232 }
00233
00234
00235 int XrdCryptosslRSA::ImportPrivate(const char *pri, int lpri)
00236 {
00237
00238
00239
00240
00241
00242
00243
00244 if (!fEVP)
00245 return -1;
00246 prilen = -1;
00247
00248
00249 BIO *bpri = BIO_new(BIO_s_mem());
00250
00251
00252 lpri = (lpri <= 0) ? strlen(pri) : lpri;
00253
00254
00255 BIO_write(bpri,(void *)pri,lpri);
00256
00257
00258 if (PEM_read_bio_PrivateKey(bpri, &fEVP, 0, 0)) {
00259
00260 status = kComplete;
00261 return 0;
00262 }
00263 return -1;
00264 }
00265
00266
00267 void XrdCryptosslRSA::Dump()
00268 {
00269
00270 EPNAME("RSA::Dump");
00271
00272 DEBUG("---------------------------------------");
00273 DEBUG("address: "<<this);
00274 if (IsValid()) {
00275 char *btmp = new char[GetPublen()+1];
00276 if (btmp) {
00277 ExportPublic(btmp,GetPublen()+1);
00278 DEBUG("export pub key:"<<endl<<btmp);
00279 delete[] btmp;
00280 } else {
00281 DEBUG("cannot allocate memory for public key");
00282 }
00283 } else {
00284 DEBUG("key is invalid");
00285 }
00286 DEBUG("---------------------------------------");
00287 }
00288
00289
00290 int XrdCryptosslRSA::GetPublen()
00291 {
00292
00293
00294 if (publen < 0) {
00295
00296 BIO *bkey = BIO_new(BIO_s_mem());
00297
00298 PEM_write_bio_PUBKEY(bkey,fEVP);
00299
00300 char *cbio = 0;
00301 publen = (int) BIO_get_mem_data(bkey, &cbio);
00302 BIO_free(bkey);
00303 }
00304 return publen;
00305 }
00306
00307 int XrdCryptosslRSA::ExportPublic(char *out, int)
00308 {
00309
00310
00311
00312
00313 EPNAME("RSA::ExportPublic");
00314
00315
00316 if (!IsValid()) {
00317 DEBUG("key not valid");
00318 return -1;
00319 }
00320
00321
00322 BIO *bkey = BIO_new(BIO_s_mem());
00323
00324
00325 PEM_write_bio_PUBKEY(bkey,fEVP);
00326
00327
00328 char *cbio = 0;
00329 int lbio = (int) BIO_get_mem_data(bkey, &cbio);
00330 if (lbio <= 0 || !cbio) {
00331 DEBUG("problems attaching to BIO content");
00332 return -1;
00333 }
00334
00335
00336 if (!out) {
00337 out = (char *) malloc(lbio+1);
00338 if (!out) {
00339 DEBUG("problems allocating output buffer");
00340 return -1;
00341 }
00342 }
00343
00344 memcpy(out, cbio, lbio);
00345
00346 out[lbio] = 0;
00347 DEBUG("("<<lbio<<" bytes) "<< endl <<out);
00348 BIO_free(bkey);
00349
00350 return 0;
00351 }
00352
00353
00354 int XrdCryptosslRSA::GetPrilen()
00355 {
00356
00357
00358 if (prilen < 0) {
00359
00360 BIO *bkey = BIO_new(BIO_s_mem());
00361
00362 PEM_write_bio_PrivateKey(bkey,fEVP,0,0,0,0,0);
00363
00364 char *cbio = 0;
00365 prilen = (int) BIO_get_mem_data(bkey, &cbio);
00366 BIO_free(bkey);
00367 }
00368 return prilen;
00369 }
00370
00371
00372 int XrdCryptosslRSA::ExportPrivate(char *out, int)
00373 {
00374
00375
00376
00377
00378 EPNAME("RSA::ExportPrivate");
00379
00380
00381 if (!IsValid()) {
00382 DEBUG("key not valid");
00383 return -1;
00384 }
00385
00386
00387 BIO *bkey = BIO_new(BIO_s_mem());
00388
00389
00390 PEM_write_bio_PrivateKey(bkey,fEVP,0,0,0,0,0);
00391
00392
00393 char *cbio = 0;
00394 int lbio = (int) BIO_get_mem_data(bkey, &cbio);
00395 if (lbio <= 0 || !cbio) {
00396 DEBUG("problems attaching to BIO content");
00397 return -1;
00398 }
00399
00400
00401 if (!out) {
00402 out = (char *) malloc(lbio+1);
00403 if (!out) {
00404 DEBUG("problems allocating output buffer");
00405 return -1;
00406 }
00407 }
00408
00409 memcpy(out, cbio, lbio);
00410
00411 out[lbio] = 0;
00412 DEBUG("("<<lbio<<" bytes) "<< endl <<out);
00413 BIO_free(bkey);
00414
00415 return 0;
00416 }
00417
00418
00419 int XrdCryptosslRSA::EncryptPrivate(const char *in, int lin, char *out, int loutmax)
00420 {
00421
00422
00423
00424
00425 EPNAME("RSA::EncryptPrivate");
00426
00427
00428 if (!in || lin <= 0) {
00429 DEBUG("input buffer undefined");
00430 return -1;
00431 }
00432
00433
00434 if (!out || loutmax <= 0) {
00435 DEBUG("output buffer undefined");
00436 return -1;
00437 }
00438
00439
00440
00441 int lcmax = RSA_size(fEVP->pkey.rsa) - 11;
00442 int lout = 0;
00443 int len = lin;
00444 int kk = 0;
00445 int ke = 0;
00446
00447 while (len > 0 && ke <= (loutmax - lout)) {
00448 int lc = (len > lcmax) ? lcmax : len ;
00449 if ((lout = RSA_private_encrypt(lc, (unsigned char *)&in[kk],
00450 (unsigned char *)&out[ke],
00451 fEVP->pkey.rsa, RSA_PKCS1_PADDING)) < 0) {
00452 char serr[120];
00453 ERR_error_string(ERR_get_error(), serr);
00454 DEBUG("error: " <<serr);
00455 return -1;
00456 }
00457 kk += lc;
00458 ke += lout;
00459 len -= lc;
00460 }
00461 if (len > 0 && ke > (loutmax - lout))
00462 DEBUG("buffer truncated");
00463 lout = ke;
00464
00465
00466 return lout;
00467 }
00468
00469
00470 int XrdCryptosslRSA::EncryptPublic(const char *in, int lin, char *out, int loutmax)
00471 {
00472
00473
00474
00475
00476 EPNAME("RSA::EncryptPublic");
00477
00478
00479 if (!in || lin <= 0) {
00480 DEBUG("input buffer undefined");
00481 return -1;
00482 }
00483
00484
00485 if (!out || loutmax <= 0) {
00486 DEBUG("output buffer undefined");
00487 return -1;
00488 }
00489
00490
00491
00492 int lcmax = RSA_size(fEVP->pkey.rsa) - 42;
00493 int lout = 0;
00494 int len = lin;
00495 int kk = 0;
00496 int ke = 0;
00497
00498 while (len > 0 && ke <= (loutmax - lout)) {
00499 int lc = (len > lcmax) ? lcmax : len ;
00500 if ((lout = RSA_public_encrypt(lc, (unsigned char *)&in[kk],
00501 (unsigned char *)&out[ke],
00502 fEVP->pkey.rsa, RSA_PKCS1_OAEP_PADDING)) < 0) {
00503 char serr[120];
00504 ERR_error_string(ERR_get_error(), serr);
00505 DEBUG("error: " <<serr);
00506 return -1;
00507 }
00508 kk += lc;
00509 ke += lout;
00510 len -= lc;
00511 }
00512 if (len > 0 && ke > (loutmax - lout))
00513 DEBUG("buffer truncated");
00514 lout = ke;
00515
00516
00517 return lout;
00518 }
00519
00520
00521 int XrdCryptosslRSA::DecryptPrivate(const char *in, int lin, char *out, int loutmax)
00522 {
00523
00524
00525
00526
00527 EPNAME("RSA::DecryptPrivate");
00528
00529
00530 if (!in || lin <= 0) {
00531 DEBUG("input buffer undefined");
00532 return -1;
00533 }
00534
00535
00536 if (!out || loutmax <= 0) {
00537 DEBUG("output buffer undefined");
00538 return -1;
00539 }
00540
00541 int lout = 0;
00542 int len = lin;
00543 int lcmax = RSA_size(fEVP->pkey.rsa);
00544 int kk = 0;
00545 int ke = 0;
00546
00547
00548
00549 while (len > 0 && ke <= (loutmax - lout)) {
00550 if ((lout = RSA_private_decrypt(lcmax, (unsigned char *)&in[kk],
00551 (unsigned char *)&out[ke],
00552 fEVP->pkey.rsa, RSA_PKCS1_OAEP_PADDING)) < 0) {
00553 char serr[120];
00554 ERR_error_string(ERR_get_error(), serr);
00555 DEBUG("error: " <<serr);
00556 return -1;
00557 }
00558 kk += lcmax;
00559 len -= lcmax;
00560 ke += lout;
00561 }
00562 if (len > 0 && ke > (loutmax - lout))
00563 PRINT("buffer truncated");
00564 lout = ke;
00565
00566 return lout;
00567 }
00568
00569
00570 int XrdCryptosslRSA::DecryptPublic(const char *in, int lin, char *out, int loutmax)
00571 {
00572
00573
00574
00575
00576 EPNAME("RSA::DecryptPublic");
00577
00578
00579 if (!in || lin <= 0) {
00580 DEBUG("input buffer undefined");
00581 return -1;
00582 }
00583
00584
00585 if (!out || loutmax <= 0) {
00586 DEBUG("output buffer undefined");
00587 return -1;
00588 }
00589
00590 int lout = 0;
00591 int len = lin;
00592 int lcmax = RSA_size(fEVP->pkey.rsa);
00593 int kk = 0;
00594 int ke = 0;
00595
00596
00597
00598 while (len > 0 && ke <= (loutmax - lout)) {
00599 if ((lout = RSA_public_decrypt(lcmax, (unsigned char *)&in[kk],
00600 (unsigned char *)&out[ke],
00601 fEVP->pkey.rsa, RSA_PKCS1_PADDING)) < 0) {
00602 char serr[120];
00603 ERR_error_string(ERR_get_error(), serr);
00604 PRINT("error: " <<serr);
00605 return -1;
00606 }
00607 kk += lcmax;
00608 len -= lcmax;
00609 ke += lout;
00610 }
00611 if (len > 0 && ke > (loutmax - lout))
00612 PRINT("buffer truncated");
00613 lout = ke;
00614
00615 return lout;
00616 }