....................................../////.===Shadow-Here===./////................................................ > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < ------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RIFF¤ WEBPVP8 ˜ ðÑ *ôô>‘HŸK¥¤"§£±¨àð enü¹%½_F‘åè¿2ºQú³íªú`N¿­3ÿƒügµJžaÿ¯ÿ°~¼ÎùnúîÞÖô•òíôÁÉß®Sm¥Ü/ ‡ó˜f£Ùà<˜„xëJ¢Ù€SO3x<ªÔ©4¿+ç¶A`q@Ì“Úñè™ÍÿJÌ´ª-˜ÆtÊÛL]Ïq*‘Ý”ì#ŸÌÏãY]@ê`¿ /ªfkØB4·®£ó z—Üw¥Pxù–ÞLШKÇN¾AkÙTf½è'‰g gÆv›Øuh~ a˜Z— ïj*á¥t d£“uÒ ¨`K˜¹ßþ]b>˜]_ÏÔ6W—è2r4x•íÖ…"ƒÖNîä!¦å Ú}ýxGøÌ —@ ;ÆÚŠ=ɾ1ý8lªË¥ô ^yf®Œ¢u&2©nÙÇ›ñÂñŒ³ aPo['½»øFùà­+4ê“$!lövlüÞ=;N®3ð‚õ›DÉKòÞ>ÄÍ ¥ˆuߤ#ˆ$6ù™¥îЇy’ÍB¼ çxÛ;X"WL£R÷͝*ó-¶Zu}º.s¸sšXqù–DþÿvªhüïwyŸ ¯é³lÀ:KCûÄ£Ëá\…­ ~—ýóî ¼ûûÜTÓüÇy…ŽÆvc»¾×U ñ¸žþоP÷¦ó:Ò¨¨5;Ð#&#ÖúñläÿÁœ GxÉ­/ñ‡áQðìYÉtÒw޼GÔ´zàÒò ð*ëzƒ•4~H]Ø‹f ñÓÈñ`NåWçs'ÆÏW^ø¹!XžµmQ5ÃËoLœÎ: ÞËÍ¥J ù…î èo£ßPÎñ¶ž8.Œ]ʵ~5›ÙË-ù*8ÙÖß±~ ©¹rÓê‚j¶d¸{^Q'˜±Crß ÚH—#¥¥QlÀ×ëã‡DÜ«èî þ&Çæžî;ŽÏºò6ÒLÃXy&ZŒ'j‚¢Ù€IßÚù+–MGi‰*jE€‘JcÜ ÓÌ EÏÚj]o˜ Þr <¾U ûŪæÍ/šÝH¥˜b”¼ ÁñßX GP›ï2›4WŠÏà×£…íÓk†¦H·ÅíMh–*nó÷à]ÁjCº€b7<ب‹¨5車bp2:Á[UªM„QŒçiNMa#<5›áËó¸HýÊ"…×Éw¹¦ì2º–x<›»a±¸3Weü®FÝ⑱ö–î–³|LPÈ~çð~Çå‡|º kD¢µÏàÆAI %1À% ¹Ò – ”ϝS¦‰4&¶£°à Öý”û_Ò Áw°A«Å€?mÇÛgHÉ/8)á¾ÛìáöŽP í¨PŸNÙµº¦‡§Ùš"ÿ«>+ªÕ`Ê÷‡‚ß Õû˜þãÇ-PÍ.¾XV‘€ dÜ"þ4¹ ±Oú‘©t¥¦FªÄÃÄ•b‚znýu½—#cDs˜ÃiÑOˆñ×QO=*IAÊ,¶ŽZƒ;‡wøXè%EÐk:F±Ú” .Ѽ+Áu&Ç`."pÈÉw o&¿dE6‘’EqTuK@Ì¥ã™À(Êk(h‰,H}RÀIXÛš3µ1©_OqÚÒJAñ$ÊÙÜ;D3çŒ[þùœh¬Ã³™ö6ç†NY".Ú‰ï[ªŸŒ '²Ð öø_¨ÂÉ9ué¶³ÒŠõTàîMØ#û¯gN‡bÙ놚X„ö …ÉeüÌ^J ‹€.œ$Æ)βÄeæW#óüßĺŸ€ ÀzwV 9oä»f4V*uB «Ë†¹ì¯žR霓æHXa=&“I4K;¯ç‹h×·"UŠ~<•╪Vêª&ÍSÃÆÅ?ÔqÎ*mTM ˜›µwêd#[C¡©§‘D<©àb†–ÁœøvH/,í:¯( ²£|4-„Æövv„Yͼ™^Á$ˆ„¢Û[6yB.åH*V¨æ?$=˜Ñ€•ñ·­(VlŸ‘ nÀt8W÷´Bûba?q9ú¶Xƒl«ÿ\ù¶’þòUÐj/õ¢Ìµ³g$ƒÎR!¸»|Oߍë’BhîÚÑ¢ñåŒJ„®„£2Ð3•ô02Nt…!£Í]Ïc½Qÿ?ˆ<&ÃA¾Ú,JˆijÌ#5yz„‰Î|ÊŽ5QÏ:‹ÐaóVÔxW—CpeÏzÐïíçôÿÅ_[hãsÐ_/ŽTÝ?BîˆííV$<¿i>²F¬_Eß¿ †bÊŒº­ÿ®Z H“C}”¬,Mp ý/Bá£w>˜YV°aƒúh+cŠ- r/[%|üUMHäQ°X»|û/@|°¥Ð !BÔ Ç¢Ä©š+Õì D«7ìN¶ŽðÔ " ƶ’ÖçtA‰Û×}{tþz­¾GÍ›k¹OEJR$ Â׃ «ëÁ"oÉôž$oUK(Ä)Ãz³Ê-‹êN[Ò3Œñbï8P 4ƒ×q¢bo|?<ÛX¬òÄͰL–±›(™ûG?ýË©ÚÄ–ÂDØÐ_Ç¡ô ¾–ÄÏø ×e8Ë©$ÄF¹Å‹ì[©óìl:F¾f´‹‹Xì²ï®\¬ôùƒ ÿat¥óèÒùHß0äe‚;ü×h:ÆWðHž=Ã8骣"kœ'Y?³}Tûè€>?0l›e1Lòñ„aæKÆw…hÖŠùW…ÈÆÄ0ši·›[pcwËþñiêíY/~-Á5˜!¿†A›™Mÿþ(±“t@â“ö2­´TG5yé]çå僳 .·ÍïçÝ7UÚ±Ð/Nè»,_Ï ùdj7\ï Wì4›„»c¸àešg#ÒÊ⥭áØo5‘?ÌdÝô¯ ¹kzsƒ=´#ëÉK›Ø´±-¥eW?‡çßtòTã…$Ý+qÿ±ƒ÷_3Ô¥í÷:æ–ž<·Ö‡‰Å¢ š‡%Ô—utÌÈìðžgÖÀz²À—ï÷Óîäõ{K'´È÷³yaÏÁjƒô}ž§®æÊydÕÈë5¯èˆõvÕ©ã*çD„ “z„Ó‡^^xÂ3M§A´JG‚öï 3W'ˆ.OvXè¡ÊÕª?5º7†˜(˜Ç¶#çê’¶!ÌdZK§æ 0fãaN]òY³RV ™î$®K2R¨`W!1Ôó\;Ý ýB%qæK•&ÓÈe9È0êI±žeŸß -ú@žQr¦ ö4»M¼Áè¹µmw 9 EÆE_°2ó„ŸXKWÁ×Hóì^´²GѝF©óäR†¦‰ç"V»eØ<3ùd3ÿÚ¤Žú“Gi" —‘_ÙËÎ~Üö¯¥½Î»üŸEÚŽåmÞþí ;ÞólËΦMzA"Âf(´òá;Éï(/7½ûñÌ­cïÕçлþÝz¾-ÍvÑ“pH­–ðÓj$¸Äû¤‚‘ãUBË-n“2åPkS5&‹Â|+g^œ®Ì͆d!OïäîU«c;{Û!ÅŽ«ëZ9Ókóˆ]¯ƒ›né `ÇÒ+tÆš (ØKá¾—=3œ®•vuMñg²\ï Ec€ 05±d™‡×iÇ×›UúvÌ¢£Èþ¡ÕØô¶ßÎA"ß±#Ö²ˆÊŸ¦*Ä~ij|àø.-¼'»Ú¥£h ofº¦‡VsR=N½„Î v˜Z*SÌ{=jÑB‹tê…;’HžH¯8–îDù8ñ¢|Q•bÛçš–‹m³“ê¨ åÏ^m¬Žãþ©ïêO‡½6] µÆ„Ooòü ²x}N¦Ë3ïé¿»€›HA˜m%çÞ/¿í7Fø“‹léUk)É°Œµ8Q8›:ÀŠeT*šõ~ôڝG6 ¢}`ùH­–”¡k ‰P1>š†®9z11!X wKfmÁ¦xÑ,N1Q”–æB¶M…ÒÃv6SMˆhU¬ÊPŽï‘öj=·CŒ¯u¹ƒVIЃsx4’ömÛýcå¡¶7ßŠß 57^\wÒÐÆ k§h,Œý î«q^R½3]J¸ÇðN ‚çU¬ôº^Áì} ³f©Õœ§ˆã:FÄÈ‚é(€™?àýÓüè1Gô£¼éj‚OÅñ  #>×—ßtà 0G¥Åa뀐kßhc™À_ÉñÞ#±)GD" YîäË-ÿÙ̪ ¹™a¯´¢E\ÝÒö‚;™„ë]_ p8‰o¡ñ+^÷ 3‘'dT4œŽ ðVë½° :¬víÑ«£tßÚS-3¶“þ2 †üüʨòrš¹M{É_¤`Û¨0ìjœøJ‡:÷ÃáZ˜†@GP&œÑDGÏs¡þ¦þDGú‘1Yá9Ôþ¼ ûø…§÷8&–ÜÑnÄ_m®^üÆ`;ÉVÁJ£?â€-ßê}suÍ2sõA NÌúA磸‘îÿÚ»ƒìö·á¿±tÑÐ"Tÿü˜[@/äj¬€uüªìù¥Ý˜á8Ý´sõj 8@rˆð äþZÇD®ÿUÏ2ùôõrBzÆÏÞž>Ì™xœ“ wiÎ×7_… ¸ \#€MɁV¶¥üÕÿPÔ9Z‡ø§É8#H:ƒ5ÀÝå9ÍIŒ5åKÙŠ÷qÄ>1AÈøžj"µÂд/ªnÀ qªã}"iŸBå˜ÓÛŽ¦…&ݧ;G@—³b¯“•"´4í¨ôM¨åñC‹ïùÉó¯ÓsSH2Ý@ßáM‡ˆKÀªÛUeø/4\gnm¥‹ŸŒ qÄ b9ÞwÒNÏ_4Ég³ú=܆‚´ •â¥õeíþkjz>éÚyU«Íӝ݃6"8/ø{=Ô¢»G¥ äUw°W«,ô—¿ãㆅү¢³xŠUû™yŒ (øSópÐ 9\åTâ»—*oG$/×ÍT†Y¿1¤Þ¢_‡ ¼ „±ÍçèSaÓ 3ÛMÁBkxs‰’R/¡¤ˆÙçª(*õ„üXÌ´ƒ E§´¬EF"Ù”R/ÐNyÆÂ^°?™6¡œïJ·±$§?º>ÖüœcNÌù¯G ‹ñ2ЁBB„^·úìaz¨k:#¨Æ¨8LÎõލ£^§S&cŒÐU€ü(‡F±Š¼&P>8ÙÁ ‰ p5?0ÊÆƒZl¸aô š¼¡}gÿ¶zÆC²¹¬ÎÖG*HB¡O<º2#ñŒAƒ–¡B˜´É$¥›É:FÀÔx¾u?XÜÏÓvN©RS{2ʈãk9rmP¼Qq̳ è¼ÐFׄ^¡Öì fE“F4A…!ì/…¦Lƒ… … $%´¾yã@CI¬ á—3PþBÏNÿ<ý°4Ü ËÃ#ØÍ~âW«rEñw‹eùMMHß²`¬Öó½íf³:‹k˜¯÷}Z!ã¿<¥,\#öµÀ¯aÒNÆIé,Ћ–lŽ#Àæ9ÀÒS·I’½-Ïp Äz¤Š Â* ­íÄ9­< h>׍3ZkËU¹§˜ŒŠ±f­’¤º³Q ÏB?‹#µíÃ¥®@(Gs«†vI¥Mµ‹Á©e~2ú³ÁP4ìÕi‚²Ê^ö@-DþÓàlÜOÍ]n"µã:žpsŽ¢:! Aõ.ç~ÓBûH÷JCÌ]õVƒd «ú´QÙEA–¯¯Œ!.ˆˆëQ±ù œ·Ì!Õâ )ùL„ÅÀlÚè5@B…o´Æ¸XÓ&Û…O«˜”_#‡ƒ„ûÈt!¤ÁÏ›ÎÝŠ?c9 â\>lÓÁVÄÑ™£eØY]:fÝ–—ù+p{™ðè û³”g±OƒÚSù£áÁÊ„ä,ï7š²G ÕÌBk)~ÑiCµ|h#u¤¶îK¨² #²vݯGãeÖ϶ú…¾múÀ¶þÔñ‚Š9'^($¤§ò “š½{éúp÷J›ušS¹áªCÂubÃH9™D™/ZöØÁ‡¦ÝÙŸ·kð*_”.C‹{áXó€‡c¡c€§/šò/&éš÷,àéJþ‰X›fµ“C¨œ®r¬"kL‰Â_q…Z–.ÉL~O µ›zn‚¹À¦Öª7\àHµšÖ %»ÇníV[¥*Õ;ƒ#½¾HK-ÖIÊdÏEÚ#=o÷Óò³´Š: Ç?{¾+9›–‘OEáU·S€˜j"ÄaÜ ŒÛWt› á–c#a»pÔZÞdŽtWê=9éöÊ¢µ~ ë ;Öe‡Œ®:bî3±ýê¢wà¼îpêñ¹¾4 zc¾ðÖÿzdêŒÑÒŝÀ‰s6¤í³ÎÙB¿OZ”+F¤á‡3@Ñëäg©·Ž ˆèª<ù@É{&S„œÕúÀA)‰h:YÀ5^ÂÓŒ°õäU\ ùËÍû#²?Xe¬tu‰^zÒÔãë¼ÛWtEtû …‚g¶Úüâî*moGè¨7%u!]PhÏd™Ý%Îx: VÒ¦ôÊD3ÀŽKÛËãvÆî…N¯ä>Eró–ð`5 Œ%u5XkñÌ*NU%¶áœÊ:Qÿú»“úzyÏ6å-၇¾ ´ ÒÊ]y žO‘w2Äøæ…H’²f±ÎÇ.ª|¥'gîV•Ü .̘¯€šòü¤U~Ù†*¢!?ò wý,}´°ÔÞnïoKq5µb!áÓ3"vAßH¡³¡·G(ÐÎ0Îò¼MG!/ài®@—¬04*`…«é8ªøøló“ˆÊ”èù¤…ßÊoÿé'ËuÌÖ5×È¡§ˆˆfŽë9}hìâ_!!¯  B&Ëö¶‰ÀAÙNVŸ Wh›¸®XÑJì¨ú“¿÷3uj²˜¨ÍÎìë±aúŠÝå¯ð*Ó¨ôJ“yºØ)m°WýOè68†ŸÏ2—‰Ïüꪫٚ¥‹l1 ø ÏÄFjêµvÌbü¦èÝx:X±¢H=MÐß—,ˆÉÇ´(9ú¾^ÅÚ4¿m‡$âX‘å%(AlZo@½¨UOÌÕ”1ø¸jÎÀÃÃ_ µ‘Ü.œº¦Ut: Æï’!=¯uwû#,“pþÇúŒø(é@?³ü¥‘Mo §—s@Œ#)§ŒùkL}NOÆêA›¸~r½¼ÙA—HJ«eˆÖ´*¡ÓpÌŸö.m<-"³ûÈ$¬_6­åf£ïÚâj1y§ÕJ½@dÞÁr&Í\Z%D£Íñ·AZ Û³øüd/ªAi†/Й~  ‡âĮҮÏh§°b—›Û«mJžòG'[ÈYýŒ¦9psl ýÁ ®±f¦x,‰½tN ‚Xª9 ÙÖH.«Lo0×?͹m¡å†Ѽ+›2ƒF ±Ê8 7Hցϓ²Æ–m9…òŸï]Â1äN†VLâCˆU .ÿ‰Ts +ÅÎx(%¦u]6AF Š ØF鈄‘ |¢¶c±soŒ/t[a¾–û:s·`i햍ê›ËchÈ…8ßÀUÜewŒðNOƒõD%q#éû\9¤x¹&UE×G¥ Í—™$ð E6-‡¼!ýpãÔM˜ Âsìe¯ñµK¢Ç¡ùôléœ4Ö£”À Š®Ðc ^¨À}ÙËŸ§›ºê{ÊuÉC ×Sr€¤’fÉ*j!úÓ’Gsùìoîßîn%ò· àc Wp÷$¨˜)û»H ×8ŽÒ€Zj¤3ÀÙºY'Ql¦py{-6íÔCeiØp‘‡XÊîÆUߢ܂ž£Xé¼Y8þ©ëgñß}é.ÎógÒ„ÃØËø¯»™§Xýy M%@NŠ À(~áÐvu7&•,Ù˜ó€uP‡^^®=_E„jt’ 403WebShell
403Webshell
Server IP : 104.19.154.92  /  Your IP : 216.73.216.150
Web Server : Apache
System : Linux lon12.onrocket.com 4.18.0-513.9.1.lve.el8.x86_64 #1 SMP Mon Dec 4 15:01:22 UTC 2023 x86_64
User : gd5hzp4 ( 1069)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/cpanel/ea-ruby27/src/passenger-release-6.0.23/src/cxx_supportlib/SecurityKit/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/cpanel/ea-ruby27/src/passenger-release-6.0.23/src/cxx_supportlib/SecurityKit/Crypto.cpp
/*
 *  Phusion Passenger - https://www.phusionpassenger.com/
 *  Copyright (c) 2010-2018 Phusion Holding B.V.
 *
 *  "Passenger", "Phusion Passenger" and "Union Station" are registered
 *  trademarks of Phusion Holding B.V.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */

#include <SecurityKit/Crypto.h>
#include <modp_b64.h>
#include <LoggingKit/LoggingKit.h>
#include <string>
#include <SystemTools/SystemTime.h>
#include <StrIntTools/StrIntUtils.h>

#if BOOST_OS_MACOS
#else
#include <openssl/aes.h>
#endif

#define AES_KEY_BYTESIZE (256/8)
#define AES_CBC_IV_BYTESIZE (128/8)

namespace Passenger {

using namespace std;
using namespace boost;
using namespace oxt;

#if BOOST_OS_MACOS

Crypto::Crypto()
	:id(NULL) {
}

Crypto::~Crypto() {
}

CFDictionaryRef Crypto::createQueryDict(const char *label) {
	if (kSecClassIdentity != NULL) {
		const size_t size = 5L;
		CFStringRef cfLabel = CFStringCreateWithCString(NULL, label, kCFStringEncodingUTF8);
		SecPolicyRef policy = SecPolicyCreateSSL(false, NULL);
		CFTypeRef keys[] = {kSecClass, kSecReturnRef, kSecMatchLimit, kSecMatchPolicy, kSecMatchSubjectWholeString};
		CFTypeRef values[] = {kSecClassIdentity, kCFBooleanTrue, kSecMatchLimitOne, policy, cfLabel};

		CFDictionaryRef queryDict = CFDictionaryCreate(NULL, keys, values, size,
									   &kCFCopyStringDictionaryKeyCallBacks,
									   &kCFTypeDictionaryValueCallBacks);
		CFRelease(policy);
		CFRelease(cfLabel);

		return queryDict;
	}
	return NULL;
}

SecAccessRef Crypto::createAccess(const char *cLabel) {
	SecAccessRef access = NULL;
	CFStringRef label = CFStringCreateWithCString(NULL, cLabel, kCFStringEncodingUTF8);
	if (SecAccessCreate(label, NULL, &access)) {
		logError("SecAccessCreate failed.");
		CFRelease(label);
		return NULL;
	}
	CFRelease(label);
	return access;
}

OSStatus Crypto::copyIdentityFromPKCS12File(const char *cPath,
											const char *cPassword,
											const char *cLabel) {
	OSStatus status = errSecItemNotFound;
	if (strlen(cPath) == 0) {
		return errSecMissingValue;
	}
	CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL,
														   (const UInt8 *) cPath, strlen(cPath), false);
	CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
																 cPassword, kCFStringEncodingUTF8) : NULL;

	CFReadStreamRef cfrs = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
	SecTransformRef readTransform = SecTransformCreateReadTransformWithReadStream(cfrs);
	CFErrorRef error = NULL;
	CFDataRef pkcsData = (CFDataRef) SecTransformExecute(readTransform, &error);
	if (error != NULL) {
		logFreeErrorExtended("ReadTransform", error);
		return status;
	}

	SecAccessRef access = createAccess(cLabel);
	if (access == NULL) {
		return status;
	}
	CFTypeRef cKeys[] = {kSecImportExportPassphrase, kSecImportExportAccess};
	CFTypeRef cValues[] = {password, access};
	CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues, 2L, NULL, NULL);
	CFArrayRef items = NULL;

	/* Here we go: */
	status = SecPKCS12Import(pkcsData, options, &items);
	if (!(status == noErr && items && CFArrayGetCount(items))) {
		string suffix = string("Please check for a certificate labeled: ") + cLabel + " in your keychain, and remove the associated private key. For more help please read: https://www.phusionpassenger.com/library/admin/standalone/mac_keychain_popups.html";
		string prefix = "Loading Passenger Cert failed";
		if (status == noErr) {
			status = errSecAuthFailed;
			logError( prefix + ". " + suffix );
		}else{
			CFStringRef str = SecCopyErrorMessageString(status, NULL);
			logError( prefix + ": " + CFStringGetCStringPtr(str, kCFStringEncodingUTF8) + "\n" + suffix );
			CFRelease(str);
		}
	}else{
	  id = (CFDataRef)CFDictionaryGetValue((CFDictionaryRef)CFArrayGetValueAtIndex(items, 0),kSecImportItemKeyID);
	  CFRetain(id);
	}

	if (items) {
		CFRelease(items);
	}
	CFRelease(options);
	CFRelease(access);
	if (pkcsData) {
		CFRelease(pkcsData);
	}
	CFRelease(readTransform);
	CFRelease(cfrs);
	if (password) {
		CFRelease(password);
	}
	CFRelease(url);
	return status;
}

bool Crypto::generateRandomChars(unsigned char *rndChars, int rndLen) {
	FILE *fPtr = fopen("/dev/random", "r");
	if (fPtr == NULL) {
		CFIndex errNum = errno;
		char* errMsg = strerror(errno);
		const UInt8 numKeys = 4;
		CFTypeRef userInfoKeys[numKeys] = { kCFErrorFilePathKey,
											kCFErrorLocalizedDescriptionKey,
											kCFErrorLocalizedFailureReasonKey,
											kCFErrorLocalizedRecoverySuggestionKey };
		CFTypeRef userInfoValues[numKeys] = { CFSTR("/dev/random"),
											  CFSTR("Couldn't open file for reading."),
											  CFStringCreateWithCStringNoCopy(NULL, errMsg, kCFStringEncodingUTF8, NULL),
											  CFSTR("Have you tried turning it off and on again?") };

		CFErrorRef error = CFErrorCreateWithUserInfoKeysAndValues(NULL, kCFErrorDomainOSStatus, errNum, userInfoKeys, userInfoValues, numKeys);
		logFreeErrorExtended("generateRandomChars failed", error);
		return false;
	}
	for (int i = 0; i < rndLen; i++) {
		rndChars[i] = fgetc(fPtr);
	}
	fclose(fPtr);

	return true;
}

bool Crypto::generateAndAppendNonce(string &nonce) {
	nonce.append(toString(SystemTime::getUsec()));

	int rndLen = 16;
	unsigned char rndChars[rndLen];

	if (generateRandomChars(rndChars, rndLen)) {
		char rndChars64[modp_b64_encode_len(rndLen)];
		modp_b64_encode(rndChars64, (const char *) rndChars, rndLen);

		nonce.append(rndChars64);
		return true;
	} else {
		return false;
	}
}

CFDataRef Crypto::genIV(size_t ivSize) {
	UInt8 *ivBytesPtr = (UInt8*) malloc(ivSize);//freed when iv is freed
	if (generateRandomChars(ivBytesPtr, ivSize)) {
		return CFDataCreateWithBytesNoCopy(NULL, ivBytesPtr, ivSize, kCFAllocatorMalloc);
	} else {
		return NULL;
	}
}

bool Crypto::getKeyBytes(SecKeyRef cryptokey, void **target, size_t &len) {
	const CSSM_KEY *cssmKey;
	CSSM_WRAP_KEY wrappedKey;

	CSSM_CSP_HANDLE cspHandle = 0;
	CSSM_CC_HANDLE ccHandle = 0;

	const CSSM_ACCESS_CREDENTIALS *creds;
	CSSM_RETURN error = SecKeyGetCredentials(cryptokey,
											 CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
											 kSecCredentialTypeDefault, &creds);
	if (error != CSSM_OK) { cssmPerror("SecKeyGetCredentials", error); }

	error = SecKeyGetCSSMKey(cryptokey, &cssmKey);
	if (error != CSSM_OK) { cssmPerror("SecKeyGetCSSMKey", error); }

	error = SecKeyGetCSPHandle(cryptokey, &cspHandle);
	if (error != CSSM_OK) { cssmPerror("SecKeyGetCSPHandle", error); }

	error = CSSM_CSP_CreateSymmetricContext(cspHandle,
											CSSM_ALGID_NONE,
											CSSM_ALGMODE_NONE,
											creds,
											NULL,
											NULL,
											CSSM_PADDING_NONE,
											0,
											&ccHandle);
	if (error != CSSM_OK) { cssmPerror("CSSM_CSP_CreateSymmetricContext",error); }

	memset(&wrappedKey, 0, sizeof(wrappedKey));
	error = CSSM_WrapKey(ccHandle,
				 creds,
				 cssmKey,
				 NULL,
				 &wrappedKey);
	if (error != CSSM_OK) { cssmPerror("CSSM_WrapKey", error); }

	CSSM_DeleteContext(ccHandle);

	len = wrappedKey.KeyData.Length;

	return innerMemoryBridge(wrappedKey.KeyData.Data,target,wrappedKey.KeyData.Length);
}

bool Crypto::encryptAES256(char *dataChars, size_t dataLen, AESEncResult &aesEnc) {
	CFErrorRef error = NULL;
	bool retVal = false;

	CFNumberRef cfSize = NULL;
	CFDictionaryRef parameters = NULL;
	SecKeyRef cryptokey = NULL;
	CFDataRef iv = NULL;
	SecTransformRef encrypt = NULL;
	CFDataRef message = NULL;
	CFDataRef enc = NULL;

	do {
		UInt32 size = kSecAES256; // c++ is dumb
		CFNumberRef cfSize = CFNumberCreate(NULL, kCFNumberSInt32Type, &size);
		CFTypeRef cKeys[] = {kSecAttrKeyType, kSecAttrKeySizeInBits};
		CFTypeRef cValues[] = {kSecAttrKeyTypeAES, cfSize};
		CFDictionaryRef parameters = CFDictionaryCreate(NULL, cKeys, cValues, 2L, NULL, NULL);
		if (parameters == NULL) {
			logError("CFDictionaryCreate failed.");
			retVal = false;
			break;
		}

		SecKeyRef cryptokey = SecKeyGenerateSymmetric(parameters, &error);
		if (error != NULL) {
			logFreeErrorExtended("SecKeyGenerateSymmetric", error);
			retVal = false;
			break;
		}

		if (!getKeyBytes(cryptokey, (void **) &aesEnc.key, aesEnc.keyLen)) {
			retVal = false;
			break;
		}

		CFDataRef iv = genIV(AES_CBC_IV_BYTESIZE);
		if (iv == NULL) {
			logError("genIV failed.");
			retVal = false;
			break;
		} else if (!memoryBridge(iv, (void **) &aesEnc.iv, aesEnc.ivLen)) {
			retVal = false;
			break;
		}

		SecTransformRef encrypt = SecEncryptTransformCreate(cryptokey, &error);
		if (error != NULL) {
			logFreeErrorExtended("SecEncryptTransformCreate", error);
			retVal = false;
			break;
		}
		SecTransformSetAttribute(encrypt, kSecIVKey, iv, &error);
		if (error != NULL) {
			logFreeErrorExtended("SecTransformSetAttribute", error);
			retVal = false;
			break;
		}
		CFDataRef message = CFDataCreateWithBytesNoCopy(NULL,
														(UInt8*) dataChars,
														dataLen,
														kCFAllocatorNull);
		SecTransformSetAttribute(encrypt, kSecTransformInputAttributeName, message, &error);
		if (error != NULL) {
			logFreeErrorExtended("SecTransformSetAttribute", error);
			retVal = false;
			break;
		}
		CFDataRef enc = (CFDataRef) SecTransformExecute(encrypt, &error);
		if (error != NULL) {
			logFreeErrorExtended("SecTransformExecute", error);
			retVal = false;
			break;
		}

		if (!memoryBridge(enc, (void **) &aesEnc.encrypted, aesEnc.encryptedLen)) {
			retVal = false;
			break;
		}
		retVal = true;
	} while (false);

	if (enc) { CFRelease(enc); }
	if (message) { CFRelease(message); }
	if (encrypt) { CFRelease(encrypt); }
	if (iv) { CFRelease(iv); }
	if (cryptokey) { CFRelease(cryptokey); }
	if (parameters) { CFRelease(parameters); }
	if (cfSize) { CFRelease(cfSize); }

	return retVal;
}

void Crypto::freeAESEncrypted(AESEncResult &aesEnc) {
	if (aesEnc.encrypted != NULL) {
		free(aesEnc.encrypted);
		aesEnc.encrypted = NULL;
	}
	if (aesEnc.iv != NULL) {
		free(aesEnc.iv);
		aesEnc.iv = NULL;
	}
	if (aesEnc.key != NULL) {
		memset(aesEnc.key, 0, aesEnc.keyLen);
		free(aesEnc.key);
		aesEnc.key = NULL;
	}
}

bool Crypto::encryptRSA(unsigned char *dataChars, size_t dataLen,
						string encryptPubKeyPath, unsigned char **encryptedCharsPtr, size_t &encryptedLen) {
	bool retVal = false;
	CFErrorRef error = NULL;
	SecKeyRef rsaPubKey = loadPubKey(encryptPubKeyPath.c_str());

	CFDataRef aesKeyData = NULL;
	SecTransformRef rsaEncryptContext = NULL;
	CFDataRef encryptedKey = NULL;

	do {
		if (rsaPubKey == NULL) {
			logError("loadPubKey failed");
			retVal = false;
			break;
		}

		aesKeyData = CFDataCreateWithBytesNoCopy(NULL, (UInt8*) dataChars, dataLen, kCFAllocatorNull);
		if (aesKeyData == NULL) {
			logError("CFDataCreateWithBytesNoCopy failed");
			retVal = false;
			break;
		}

		rsaEncryptContext = SecEncryptTransformCreate(rsaPubKey, &error);
		if (error) {
			logFreeErrorExtended("SecEncryptTransformCreate", error);
			retVal = false;
			break;
		}
		SecTransformSetAttribute(rsaEncryptContext,
								 kSecPaddingKey,
								 kSecPaddingOAEPKey,
								 &error);
		if (error) {
			logFreeErrorExtended("SecTransformSetAttribute", error);
			retVal = false;
			break;
		}

		SecTransformSetAttribute(rsaEncryptContext, kSecTransformInputAttributeName, aesKeyData, &error);
		if (error) {
			logFreeErrorExtended("SecTransformSetAttribute", error);
			retVal = false;
			break;
		}
		encryptedKey = (CFDataRef) SecTransformExecute(rsaEncryptContext, &error);
		if (error) {
			logFreeErrorExtended("SecTransformExecute", error);
			retVal = false;
			break;
		}

		if (!memoryBridge(encryptedKey, (void **) encryptedCharsPtr, encryptedLen)) {
			retVal = false;
			break;
		}
		retVal = true;
	} while (false);

	if (encryptedKey) { CFRelease(encryptedKey); }
	if (rsaEncryptContext) { CFRelease(rsaEncryptContext); }
	if (aesKeyData) { CFRelease(aesKeyData); }
	if (rsaPubKey) { CFRelease(rsaPubKey); }

	return retVal;
}

bool Crypto::memoryBridge(CFDataRef input, void **target, size_t &len) {
	len = CFDataGetLength(input);
	return innerMemoryBridge((void *) CFDataGetBytePtr(input), target, len);
}

bool Crypto::innerMemoryBridge(void *input, void **target, size_t len){
	*target = malloc(len);
	if (*target == NULL) {
		logError("malloc failed: " + toString(len));
		return false;
	}
	memcpy(*target, input, len);
	return true;
}

bool Crypto::verifySignature(string signaturePubKeyPath, char *signatureChars, int signatureLen, string data) {
	SecKeyRef rsaPubKey = NULL;
	bool result = false;

	SecTransformRef verifier = NULL;
	CFNumberRef cfSize = NULL;
	do {
		rsaPubKey = loadPubKey(signaturePubKeyPath.c_str());
		if (rsaPubKey == NULL) {
			logError("Failed to load public key at " + signaturePubKeyPath);
			break;
		}

		CFDataRef signatureRef = CFDataCreateWithBytesNoCopy(NULL, (UInt8*) signatureChars, signatureLen, kCFAllocatorNull);

		CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL, reinterpret_cast<const UInt8*>(data.c_str()), data.length(), kCFAllocatorNull);

		CFErrorRef error = NULL;
		verifier = SecVerifyTransformCreate(rsaPubKey, signatureRef, &error);
		if (error) {
			logFreeErrorExtended("SecVerifyTransformCreate", error);
			result = -20;
			break;
		}

		SecTransformSetAttribute(verifier, kSecTransformInputAttributeName, dataRef, &error);
		if (error) {
			logFreeErrorExtended("SecTransformSetAttribute InputName", error);
			result = -21;
			break;
		}

		SecTransformSetAttribute(verifier, kSecDigestTypeAttribute, kSecDigestSHA2, &error);
		if (error) {
			logFreeErrorExtended("SecTransformSetAttribute DigestType", error);
			result = -22;
			break;
		}

		UInt32 size = kSecAES256; // c++ is dumb
		cfSize = CFNumberCreate(NULL, kCFNumberSInt32Type, &size);
		SecTransformSetAttribute(verifier, kSecDigestLengthAttribute, cfSize, &error);
		if (error) {
			logFreeErrorExtended("SecTransformSetAttribute DigestLength", error);
			result = -23;
			break;
		}

		CFTypeRef verifyResult = SecTransformExecute(verifier, &error);
		if (error) {
			logFreeErrorExtended("SecTransformExecute", error);
			result = -24;
			break;
		}

		result = (verifyResult == kCFBooleanTrue);
	} while(0);

	if (cfSize) {
		CFRelease(cfSize);
	}
	if (verifier) {
		CFRelease(verifier);
	}
	freePubKey(rsaPubKey);

	return result;
}

PUBKEY_TYPE Crypto::loadPubKey(const char *filename) {
	SecKeyRef pubKey = NULL;
	CFDataRef keyData = NULL;
	CFURLRef url = NULL;
	CFReadStreamRef cfrs = NULL;
	SecTransformRef readTransform = NULL;
	CFArrayRef temparray = NULL;
	do {
		url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
													  reinterpret_cast<const UInt8*>(filename), strlen(filename), false);
		if (url == NULL) {
			logError("CFURLCreateFromFileSystemRepresentation failed.");
			break;
		}

		cfrs = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
		if (cfrs == NULL) {
			logError("CFReadStreamCreateWithFile failed");
			break;
		}

		readTransform = SecTransformCreateReadTransformWithReadStream(cfrs);
		if (readTransform == NULL) {
			logError("SecTransformCreateReadTransformWithReadStream failed");
			break;
		}
		CFErrorRef error = NULL;
		keyData = (CFDataRef) SecTransformExecute(readTransform, &error);
		if (keyData == NULL) {
			logError("SecTransformExecute failed to get keyData");
			break;
		}
		if (error) {
			logFreeErrorExtended("SecTransformExecute", error);
			break;
		}

		SecExternalItemType itemType = kSecItemTypePublicKey;
		SecExternalFormat externalFormat = kSecFormatPEMSequence;
		OSStatus oserr = SecItemImport(keyData,
									   NULL, // filename or extension
									   &externalFormat, // See SecExternalFormat for details
									   &itemType,
									   0, // See SecItemImportExportFlags for details, Note that PEM formatting
									   // is determined internally via inspection of the incoming data, so
									   // the kSecItemPemArmour flag is ignored.
									   NULL,
									   NULL, // Don't import into a keychain
									   &temparray);
		if (oserr) {
			CFStringRef str = SecCopyErrorMessageString(oserr, NULL);
			logError(string("SecItemImport: ") + CFStringGetCStringPtr(str, kCFStringEncodingUTF8));
			CFRelease(str);
			break;
		}
		pubKey = reinterpret_cast<SecKeyRef>(const_cast<void*>(CFArrayGetValueAtIndex(temparray, 0)));
		CFRetain(pubKey); //bump ref count, now we own this and need to release it eventually
	} while (0);

	if (keyData) {
		CFRelease(keyData); //might be wrong to release here, not sure if SecItemImport makes a copy of the bytes, it looks like it does
		//https://opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55035/lib/SecImport.cpp
		//http://opensource.apple.com//source/libsecurity_keychain/libsecurity_keychain-14/lib/SecImportExportPem.cpp
	}
	if (temparray) {
		CFRelease(temparray);
	}
	if (readTransform) {
		CFRelease(readTransform);
	}
	if (cfrs) {
		CFRelease(cfrs);
	}
	if (url) {
		CFRelease(url);
	}

	return pubKey;
}

void Crypto::freePubKey(PUBKEY_TYPE pubKey) {
	if (pubKey) {
		CFRelease(pubKey);
	}
}

void Crypto::logFreeErrorExtended(const StaticString &prefix, CFErrorRef &error) {
	if (error) {
		CFStringRef description = CFErrorCopyDescription((CFErrorRef) error);
		CFStringRef failureReason = CFErrorCopyFailureReason((CFErrorRef) error);
		CFStringRef recoverySuggestion = CFErrorCopyRecoverySuggestion((CFErrorRef) error);

		logError(prefix +
				": " + CFStringGetCStringPtr(description, kCFStringEncodingUTF8) +
				"; " + CFStringGetCStringPtr(failureReason, kCFStringEncodingUTF8) +
				"; " + CFStringGetCStringPtr(recoverySuggestion, kCFStringEncodingUTF8)
				);

		CFRelease(recoverySuggestion);
		CFRelease(failureReason);
		CFRelease(description);
		CFRelease(error);
		error = NULL;
	}
}

#else

Crypto::Crypto() {
	OpenSSL_add_all_algorithms();
}

Crypto::~Crypto() {
	EVP_cleanup();
}

bool Crypto::generateAndAppendNonce(string &nonce) {
	nonce.append(toString(SystemTime::getUsec()));

	int rndLen = 16;
	unsigned char rndChars[rndLen];

	if (1 != RAND_bytes(rndChars, rndLen)) {
		logErrorExtended("RAND_bytes failed for nonce");
		return false;
	}

	char rndChars64[modp_b64_encode_len(rndLen)];
	modp_b64_encode(rndChars64, (const char *) rndChars, rndLen);

	nonce.append(rndChars64);
	return true;
}

bool Crypto::encryptAES256(char *dataChars, size_t dataLen, AESEncResult &aesEnc) {
	assert(dataLen > 0 && dataChars != NULL);

	aesEnc.encrypted = NULL;
	aesEnc.key = NULL;
	aesEnc.iv = NULL;

	bool result = false;
	EVP_CIPHER_CTX *aesEncryptContext = NULL;

	do {
		// 1. Generate random key (secret) and init vector to be used for the encryption
		aesEnc.keyLen = AES_KEY_BYTESIZE;
		aesEnc.key = (unsigned char*) OPENSSL_malloc(aesEnc.keyLen);
		if (aesEnc.key == NULL) {
			logErrorExtended("OPENSSL_malloc failed");
			break;
		}

		aesEnc.ivLen = AES_CBC_IV_BYTESIZE;
		aesEnc.iv = (unsigned char*) malloc(aesEnc.ivLen); // not secret
		if (aesEnc.iv == NULL) {
			logError("malloc for IV failed");
			break;
		}

		if (1 != RAND_bytes(aesEnc.key, aesEnc.keyLen)) {
			logErrorExtended("RAND_bytes failed for AES key");
			break;
		}
		if (1 != RAND_bytes(aesEnc.iv, aesEnc.ivLen)) {
			logErrorExtended("RAND_bytes failed for IV");
			break;
		}

		// 2. Get ready to encrypt
		aesEncryptContext = EVP_CIPHER_CTX_new();
		if (aesEncryptContext == NULL) {
			logErrorExtended("EVP_CIPHER_CTX_new failed");
			break;
		}

		aesEnc.encrypted = (unsigned char*) malloc(dataLen + AES_BLOCK_SIZE); // not secret
		if (aesEnc.encrypted == NULL) {
			logError("malloc for encryptedChars failed " + toString(dataLen + AES_BLOCK_SIZE));
			break;
		}

		// 3. Let's go
		if (1 != EVP_EncryptInit_ex(aesEncryptContext, EVP_aes_256_cbc(), NULL, aesEnc.key, aesEnc.iv)) {
			logErrorExtended("EVP_EncryptInit_ex failed");
			break;
		}

		size_t blockLength = 0;
		size_t writeIdx = 0;
		if (1 != EVP_EncryptUpdate(aesEncryptContext, aesEnc.encrypted + writeIdx, (int *) &blockLength, (unsigned char*) dataChars, dataLen)) {
			logErrorExtended("EVP_EncryptUpdate failed");
			break;
		}
		writeIdx += blockLength;

		if (1 != EVP_EncryptFinal_ex(aesEncryptContext, aesEnc.encrypted + writeIdx, (int *) &blockLength)) {
			logErrorExtended("EVP_EncryptFinal_ex failed");
			break;
		}
		writeIdx += blockLength;
		aesEnc.encryptedLen = writeIdx;

		result = true;
	} while(0);

	if (!result) {
		// convenience: free the result if it's not valid anyway
		freeAESEncrypted(aesEnc);
	}

	if (aesEncryptContext != NULL) {
		EVP_CIPHER_CTX_free(aesEncryptContext);
	}

	return result;
}

void Crypto::freeAESEncrypted(AESEncResult &aesEnc) {
	if (aesEnc.encrypted != NULL) {
		free(aesEnc.encrypted);
		aesEnc.encrypted = NULL;
	}
	if (aesEnc.iv != NULL) {
		free(aesEnc.iv);
		aesEnc.iv = NULL;
	}

	// Secret parts were allocated differently
	if (aesEnc.key != NULL) {
		OPENSSL_free(aesEnc.key);
		aesEnc.key = NULL;
	}
}

bool Crypto::encryptRSA(unsigned char *dataChars, size_t dataLen,
		string encryptPubKeyPath, unsigned char **encryptedCharsPtr, size_t &encryptedLen) {
	RSA *rsaPubKey = NULL;
	EVP_PKEY *rsaPubKeyEVP = NULL;
	EVP_PKEY_CTX *ctx = NULL;
	bool result = false;

	do {
		// 1. Get the RSA public key to encrypt with
		rsaPubKey = loadPubKey(encryptPubKeyPath.c_str());
		if (rsaPubKey == NULL) {
			logError("Failed to load public key at " + encryptPubKeyPath);
			break;
		}

		rsaPubKeyEVP = EVP_PKEY_new();
		if (1 != EVP_PKEY_assign_RSA(rsaPubKeyEVP, rsaPubKey)) {
			logErrorExtended("EVP_PKEY_assign_RSA");
			freePubKey(rsaPubKey); // since it's not tied to EVP key yet
			break;
		}

		// 2. Prepare for encryption
		ctx = EVP_PKEY_CTX_new(rsaPubKeyEVP, NULL);
		if (ctx == NULL) {
			logErrorExtended("EVP_PKEY_CTX_new");
			break;
		}
		if (1 != EVP_PKEY_encrypt_init(ctx)) {
			logErrorExtended("EVP_PKEY_encrypt_init");
			break;
		}
		if (1 != EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING)) {
			logErrorExtended("EVP_PKEY_CTX_set_rsa_padding");
			break;
		}

		// 3. First encrypt to get encryptedLen
		if (1 != EVP_PKEY_encrypt(ctx, NULL, &encryptedLen, (unsigned char *) dataChars, dataLen)) {
			logErrorExtended("EVP_PKEY_encrypt (first)");
			break;
		}

		*encryptedCharsPtr = (unsigned char *) malloc(encryptedLen); // not secret
		if (*encryptedCharsPtr == NULL) {
			logError("malloc for encryptedChars failed" + toString(encryptedLen));
			break;
		}

		if (1 != EVP_PKEY_encrypt(ctx, (unsigned char *) *encryptedCharsPtr, &encryptedLen,
				(unsigned char *) dataChars, AES_KEY_BYTESIZE)) {
			logErrorExtended("EVP_PKEY_encrypt (second)");
			break;
		}

		result = true;
	} while (0);

	if (ctx != NULL) {
		EVP_PKEY_CTX_free(ctx);
	}
	if (rsaPubKeyEVP != NULL) {
		EVP_PKEY_free(rsaPubKeyEVP); // also frees the rsaPubKey
	}

	return result;
}

bool Crypto::verifySignature(string signaturePubKeyPath, char *signatureChars, int signatureLen, string data) {
	RSA *rsaPubKey = NULL;
	EVP_PKEY *rsaPubKeyEVP = NULL;
	EVP_MD_CTX *mdctx = NULL;
	bool result = false;

	do {
		rsaPubKey = loadPubKey(signaturePubKeyPath.c_str());
		if (rsaPubKey == NULL) {
			logError("Failed to load public key at " + signaturePubKeyPath);
			break;
		}

		rsaPubKeyEVP = EVP_PKEY_new();
		if (!EVP_PKEY_assign_RSA(rsaPubKeyEVP, rsaPubKey)) {
			freePubKey(rsaPubKey);
			logErrorExtended("EVP_PKEY_assign_RSA");
			break;
		}

		if (!(mdctx = EVP_MD_CTX_create())) {
			logErrorExtended("EVP_MD_CTX_create");
			break;
		}

		if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, rsaPubKeyEVP)) {
			logErrorExtended("EVP_DigestVerifyInit");
			break;
		}

		if (1 != EVP_DigestVerifyUpdate(mdctx, data.c_str(), data.length())) {
			logErrorExtended("EVP_DigestVerifyUpdate");
			break;
		}

		if (1 != EVP_DigestVerifyFinal(mdctx, (unsigned char *) signatureChars, signatureLen)) {
			logErrorExtended("EVP_DigestVerifyFinal");
			break;
		}

		result = true;
	} while(0);

	if (mdctx) {
		EVP_MD_CTX_destroy(mdctx);
	}

	if (rsaPubKeyEVP) {
		EVP_PKEY_free(rsaPubKeyEVP);
		// freePubKey not needed, already free by EVP_PKEY_free.
	}

	return result;
}

PUBKEY_TYPE Crypto::loadPubKey(const char *filename) {
	FILE *fp = fopen(filename, "rb");
	if (fp == NULL) {
		return NULL;
	}

	RSA *rsa = RSA_new();
	rsa = PEM_read_RSA_PUBKEY(fp, &rsa, NULL, NULL);
	fclose(fp);
	return rsa;
}

void Crypto::freePubKey(PUBKEY_TYPE pubKey) {
	if (pubKey) {
		RSA_free(pubKey);
	}
}

void Crypto::logErrorExtended(const StaticString &prefix) {
	char err[500];
	ERR_load_crypto_strings();
	ERR_error_string(ERR_get_error(), err);
	P_ERROR(prefix << ": " << err);
	ERR_free_strings();
}

#endif

void Crypto::logError(const StaticString &error) {
	P_ERROR(error);
}

} // namespace Passenger

Youez - 2016 - github.com/yon3zu
LinuXploit