eapol.c 83 KB

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