eapol.c 82 KB

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