eapol.c 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293
  1. /*++
  2. Copyright (c) 2015 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. eapol.c
  9. Abstract:
  10. This module implements support for the Extensible Authentication Protocol
  11. over LAN, which an authentication procedure for joining a LAN or WLAN.
  12. Author:
  13. Chris Stevens 29-Oct-2015
  14. Environment:
  15. Kernel
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. //
  21. // Network layer drivers are supposed to be able to stand on their own (i.e. be
  22. // able to be implemented outside the core net library). For the builtin ones,
  23. // avoid including netcore.h, but still redefine those functions that would
  24. // otherwise generate imports.
  25. //
  26. #define NET80211_API __DLLEXPORT
  27. #include <minoca/kernel/driver.h>
  28. #include <minoca/net/netdrv.h>
  29. #include <minoca/net/net80211.h>
  30. #include <minoca/lib/crypto.h>
  31. #include "eapol.h"
  32. //
  33. // --------------------------------------------------------------------- Macros
  34. //
  35. //
  36. // These macros return the KCK, KEK, and TK from the given PTK.
  37. //
  38. #define EAPOL_PTK_GET_KCK(_Ptk) &((_Ptk)[0])
  39. #define EAPOL_PTK_GET_KEK(_Ptk) &((_Ptk)[EAPOL_KCK_SIZE])
  40. #define EAPOL_PTK_GET_TK(_Ptk) &((_Ptk)[EAPOL_KCK_SIZE + EAPOL_KEK_SIZE])
  41. //
  42. // This macro returns the TK from the given GTK.
  43. //
  44. #define EAPOL_GTK_GET_TK(_Gtk) &((_Gtk)[0])
  45. //
  46. // ---------------------------------------------------------------- Definitions
  47. //
  48. #define EAPOL_ALLOCATION_TAG 0x21706145 // '!paE'
  49. //
  50. // Define the current EAPOL protocol version.
  51. //
  52. #define EAPOL_PROTOCOL_VERSION 2
  53. //
  54. // Define the EAPOL packet types.
  55. //
  56. #define EAPOL_PACKET_TYPE_KEY_FRAME 3
  57. //
  58. // Define the current EAPOL key frame version.
  59. //
  60. #define EAPOL_KEY_FRAME_VERSION 1
  61. //
  62. // Define the EAPOL key frame descriptor types.
  63. //
  64. #define EAPOL_KEY_DESCRIPTOR_TYPE_RSN 2
  65. //
  66. // Define the bits in the EAPOL key information field.
  67. //
  68. #define EAPOL_KEY_INFORMATION_SMK_MESSAGE 0x2000
  69. #define EAPOL_KEY_INFORMATION_ENCRYPTED_KEY_DATA 0x1000
  70. #define EAPOL_KEY_INFORMATION_REQUEST 0x0800
  71. #define EAPOL_KEY_INFORMATION_ERROR 0x0400
  72. #define EAPOL_KEY_INFORMATION_SECURE 0x0200
  73. #define EAPOL_KEY_INFORMATION_MIC_PRESENT 0x0100
  74. #define EAPOL_KEY_INFORMATION_ACK_REQUIRED 0x0080
  75. #define EAPOL_KEY_INFORMATION_INSTALL 0x0040
  76. #define EAPOL_KEY_INFORMATION_TYPE_MASK 0x0008
  77. #define EAPOL_KEY_INFORMATION_TYPE_SHIFT 3
  78. #define EAPOL_KEY_INFORMATION_GROUP 0
  79. #define EAPOL_KEY_INFORMATION_PAIRWISE 1
  80. #define EAPOL_KEY_INFORMATION_VERSION_MASK 0x0007
  81. #define EAPOL_KEY_INFORMATION_VERSION_SHIFT 0
  82. //
  83. // Define the key information versions.
  84. //
  85. #define EAPOL_KEY_VERSION_ARC4_HMAC_MD5 1
  86. #define EAPOL_KEY_VERSION_NIST_AES_HMAC_SHA1_128 2
  87. #define EAPOL_KEY_VERSION_NIST_AES_AES_128_CMAC 3
  88. //
  89. // Define the mask and values for various message types.
  90. //
  91. #define EAPOL_KEY_INFORMATION_MESSAGE_MASK 0x3FC8
  92. #define EAPOL_KEY_INFORMATION_MESSAGE_1 0x0088
  93. #define EAPOL_KEY_INFORMATION_MESSAGE_2 0x0108
  94. #define EAPOL_KEY_INFORMATION_MESSAGE_3 0x13C8
  95. #define EAPOL_KEY_INFORMATION_MESSAGE_4 0x0308
  96. //
  97. // Define the length of the global key counter, in bytes.
  98. //
  99. #define EAPOL_GLOBAL_KEY_COUNTER_SIZE (256 / BITS_PER_BYTE)
  100. //
  101. // Define the size of a nonce, in bytes.
  102. //
  103. #define EAPOL_NONCE_SIZE 32
  104. //
  105. // Define the key IV size, in bytes.
  106. //
  107. #define EAPOL_KEY_IV_SIZE 16
  108. //
  109. // Define the RSC size, in bytes.
  110. //
  111. #define EAPOL_RSC_SIZE 8
  112. //
  113. // Define the default key MIC size, in bytes. This depends on the AKM being
  114. // used, but all AKMs currently have the same MIC size.
  115. //
  116. #define EAPOL_DEFAULT_KEY_MIC_SIZE 16
  117. //
  118. // Define the size of the pairwise master key (PMK), in bytes.
  119. //
  120. #define EAPOL_PMK_SIZE (256 / BITS_PER_BYTE)
  121. //
  122. // Define the size of the key confirmation key (KCK), in bytes.
  123. //
  124. #define EAPOL_KCK_SIZE (128 / BITS_PER_BYTE)
  125. //
  126. // Define the size of the key encryption key (KEK), in bytes.
  127. //
  128. #define EAPOL_KEK_SIZE (128 / BITS_PER_BYTE)
  129. //
  130. // Define the size of the CCMP temporal key (TK), in bytes.
  131. //
  132. #define EAPOL_CCMP_TK_SIZE (128 / BITS_PER_BYTE)
  133. //
  134. // Define the size, in bytes, of the random number used to seed the global key
  135. // counter.
  136. //
  137. #define EAPOL_RANDOM_NUMBER_SIZE (256 / BITS_PER_BYTE)
  138. //
  139. // Define the expected key data encapsulation (KDE) type.
  140. //
  141. #define EAPOL_KDE_TYPE 0xDD
  142. //
  143. // Define the EAPOL KDE selectors (OUI + data type).
  144. //
  145. #define EAPOL_KDE_SELECTOR_GTK 0x000FAC01
  146. #define EAPOL_KDE_SELECTOR_MAC 0x000FAC03
  147. #define EAPOL_KDE_SELECTOR_PMKID 0x000FAC04
  148. #define EAPOL_KDE_SELECTOR_SMK 0x000FAC05
  149. #define EAPOL_KDE_SELECTOR_NONCE 0x000FAC06
  150. #define EAPOL_KDE_SELECTOR_LIFETIME 0x000FAC07
  151. #define EAPOL_KDE_SELECTOR_ERROR 0x000FAC08
  152. #define EAPOL_KDE_SELECTOR_IGTK 0x000FAC09
  153. #define EAPOL_KDE_SELECTOR_KEY_ID 0x000FAC0A
  154. //
  155. // Define the bits for the KDE GTK entry flags.
  156. //
  157. #define EAPOL_KDE_GTK_FLAG_TRANSMIT 0x04
  158. #define EAPOL_KDE_GTK_FLAG_KEY_ID_MASK 0x03
  159. #define EAPOL_KDE_GTK_FLAG_KEY_ID_SHIFT 0
  160. //
  161. // Define the recommended application text to use when generating the global
  162. // key counter.
  163. //
  164. #define EAPOL_GLOBAL_KEY_COUNTER_APPLICATION_TEXT "Init Counter"
  165. #define EAPOL_GLOBAL_KEY_COUNTER_APPLICATION_TEXT_LENGTH \
  166. RtlStringLength(EAPOL_GLOBAL_KEY_COUNTER_APPLICATION_TEXT)
  167. //
  168. // Define the required application text to use when generating the pairwise
  169. // transient key.
  170. //
  171. #define EAPOL_PTK_APPLICATION_TEXT "Pairwise key expansion"
  172. #define EAPOL_PTK_APPLICATION_TEXT_LENGTH \
  173. RtlStringLength(EAPOL_PTK_APPLICATION_TEXT)
  174. //
  175. // Define the initial value for the NIST AES key wrap algorithm.
  176. //
  177. #define EAPOL_NIST_AES_KEY_WRAP_INITIAL_VALUE 0xA6A6A6A6A6A6A6A6
  178. //
  179. // Define the number of steps to perform in the NIST AES key wrap algorithm.
  180. //
  181. #define EAPOL_NIST_AES_KEY_WRAP_STEP_COUNT 6
  182. //
  183. // Define the minimum allowed length of the key data before encryption.
  184. //
  185. #define EAPOL_NIST_AES_MIN_KEY_DATA_LENGTH 16
  186. //
  187. // Define the key data alignment required for NIST AES key wrap encryption.
  188. //
  189. #define EAPOL_NIST_AES_KEY_DATA_ALIGNMENT 8
  190. //
  191. // Define the first padding byte used to align key data for NIST AES key wrap
  192. // encryption.
  193. //
  194. #define EAPOL_NIST_AES_KEY_DATA_PADDING_BYTE 0xDD
  195. //
  196. // Define the size difference between the NIST AES key wrap plaintext and
  197. // cipher text.
  198. //
  199. #define EAPOL_NIST_AES_KEY_DATA_CIPHERTEXT_LENGTH_DELTA 8
  200. //
  201. // Define the size of the data buffer used to generate a PTK using the PRF
  202. // algorithm.
  203. //
  204. #define EAPOL_PTK_DATA_SIZE \
  205. (NET80211_ADDRESS_SIZE * 2) + (EAPOL_NONCE_SIZE * 2)
  206. //
  207. // ------------------------------------------------------ Data Type Definitions
  208. //
  209. typedef enum _EAPOL_MESSAGE_TYPE {
  210. EapolMessageType1,
  211. EapolMessageType2,
  212. EapolMessageType3,
  213. EapolMessageType4
  214. } EAPOL_MESSAGE_TYPE, *PEAPOL_MESSAGE_TYPE;
  215. /*++
  216. Structure Description:
  217. This structure defines an EAPOL packet heeader.
  218. Members:
  219. ProtocolVersion - Stores the current protocol version for the packet.
  220. Should be set to EAPOL_PROTOCOL_VERSION.
  221. Type - Stores the packet type. See EAPOL_PACKET_TYPE_*.
  222. BodyLength - Stores the length of the packet body, in bytes. This does not
  223. include the length of the packet header.
  224. --*/
  225. typedef struct _EAPOL_PACKET_HEADER {
  226. UCHAR ProtocolVersion;
  227. UCHAR Type;
  228. USHORT BodyLength;
  229. } PACKED EAPOL_PACKET_HEADER, *PEAPOL_PACKET_HEADER;
  230. /*++
  231. Structure Description:
  232. This structure defines an EAPOL key frame packet. The optional key data
  233. immediately follows this structure.
  234. Members:
  235. PacketHeader - Stores the standard EAPOL packet header.
  236. DescriptorType - Stores the key frame type. See EAPOL_KEY_DESCRIPTOR_TYPE_*
  237. for definitions.
  238. KeyInformation - Stores a bitmask of key information flags. See
  239. EAPOL_KEY_INFORMATION_* for definitions.
  240. KeyLength - Stores the length of the pairwise temporal key, in bytes.
  241. Together with the KCK and KEK, the temporal key helps to make up the
  242. PTK.
  243. KeyReplayCounter - Stores a sequence number used by the EAPOL protocol to
  244. detect replayed key frames.
  245. KeyNonce - Stores an optional nonce value.
  246. KeyIv - Stores an optional IV to use with the KEK. If used, it is
  247. initialized using the global key counter.
  248. KeyRsc - Stores the receive sequence counter (RSC) for the GTK.
  249. Reserved - Stores a received value.
  250. KeyMic - Stores an option message integrity check (MIC) of the key frame
  251. calculated with the key MIC field initialized to 0. The 802.11
  252. specification indicates that the size of the MIC depends on the
  253. negotiated AKM, but all known AKMs use a 16-byte MIC.
  254. KeyDataLength - Stores the length of the optional key data.
  255. --*/
  256. typedef struct _EAPOL_KEY_FRAME {
  257. EAPOL_PACKET_HEADER PacketHeader;
  258. UCHAR DescriptorType;
  259. USHORT KeyInformation;
  260. USHORT KeyLength;
  261. ULONGLONG KeyReplayCounter;
  262. UCHAR KeyNonce[EAPOL_NONCE_SIZE];
  263. UCHAR KeyIv[EAPOL_KEY_IV_SIZE];
  264. UCHAR KeyRsc[EAPOL_RSC_SIZE];
  265. UCHAR Reserved[8];
  266. UCHAR KeyMic[EAPOL_DEFAULT_KEY_MIC_SIZE];
  267. USHORT KeyDataLength;
  268. } PACKED EAPOL_KEY_FRAME, *PEAPOL_KEY_FRAME;
  269. /*++
  270. Structure Description:
  271. This structure define the EAPOL key data encapsulation. The data
  272. immediately follows this structure.
  273. Members:
  274. Type - Stores the KDE type. Should be set to EAPOL_KDE_TYPE.
  275. Length - Stores the length of the data, in bytes. This includes the OUI,
  276. data type, and data, but not the KDE type and length fields.
  277. OuiDataType - Stores the combined OUI and data type information. See
  278. EAPOL_KDE_SELECTOR_* for definitions.
  279. --*/
  280. typedef struct _EAPOL_KDE {
  281. UCHAR Type;
  282. UCHAR Length;
  283. ULONG OuiDataType;
  284. } PACKED EAPOL_KDE, *PEAPOL_KDE;
  285. /*++
  286. Structure Description:
  287. This structure defines a KDE GTK entry.
  288. Members:
  289. Flags - Stores a bitmask of flags describing the global transient key.
  290. Reserved - Stores a reserved byte.
  291. Gtk - Stores the global transient key.
  292. --*/
  293. typedef struct _EAPOL_KDE_GTK {
  294. UCHAR Flags;
  295. UCHAR Reserved;
  296. UCHAR Gtk[ANYSIZE_ARRAY];
  297. } PACKED EAPOL_KDE_GTK, *PEAPOL_KDE_GTK;
  298. /*++
  299. Structure Description:
  300. This structure defines the information needed for the two nodes
  301. participating in an EAPOL exchange.
  302. Members:
  303. Address - Stores the physical address of the node.
  304. Rsn - Stores the robust security network (RSN) information for the node.
  305. For the local station, this must match the data sent by the association
  306. request. For the remote AP, this must match the data received by the
  307. beacon or probe response.
  308. RsnSize - Stores the size of the RSN information, in bytes.
  309. Nonce - Store the nonce value for the node.
  310. --*/
  311. typedef struct _EAPOL_NODE {
  312. NETWORK_ADDRESS Address;
  313. PUCHAR Rsn;
  314. ULONG RsnSize;
  315. UCHAR Nonce[EAPOL_NONCE_SIZE];
  316. } EAPOL_NODE, *PEAPOL_NODE;
  317. /*++
  318. Structure Description:
  319. This structure defines the context of an EAPOL instance.
  320. Members:
  321. TreeEntry - Stores the red black tree information for this node.
  322. Mode - Stores the mode for this EAPOL instance.
  323. ReferenceCount - Stores the reference count of the EAPOL link context.
  324. NetworkLink - Stores a pointer to the network link associated with this
  325. EAPOL entry.
  326. Net80211Link - Stores a pointer to the 802.11 link associated with this
  327. EAPOL entry.
  328. Lock - Stores a pointer to a queued lock that protects access to the global
  329. key counter.
  330. CompletionRoutine - Stores a pointer to the completion routine.
  331. CompletionContext - Stores a pointer to the completion context.
  332. Supplicant - Stores all the node-specific information for the supplicant
  333. node.
  334. Authenticator - Stores all the node-speficic information for the
  335. authenticating node.
  336. GlobalKeyCounter - Stores the 256-bit global key counter for the link.
  337. Pmk - Stores the pairwise master key for the link.
  338. Ptk - Stores the pairwise transient key for the link.
  339. PtkSize - Stores the size of the PTK, in bytes.
  340. Gtk - Stores the group temporal key.
  341. GtkFlags - Stores a bitmask of flags for the GTK. See EAPOL_KDE_GTK_FLAG_*
  342. for definitions.
  343. GtkSize - Stores the size of the GTK, in bytes.
  344. TemporalKeySize - Stores the size of the temporal key, in bytes.
  345. KeyReplayCounterValid - Stores a boolean indicating whether or not the key
  346. replay counter is valid. It is not valid on a supplicant until the
  347. first valid key frame (with a MIC) is received from the authenticator.
  348. KeyReplayCounter - Stores the next expected key replay counter.
  349. KeyVersion - Stores the key version indicated by the authenticator in
  350. message 1.
  351. --*/
  352. typedef struct _EAPOL_CONTEXT {
  353. RED_BLACK_TREE_NODE TreeEntry;
  354. EAPOL_MODE Mode;
  355. volatile ULONG ReferenceCount;
  356. PNET_LINK NetworkLink;
  357. PNET80211_LINK Net80211Link;
  358. PQUEUED_LOCK Lock;
  359. PEAPOL_COMPLETION_ROUTINE CompletionRoutine;
  360. PVOID CompletionContext;
  361. EAPOL_NODE Supplicant;
  362. EAPOL_NODE Authenticator;
  363. UCHAR GlobalKeyCounter[EAPOL_GLOBAL_KEY_COUNTER_SIZE];
  364. UCHAR Pmk[EAPOL_PMK_SIZE];
  365. PUCHAR Ptk;
  366. ULONG PtkSize;
  367. PUCHAR Gtk;
  368. ULONG GtkFlags;
  369. ULONG GtkSize;
  370. ULONG TemporalKeySize;
  371. BOOL KeyReplayCounterValid;
  372. ULONGLONG KeyReplayCounter;
  373. ULONG KeyVersion;
  374. } EAPOL_CONTEXT, *PEAPOL_CONTEXT;
  375. //
  376. // ----------------------------------------------- Internal Function Prototypes
  377. //
  378. KSTATUS
  379. Net80211pEapolInitializeLink (
  380. PNET_LINK Link
  381. );
  382. VOID
  383. Net80211pEapolDestroyLink (
  384. PNET_LINK Link
  385. );
  386. VOID
  387. Net80211pEapolProcessReceivedData (
  388. PNET_LINK Link,
  389. PNET_PACKET_BUFFER Packet
  390. );
  391. ULONG
  392. Net80211pEapolPrintAddress (
  393. PNETWORK_ADDRESS Address,
  394. PSTR Buffer,
  395. ULONG BufferLength
  396. );
  397. VOID
  398. Net80211pEapolSupplicantReceiveMessage (
  399. PEAPOL_CONTEXT Context,
  400. PEAPOL_KEY_FRAME KeyFrame
  401. );
  402. KSTATUS
  403. Net80211pEapolSupplicantSendMessage (
  404. PEAPOL_CONTEXT Context,
  405. EAPOL_MESSAGE_TYPE Type,
  406. ULONGLONG KeyReplayCounter
  407. );
  408. VOID
  409. Net80211pEapolReadGlobalKeyCounter (
  410. PEAPOL_CONTEXT Context,
  411. PUCHAR Buffer,
  412. ULONG BufferLength
  413. );
  414. KSTATUS
  415. Net80211pEapolConvertPassphraseToPsk (
  416. PUCHAR Passphrase,
  417. ULONG PassphraseLength,
  418. PUCHAR Ssid,
  419. ULONG SsidLength,
  420. PUCHAR Psk,
  421. ULONG PskLength
  422. );
  423. KSTATUS
  424. Net80211pGeneratePtk (
  425. PEAPOL_CONTEXT Context,
  426. ULONG TemporalKeyLength
  427. );
  428. KSTATUS
  429. Net80211pEapolEncryptKeyData (
  430. PEAPOL_CONTEXT Context,
  431. PUCHAR KeyData,
  432. ULONG KeyDataLength,
  433. PUCHAR *EncryptedKeyData,
  434. PULONG EncryptedKeyDataLength
  435. );
  436. KSTATUS
  437. Net80211pEapolDecryptKeyData (
  438. PEAPOL_CONTEXT Context,
  439. PUCHAR EncryptedKeyData,
  440. ULONG EncryptedKeyDataLength,
  441. PUCHAR *KeyData,
  442. PULONG KeyDataLength
  443. );
  444. VOID
  445. Net80211pEapolComputeMic (
  446. PEAPOL_CONTEXT Context,
  447. PEAPOL_KEY_FRAME KeyFrame
  448. );
  449. BOOL
  450. Net80211pEapolValidateMic (
  451. PEAPOL_CONTEXT Context,
  452. PEAPOL_KEY_FRAME KeyFrame
  453. );
  454. VOID
  455. Net80211pEapolNistAesKeyWrap (
  456. PUCHAR KeyData,
  457. ULONG KeyDataLength,
  458. PUCHAR Key,
  459. ULONG KeyLength,
  460. PUCHAR EncryptedKeyData,
  461. ULONG EncryptedKeyDataLength
  462. );
  463. KSTATUS
  464. Net80211pEapolNistAesKeyUnwrap (
  465. PUCHAR EncryptedKeyData,
  466. ULONG EncryptedKeyDataLength,
  467. PUCHAR Key,
  468. ULONG KeyLength,
  469. PUCHAR KeyData,
  470. ULONG KeyDataLength
  471. );
  472. KSTATUS
  473. Net80211pEapolPseudoRandomFunction (
  474. PUCHAR Key,
  475. ULONG KeyLength,
  476. PSTR ApplicationText,
  477. ULONG ApplicationTextLength,
  478. PUCHAR Data,
  479. ULONG DataLength,
  480. PUCHAR Output,
  481. ULONG OutputLength
  482. );
  483. COMPARISON_RESULT
  484. Net80211pEapolCompareMemory (
  485. PUCHAR FirstAddress,
  486. PUCHAR SecondAddress,
  487. ULONG AddressSize
  488. );
  489. COMPARISON_RESULT
  490. Net80211pEapolCompareContexts (
  491. PRED_BLACK_TREE Tree,
  492. PRED_BLACK_TREE_NODE FirstNode,
  493. PRED_BLACK_TREE_NODE SecondNode
  494. );
  495. VOID
  496. Net80211pEapolContextAddReference (
  497. PEAPOL_CONTEXT Context
  498. );
  499. VOID
  500. Net80211pEapolContextReleaseReference (
  501. PEAPOL_CONTEXT Context
  502. );
  503. VOID
  504. Net80211pEapolDestroyContext (
  505. PEAPOL_CONTEXT Context
  506. );
  507. VOID
  508. Net80211pEapolCompleteInstance (
  509. PEAPOL_CONTEXT Context,
  510. KSTATUS CompletionStatus
  511. );
  512. //
  513. // -------------------------------------------------------------------- Globals
  514. //
  515. BOOL Net80211EapolDebug;
  516. //
  517. // Store a global tree of all the contexts that are actively looking for EAPOL
  518. // frames.
  519. //
  520. RED_BLACK_TREE Net80211EapolTree;
  521. PQUEUED_LOCK Net80211EapolTreeLock;
  522. //
  523. // Store the handle to the registered EAPOL network layer.
  524. //
  525. HANDLE Net80211EapolNetworkHandle = INVALID_HANDLE;
  526. //
  527. // ------------------------------------------------------------------ Functions
  528. //
  529. KSTATUS
  530. Net80211pEapolInitialize (
  531. VOID
  532. )
  533. /*++
  534. Routine Description:
  535. This routine initializes support for EAPOL packets.
  536. Arguments:
  537. None.
  538. Return Value:
  539. Status code.
  540. --*/
  541. {
  542. NET_NETWORK_ENTRY NetworkEntry;
  543. KSTATUS Status;
  544. if (Net80211EapolDebug == FALSE) {
  545. Net80211EapolDebug = NetGetGlobalDebugFlag();
  546. }
  547. RtlRedBlackTreeInitialize(&Net80211EapolTree,
  548. 0,
  549. Net80211pEapolCompareContexts);
  550. Net80211EapolTreeLock = KeCreateQueuedLock();
  551. if (Net80211EapolTreeLock == FALSE) {
  552. Status = STATUS_INSUFFICIENT_RESOURCES;
  553. goto EapolInitializeEnd;
  554. }
  555. //
  556. // Register the EAPOL handlers with the core networking library.
  557. //
  558. RtlZeroMemory(&NetworkEntry, sizeof(NET_NETWORK_ENTRY));
  559. NetworkEntry.Domain = NetDomainEapol;
  560. NetworkEntry.ParentProtocolNumber = EAPOL_PROTOCOL_NUMBER;
  561. NetworkEntry.Interface.InitializeLink = Net80211pEapolInitializeLink;
  562. NetworkEntry.Interface.DestroyLink = Net80211pEapolDestroyLink;
  563. NetworkEntry.Interface.ProcessReceivedData =
  564. Net80211pEapolProcessReceivedData;
  565. NetworkEntry.Interface.PrintAddress = Net80211pEapolPrintAddress;
  566. Status = NetRegisterNetworkLayer(&NetworkEntry,
  567. &Net80211EapolNetworkHandle);
  568. if (!KSUCCESS(Status)) {
  569. ASSERT(FALSE);
  570. goto EapolInitializeEnd;
  571. }
  572. EapolInitializeEnd:
  573. return Status;
  574. }
  575. VOID
  576. Net80211pEapolDestroy (
  577. VOID
  578. )
  579. /*++
  580. Routine Description:
  581. This routine tears down support for EAPOL packets.
  582. Arguments:
  583. None.
  584. Return Value:
  585. None.
  586. --*/
  587. {
  588. ASSERT(RED_BLACK_TREE_EMPTY(&Net80211EapolTree) != FALSE);
  589. if (Net80211EapolTreeLock != NULL) {
  590. KeDestroyQueuedLock(Net80211EapolTreeLock);
  591. Net80211EapolTreeLock = NULL;
  592. }
  593. if (Net80211EapolNetworkHandle != INVALID_HANDLE) {
  594. NetUnregisterNetworkLayer(Net80211EapolNetworkHandle);
  595. }
  596. return;
  597. }
  598. KSTATUS
  599. Net80211pEapolCreateInstance (
  600. PEAPOL_CREATION_PARAMETERS Parameters,
  601. PHANDLE EapolHandle
  602. )
  603. /*++
  604. Routine Description:
  605. This routine creates an EAPOL instance through which a session's private
  606. key will be derived. The caller can indicate if it intends to be the
  607. supplicant or the authenticator in the parameters.
  608. Arguments:
  609. Parameters - Supplies a pointer to the EAPOL instance creation parameters.
  610. EapolHandle - Supplies a pointer that receives a handle to the created
  611. EAPOL instance.
  612. Return Value:
  613. Status code.
  614. --*/
  615. {
  616. ULONG AllocationSize;
  617. PEAPOL_CONTEXT Context;
  618. UCHAR Data[NET80211_ADDRESS_SIZE + sizeof(SYSTEM_TIME)];
  619. UCHAR RandomNumber[EAPOL_RANDOM_NUMBER_SIZE];
  620. KSTATUS Status;
  621. SYSTEM_TIME SystemTime;
  622. Context = NULL;
  623. *EapolHandle = INVALID_HANDLE;
  624. //
  625. // Check for valid parameters.
  626. //
  627. if ((Parameters->NetworkLink == NULL) ||
  628. (Parameters->Net80211Link == NULL) ||
  629. (Parameters->SupplicantAddress == NULL) ||
  630. (Parameters->AuthenticatorAddress == NULL) ||
  631. (Parameters->Ssid == NULL) ||
  632. (Parameters->SsidLength <= 1) ||
  633. (Parameters->Passphrase == NULL) ||
  634. (Parameters->PassphraseLength == 0) ||
  635. (Parameters->SupplicantRsn == NULL) ||
  636. (Parameters->SupplicantRsnSize == 0) ||
  637. (Parameters->AuthenticatorRsn == NULL) ||
  638. (Parameters->AuthenticatorRsnSize == 0) ||
  639. (Parameters->CompletionRoutine == NULL)) {
  640. Status = STATUS_INVALID_PARAMETER;
  641. goto CreateEnd;
  642. }
  643. //
  644. // Allocate a context for this EAPOL instance.
  645. //
  646. AllocationSize = sizeof(EAPOL_CONTEXT) +
  647. Parameters->SupplicantRsnSize +
  648. Parameters->AuthenticatorRsnSize;
  649. Context = MmAllocatePagedPool(AllocationSize, EAPOL_ALLOCATION_TAG);
  650. if (Context == NULL) {
  651. Status = STATUS_INSUFFICIENT_RESOURCES;
  652. goto CreateEnd;
  653. }
  654. RtlZeroMemory(Context, sizeof(EAPOL_CONTEXT));
  655. NetLinkAddReference(Parameters->NetworkLink);
  656. Net80211LinkAddReference(Parameters->Net80211Link);
  657. Context->ReferenceCount = 1;
  658. Context->Mode = Parameters->Mode;
  659. Context->NetworkLink = Parameters->NetworkLink;
  660. Context->Net80211Link = Parameters->Net80211Link;
  661. Context->CompletionRoutine = Parameters->CompletionRoutine;
  662. Context->CompletionContext = Parameters->CompletionContext;
  663. Context->Lock = KeCreateQueuedLock();
  664. if (Context->Lock == NULL) {
  665. Status = STATUS_INSUFFICIENT_RESOURCES;
  666. goto CreateEnd;
  667. }
  668. //
  669. // Copy both the supplicant and authenticator addresses to the context.
  670. //
  671. RtlCopyMemory(&(Context->Supplicant.Address),
  672. Parameters->SupplicantAddress,
  673. sizeof(NETWORK_ADDRESS));
  674. RtlCopyMemory(&(Context->Authenticator.Address),
  675. Parameters->AuthenticatorAddress,
  676. sizeof(NETWORK_ADDRESS));
  677. //
  678. // Copy the RSN information for the supplicant and authenticator to the end
  679. // of the context.
  680. //
  681. Context->Supplicant.Rsn = (PUCHAR)(Context + 1);
  682. RtlCopyMemory(Context->Supplicant.Rsn,
  683. Parameters->SupplicantRsn,
  684. Parameters->SupplicantRsnSize);
  685. Context->Supplicant.RsnSize = Parameters->SupplicantRsnSize;
  686. Context->Authenticator.Rsn = Context->Supplicant.Rsn +
  687. Context->Supplicant.RsnSize;
  688. RtlCopyMemory(Context->Authenticator.Rsn,
  689. Parameters->AuthenticatorRsn,
  690. Parameters->AuthenticatorRsnSize);
  691. Context->Authenticator.RsnSize = Parameters->AuthenticatorRsnSize;
  692. //
  693. // Concatenate the local MAC address with the current time to use as the
  694. // data portion for global key counter generation.
  695. //
  696. if (Context->Mode == EapolModeSupplicant) {
  697. ASSERT(Context->Supplicant.Address.Domain == NetDomain80211);
  698. RtlCopyMemory(Data,
  699. Context->Supplicant.Address.Address,
  700. NET80211_ADDRESS_SIZE);
  701. Context->KeyReplayCounterValid = FALSE;
  702. } else {
  703. ASSERT(Context->Mode == EapolModeAuthenticator);
  704. ASSERT(Context->Authenticator.Address.Domain == NetDomain80211);
  705. RtlCopyMemory(Data,
  706. Context->Authenticator.Address.Address,
  707. NET80211_ADDRESS_SIZE);
  708. Context->KeyReplayCounterValid = TRUE;
  709. }
  710. KeGetSystemTime(&SystemTime);
  711. RtlCopyMemory(&(Data[NET80211_ADDRESS_SIZE]),
  712. &SystemTime,
  713. sizeof(SYSTEM_TIME));
  714. //
  715. // Generate a random number to use as the key for global key counter
  716. // generation.
  717. //
  718. Status = KeGetRandomBytes(RandomNumber, EAPOL_RANDOM_NUMBER_SIZE);
  719. if (!KSUCCESS(Status)) {
  720. goto CreateEnd;
  721. }
  722. //
  723. // Initialize the global key counter for this link.
  724. //
  725. Status = Net80211pEapolPseudoRandomFunction(
  726. RandomNumber,
  727. EAPOL_RANDOM_NUMBER_SIZE,
  728. EAPOL_GLOBAL_KEY_COUNTER_APPLICATION_TEXT,
  729. EAPOL_GLOBAL_KEY_COUNTER_APPLICATION_TEXT_LENGTH,
  730. Data,
  731. NET80211_ADDRESS_SIZE + sizeof(SYSTEM_TIME),
  732. Context->GlobalKeyCounter,
  733. EAPOL_GLOBAL_KEY_COUNTER_SIZE);
  734. if (!KSUCCESS(Status)) {
  735. goto CreateEnd;
  736. }
  737. //
  738. // Generate a nonce for the supplicant.
  739. //
  740. Net80211pEapolReadGlobalKeyCounter(Context,
  741. Context->Supplicant.Nonce,
  742. EAPOL_NONCE_SIZE);
  743. //
  744. // If the passphrase is less than the size of the PMK, then it needs to be
  745. // converted into the PMK, which is the PSK in this case.
  746. //
  747. if (Parameters->PassphraseLength < EAPOL_PMK_SIZE) {
  748. Status = Net80211pEapolConvertPassphraseToPsk(
  749. Parameters->Passphrase,
  750. Parameters->PassphraseLength,
  751. Parameters->Ssid,
  752. Parameters->SsidLength,
  753. Context->Pmk,
  754. EAPOL_PMK_SIZE);
  755. if (!KSUCCESS(Status)) {
  756. goto CreateEnd;
  757. }
  758. //
  759. // Otherwise the given passphrase is the PMK.
  760. //
  761. } else {
  762. RtlCopyMemory(Context->Pmk, Parameters->Passphrase, EAPOL_PMK_SIZE);
  763. }
  764. //
  765. // Insert the EAPOL context into the global tree.
  766. //
  767. KeAcquireQueuedLock(Net80211EapolTreeLock);
  768. RtlRedBlackTreeInsert(&Net80211EapolTree, &(Context->TreeEntry));
  769. KeReleaseQueuedLock(Net80211EapolTreeLock);
  770. Status = STATUS_SUCCESS;
  771. *EapolHandle = Context;
  772. CreateEnd:
  773. if (!KSUCCESS(Status)) {
  774. if (Context != NULL) {
  775. Net80211pEapolContextReleaseReference(Context);
  776. Context = NULL;
  777. }
  778. }
  779. return Status;
  780. }
  781. VOID
  782. Net80211pEapolDestroyInstance (
  783. HANDLE EapolHandle
  784. )
  785. /*++
  786. Routine Description:
  787. This routine destroys the given EAPOL instance.
  788. Arguments:
  789. EapolHandle - Supplies the handle to the EAPOL instance to destroy.
  790. Return Value:
  791. None.
  792. --*/
  793. {
  794. PEAPOL_CONTEXT Context;
  795. Context = (PEAPOL_CONTEXT)EapolHandle;
  796. //
  797. // Remove the instance's context from the global tree so that it can no
  798. // longer process packets.
  799. //
  800. KeAcquireQueuedLock(Net80211EapolTreeLock);
  801. if (Context->TreeEntry.Parent != NULL) {
  802. RtlRedBlackTreeRemove(&Net80211EapolTree, &(Context->TreeEntry));
  803. Context->TreeEntry.Parent = NULL;
  804. }
  805. KeReleaseQueuedLock(Net80211EapolTreeLock);
  806. Net80211pEapolContextReleaseReference(Context);
  807. return;
  808. }
  809. //
  810. // --------------------------------------------------------- Internal Functions
  811. //
  812. KSTATUS
  813. Net80211pEapolInitializeLink (
  814. PNET_LINK Link
  815. )
  816. /*++
  817. Routine Description:
  818. This routine initializes any pieces of information needed by the network
  819. layer for a new link.
  820. Arguments:
  821. Link - Supplies a pointer to the new link.
  822. Return Value:
  823. Status code.
  824. --*/
  825. {
  826. return STATUS_SUCCESS;
  827. }
  828. VOID
  829. Net80211pEapolDestroyLink (
  830. PNET_LINK Link
  831. )
  832. /*++
  833. Routine Description:
  834. This routine allows the network layer to tear down any state before a link
  835. is destroyed.
  836. Arguments:
  837. Link - Supplies a pointer to the dying link.
  838. Return Value:
  839. None.
  840. --*/
  841. {
  842. return;
  843. }
  844. VOID
  845. Net80211pEapolProcessReceivedData (
  846. PNET_LINK Link,
  847. PNET_PACKET_BUFFER Packet
  848. )
  849. /*++
  850. Routine Description:
  851. This routine is called to process a received packet.
  852. Arguments:
  853. Link - Supplies a pointer to the link that received the packet.
  854. Packet - Supplies a pointer to a structure describing the incoming packet.
  855. This structure may be used as a scratch space while this routine
  856. executes and the packet travels up the stack, but will not be accessed
  857. after this routine returns.
  858. Return Value:
  859. None. When the function returns, the memory associated with the packet may
  860. be reclaimed and reused.
  861. --*/
  862. {
  863. PEAPOL_CONTEXT Context;
  864. PRED_BLACK_TREE_NODE FoundNode;
  865. PEAPOL_KEY_FRAME KeyFrame;
  866. USHORT PacketBodyLength;
  867. EAPOL_CONTEXT SearchEntry;
  868. //
  869. // Lookup to see if this is link is registered for an authentication
  870. // sequence. Take a reference on a found context while holding the lock to
  871. // guarantee it does not get destroyed while processing the packet.
  872. //
  873. Context = NULL;
  874. SearchEntry.NetworkLink = Link;
  875. KeAcquireQueuedLock(Net80211EapolTreeLock);
  876. FoundNode = RtlRedBlackTreeSearch(&Net80211EapolTree,
  877. &(SearchEntry.TreeEntry));
  878. if (FoundNode != NULL) {
  879. Context = RED_BLACK_TREE_VALUE(FoundNode, EAPOL_CONTEXT, TreeEntry);
  880. Net80211pEapolContextAddReference(Context);
  881. }
  882. KeReleaseQueuedLock(Net80211EapolTreeLock);
  883. //
  884. // If no context was found, drop the packet.
  885. //
  886. if (Context == NULL) {
  887. if (Net80211EapolDebug != FALSE) {
  888. RtlDebugPrint("EAPOL: Failed to find entry for link 0x%08x. "
  889. "Dropping packet.\n",
  890. Link);
  891. }
  892. goto ProcessReceivedDataEnd;
  893. }
  894. //
  895. // Validate the packet header.
  896. //
  897. KeyFrame = Packet->Buffer + Packet->DataOffset;
  898. if (KeyFrame->PacketHeader.ProtocolVersion > EAPOL_PROTOCOL_VERSION) {
  899. RtlDebugPrint("EAPOL: Version mismatch. Received %d, expected %d.\n",
  900. KeyFrame->PacketHeader.ProtocolVersion,
  901. EAPOL_PROTOCOL_VERSION);
  902. goto ProcessReceivedDataEnd;
  903. }
  904. if (KeyFrame->PacketHeader.Type != EAPOL_PACKET_TYPE_KEY_FRAME) {
  905. RtlDebugPrint("EAPOL: Unexpected EAPOL packet type %d\n",
  906. KeyFrame->PacketHeader.Type);
  907. goto ProcessReceivedDataEnd;
  908. }
  909. PacketBodyLength = NETWORK_TO_CPU16(KeyFrame->PacketHeader.BodyLength);
  910. if ((PacketBodyLength + sizeof(EAPOL_PACKET_HEADER)) >
  911. (Packet->FooterOffset - Packet->DataOffset)) {
  912. RtlDebugPrint("EAPOL: Invalid length %d is bigger than packet data, "
  913. "which is only %d bytes.\n",
  914. PacketBodyLength + sizeof(EAPOL_PACKET_HEADER),
  915. (Packet->FooterOffset - Packet->DataOffset));
  916. goto ProcessReceivedDataEnd;
  917. }
  918. //
  919. // The packet body should at least be the size of an EAPOL key frame, minus
  920. // the packet header.
  921. //
  922. if (PacketBodyLength <
  923. (sizeof(EAPOL_KEY_FRAME) - sizeof(EAPOL_PACKET_HEADER))) {
  924. RtlDebugPrint("EAPOL: Invalid packet length %d that does not at least "
  925. "hold a key frame of size %d.\n",
  926. PacketBodyLength,
  927. sizeof(EAPOL_KEY_FRAME) - sizeof(EAPOL_PACKET_HEADER));
  928. goto ProcessReceivedDataEnd;
  929. }
  930. //
  931. // EAPOL currnetly supports the 802.11 RSN key descriptor.
  932. //
  933. if (KeyFrame->DescriptorType != EAPOL_KEY_DESCRIPTOR_TYPE_RSN) {
  934. RtlDebugPrint("EAPOL: Unsupported key frame descriptor type %d\n",
  935. KeyFrame->DescriptorType);
  936. goto ProcessReceivedDataEnd;
  937. }
  938. //
  939. // Parse the key frame based on the mode.
  940. //
  941. if (Context->Mode == EapolModeSupplicant) {
  942. Net80211pEapolSupplicantReceiveMessage(Context, KeyFrame);
  943. } else {
  944. RtlDebugPrint("EAPOL: Packet arrived for unsupported mode %d.\n",
  945. Context->Mode);
  946. }
  947. ProcessReceivedDataEnd:
  948. if (Context != NULL) {
  949. Net80211pEapolContextReleaseReference(Context);
  950. }
  951. return;
  952. }
  953. ULONG
  954. Net80211pEapolPrintAddress (
  955. PNETWORK_ADDRESS Address,
  956. PSTR Buffer,
  957. ULONG BufferLength
  958. )
  959. /*++
  960. Routine Description:
  961. This routine is called to convert a network address into a string, or
  962. determine the length of the buffer needed to convert an address into a
  963. string.
  964. Arguments:
  965. Address - Supplies an optional pointer to a network address to convert to
  966. a string.
  967. Buffer - Supplies an optional pointer where the string representation of
  968. the address will be returned.
  969. BufferLength - Supplies the length of the supplied buffer, in bytes.
  970. Return Value:
  971. Returns the maximum length of any address if no network address is
  972. supplied.
  973. Returns the actual length of the network address string if a network address
  974. was supplied, including the null terminator.
  975. --*/
  976. {
  977. //
  978. // There is no such thing as an EAPOL address. The packets destination is
  979. // determined by the data link layer.
  980. //
  981. return 0;
  982. }
  983. VOID
  984. Net80211pEapolSupplicantReceiveMessage (
  985. PEAPOL_CONTEXT Context,
  986. PEAPOL_KEY_FRAME KeyFrame
  987. )
  988. /*++
  989. Routine Description:
  990. This routine processes a message key frame received by an EAPOL supplicant.
  991. Arguments:
  992. Context - Supplies a pointer to the EAPOL supplicant context processing the
  993. key frame.
  994. KeyFrame - Supplies a pointer to a key frame sent to the supplicant that
  995. needs to be processed.
  996. Return Value:
  997. None.
  998. --*/
  999. {
  1000. BOOL CompleteExchange;
  1001. KSTATUS CompletionStatus;
  1002. PUCHAR EncryptedKeyData;
  1003. USHORT EncryptedKeyDataLength;
  1004. ULONG GtkLength;
  1005. PEAPOL_KDE Kde;
  1006. PEAPOL_KDE_GTK KdeGtk;
  1007. ULONG KdeOuiDataType;
  1008. PUCHAR KeyData;
  1009. ULONG KeyDataLength;
  1010. USHORT KeyInformation;
  1011. USHORT KeyLength;
  1012. ULONGLONG KeyReplayCounter;
  1013. ULONG KeyVersion;
  1014. BOOL Match;
  1015. USHORT MessageType;
  1016. KSTATUS Status;
  1017. BOOL ValidMic;
  1018. ASSERT(Context->Mode == EapolModeSupplicant);
  1019. CompleteExchange = FALSE;
  1020. CompletionStatus = STATUS_SUCCESS;
  1021. KeyData = NULL;
  1022. //
  1023. // Synchronize with other packets arriving for this EAPOL context.
  1024. //
  1025. KeAcquireQueuedLock(Context->Lock);
  1026. //
  1027. // If this context has already been removed from the tree, then a previous
  1028. // packet completed it.
  1029. //
  1030. if (Context->TreeEntry.Parent == NULL) {
  1031. goto SupplicantProcessKeyFrameEnd;
  1032. }
  1033. //
  1034. // Make sure the replay counter has not been used. It should be greater
  1035. // than the current replay counter. The local key replay counter, however,
  1036. // is not valid until a message with a MIC is received.
  1037. //
  1038. KeyReplayCounter = NETWORK_TO_CPU64(KeyFrame->KeyReplayCounter);
  1039. if ((Context->KeyReplayCounterValid != FALSE) &&
  1040. (KeyReplayCounter <= Context->KeyReplayCounter)) {
  1041. RtlDebugPrint("EAPOL: Skipping key frame with old replay counter "
  1042. "%I64d. Expected %I64d or greater.\n",
  1043. KeyReplayCounter,
  1044. Context->KeyReplayCounter);
  1045. goto SupplicantProcessKeyFrameEnd;
  1046. }
  1047. //
  1048. // Act based on the message type. Even though a previous message 1 has been
  1049. // received and replied to with a message 2, if this supplicant receives a
  1050. // message 1 it should go through the same reply process and forget the old
  1051. // message 1 ever arrived. The message # can be determined by the key
  1052. // information.
  1053. //
  1054. KeyInformation = NETWORK_TO_CPU16(KeyFrame->KeyInformation);
  1055. KeyVersion = (KeyInformation & EAPOL_KEY_INFORMATION_VERSION_MASK) >>
  1056. EAPOL_KEY_INFORMATION_VERSION_SHIFT;
  1057. MessageType = KeyInformation & EAPOL_KEY_INFORMATION_MESSAGE_MASK;
  1058. switch (MessageType) {
  1059. case EAPOL_KEY_INFORMATION_MESSAGE_1:
  1060. //
  1061. // Save the nonce sent from the authenticator.
  1062. //
  1063. RtlCopyMemory(Context->Authenticator.Nonce,
  1064. KeyFrame->KeyNonce,
  1065. EAPOL_NONCE_SIZE);
  1066. //
  1067. // Derive the pairwise transient key (PTK) for this link. The length of
  1068. // the temporal key portion of the PTK is indicated by the AP.
  1069. //
  1070. KeyLength = NETWORK_TO_CPU16(KeyFrame->KeyLength);
  1071. Status = Net80211pGeneratePtk(Context, KeyLength);
  1072. if (!KSUCCESS(Status)) {
  1073. goto SupplicantProcessKeyFrameEnd;
  1074. }
  1075. //
  1076. // Save the key version for use in sending message 2 and parsing
  1077. // message 3.
  1078. //
  1079. Context->KeyVersion = KeyVersion;
  1080. //
  1081. // Send message 2 back to the authenticator.
  1082. //
  1083. Status = Net80211pEapolSupplicantSendMessage(Context,
  1084. EapolMessageType2,
  1085. KeyReplayCounter);
  1086. if (!KSUCCESS(Status)) {
  1087. RtlDebugPrint("EAPOL: Failed to send supplicant message 2: %d.\n",
  1088. Status);
  1089. goto SupplicantProcessKeyFrameEnd;
  1090. }
  1091. break;
  1092. case EAPOL_KEY_INFORMATION_MESSAGE_3:
  1093. //
  1094. // Validate the version matches that of message 1.
  1095. //
  1096. if (Context->KeyVersion != KeyVersion) {
  1097. RtlDebugPrint("EAPOL: Found unexpected key version in message 3. "
  1098. "Expected %d, received %d.\n",
  1099. Context->KeyVersion,
  1100. KeyVersion);
  1101. goto SupplicantProcessKeyFrameEnd;
  1102. }
  1103. //
  1104. // Make sure the authenticator's nonce matches that of message 1.
  1105. //
  1106. Match = RtlCompareMemory(KeyFrame->KeyNonce,
  1107. Context->Authenticator.Nonce,
  1108. EAPOL_NONCE_SIZE);
  1109. if (Match == FALSE) {
  1110. RtlDebugPrint("EAPOL: Mismatching nonce from authenticator in "
  1111. "message 3.\n");
  1112. goto SupplicantProcessKeyFrameEnd;
  1113. }
  1114. //
  1115. // Decrypt the key data and validate the RSN information for the
  1116. // authenticator.
  1117. //
  1118. EncryptedKeyDataLength = NETWORK_TO_CPU16(KeyFrame->KeyDataLength);
  1119. if (EncryptedKeyDataLength == 0) {
  1120. RtlDebugPrint("EAPOL: Supplicant expected encrypted key data in "
  1121. "message 3, but found no key data.\n");
  1122. goto SupplicantProcessKeyFrameEnd;
  1123. }
  1124. EncryptedKeyData = (PUCHAR)(KeyFrame + 1);
  1125. Status = Net80211pEapolDecryptKeyData(Context,
  1126. EncryptedKeyData,
  1127. EncryptedKeyDataLength,
  1128. &KeyData,
  1129. &KeyDataLength);
  1130. if (!KSUCCESS(Status)) {
  1131. goto SupplicantProcessKeyFrameEnd;
  1132. }
  1133. //
  1134. // Compare the decrypted key data with the RSN from the beacon/probe.
  1135. //
  1136. Match = RtlCompareMemory(KeyData,
  1137. Context->Authenticator.Rsn,
  1138. Context->Authenticator.RsnSize);
  1139. if (Match == FALSE) {
  1140. RtlDebugPrint("EAPOL: Mismatching encrypted RSN in message 3.\n");
  1141. CompleteExchange = TRUE;
  1142. CompletionStatus = STATUS_UNSUCCESSFUL;
  1143. goto SupplicantProcessKeyFrameEnd;
  1144. }
  1145. //
  1146. // Validate the MIC. If it is not valid, drop the packet.
  1147. //
  1148. ValidMic = Net80211pEapolValidateMic(Context, KeyFrame);
  1149. if (ValidMic == FALSE) {
  1150. goto SupplicantProcessKeyFrameEnd;
  1151. }
  1152. //
  1153. // Parse the rest of the decrypted key data to see if an GTK was
  1154. // supplied.
  1155. //
  1156. KeyDataLength -= Context->Authenticator.RsnSize;
  1157. Kde = (PEAPOL_KDE)(KeyData + Context->Authenticator.RsnSize);
  1158. if ((KeyDataLength >= sizeof(EAPOL_KDE)) &&
  1159. (Kde->Type == EAPOL_KDE_TYPE)) {
  1160. KdeOuiDataType = NETWORK_TO_CPU32(Kde->OuiDataType);
  1161. switch (KdeOuiDataType) {
  1162. case EAPOL_KDE_SELECTOR_GTK:
  1163. GtkLength = Kde->Length - 6;
  1164. if ((GtkLength > Kde->Length) || (GtkLength == 0)) {
  1165. break;
  1166. }
  1167. //
  1168. // The length should match the key data length specified in
  1169. // message 1, which was cached in the context.
  1170. //
  1171. if (GtkLength != Context->TemporalKeySize) {
  1172. break;
  1173. }
  1174. KdeGtk = (PEAPOL_KDE_GTK)(Kde + 1);
  1175. Context->GtkFlags = KdeGtk->Flags;
  1176. Context->Gtk = MmAllocatePagedPool(GtkLength,
  1177. EAPOL_ALLOCATION_TAG);
  1178. if (Context->Gtk == NULL) {
  1179. goto SupplicantProcessKeyFrameEnd;
  1180. }
  1181. Context->GtkSize = GtkLength;
  1182. RtlCopyMemory(Context->Gtk, KdeGtk->Gtk, GtkLength);
  1183. break;
  1184. default:
  1185. break;
  1186. }
  1187. }
  1188. //
  1189. // The MIC was valid. Update the local key replay counter.
  1190. //
  1191. Context->KeyReplayCounter = KeyReplayCounter;
  1192. Context->KeyReplayCounterValid = TRUE;
  1193. //
  1194. // Send message 4 back to the authenticator.
  1195. //
  1196. Status = Net80211pEapolSupplicantSendMessage(Context,
  1197. EapolMessageType4,
  1198. KeyReplayCounter);
  1199. if (!KSUCCESS(Status)) {
  1200. RtlDebugPrint("EAPOL: Failed to send supplicant message 4.\n");
  1201. goto SupplicantProcessKeyFrameEnd;
  1202. }
  1203. CompleteExchange = TRUE;
  1204. CompletionStatus = STATUS_SUCCESS;
  1205. break;
  1206. default:
  1207. RtlDebugPrint("EAPOL: Supplicant received unknown message type "
  1208. "0x%04x.\n",
  1209. MessageType);
  1210. goto SupplicantProcessKeyFrameEnd;
  1211. }
  1212. SupplicantProcessKeyFrameEnd:
  1213. //
  1214. // In order to not process more packets for a completed context, remove the
  1215. // context from the global tree while the context lock is still held.
  1216. //
  1217. if (CompleteExchange != FALSE) {
  1218. KeAcquireQueuedLock(Net80211EapolTreeLock);
  1219. if (Context->TreeEntry.Parent != NULL) {
  1220. RtlRedBlackTreeRemove(&Net80211EapolTree, &(Context->TreeEntry));
  1221. Context->TreeEntry.Parent = NULL;
  1222. }
  1223. KeReleaseQueuedLock(Net80211EapolTreeLock);
  1224. }
  1225. KeReleaseQueuedLock(Context->Lock);
  1226. //
  1227. // Now that the context lock has been released, call the completion
  1228. // routine if necessary.
  1229. //
  1230. if (CompleteExchange != FALSE) {
  1231. Net80211pEapolCompleteInstance(Context, CompletionStatus);
  1232. }
  1233. if (KeyData != NULL) {
  1234. MmFreePagedPool(KeyData);
  1235. }
  1236. return;
  1237. }
  1238. KSTATUS
  1239. Net80211pEapolSupplicantSendMessage (
  1240. PEAPOL_CONTEXT Context,
  1241. EAPOL_MESSAGE_TYPE Type,
  1242. ULONGLONG KeyReplayCounter
  1243. )
  1244. /*++
  1245. Routine Description:
  1246. This routine sends a message to the authenticator from the supplicant.
  1247. Arguments:
  1248. Context - Supplies a pointer to the EAPOL context sending the message.
  1249. Type - Supplies the message type to send to the authenticator.
  1250. KeyReplayCounter - Supplies the key replay counter for the authenticator's
  1251. message to which this message is replying.
  1252. Return Value:
  1253. Status code.
  1254. --*/
  1255. {
  1256. USHORT BodyLength;
  1257. ULONG Flags;
  1258. PUCHAR KeyData;
  1259. ULONG KeyDataLength;
  1260. PEAPOL_KEY_FRAME KeyFrame;
  1261. USHORT KeyInformation;
  1262. PNET_PACKET_BUFFER Packet;
  1263. NET_PACKET_LIST PacketList;
  1264. ULONG PacketSize;
  1265. PNET_DATA_LINK_SEND Send;
  1266. KSTATUS Status;
  1267. ASSERT((Type == EapolMessageType2) || (Type == EapolMessageType4));
  1268. KeyDataLength = 0;
  1269. if (Type == EapolMessageType2) {
  1270. KeyDataLength = Context->Supplicant.RsnSize;
  1271. }
  1272. //
  1273. // Allocate a network packet buffer large enough to hold the key frame and
  1274. // key data.
  1275. //
  1276. Flags = NET_ALLOCATE_BUFFER_FLAG_ADD_DATA_LINK_FOOTERS |
  1277. NET_ALLOCATE_BUFFER_FLAG_ADD_DATA_LINK_HEADERS |
  1278. NET_ALLOCATE_BUFFER_FLAG_ADD_DEVICE_LINK_FOOTERS |
  1279. NET_ALLOCATE_BUFFER_FLAG_ADD_DEVICE_LINK_HEADERS |
  1280. NET_ALLOCATE_BUFFER_FLAG_UNENCRYPTED;
  1281. Packet = NULL;
  1282. PacketSize = sizeof(EAPOL_KEY_FRAME) + KeyDataLength;
  1283. Status = NetAllocateBuffer(0,
  1284. PacketSize,
  1285. 0,
  1286. Context->NetworkLink,
  1287. Flags,
  1288. &Packet);
  1289. if (!KSUCCESS(Status)) {
  1290. goto SupplicantSendMessageEnd;
  1291. }
  1292. //
  1293. // EAPOL packets may need to be sent while the transmit queue is paused.
  1294. // Force the transmission through.
  1295. //
  1296. Packet->Flags |= NET_PACKET_FLAG_FORCE_TRANSMIT |
  1297. NET_PACKET_FLAG_UNENCRYPTED;
  1298. //
  1299. // Initialize the key frame.
  1300. //
  1301. KeyFrame = Packet->Buffer + Packet->DataOffset;
  1302. RtlZeroMemory(KeyFrame, sizeof(EAPOL_KEY_FRAME));
  1303. KeyFrame->PacketHeader.ProtocolVersion = EAPOL_PROTOCOL_VERSION;
  1304. KeyFrame->PacketHeader.Type = EAPOL_PACKET_TYPE_KEY_FRAME;
  1305. BodyLength = (USHORT)PacketSize - sizeof(EAPOL_PACKET_HEADER);
  1306. KeyFrame->PacketHeader.BodyLength = CPU_TO_NETWORK16(BodyLength);
  1307. KeyFrame->DescriptorType = EAPOL_KEY_DESCRIPTOR_TYPE_RSN;
  1308. KeyInformation = (Context->KeyVersion <<
  1309. EAPOL_KEY_INFORMATION_VERSION_SHIFT) |
  1310. (EAPOL_KEY_INFORMATION_PAIRWISE <<
  1311. EAPOL_KEY_INFORMATION_TYPE_SHIFT) |
  1312. EAPOL_KEY_INFORMATION_MIC_PRESENT;
  1313. if (Type == EapolMessageType4) {
  1314. KeyInformation |= EAPOL_KEY_INFORMATION_SECURE;
  1315. }
  1316. KeyFrame->KeyInformation = CPU_TO_NETWORK16(KeyInformation);
  1317. KeyFrame->KeyReplayCounter = CPU_TO_NETWORK64(KeyReplayCounter);
  1318. //
  1319. // Send the supplicant's nonce value to the authenticator so it can
  1320. // generate the PTK.
  1321. //
  1322. if (Type == EapolMessageType2) {
  1323. RtlCopyMemory(KeyFrame->KeyNonce,
  1324. Context->Supplicant.Nonce,
  1325. EAPOL_NONCE_SIZE);
  1326. //
  1327. // The key data is the RSNE. Same as the 802.11 (re)assocation request
  1328. // would send.
  1329. //
  1330. ASSERT(KeyDataLength != 0);
  1331. KeyFrame->KeyDataLength = CPU_TO_NETWORK16(KeyDataLength);
  1332. KeyData = (PUCHAR)(KeyFrame + 1);
  1333. RtlCopyMemory(KeyData, Context->Supplicant.Rsn, KeyDataLength);
  1334. }
  1335. //
  1336. // Compute the MIC for the key frame.
  1337. //
  1338. Net80211pEapolComputeMic(Context, KeyFrame);
  1339. //
  1340. // Send the packet down to the data link layer.
  1341. //
  1342. NET_INITIALIZE_PACKET_LIST(&PacketList);
  1343. NET_ADD_PACKET_TO_LIST(Packet, &PacketList);
  1344. Send = Context->NetworkLink->DataLinkEntry->Interface.Send;
  1345. Status = Send(Context->NetworkLink->DataLinkContext,
  1346. &PacketList,
  1347. &(Context->Supplicant.Address),
  1348. &(Context->Authenticator.Address),
  1349. EAPOL_PROTOCOL_NUMBER);
  1350. if (!KSUCCESS(Status)) {
  1351. goto SupplicantSendMessageEnd;
  1352. }
  1353. SupplicantSendMessageEnd:
  1354. if (!KSUCCESS(Status)) {
  1355. NetDestroyBufferList(&PacketList);
  1356. }
  1357. return Status;
  1358. }
  1359. VOID
  1360. Net80211pEapolReadGlobalKeyCounter (
  1361. PEAPOL_CONTEXT Context,
  1362. PUCHAR ReadBuffer,
  1363. ULONG ReadSize
  1364. )
  1365. /*++
  1366. Routine Description:
  1367. This routine reads a portion of the EAPOL instances's global key counter
  1368. into the given buffer. If the read size is greater than the size of the
  1369. global key counter, then the rest of the buffer will be left untouched.
  1370. Once the global key is read, it is incremented by 1.
  1371. Arguments:
  1372. Context - Supplies a pointer to the context of the EAPOL instance whose
  1373. global key counter is to be read and incremented.
  1374. ReadBuffer - Supplies a pointer to a buffer that receives the current
  1375. global key counter value.
  1376. ReadSize - Supplies the number of bytes to read in the given buffer.
  1377. Return Value:
  1378. None.
  1379. --*/
  1380. {
  1381. ULONG Index;
  1382. ULONG Offset;
  1383. if (ReadSize > EAPOL_GLOBAL_KEY_COUNTER_SIZE) {
  1384. ReadSize = EAPOL_GLOBAL_KEY_COUNTER_SIZE;
  1385. }
  1386. Offset = EAPOL_GLOBAL_KEY_COUNTER_SIZE - ReadSize;
  1387. //
  1388. // Copy the lowest N-bytes from the global key counter to the read buffer.
  1389. // The global key counter is a 32-byte big endian value.
  1390. //
  1391. KeAcquireQueuedLock(Context->Lock);
  1392. RtlCopyMemory(ReadBuffer, Context->GlobalKeyCounter + Offset, ReadSize);
  1393. //
  1394. // Increment the key. The key is saved in big endian byte order where the
  1395. // least significant byte is at the end.
  1396. //
  1397. for (Index = EAPOL_GLOBAL_KEY_COUNTER_SIZE; Index > 0; Index += 1) {
  1398. Context->GlobalKeyCounter[Index - 1] += 1;
  1399. if (Context->GlobalKeyCounter[Index - 1] != 0) {
  1400. break;
  1401. }
  1402. }
  1403. KeReleaseQueuedLock(Context->Lock);
  1404. return;
  1405. }
  1406. KSTATUS
  1407. Net80211pEapolConvertPassphraseToPsk (
  1408. PUCHAR Passphrase,
  1409. ULONG PassphraseLength,
  1410. PUCHAR Ssid,
  1411. ULONG SsidLength,
  1412. PUCHAR Psk,
  1413. ULONG PskLength
  1414. )
  1415. /*++
  1416. Routine Description:
  1417. This routine converts the 8 to 63 character passphrase into a 256-bit PSK
  1418. using the SSID as a salt.
  1419. Arguments:
  1420. Passphrase - Supplies an array of ASCII characters used as the passphrase.
  1421. PassphraseLength - Supplies the length of the passphrase.
  1422. Ssid - Supplies the SSID string for the BSS to which the passphrase belongs.
  1423. SsidLength - Supplies the length of the SSID.
  1424. Psk - Supplies a pointer that receives the 256-bit PSK derived from the
  1425. passphrase.
  1426. PskLength - Supplies the length of the desired PSK, in bytes.
  1427. Return Value:
  1428. Status code.
  1429. --*/
  1430. {
  1431. UCHAR Digest[SHA1_HASH_SIZE];
  1432. ULONG HashIndex;
  1433. PUCHAR Message;
  1434. ULONG MessageLength;
  1435. PUCHAR Output;
  1436. PUCHAR PskBuffer;
  1437. ULONG PskIndex;
  1438. ULONG RequiredSha1Count;
  1439. KSTATUS Status;
  1440. ULONG XorIndex;
  1441. PskBuffer = NULL;
  1442. //
  1443. // Allocate a buffer to hold the SSID plus the PSK index. It must be at
  1444. // least the size of a SHA1 hash.
  1445. //
  1446. MessageLength = SsidLength + sizeof(ULONG);
  1447. if (MessageLength < SHA1_HASH_SIZE) {
  1448. MessageLength = SHA1_HASH_SIZE;
  1449. }
  1450. Message = MmAllocatePagedPool(MessageLength, EAPOL_ALLOCATION_TAG);
  1451. if (Message == NULL) {
  1452. Status = STATUS_INSUFFICIENT_RESOURCES;
  1453. goto ConvertPassphraseToPskEnd;
  1454. }
  1455. //
  1456. // If the given PSK buffer is not big enough to hold the contents of
  1457. // the necessary number of SHA-1 HMAC signatures, then allocate a temporary
  1458. // buffer to hold the output.
  1459. //
  1460. RequiredSha1Count = PskLength / SHA1_HASH_SIZE;
  1461. if ((PskLength % SHA1_HASH_SIZE) != 0) {
  1462. RequiredSha1Count += 1;
  1463. PskBuffer = MmAllocatePagedPool(RequiredSha1Count * SHA1_HASH_SIZE,
  1464. EAPOL_ALLOCATION_TAG);
  1465. if (PskBuffer == NULL) {
  1466. Status = STATUS_INSUFFICIENT_RESOURCES;
  1467. goto ConvertPassphraseToPskEnd;
  1468. }
  1469. } else {
  1470. PskBuffer = Psk;
  1471. }
  1472. //
  1473. // Perform as many iterations as necessary to fill the PSK with SHA-1 HMAC
  1474. // signatures.
  1475. //
  1476. Output = PskBuffer;
  1477. for (PskIndex = 1; PskIndex <= RequiredSha1Count; PskIndex += 1) {
  1478. RtlCopyMemory(Message, Ssid, SsidLength);
  1479. *((PULONG)&(Message[SsidLength])) = RtlByteSwapUlong(PskIndex);
  1480. //
  1481. // Compute the first digest and save it to the output.
  1482. //
  1483. CySha1ComputeHmac(Message,
  1484. SsidLength + sizeof(ULONG),
  1485. Passphrase,
  1486. PassphraseLength,
  1487. Digest);
  1488. RtlCopyMemory(Output, Digest, SHA1_HASH_SIZE);
  1489. RtlCopyMemory(Message, Digest, SHA1_HASH_SIZE);
  1490. //
  1491. // Now compute the rest of the interations reusing each computed digest
  1492. // as the next message.
  1493. //
  1494. for (HashIndex = 1; HashIndex < 4096; HashIndex += 1) {
  1495. CySha1ComputeHmac(Message,
  1496. SHA1_HASH_SIZE,
  1497. Passphrase,
  1498. PassphraseLength,
  1499. Digest);
  1500. RtlCopyMemory(Message, Digest, SHA1_HASH_SIZE);
  1501. //
  1502. // XOR the total output with the current digest.
  1503. //
  1504. for (XorIndex = 0; XorIndex < SHA1_HASH_SIZE; XorIndex += 1) {
  1505. Output[XorIndex] ^= Digest[XorIndex];
  1506. }
  1507. }
  1508. Output += SHA1_HASH_SIZE;
  1509. }
  1510. //
  1511. // If a temporary buffer was allocated for the PSK, copy the desired bytes
  1512. // back to the supplied buffer.
  1513. //
  1514. if (PskBuffer != Psk) {
  1515. RtlCopyMemory(Psk, PskBuffer, PskLength);
  1516. }
  1517. Status = STATUS_SUCCESS;
  1518. ConvertPassphraseToPskEnd:
  1519. if (Message != NULL) {
  1520. MmFreePagedPool(Message);
  1521. }
  1522. if ((PskBuffer != NULL) && (PskBuffer != Psk)) {
  1523. MmFreePagedPool(PskBuffer);
  1524. }
  1525. return Status;
  1526. }
  1527. KSTATUS
  1528. Net80211pGeneratePtk (
  1529. PEAPOL_CONTEXT Context,
  1530. ULONG TemporalKeyLength
  1531. )
  1532. /*++
  1533. Routine Description:
  1534. This routine generates the pairwise transient key (PTK) for a session
  1535. between a supplicant and an authenticator. It uses the MAC address and
  1536. nonce values stored in the context.
  1537. Arguments:
  1538. Context - Supplies a pointer to context of the EAPOL instance for which the
  1539. PTK should be generated.
  1540. TemporalKeyLength - Supplies the length of the temporal key portion of the
  1541. PTK, in bytes.
  1542. Return Value:
  1543. Status code.
  1544. --*/
  1545. {
  1546. PUCHAR CurrentData;
  1547. UCHAR Data[EAPOL_PTK_DATA_SIZE];
  1548. PUCHAR MaxAddress;
  1549. PUCHAR MaxNonce;
  1550. PUCHAR MinAddress;
  1551. PUCHAR MinNonce;
  1552. ULONG PtkSize;
  1553. COMPARISON_RESULT Result;
  1554. KSTATUS Status;
  1555. //
  1556. // Release the existing PTK.
  1557. //
  1558. if (Context->Ptk != NULL) {
  1559. MmFreePagedPool(Context->Ptk);
  1560. Context->Ptk = NULL;
  1561. }
  1562. //
  1563. // Concatenate both MAC addresses and both nonce values from the
  1564. // authenticator and the supplicant in to the data buffer.
  1565. //
  1566. CurrentData = Data;
  1567. //
  1568. // Set the MAC addresses in ascending order.
  1569. //
  1570. MinAddress = (PUCHAR)(Context->Authenticator.Address.Address);
  1571. MaxAddress = (PUCHAR)(Context->Supplicant.Address.Address);
  1572. Result = Net80211pEapolCompareMemory(MinAddress,
  1573. MaxAddress,
  1574. NET80211_ADDRESS_SIZE);
  1575. if (Result == ComparisonResultDescending) {
  1576. MinAddress = (PUCHAR)(Context->Supplicant.Address.Address);
  1577. MaxAddress = (PUCHAR)(Context->Authenticator.Address.Address);
  1578. }
  1579. RtlCopyMemory(CurrentData, MinAddress, NET80211_ADDRESS_SIZE);
  1580. CurrentData += NET80211_ADDRESS_SIZE;
  1581. RtlCopyMemory(CurrentData, MaxAddress, NET80211_ADDRESS_SIZE);
  1582. CurrentData += NET80211_ADDRESS_SIZE;
  1583. //
  1584. // Set the nonce's in ascending order.
  1585. //
  1586. MinNonce = Context->Authenticator.Nonce;
  1587. MaxNonce = Context->Supplicant.Nonce;
  1588. Result = Net80211pEapolCompareMemory(MinNonce, MaxNonce, EAPOL_NONCE_SIZE);
  1589. if (Result == ComparisonResultDescending) {
  1590. MinNonce = Context->Supplicant.Nonce;
  1591. MaxNonce = Context->Authenticator.Nonce;
  1592. }
  1593. RtlCopyMemory(CurrentData, MinNonce, EAPOL_NONCE_SIZE);
  1594. CurrentData += EAPOL_NONCE_SIZE;
  1595. RtlCopyMemory(CurrentData, MaxNonce, EAPOL_NONCE_SIZE);
  1596. CurrentData += EAPOL_NONCE_SIZE;
  1597. //
  1598. // Allocate a buffer for the PTK, which includes the KCK, KEK, and temporal
  1599. // key.
  1600. //
  1601. PtkSize = EAPOL_KCK_SIZE + EAPOL_KEK_SIZE + TemporalKeyLength;
  1602. Context->Ptk = MmAllocatePagedPool(PtkSize, EAPOL_ALLOCATION_TAG);
  1603. if (Context->Ptk == NULL) {
  1604. Status = STATUS_INSUFFICIENT_RESOURCES;
  1605. goto GeneratePtkEnd;
  1606. }
  1607. Context->PtkSize = PtkSize;
  1608. Context->TemporalKeySize = TemporalKeyLength;
  1609. //
  1610. // Run the data through the PRF using the PMK as a key.
  1611. //
  1612. Status = Net80211pEapolPseudoRandomFunction(
  1613. Context->Pmk,
  1614. EAPOL_PMK_SIZE,
  1615. EAPOL_PTK_APPLICATION_TEXT,
  1616. EAPOL_PTK_APPLICATION_TEXT_LENGTH,
  1617. Data,
  1618. EAPOL_PTK_DATA_SIZE,
  1619. Context->Ptk,
  1620. Context->PtkSize);
  1621. if (!KSUCCESS(Status)) {
  1622. goto GeneratePtkEnd;
  1623. }
  1624. GeneratePtkEnd:
  1625. if (!KSUCCESS(Status)) {
  1626. if (Context->Ptk != NULL) {
  1627. MmFreePagedPool(Context->Ptk);
  1628. Context->Ptk = NULL;
  1629. Context->PtkSize = 0;
  1630. }
  1631. }
  1632. return Status;
  1633. }
  1634. KSTATUS
  1635. Net80211pEapolEncryptKeyData (
  1636. PEAPOL_CONTEXT Context,
  1637. PUCHAR KeyData,
  1638. ULONG KeyDataLength,
  1639. PUCHAR *EncryptedKeyData,
  1640. PULONG EncryptedKeyDataLength
  1641. )
  1642. /*++
  1643. Routine Description:
  1644. This routine encrypts the given key data using the appropriate algorithm
  1645. as defined by the key encryption type, which is gathered from the key
  1646. information version.
  1647. Arguments:
  1648. Context - Supplies a pointer to the context of the EAPOL instance to which
  1649. the key data belongs.
  1650. KeyData - Supplies a pointer to the plaintext key data to encrypt.
  1651. KeyDataLength - Supplies the length of the key data, in bytes.
  1652. EncryptedKeyData - Supplies a pointer that receives a pointer to a buffer
  1653. containing the encrypted key data. The caller is responsible for
  1654. releasing this resource.
  1655. EncryptedKeyDataLength - Supplies a pointer that receives the length of the
  1656. encrypted key data.
  1657. Return Value:
  1658. Status code.
  1659. --*/
  1660. {
  1661. PUCHAR Ciphertext;
  1662. ULONG CiphertextLength;
  1663. PUCHAR Plaintext;
  1664. ULONG PlaintextLength;
  1665. KSTATUS Status;
  1666. ASSERT((Context->KeyVersion == EAPOL_KEY_VERSION_NIST_AES_HMAC_SHA1_128) ||
  1667. (Context->KeyVersion == EAPOL_KEY_VERSION_NIST_AES_AES_128_CMAC));
  1668. Ciphertext = NULL;
  1669. CiphertextLength = 0;
  1670. //
  1671. // If the key data is less than 16 bytes or not 8-byte aligned, then it
  1672. // needs to be padded.
  1673. //
  1674. PlaintextLength = KeyDataLength;
  1675. if (PlaintextLength < EAPOL_NIST_AES_MIN_KEY_DATA_LENGTH) {
  1676. PlaintextLength = EAPOL_NIST_AES_MIN_KEY_DATA_LENGTH;
  1677. } else if (IS_ALIGNED(PlaintextLength,
  1678. EAPOL_NIST_AES_KEY_DATA_ALIGNMENT) == FALSE) {
  1679. PlaintextLength = ALIGN_RANGE_UP(PlaintextLength,
  1680. EAPOL_NIST_AES_KEY_DATA_ALIGNMENT);
  1681. }
  1682. //
  1683. // If padding is required, allocate a new buffer and pad it.
  1684. //
  1685. if (PlaintextLength != KeyDataLength) {
  1686. Plaintext = MmAllocatePagedPool(PlaintextLength, EAPOL_ALLOCATION_TAG);
  1687. if (Plaintext == NULL) {
  1688. Status = STATUS_INSUFFICIENT_RESOURCES;
  1689. goto EncryptKeyDataEnd;
  1690. }
  1691. RtlCopyMemory(Plaintext, KeyData, KeyDataLength);
  1692. Plaintext[KeyDataLength] = EAPOL_NIST_AES_KEY_DATA_PADDING_BYTE;
  1693. RtlZeroMemory((Plaintext + KeyDataLength + 1),
  1694. PlaintextLength - KeyDataLength - 1);
  1695. } else {
  1696. Plaintext = KeyData;
  1697. }
  1698. //
  1699. // Allocate a buffer to hold the encrypted key data. It should be 8 bytes
  1700. // longer than the plaintext.
  1701. //
  1702. CiphertextLength = PlaintextLength +
  1703. EAPOL_NIST_AES_KEY_DATA_CIPHERTEXT_LENGTH_DELTA;
  1704. Ciphertext = MmAllocatePagedPool(CiphertextLength, EAPOL_ALLOCATION_TAG);
  1705. if (Ciphertext == NULL) {
  1706. Status = STATUS_INSUFFICIENT_RESOURCES;
  1707. goto EncryptKeyDataEnd;
  1708. }
  1709. //
  1710. // Perform the NIST AES key wrap to encrypt the key data.
  1711. //
  1712. Net80211pEapolNistAesKeyWrap(Plaintext,
  1713. PlaintextLength,
  1714. EAPOL_PTK_GET_KEK(Context->Ptk),
  1715. EAPOL_KEK_SIZE,
  1716. Ciphertext,
  1717. CiphertextLength);
  1718. if (!KSUCCESS(Status)) {
  1719. goto EncryptKeyDataEnd;
  1720. }
  1721. EncryptKeyDataEnd:
  1722. if ((Plaintext != KeyData) && (Plaintext != NULL)) {
  1723. MmFreePagedPool(Plaintext);
  1724. }
  1725. if (!KSUCCESS(Status)) {
  1726. if (Ciphertext != NULL) {
  1727. MmFreePagedPool(Ciphertext);
  1728. Ciphertext = NULL;
  1729. CiphertextLength = 0;
  1730. }
  1731. }
  1732. *EncryptedKeyData = Ciphertext;
  1733. *EncryptedKeyDataLength = CiphertextLength;
  1734. return Status;
  1735. }
  1736. KSTATUS
  1737. Net80211pEapolDecryptKeyData (
  1738. PEAPOL_CONTEXT Context,
  1739. PUCHAR EncryptedKeyData,
  1740. ULONG EncryptedKeyDataLength,
  1741. PUCHAR *KeyData,
  1742. PULONG KeyDataLength
  1743. )
  1744. /*++
  1745. Routine Description:
  1746. This routine decrypts the given key data using the appropriate algorithm
  1747. as defined by the key encryption type, which is gathered from the key
  1748. information version.
  1749. Arguments:
  1750. Context - Supplies a pointer to the context of the EAPOL instance to which
  1751. the key data belongs.
  1752. EncryptedKeyData - Supplies a pointer to the ciphertext key data to decrypt.
  1753. EncryptedKeyDataLength - Supplies the length of the encrypted key data, in
  1754. bytes.
  1755. KeyData - Supplies a pointer that receives a pointer to a buffer containing
  1756. the plaintext key data. The caller is responsible for releasing this
  1757. resource.
  1758. KeyDataLength - Supplies a pointer that receives the length of the
  1759. decrypted key data.
  1760. Return Value:
  1761. Status code.
  1762. --*/
  1763. {
  1764. PUCHAR Plaintext;
  1765. ULONG PlaintextLength;
  1766. KSTATUS Status;
  1767. ASSERT((Context->KeyVersion == EAPOL_KEY_VERSION_NIST_AES_HMAC_SHA1_128) ||
  1768. (Context->KeyVersion == EAPOL_KEY_VERSION_NIST_AES_AES_128_CMAC));
  1769. //
  1770. // The final decrypted key data is 8 bytes shorter than the encrypted key
  1771. // data.
  1772. //
  1773. PlaintextLength = EncryptedKeyDataLength -
  1774. EAPOL_NIST_AES_KEY_DATA_CIPHERTEXT_LENGTH_DELTA;
  1775. Plaintext = MmAllocatePagedPool(PlaintextLength, EAPOL_ALLOCATION_TAG);
  1776. if (Plaintext == NULL) {
  1777. Status = STATUS_INSUFFICIENT_RESOURCES;
  1778. goto DecryptKeyDataEnd;
  1779. }
  1780. Status = Net80211pEapolNistAesKeyUnwrap(EncryptedKeyData,
  1781. EncryptedKeyDataLength,
  1782. EAPOL_PTK_GET_KEK(Context->Ptk),
  1783. EAPOL_KEK_SIZE,
  1784. Plaintext,
  1785. PlaintextLength);
  1786. if (!KSUCCESS(Status)) {
  1787. goto DecryptKeyDataEnd;
  1788. }
  1789. DecryptKeyDataEnd:
  1790. if (!KSUCCESS(Status)) {
  1791. if (Plaintext != NULL) {
  1792. MmFreePagedPool(Plaintext);
  1793. Plaintext = NULL;
  1794. }
  1795. PlaintextLength = 0;
  1796. }
  1797. *KeyData = Plaintext;
  1798. *KeyDataLength = PlaintextLength;
  1799. return Status;
  1800. }
  1801. VOID
  1802. Net80211pEapolComputeMic (
  1803. PEAPOL_CONTEXT Context,
  1804. PEAPOL_KEY_FRAME KeyFrame
  1805. )
  1806. /*++
  1807. Routine Description:
  1808. This routine computes the MIC for the given key frame and sets it into the
  1809. key frame's MIC field.
  1810. Arguments:
  1811. Context - Supplies a pointer to the EAPOL context generating the key frame.
  1812. KeyFrame - Supplies a pointer to the key frame whose MIC needs to be
  1813. computed.
  1814. Return Value:
  1815. None.
  1816. --*/
  1817. {
  1818. PUCHAR ComputedMic;
  1819. UCHAR Digest[SHA1_HASH_SIZE];
  1820. ULONG KeyFrameLength;
  1821. ASSERT(Context->Ptk != NULL);
  1822. //
  1823. // Compute the MIC. The algorithm depends on the key version.
  1824. //
  1825. KeyFrameLength = sizeof(EAPOL_KEY_FRAME) +
  1826. NETWORK_TO_CPU16(KeyFrame->KeyDataLength);
  1827. switch (Context->KeyVersion) {
  1828. case EAPOL_KEY_VERSION_NIST_AES_HMAC_SHA1_128:
  1829. CySha1ComputeHmac((PUCHAR)KeyFrame,
  1830. KeyFrameLength,
  1831. EAPOL_PTK_GET_KCK(Context->Ptk),
  1832. EAPOL_KCK_SIZE,
  1833. Digest);
  1834. ComputedMic = Digest;
  1835. break;
  1836. case EAPOL_KEY_VERSION_NIST_AES_AES_128_CMAC:
  1837. case EAPOL_KEY_VERSION_ARC4_HMAC_MD5:
  1838. default:
  1839. RtlDebugPrint("EAPOL: Unsupported MIC algorithm %d.\n",
  1840. Context->KeyVersion);
  1841. goto ComputeMicEnd;
  1842. }
  1843. //
  1844. // Save the compute MIC in the key frame.
  1845. //
  1846. RtlCopyMemory(KeyFrame->KeyMic, ComputedMic, EAPOL_DEFAULT_KEY_MIC_SIZE);
  1847. ComputeMicEnd:
  1848. return;
  1849. }
  1850. BOOL
  1851. Net80211pEapolValidateMic (
  1852. PEAPOL_CONTEXT Context,
  1853. PEAPOL_KEY_FRAME KeyFrame
  1854. )
  1855. /*++
  1856. Routine Description:
  1857. This routine validates the MIC in the given key frame. It assumes that the
  1858. key frame does indeed have a MIC to validate.
  1859. Arguments:
  1860. Context - Supplies a pointer to the EAPOL context that received the key
  1861. frame.
  1862. KeyFrame - Supplies a pointer to the key frame whose MIC needs to be
  1863. validated.
  1864. Return Value:
  1865. Returns TRUE if the MIC is valid or FALSE otherwise.
  1866. --*/
  1867. {
  1868. PUCHAR ComputedMic;
  1869. UCHAR Digest[SHA1_HASH_SIZE];
  1870. ULONG KeyFrameLength;
  1871. BOOL Match;
  1872. UCHAR SavedMic[EAPOL_DEFAULT_KEY_MIC_SIZE];
  1873. BOOL Valid;
  1874. Valid = FALSE;
  1875. if (Context->Ptk == NULL) {
  1876. RtlDebugPrint("EAPOL: Unexpected key frame MIC for link that has "
  1877. "no PTK to validate the MIC.\n");
  1878. goto ValidateMicEnd;
  1879. }
  1880. //
  1881. // Save the MIC and zero it in the key frame.
  1882. //
  1883. RtlCopyMemory(SavedMic, KeyFrame->KeyMic, EAPOL_DEFAULT_KEY_MIC_SIZE);
  1884. RtlZeroMemory(KeyFrame->KeyMic, EAPOL_DEFAULT_KEY_MIC_SIZE);
  1885. //
  1886. // Recompute the MIC. The algorithm depends on the key version.
  1887. //
  1888. KeyFrameLength = sizeof(EAPOL_KEY_FRAME) +
  1889. NETWORK_TO_CPU16(KeyFrame->KeyDataLength);
  1890. switch (Context->KeyVersion) {
  1891. case EAPOL_KEY_VERSION_NIST_AES_HMAC_SHA1_128:
  1892. CySha1ComputeHmac((PUCHAR)KeyFrame,
  1893. KeyFrameLength,
  1894. EAPOL_PTK_GET_KCK(Context->Ptk),
  1895. EAPOL_KCK_SIZE,
  1896. Digest);
  1897. ComputedMic = Digest;
  1898. break;
  1899. case EAPOL_KEY_VERSION_NIST_AES_AES_128_CMAC:
  1900. case EAPOL_KEY_VERSION_ARC4_HMAC_MD5:
  1901. default:
  1902. RtlDebugPrint("EAPOL: Unsupported MIC algorithm %d.\n",
  1903. Context->KeyVersion);
  1904. goto ValidateMicEnd;
  1905. }
  1906. //
  1907. // Compare the saved MIC to the computed MIC. The key frame is not
  1908. // valid unless they match.
  1909. //
  1910. Match = RtlCompareMemory(SavedMic, ComputedMic, EAPOL_DEFAULT_KEY_MIC_SIZE);
  1911. if (Match == FALSE) {
  1912. RtlDebugPrint("EAPOL: Invalid MIC received.\n");
  1913. goto ValidateMicEnd;
  1914. }
  1915. Valid = TRUE;
  1916. ValidateMicEnd:
  1917. return Valid;
  1918. }
  1919. VOID
  1920. Net80211pEapolNistAesKeyWrap (
  1921. PUCHAR KeyData,
  1922. ULONG KeyDataLength,
  1923. PUCHAR Key,
  1924. ULONG KeyLength,
  1925. PUCHAR EncryptedKeyData,
  1926. ULONG EncryptedKeyDataLength
  1927. )
  1928. /*++
  1929. Routine Description:
  1930. This routine performs the NIST AES Key Wrap algorithm on the given key data
  1931. using the provided key. The encrypted key data is returned to the caller in
  1932. the encrypted key data buffer.
  1933. Arguments:
  1934. KeyData - Supplies a pointer to the key data to wrap.
  1935. KeyDataLength - Supplies the length of the key data. This should be 8-byte
  1936. aligned.
  1937. Key - Supplies a pointer to the key encryption key to use for encrypting
  1938. the key data.
  1939. KeyLength - Supplies the length of the key encryption key.
  1940. EncryptedKeyData - Supplies a pointer to a buffer that receives the wrapped
  1941. key data.
  1942. EncryptedKeyDataLength - Supplies the length of the encrypted key data
  1943. buffer. It must be 8-byte aligned and should be at least 8 bytes larger
  1944. than the key data buffer.
  1945. Return Value:
  1946. None.
  1947. --*/
  1948. {
  1949. ULONGLONG CipherText[2];
  1950. AES_CONTEXT Context;
  1951. ULONG Index;
  1952. PULONGLONG Output;
  1953. ULONGLONG PlainText[2];
  1954. ULONG QuadwordCount;
  1955. ULONGLONG Register;
  1956. ULONG Step;
  1957. ULONGLONG XorValue;
  1958. ASSERT(IS_ALIGNED(KeyDataLength, EAPOL_NIST_AES_KEY_DATA_ALIGNMENT) !=
  1959. FALSE);
  1960. ASSERT((KeyDataLength + EAPOL_NIST_AES_KEY_DATA_CIPHERTEXT_LENGTH_DELTA) ==
  1961. EncryptedKeyDataLength);
  1962. ASSERT(KeyLength == AES_CBC128_KEY_SIZE);
  1963. //
  1964. // Initialize the AES context for codebook encryption.
  1965. //
  1966. CyAesInitialize(&Context, AesModeEcb128, Key, NULL);
  1967. //
  1968. // The algorithm treats the input and output as arrays of 64-bit words.
  1969. // Initialize the register and the output buffer. The register gets the
  1970. // default initial value and the output gets the input values, leaving
  1971. // space for the final register value to fill the first 64-bit word. The
  1972. // output buffer must be 8-byte aligned, but it cannot be assumed that the
  1973. // input key data (that originates from the network packet) is aligned.
  1974. //
  1975. ASSERT(IS_POINTER_ALIGNED(EncryptedKeyData,
  1976. EAPOL_NIST_AES_KEY_DATA_ALIGNMENT) != FALSE);
  1977. Output = (PULONGLONG)EncryptedKeyData;
  1978. QuadwordCount = KeyDataLength / sizeof(ULONGLONG);
  1979. Register = EAPOL_NIST_AES_KEY_WRAP_INITIAL_VALUE;
  1980. RtlCopyMemory(Output + 1, KeyData, KeyDataLength);
  1981. //
  1982. // The input is wrapped 6 times in order to produce the encrypted key data.
  1983. //
  1984. for (Step = 0; Step < EAPOL_NIST_AES_KEY_WRAP_STEP_COUNT; Step += 1) {
  1985. for (Index = 1; Index <= QuadwordCount; Index += 1) {
  1986. PlainText[0] = Register;
  1987. PlainText[1] = Output[Index];
  1988. //
  1989. // Encrypt this iteration's plaintext.
  1990. //
  1991. CyAesEcbEncrypt(&Context,
  1992. (PUCHAR)PlainText,
  1993. (PUCHAR)CipherText,
  1994. sizeof(PlainText));
  1995. //
  1996. // Treating the result as big-endian, the most significant bits go
  1997. // back into the register and the least significant bits get stored
  1998. // in the output buffer.
  1999. //
  2000. Output[Index] = CipherText[1];
  2001. Register = CipherText[0];
  2002. XorValue = (QuadwordCount * Step) + Index;
  2003. Register ^= CPU_TO_NETWORK64(XorValue);
  2004. }
  2005. }
  2006. Output[0] = Register;
  2007. return;
  2008. }
  2009. KSTATUS
  2010. Net80211pEapolNistAesKeyUnwrap (
  2011. PUCHAR EncryptedKeyData,
  2012. ULONG EncryptedKeyDataLength,
  2013. PUCHAR Key,
  2014. ULONG KeyLength,
  2015. PUCHAR KeyData,
  2016. ULONG KeyDataLength
  2017. )
  2018. /*++
  2019. Routine Description:
  2020. This routine performs the NIST AES Key Unwrap algorithm on the given
  2021. encrypted key data using the provided key. The decrypted key data is
  2022. returned to the caller in the key data buffer.
  2023. Arguments:
  2024. EncryptedKeyData - Supplies a pointer to the encrypted key data to unwrap.
  2025. EncryptedKeyDataLength - Supplies the length of the encrypted key data.
  2026. This should be 8-byte aligned.
  2027. Key - Supplies a pointer to the key encryption key to use for decrypting
  2028. the key data.
  2029. KeyLength - Supplies the length of the key encryption key.
  2030. KeyData - Supplies a pointer to a buffer that receives the unwrapped key
  2031. data.
  2032. KeyDataLength - Supplies the length of the key data buffer. It must be
  2033. 8-byte aligned. It should be 8 bytes less than the encrypted key data.
  2034. Return Value:
  2035. Status code.
  2036. --*/
  2037. {
  2038. ULONGLONG Ciphertext[2];
  2039. AES_CONTEXT Context;
  2040. ULONG Index;
  2041. PULONGLONG Output;
  2042. ULONGLONG Plaintext[2];
  2043. ULONG QuadwordCount;
  2044. ULONGLONG Register;
  2045. KSTATUS Status;
  2046. ULONG Step;
  2047. ULONGLONG XorValue;
  2048. ASSERT(IS_ALIGNED(EncryptedKeyDataLength,
  2049. EAPOL_NIST_AES_KEY_DATA_ALIGNMENT) != FALSE);
  2050. ASSERT((KeyDataLength + EAPOL_NIST_AES_KEY_DATA_CIPHERTEXT_LENGTH_DELTA) ==
  2051. EncryptedKeyDataLength);
  2052. ASSERT(KeyLength == AES_ECB128_KEY_SIZE);
  2053. //
  2054. // Initailize the AES context for codebook decryption.
  2055. //
  2056. CyAesInitialize(&Context, AesModeEcb128, Key, NULL);
  2057. CyAesConvertKeyForDecryption(&Context);
  2058. //
  2059. // The algorithm treats the input and output as arrays of 64-bit words.
  2060. // Initialize the register and the output buffer. The register gets the
  2061. // first 64-bit word and the output gets the remaining input values. The
  2062. // input may not be aligned for quadword access, so be careful.
  2063. //
  2064. ASSERT(IS_POINTER_ALIGNED(KeyData, EAPOL_NIST_AES_KEY_DATA_ALIGNMENT));
  2065. Output = (PULONGLONG)KeyData;
  2066. QuadwordCount = KeyDataLength / sizeof(ULONGLONG);
  2067. RtlCopyMemory(&Register, EncryptedKeyData, sizeof(ULONGLONG));
  2068. RtlCopyMemory(Output, EncryptedKeyData + sizeof(ULONGLONG), KeyDataLength);
  2069. //
  2070. // The input is unwrapped 6 times in order to reproduce the key data.
  2071. //
  2072. for (Step = EAPOL_NIST_AES_KEY_WRAP_STEP_COUNT; Step > 0; Step -= 1) {
  2073. for (Index = QuadwordCount; Index > 0; Index -= 1) {
  2074. XorValue = (QuadwordCount * (Step - 1)) + Index;
  2075. Register ^= CPU_TO_NETWORK64(XorValue);
  2076. Ciphertext[0] = Register;
  2077. Ciphertext[1] = Output[Index - 1];
  2078. //
  2079. // Decrypt this iteration's ciphertext.
  2080. //
  2081. CyAesEcbDecrypt(&Context,
  2082. (PUCHAR)Ciphertext,
  2083. (PUCHAR)Plaintext,
  2084. sizeof(Ciphertext));
  2085. //
  2086. // Treating the result as big-endian, the most significant bits go
  2087. // back into the register and the least significant bits get stored
  2088. // in the output buffer.
  2089. //
  2090. Register = Plaintext[0];
  2091. Output[Index - 1] = Plaintext[1];
  2092. }
  2093. }
  2094. //
  2095. // Check the register for the initial value.
  2096. //
  2097. Status = STATUS_SUCCESS;
  2098. if (Register != EAPOL_NIST_AES_KEY_WRAP_INITIAL_VALUE) {
  2099. RtlDebugPrint("EAPOL: NIST AES key unwrap failed. Found initial value "
  2100. "0x%I64x, expected 0x%I64x.\n",
  2101. Register,
  2102. EAPOL_NIST_AES_KEY_WRAP_INITIAL_VALUE);
  2103. Status = STATUS_UNSUCCESSFUL;
  2104. }
  2105. return Status;
  2106. }
  2107. KSTATUS
  2108. Net80211pEapolPseudoRandomFunction (
  2109. PUCHAR Key,
  2110. ULONG KeyLength,
  2111. PSTR ApplicationText,
  2112. ULONG ApplicationTextLength,
  2113. PUCHAR Data,
  2114. ULONG DataLength,
  2115. PUCHAR Output,
  2116. ULONG OutputLength
  2117. )
  2118. /*++
  2119. Routine Description:
  2120. This routine converts the key, application text, and data set into a
  2121. pseudorandom number of the specified output length. This algorithm is
  2122. specific to the EAP specification.
  2123. Arguments:
  2124. Key - Supplies a pointer to a private key.
  2125. KeyLength - Supplies the length of the private key.
  2126. ApplicationText - Supplies the well-known text to use when calculating
  2127. pseudorandom numbers for different EAP applications.
  2128. ApplicationTextLength - Supplies the length of the application text. This
  2129. should not include the NULL terminator for any strings.
  2130. Data - Supplies a pointer to the data to input into the pseudorandom
  2131. function along with the application text.
  2132. DataLength - Supplies the length of the data.
  2133. Output - Supplies a pointer to the buffer that will receive the output of
  2134. the pseudorandom number computation.
  2135. OutputLength - Supplies the desired length of the output, in bytes.
  2136. Return Value:
  2137. Status code.
  2138. --*/
  2139. {
  2140. ULONG Index;
  2141. PUCHAR Input;
  2142. ULONG InputLength;
  2143. PUCHAR OutputBuffer;
  2144. ULONG OutputOffset;
  2145. ULONG RequiredSha1Count;
  2146. KSTATUS Status;
  2147. //
  2148. // Allocate an input buffer to hold the concatenated strings.
  2149. //
  2150. OutputBuffer = NULL;
  2151. InputLength = ApplicationTextLength + DataLength + 2;
  2152. Input = MmAllocatePagedPool(InputLength, EAPOL_ALLOCATION_TAG);
  2153. if (Input == NULL) {
  2154. Status = STATUS_INSUFFICIENT_RESOURCES;
  2155. goto PseudoRandomFunctionEnd;
  2156. }
  2157. //
  2158. // If the given output buffer is not big enough to hold the contents of
  2159. // the necessary number of SHA-1 HMAC signatures, then allocate a temporary
  2160. // buffer to hold the output.
  2161. //
  2162. RequiredSha1Count = OutputLength / SHA1_HASH_SIZE;
  2163. if ((OutputLength % SHA1_HASH_SIZE) != 0) {
  2164. RequiredSha1Count += 1;
  2165. OutputBuffer = MmAllocatePagedPool(RequiredSha1Count * SHA1_HASH_SIZE,
  2166. EAPOL_ALLOCATION_TAG);
  2167. if (OutputBuffer == NULL) {
  2168. Status = STATUS_INSUFFICIENT_RESOURCES;
  2169. goto PseudoRandomFunctionEnd;
  2170. }
  2171. } else {
  2172. OutputBuffer = Output;
  2173. }
  2174. //
  2175. // Concatenate the application text and the data, leaving a 0 byte
  2176. // inbetween and an initial 0 at the end.
  2177. //
  2178. RtlCopyMemory(Input, ApplicationText, ApplicationTextLength);
  2179. Input[ApplicationTextLength] = 0;
  2180. RtlCopyMemory(&(Input[ApplicationTextLength + 1]), Data, DataLength);
  2181. Input[InputLength - 1] = 0;
  2182. //
  2183. // Repeatedly compute the SHA-1 HMAC signature, changing the input each
  2184. // time, until the desired output length is obtained. The last byte of the
  2185. // input array gets incremented for each iteration.
  2186. //
  2187. OutputOffset = 0;
  2188. for (Index = 0; Index < RequiredSha1Count; Index += 1) {
  2189. CySha1ComputeHmac(Input,
  2190. InputLength,
  2191. Key,
  2192. KeyLength,
  2193. &(OutputBuffer[OutputOffset]));
  2194. OutputOffset += SHA1_HASH_SIZE;
  2195. Input[InputLength - 1] += 1;
  2196. }
  2197. //
  2198. // Copy the contents back to the original output if it a buffer was
  2199. // allocated to account for overflow.
  2200. //
  2201. if (Output != OutputBuffer) {
  2202. RtlCopyMemory(Output, OutputBuffer, OutputLength);
  2203. }
  2204. Status = STATUS_SUCCESS;
  2205. PseudoRandomFunctionEnd:
  2206. if (Input != NULL) {
  2207. MmFreePagedPool(Input);
  2208. }
  2209. if ((OutputBuffer != NULL) && (OutputBuffer != Output)) {
  2210. MmFreePagedPool(OutputBuffer);
  2211. }
  2212. return Status;
  2213. }
  2214. COMPARISON_RESULT
  2215. Net80211pEapolCompareMemory (
  2216. PUCHAR FirstBuffer,
  2217. PUCHAR SecondBuffer,
  2218. ULONG BufferSize
  2219. )
  2220. /*++
  2221. Routine Description:
  2222. This routine compares two buffers of equal size, treating the first byte as
  2223. the most significant byte (i.e. big endian). This can be used to compare
  2224. MAC address and nonce values.
  2225. Arguments:
  2226. FirstBuffer - Supplies a pointer to the first buffer to compare.
  2227. SecondBuffer - Supplies a pointer to the second buffer to compare.
  2228. BufferSize - Supplies the size of the buffers.
  2229. Return Value:
  2230. Same if the two addresses are the same.
  2231. Ascending if the first address is less than the second address.
  2232. Descending if the second address is less than the first address.
  2233. --*/
  2234. {
  2235. ULONG Index;
  2236. for (Index = 0; Index < BufferSize; Index += 1) {
  2237. if (FirstBuffer[Index] < SecondBuffer[Index]) {
  2238. return ComparisonResultAscending;
  2239. } else if (FirstBuffer[Index] > SecondBuffer[Index]) {
  2240. return ComparisonResultDescending;
  2241. }
  2242. }
  2243. return ComparisonResultSame;
  2244. }
  2245. COMPARISON_RESULT
  2246. Net80211pEapolCompareContexts (
  2247. PRED_BLACK_TREE Tree,
  2248. PRED_BLACK_TREE_NODE FirstNode,
  2249. PRED_BLACK_TREE_NODE SecondNode
  2250. )
  2251. /*++
  2252. Routine Description:
  2253. This routine compares two Red-Black tree nodes, in this case two EAPOL
  2254. contexts.
  2255. Arguments:
  2256. Tree - Supplies a pointer to the Red-Black tree that owns both nodes.
  2257. FirstNode - Supplies a pointer to the left side of the comparison.
  2258. SecondNode - Supplies a pointer to the second side of the comparison.
  2259. Return Value:
  2260. Same if the two nodes have the same value.
  2261. Ascending if the first node is less than the second node.
  2262. Descending if the second node is less than the first node.
  2263. --*/
  2264. {
  2265. PEAPOL_CONTEXT FirstEntry;
  2266. PEAPOL_CONTEXT SecondEntry;
  2267. FirstEntry = RED_BLACK_TREE_VALUE(FirstNode, EAPOL_CONTEXT, TreeEntry);
  2268. SecondEntry = RED_BLACK_TREE_VALUE(SecondNode, EAPOL_CONTEXT, TreeEntry);
  2269. if (FirstEntry->NetworkLink < SecondEntry->NetworkLink) {
  2270. return ComparisonResultAscending;
  2271. } else if (FirstEntry->NetworkLink > SecondEntry->NetworkLink) {
  2272. return ComparisonResultDescending;
  2273. }
  2274. return ComparisonResultSame;
  2275. }
  2276. VOID
  2277. Net80211pEapolContextAddReference (
  2278. PEAPOL_CONTEXT Context
  2279. )
  2280. /*++
  2281. Routine Description:
  2282. This routine increases the reference count on an EAPOL context.
  2283. Arguments:
  2284. Context - Supplies a pointer to the EAPOL context whose reference count
  2285. should be incremented.
  2286. Return Value:
  2287. None.
  2288. --*/
  2289. {
  2290. ULONG OldReferenceCount;
  2291. OldReferenceCount = RtlAtomicAdd32(&(Context->ReferenceCount), 1);
  2292. ASSERT((OldReferenceCount != 0) & (OldReferenceCount < 0x20000000));
  2293. return;
  2294. }
  2295. VOID
  2296. Net80211pEapolContextReleaseReference (
  2297. PEAPOL_CONTEXT Context
  2298. )
  2299. /*++
  2300. Routine Description:
  2301. This routine decreases the reference count of an EAPOL context, and
  2302. destroys the context if the reference count drops to zero.
  2303. Arguments:
  2304. Context - Supplies a pointer to the EAPOL context whose reference count
  2305. should be decremented.
  2306. Return Value:
  2307. None.
  2308. --*/
  2309. {
  2310. ULONG OldReferenceCount;
  2311. OldReferenceCount = RtlAtomicAdd32(&(Context->ReferenceCount), -1);
  2312. ASSERT(OldReferenceCount != 0);
  2313. if (OldReferenceCount == 1) {
  2314. Net80211pEapolDestroyContext(Context);
  2315. }
  2316. return;
  2317. }
  2318. VOID
  2319. Net80211pEapolDestroyContext (
  2320. PEAPOL_CONTEXT Context
  2321. )
  2322. /*++
  2323. Routine Description:
  2324. This routine destroys the given EAPOL context, releasing all of its
  2325. resources.
  2326. Arguments:
  2327. Context - Supplies a pointer to the EAPOL context to release.
  2328. Return Value:
  2329. None.
  2330. --*/
  2331. {
  2332. if (Context->Lock != NULL) {
  2333. KeDestroyQueuedLock(Context->Lock);
  2334. }
  2335. if (Context->Ptk != NULL) {
  2336. MmFreePagedPool(Context->Ptk);
  2337. }
  2338. if (Context->Gtk != NULL) {
  2339. MmFreePagedPool(Context->Gtk);
  2340. }
  2341. if (Context->NetworkLink != NULL) {
  2342. NetLinkReleaseReference(Context->NetworkLink);
  2343. }
  2344. if (Context->Net80211Link != NULL) {
  2345. Net80211LinkReleaseReference(Context->Net80211Link);
  2346. }
  2347. MmFreePagedPool(Context);
  2348. return;
  2349. }
  2350. VOID
  2351. Net80211pEapolCompleteInstance (
  2352. PEAPOL_CONTEXT Context,
  2353. KSTATUS CompletionStatus
  2354. )
  2355. /*++
  2356. Routine Description:
  2357. This routine completes an EAPOL instance. If the exchange was successful,
  2358. then this routine sets the acquired keys in the link. The routine always
  2359. notified the creator of the instance via the completion callback.
  2360. Arguments:
  2361. Context - Supplies a pointer to the context of the completed EAPOL instance.
  2362. CompletionStatus - Supplies the completion status for the instance.
  2363. Return Value:
  2364. None.
  2365. --*/
  2366. {
  2367. ULONG KeyFlags;
  2368. ULONG KeyId;
  2369. if (!KSUCCESS(CompletionStatus)) {
  2370. goto InstanceCompleteEnd;
  2371. }
  2372. if (Context->Ptk != NULL) {
  2373. KeyFlags = NET80211_KEY_FLAG_CCMP | NET80211_KEY_FLAG_TRANSMIT;
  2374. CompletionStatus = Net80211SetKey(Context->Net80211Link,
  2375. EAPOL_PTK_GET_TK(Context->Ptk),
  2376. Context->TemporalKeySize,
  2377. KeyFlags,
  2378. 0);
  2379. if (!KSUCCESS(CompletionStatus)) {
  2380. goto InstanceCompleteEnd;
  2381. }
  2382. }
  2383. if (Context->Gtk != NULL) {
  2384. KeyFlags = NET80211_KEY_FLAG_CCMP | NET80211_KEY_FLAG_GLOBAL;
  2385. if ((Context->GtkFlags & EAPOL_KDE_GTK_FLAG_TRANSMIT) != 0) {
  2386. KeyFlags |= NET80211_KEY_FLAG_TRANSMIT;
  2387. }
  2388. KeyId = (Context->GtkFlags & EAPOL_KDE_GTK_FLAG_KEY_ID_MASK) >>
  2389. EAPOL_KDE_GTK_FLAG_KEY_ID_SHIFT;
  2390. CompletionStatus = Net80211SetKey(Context->Net80211Link,
  2391. EAPOL_GTK_GET_TK(Context->Gtk),
  2392. Context->TemporalKeySize,
  2393. KeyFlags,
  2394. KeyId);
  2395. if (!KSUCCESS(CompletionStatus)) {
  2396. goto InstanceCompleteEnd;
  2397. }
  2398. }
  2399. InstanceCompleteEnd:
  2400. Context->CompletionRoutine(Context->CompletionContext, CompletionStatus);
  2401. return;
  2402. }