SecureBootConfigImpl.c 160 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047
  1. /** @file
  2. HII Config Access protocol implementation of SecureBoot configuration module.
  3. Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
  4. (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "SecureBootConfigImpl.h"
  8. #include <Library/BaseCryptLib.h>
  9. CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";
  10. SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate = {
  11. SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,
  12. {
  13. SecureBootExtractConfig,
  14. SecureBootRouteConfig,
  15. SecureBootCallback
  16. }
  17. };
  18. HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath = {
  19. {
  20. {
  21. HARDWARE_DEVICE_PATH,
  22. HW_VENDOR_DP,
  23. {
  24. (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
  25. (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
  26. }
  27. },
  28. SECUREBOOT_CONFIG_FORM_SET_GUID
  29. },
  30. {
  31. END_DEVICE_PATH_TYPE,
  32. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  33. {
  34. (UINT8) (END_DEVICE_PATH_LENGTH),
  35. (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
  36. }
  37. }
  38. };
  39. BOOLEAN mIsEnterSecureBootForm = FALSE;
  40. //
  41. // OID ASN.1 Value for Hash Algorithms
  42. //
  43. UINT8 mHashOidValue[] = {
  44. 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
  45. 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
  46. 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
  47. 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
  48. 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
  49. 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
  50. };
  51. HASH_TABLE mHash[] = {
  52. { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL },
  53. { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},
  54. { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},
  55. { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}
  56. };
  57. //
  58. // Variable Definitions
  59. //
  60. UINT32 mPeCoffHeaderOffset = 0;
  61. WIN_CERTIFICATE *mCertificate = NULL;
  62. IMAGE_TYPE mImageType;
  63. UINT8 *mImageBase = NULL;
  64. UINTN mImageSize = 0;
  65. UINT8 mImageDigest[MAX_DIGEST_SIZE];
  66. UINTN mImageDigestSize;
  67. EFI_GUID mCertType;
  68. EFI_IMAGE_SECURITY_DATA_DIRECTORY *mSecDataDir = NULL;
  69. EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
  70. //
  71. // Possible DER-encoded certificate file suffixes, end with NULL pointer.
  72. //
  73. CHAR16* mDerEncodedSuffix[] = {
  74. L".cer",
  75. L".der",
  76. L".crt",
  77. NULL
  78. };
  79. CHAR16* mSupportX509Suffix = L"*.cer/der/crt";
  80. SECUREBOOT_CONFIG_PRIVATE_DATA *gSecureBootPrivateData = NULL;
  81. /**
  82. This code cleans up enrolled file by closing file & free related resources attached to
  83. enrolled file.
  84. @param[in] FileContext FileContext cached in SecureBootConfig driver
  85. **/
  86. VOID
  87. CloseEnrolledFile(
  88. IN SECUREBOOT_FILE_CONTEXT *FileContext
  89. )
  90. {
  91. if (FileContext->FHandle != NULL) {
  92. CloseFile (FileContext->FHandle);
  93. FileContext->FHandle = NULL;
  94. }
  95. if (FileContext->FileName != NULL){
  96. FreePool(FileContext->FileName);
  97. FileContext->FileName = NULL;
  98. }
  99. FileContext->FileType = UNKNOWN_FILE_TYPE;
  100. }
  101. /**
  102. This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
  103. @param[in] FileSuffix The suffix of the input certificate file
  104. @retval TRUE It's a DER-encoded certificate.
  105. @retval FALSE It's NOT a DER-encoded certificate.
  106. **/
  107. BOOLEAN
  108. IsDerEncodeCertificate (
  109. IN CONST CHAR16 *FileSuffix
  110. )
  111. {
  112. UINTN Index;
  113. for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {
  114. if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {
  115. return TRUE;
  116. }
  117. }
  118. return FALSE;
  119. }
  120. /**
  121. This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format
  122. The function reads file content but won't open/close given FileHandle.
  123. @param[in] FileHandle The FileHandle to be checked
  124. @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format.
  125. @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.
  126. **/
  127. BOOLEAN
  128. IsAuthentication2Format (
  129. IN EFI_FILE_HANDLE FileHandle
  130. )
  131. {
  132. EFI_STATUS Status;
  133. EFI_VARIABLE_AUTHENTICATION_2 *Auth2;
  134. BOOLEAN IsAuth2Format;
  135. IsAuth2Format = FALSE;
  136. //
  137. // Read the whole file content
  138. //
  139. Status = ReadFileContent(
  140. FileHandle,
  141. (VOID **) &mImageBase,
  142. &mImageSize,
  143. 0
  144. );
  145. if (EFI_ERROR (Status)) {
  146. goto ON_EXIT;
  147. }
  148. Auth2 = (EFI_VARIABLE_AUTHENTICATION_2 *)mImageBase;
  149. if (Auth2->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {
  150. goto ON_EXIT;
  151. }
  152. if (CompareGuid(&gEfiCertPkcs7Guid, &Auth2->AuthInfo.CertType)) {
  153. IsAuth2Format = TRUE;
  154. }
  155. ON_EXIT:
  156. //
  157. // Do not close File. simply check file content
  158. //
  159. if (mImageBase != NULL) {
  160. FreePool (mImageBase);
  161. mImageBase = NULL;
  162. }
  163. return IsAuth2Format;
  164. }
  165. /**
  166. Set Secure Boot option into variable space.
  167. @param[in] VarValue The option of Secure Boot.
  168. @retval EFI_SUCCESS The operation is finished successfully.
  169. @retval Others Other errors as indicated.
  170. **/
  171. EFI_STATUS
  172. SaveSecureBootVariable (
  173. IN UINT8 VarValue
  174. )
  175. {
  176. EFI_STATUS Status;
  177. Status = gRT->SetVariable (
  178. EFI_SECURE_BOOT_ENABLE_NAME,
  179. &gEfiSecureBootEnableDisableGuid,
  180. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
  181. sizeof (UINT8),
  182. &VarValue
  183. );
  184. return Status;
  185. }
  186. /**
  187. Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
  188. descriptor with the input data. NO authentication is required in this function.
  189. @param[in, out] DataSize On input, the size of Data buffer in bytes.
  190. On output, the size of data returned in Data
  191. buffer in bytes.
  192. @param[in, out] Data On input, Pointer to data buffer to be wrapped or
  193. pointer to NULL to wrap an empty payload.
  194. On output, Pointer to the new payload date buffer allocated from pool,
  195. it's caller's responsibility to free the memory when finish using it.
  196. @retval EFI_SUCCESS Create time based payload successfully.
  197. @retval EFI_OUT_OF_RESOURCES There are not enough memory resources to create time based payload.
  198. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  199. @retval Others Unexpected error happens.
  200. **/
  201. EFI_STATUS
  202. CreateTimeBasedPayload (
  203. IN OUT UINTN *DataSize,
  204. IN OUT UINT8 **Data
  205. )
  206. {
  207. EFI_STATUS Status;
  208. UINT8 *NewData;
  209. UINT8 *Payload;
  210. UINTN PayloadSize;
  211. EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;
  212. UINTN DescriptorSize;
  213. EFI_TIME Time;
  214. if (Data == NULL || DataSize == NULL) {
  215. return EFI_INVALID_PARAMETER;
  216. }
  217. //
  218. // In Setup mode or Custom mode, the variable does not need to be signed but the
  219. // parameters to the SetVariable() call still need to be prepared as authenticated
  220. // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
  221. // data in it.
  222. //
  223. Payload = *Data;
  224. PayloadSize = *DataSize;
  225. DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
  226. NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
  227. if (NewData == NULL) {
  228. return EFI_OUT_OF_RESOURCES;
  229. }
  230. if ((Payload != NULL) && (PayloadSize != 0)) {
  231. CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
  232. }
  233. DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
  234. ZeroMem (&Time, sizeof (EFI_TIME));
  235. Status = gRT->GetTime (&Time, NULL);
  236. if (EFI_ERROR (Status)) {
  237. FreePool(NewData);
  238. return Status;
  239. }
  240. Time.Pad1 = 0;
  241. Time.Nanosecond = 0;
  242. Time.TimeZone = 0;
  243. Time.Daylight = 0;
  244. Time.Pad2 = 0;
  245. CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
  246. DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
  247. DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;
  248. DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
  249. CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
  250. if (Payload != NULL) {
  251. FreePool(Payload);
  252. }
  253. *DataSize = DescriptorSize + PayloadSize;
  254. *Data = NewData;
  255. return EFI_SUCCESS;
  256. }
  257. /**
  258. Internal helper function to delete a Variable given its name and GUID, NO authentication
  259. required.
  260. @param[in] VariableName Name of the Variable.
  261. @param[in] VendorGuid GUID of the Variable.
  262. @retval EFI_SUCCESS Variable deleted successfully.
  263. @retval Others The driver failed to start the device.
  264. **/
  265. EFI_STATUS
  266. DeleteVariable (
  267. IN CHAR16 *VariableName,
  268. IN EFI_GUID *VendorGuid
  269. )
  270. {
  271. EFI_STATUS Status;
  272. VOID* Variable;
  273. UINT8 *Data;
  274. UINTN DataSize;
  275. UINT32 Attr;
  276. GetVariable2 (VariableName, VendorGuid, &Variable, NULL);
  277. if (Variable == NULL) {
  278. return EFI_SUCCESS;
  279. }
  280. FreePool (Variable);
  281. Data = NULL;
  282. DataSize = 0;
  283. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
  284. | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  285. Status = CreateTimeBasedPayload (&DataSize, &Data);
  286. if (EFI_ERROR (Status)) {
  287. DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
  288. return Status;
  289. }
  290. Status = gRT->SetVariable (
  291. VariableName,
  292. VendorGuid,
  293. Attr,
  294. DataSize,
  295. Data
  296. );
  297. if (Data != NULL) {
  298. FreePool (Data);
  299. }
  300. return Status;
  301. }
  302. /**
  303. Set the platform secure boot mode into "Custom" or "Standard" mode.
  304. @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
  305. CUSTOM_SECURE_BOOT_MODE.
  306. @return EFI_SUCCESS The platform has switched to the special mode successfully.
  307. @return other Fail to operate the secure boot mode.
  308. **/
  309. EFI_STATUS
  310. SetSecureBootMode (
  311. IN UINT8 SecureBootMode
  312. )
  313. {
  314. return gRT->SetVariable (
  315. EFI_CUSTOM_MODE_NAME,
  316. &gEfiCustomModeEnableGuid,
  317. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
  318. sizeof (UINT8),
  319. &SecureBootMode
  320. );
  321. }
  322. /**
  323. Generate the PK signature list from the X509 Certificate storing file (.cer)
  324. @param[in] X509File FileHandle of X509 Certificate storing file.
  325. @param[out] PkCert Point to the data buffer to store the signature list.
  326. @return EFI_UNSUPPORTED Unsupported Key Length.
  327. @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list.
  328. **/
  329. EFI_STATUS
  330. CreatePkX509SignatureList (
  331. IN EFI_FILE_HANDLE X509File,
  332. OUT EFI_SIGNATURE_LIST **PkCert
  333. )
  334. {
  335. EFI_STATUS Status;
  336. UINT8 *X509Data;
  337. UINTN X509DataSize;
  338. EFI_SIGNATURE_DATA *PkCertData;
  339. X509Data = NULL;
  340. PkCertData = NULL;
  341. X509DataSize = 0;
  342. Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0);
  343. if (EFI_ERROR (Status)) {
  344. goto ON_EXIT;
  345. }
  346. ASSERT (X509Data != NULL);
  347. //
  348. // Allocate space for PK certificate list and initialize it.
  349. // Create PK database entry with SignatureHeaderSize equals 0.
  350. //
  351. *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool (
  352. sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1
  353. + X509DataSize
  354. );
  355. if (*PkCert == NULL) {
  356. Status = EFI_OUT_OF_RESOURCES;
  357. goto ON_EXIT;
  358. }
  359. (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST)
  360. + sizeof(EFI_SIGNATURE_DATA) - 1
  361. + X509DataSize);
  362. (*PkCert)->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
  363. (*PkCert)->SignatureHeaderSize = 0;
  364. CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid);
  365. PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert)
  366. + sizeof(EFI_SIGNATURE_LIST)
  367. + (*PkCert)->SignatureHeaderSize);
  368. CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);
  369. //
  370. // Fill the PK database with PKpub data from X509 certificate file.
  371. //
  372. CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);
  373. ON_EXIT:
  374. if (X509Data != NULL) {
  375. FreePool (X509Data);
  376. }
  377. if (EFI_ERROR(Status) && *PkCert != NULL) {
  378. FreePool (*PkCert);
  379. *PkCert = NULL;
  380. }
  381. return Status;
  382. }
  383. /**
  384. Enroll new PK into the System without original PK's authentication.
  385. The SignatureOwner GUID will be the same with PK's vendorguid.
  386. @param[in] PrivateData The module's private data.
  387. @retval EFI_SUCCESS New PK enrolled successfully.
  388. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  389. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  390. **/
  391. EFI_STATUS
  392. EnrollPlatformKey (
  393. IN SECUREBOOT_CONFIG_PRIVATE_DATA* Private
  394. )
  395. {
  396. EFI_STATUS Status;
  397. UINT32 Attr;
  398. UINTN DataSize;
  399. EFI_SIGNATURE_LIST *PkCert;
  400. UINT16* FilePostFix;
  401. UINTN NameLength;
  402. if (Private->FileContext->FileName == NULL) {
  403. return EFI_INVALID_PARAMETER;
  404. }
  405. PkCert = NULL;
  406. Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
  407. if (EFI_ERROR (Status)) {
  408. return Status;
  409. }
  410. //
  411. // Parse the file's postfix. Only support DER encoded X.509 certificate files.
  412. //
  413. NameLength = StrLen (Private->FileContext->FileName);
  414. if (NameLength <= 4) {
  415. return EFI_INVALID_PARAMETER;
  416. }
  417. FilePostFix = Private->FileContext->FileName + NameLength - 4;
  418. if (!IsDerEncodeCertificate(FilePostFix)) {
  419. DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));
  420. return EFI_INVALID_PARAMETER;
  421. }
  422. DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));
  423. DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));
  424. //
  425. // Prase the selected PK file and generate PK certificate list.
  426. //
  427. Status = CreatePkX509SignatureList (
  428. Private->FileContext->FHandle,
  429. &PkCert
  430. );
  431. if (EFI_ERROR (Status)) {
  432. goto ON_EXIT;
  433. }
  434. ASSERT (PkCert != NULL);
  435. //
  436. // Set Platform Key variable.
  437. //
  438. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
  439. | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  440. DataSize = PkCert->SignatureListSize;
  441. Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);
  442. if (EFI_ERROR (Status)) {
  443. DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
  444. goto ON_EXIT;
  445. }
  446. Status = gRT->SetVariable(
  447. EFI_PLATFORM_KEY_NAME,
  448. &gEfiGlobalVariableGuid,
  449. Attr,
  450. DataSize,
  451. PkCert
  452. );
  453. if (EFI_ERROR (Status)) {
  454. if (Status == EFI_OUT_OF_RESOURCES) {
  455. DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n"));
  456. }
  457. goto ON_EXIT;
  458. }
  459. ON_EXIT:
  460. if (PkCert != NULL) {
  461. FreePool(PkCert);
  462. }
  463. CloseEnrolledFile(Private->FileContext);
  464. return Status;
  465. }
  466. /**
  467. Remove the PK variable.
  468. @retval EFI_SUCCESS Delete PK successfully.
  469. @retval Others Could not allow to delete PK.
  470. **/
  471. EFI_STATUS
  472. DeletePlatformKey (
  473. VOID
  474. )
  475. {
  476. EFI_STATUS Status;
  477. Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
  478. if (EFI_ERROR (Status)) {
  479. return Status;
  480. }
  481. Status = DeleteVariable (
  482. EFI_PLATFORM_KEY_NAME,
  483. &gEfiGlobalVariableGuid
  484. );
  485. return Status;
  486. }
  487. /**
  488. Enroll a new KEK item from public key storing file (*.pbk).
  489. @param[in] PrivateData The module's private data.
  490. @retval EFI_SUCCESS New KEK enrolled successfully.
  491. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  492. @retval EFI_UNSUPPORTED Unsupported command.
  493. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  494. **/
  495. EFI_STATUS
  496. EnrollRsa2048ToKek (
  497. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
  498. )
  499. {
  500. EFI_STATUS Status;
  501. UINT32 Attr;
  502. UINTN DataSize;
  503. EFI_SIGNATURE_LIST *KekSigList;
  504. UINTN KeyBlobSize;
  505. UINT8 *KeyBlob;
  506. CPL_KEY_INFO *KeyInfo;
  507. EFI_SIGNATURE_DATA *KEKSigData;
  508. UINTN KekSigListSize;
  509. UINT8 *KeyBuffer;
  510. UINTN KeyLenInBytes;
  511. Attr = 0;
  512. DataSize = 0;
  513. KeyBuffer = NULL;
  514. KeyBlobSize = 0;
  515. KeyBlob = NULL;
  516. KeyInfo = NULL;
  517. KEKSigData = NULL;
  518. KekSigList = NULL;
  519. KekSigListSize = 0;
  520. //
  521. // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
  522. // First, We have to parse out public key data from the pbk key file.
  523. //
  524. Status = ReadFileContent (
  525. Private->FileContext->FHandle,
  526. (VOID**) &KeyBlob,
  527. &KeyBlobSize,
  528. 0
  529. );
  530. if (EFI_ERROR (Status)) {
  531. goto ON_EXIT;
  532. }
  533. ASSERT (KeyBlob != NULL);
  534. KeyInfo = (CPL_KEY_INFO *) KeyBlob;
  535. if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {
  536. DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n"));
  537. Status = EFI_UNSUPPORTED;
  538. goto ON_EXIT;
  539. }
  540. //
  541. // Convert the Public key to fix octet string format represented in RSA PKCS#1.
  542. //
  543. KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;
  544. KeyBuffer = AllocateZeroPool (KeyLenInBytes);
  545. if (KeyBuffer == NULL) {
  546. Status = EFI_OUT_OF_RESOURCES;
  547. goto ON_EXIT;
  548. }
  549. Int2OctStr (
  550. (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)),
  551. KeyLenInBytes / sizeof (UINTN),
  552. KeyBuffer,
  553. KeyLenInBytes
  554. );
  555. CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);
  556. //
  557. // Form an new EFI_SIGNATURE_LIST.
  558. //
  559. KekSigListSize = sizeof(EFI_SIGNATURE_LIST)
  560. + sizeof(EFI_SIGNATURE_DATA) - 1
  561. + WIN_CERT_UEFI_RSA2048_SIZE;
  562. KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);
  563. if (KekSigList == NULL) {
  564. Status = EFI_OUT_OF_RESOURCES;
  565. goto ON_EXIT;
  566. }
  567. KekSigList->SignatureListSize = sizeof(EFI_SIGNATURE_LIST)
  568. + sizeof(EFI_SIGNATURE_DATA) - 1
  569. + WIN_CERT_UEFI_RSA2048_SIZE;
  570. KekSigList->SignatureHeaderSize = 0;
  571. KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;
  572. CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);
  573. KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST));
  574. CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);
  575. CopyMem (
  576. KEKSigData->SignatureData,
  577. KeyBlob + sizeof(CPL_KEY_INFO),
  578. WIN_CERT_UEFI_RSA2048_SIZE
  579. );
  580. //
  581. // Check if KEK entry has been already existed.
  582. // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
  583. // new KEK to original variable.
  584. //
  585. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
  586. | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  587. Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);
  588. if (EFI_ERROR (Status)) {
  589. DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
  590. goto ON_EXIT;
  591. }
  592. Status = gRT->GetVariable(
  593. EFI_KEY_EXCHANGE_KEY_NAME,
  594. &gEfiGlobalVariableGuid,
  595. NULL,
  596. &DataSize,
  597. NULL
  598. );
  599. if (Status == EFI_BUFFER_TOO_SMALL) {
  600. Attr |= EFI_VARIABLE_APPEND_WRITE;
  601. } else if (Status != EFI_NOT_FOUND) {
  602. goto ON_EXIT;
  603. }
  604. //
  605. // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
  606. //
  607. Status = gRT->SetVariable(
  608. EFI_KEY_EXCHANGE_KEY_NAME,
  609. &gEfiGlobalVariableGuid,
  610. Attr,
  611. KekSigListSize,
  612. KekSigList
  613. );
  614. if (EFI_ERROR (Status)) {
  615. goto ON_EXIT;
  616. }
  617. ON_EXIT:
  618. CloseEnrolledFile(Private->FileContext);
  619. if (Private->SignatureGUID != NULL) {
  620. FreePool (Private->SignatureGUID);
  621. Private->SignatureGUID = NULL;
  622. }
  623. if (KeyBlob != NULL) {
  624. FreePool (KeyBlob);
  625. }
  626. if (KeyBuffer != NULL) {
  627. FreePool (KeyBuffer);
  628. }
  629. if (KekSigList != NULL) {
  630. FreePool (KekSigList);
  631. }
  632. return Status;
  633. }
  634. /**
  635. Enroll a new KEK item from X509 certificate file.
  636. @param[in] PrivateData The module's private data.
  637. @retval EFI_SUCCESS New X509 is enrolled successfully.
  638. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  639. @retval EFI_UNSUPPORTED Unsupported command.
  640. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  641. **/
  642. EFI_STATUS
  643. EnrollX509ToKek (
  644. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
  645. )
  646. {
  647. EFI_STATUS Status;
  648. UINTN X509DataSize;
  649. VOID *X509Data;
  650. EFI_SIGNATURE_DATA *KEKSigData;
  651. EFI_SIGNATURE_LIST *KekSigList;
  652. UINTN DataSize;
  653. UINTN KekSigListSize;
  654. UINT32 Attr;
  655. X509Data = NULL;
  656. X509DataSize = 0;
  657. KekSigList = NULL;
  658. KekSigListSize = 0;
  659. DataSize = 0;
  660. KEKSigData = NULL;
  661. Status = ReadFileContent (
  662. Private->FileContext->FHandle,
  663. &X509Data,
  664. &X509DataSize,
  665. 0
  666. );
  667. if (EFI_ERROR (Status)) {
  668. goto ON_EXIT;
  669. }
  670. ASSERT (X509Data != NULL);
  671. KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
  672. KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);
  673. if (KekSigList == NULL) {
  674. Status = EFI_OUT_OF_RESOURCES;
  675. goto ON_EXIT;
  676. }
  677. //
  678. // Fill Certificate Database parameters.
  679. //
  680. KekSigList->SignatureListSize = (UINT32) KekSigListSize;
  681. KekSigList->SignatureHeaderSize = 0;
  682. KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
  683. CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid);
  684. KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST));
  685. CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);
  686. CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize);
  687. //
  688. // Check if KEK been already existed.
  689. // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
  690. // new kek to original variable
  691. //
  692. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
  693. | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  694. Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);
  695. if (EFI_ERROR (Status)) {
  696. DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
  697. goto ON_EXIT;
  698. }
  699. Status = gRT->GetVariable(
  700. EFI_KEY_EXCHANGE_KEY_NAME,
  701. &gEfiGlobalVariableGuid,
  702. NULL,
  703. &DataSize,
  704. NULL
  705. );
  706. if (Status == EFI_BUFFER_TOO_SMALL) {
  707. Attr |= EFI_VARIABLE_APPEND_WRITE;
  708. } else if (Status != EFI_NOT_FOUND) {
  709. goto ON_EXIT;
  710. }
  711. Status = gRT->SetVariable(
  712. EFI_KEY_EXCHANGE_KEY_NAME,
  713. &gEfiGlobalVariableGuid,
  714. Attr,
  715. KekSigListSize,
  716. KekSigList
  717. );
  718. if (EFI_ERROR (Status)) {
  719. goto ON_EXIT;
  720. }
  721. ON_EXIT:
  722. CloseEnrolledFile(Private->FileContext);
  723. if (Private->SignatureGUID != NULL) {
  724. FreePool (Private->SignatureGUID);
  725. Private->SignatureGUID = NULL;
  726. }
  727. if (KekSigList != NULL) {
  728. FreePool (KekSigList);
  729. }
  730. return Status;
  731. }
  732. /**
  733. Enroll new KEK into the System without PK's authentication.
  734. The SignatureOwner GUID will be Private->SignatureGUID.
  735. @param[in] PrivateData The module's private data.
  736. @retval EFI_SUCCESS New KEK enrolled successful.
  737. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  738. @retval others Fail to enroll KEK data.
  739. **/
  740. EFI_STATUS
  741. EnrollKeyExchangeKey (
  742. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
  743. )
  744. {
  745. UINT16* FilePostFix;
  746. EFI_STATUS Status;
  747. UINTN NameLength;
  748. if ((Private->FileContext->FHandle == NULL) || (Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {
  749. return EFI_INVALID_PARAMETER;
  750. }
  751. Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
  752. if (EFI_ERROR (Status)) {
  753. return Status;
  754. }
  755. //
  756. // Parse the file's postfix. Supports DER-encoded X509 certificate,
  757. // and .pbk as RSA public key file.
  758. //
  759. NameLength = StrLen (Private->FileContext->FileName);
  760. if (NameLength <= 4) {
  761. return EFI_INVALID_PARAMETER;
  762. }
  763. FilePostFix = Private->FileContext->FileName + NameLength - 4;
  764. if (IsDerEncodeCertificate(FilePostFix)) {
  765. return EnrollX509ToKek (Private);
  766. } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {
  767. return EnrollRsa2048ToKek (Private);
  768. } else {
  769. //
  770. // File type is wrong, simply close it
  771. //
  772. CloseEnrolledFile(Private->FileContext);
  773. return EFI_INVALID_PARAMETER;
  774. }
  775. }
  776. /**
  777. Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
  778. KEK's authentication.
  779. @param[in] PrivateData The module's private data.
  780. @param[in] VariableName Variable name of signature database, must be
  781. EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
  782. @retval EFI_SUCCESS New X509 is enrolled successfully.
  783. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  784. **/
  785. EFI_STATUS
  786. EnrollX509toSigDB (
  787. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
  788. IN CHAR16 *VariableName
  789. )
  790. {
  791. EFI_STATUS Status;
  792. UINTN X509DataSize;
  793. VOID *X509Data;
  794. EFI_SIGNATURE_LIST *SigDBCert;
  795. EFI_SIGNATURE_DATA *SigDBCertData;
  796. VOID *Data;
  797. UINTN DataSize;
  798. UINTN SigDBSize;
  799. UINT32 Attr;
  800. X509DataSize = 0;
  801. SigDBSize = 0;
  802. DataSize = 0;
  803. X509Data = NULL;
  804. SigDBCert = NULL;
  805. SigDBCertData = NULL;
  806. Data = NULL;
  807. Status = ReadFileContent (
  808. Private->FileContext->FHandle,
  809. &X509Data,
  810. &X509DataSize,
  811. 0
  812. );
  813. if (EFI_ERROR (Status)) {
  814. goto ON_EXIT;
  815. }
  816. ASSERT (X509Data != NULL);
  817. SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
  818. Data = AllocateZeroPool (SigDBSize);
  819. if (Data == NULL) {
  820. Status = EFI_OUT_OF_RESOURCES;
  821. goto ON_EXIT;
  822. }
  823. //
  824. // Fill Certificate Database parameters.
  825. //
  826. SigDBCert = (EFI_SIGNATURE_LIST*) Data;
  827. SigDBCert->SignatureListSize = (UINT32) SigDBSize;
  828. SigDBCert->SignatureHeaderSize = 0;
  829. SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
  830. CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid);
  831. SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST));
  832. CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
  833. CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize);
  834. //
  835. // Check if signature database entry has been already existed.
  836. // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
  837. // new signature data to original variable
  838. //
  839. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
  840. | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  841. Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);
  842. if (EFI_ERROR (Status)) {
  843. DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
  844. goto ON_EXIT;
  845. }
  846. Status = gRT->GetVariable(
  847. VariableName,
  848. &gEfiImageSecurityDatabaseGuid,
  849. NULL,
  850. &DataSize,
  851. NULL
  852. );
  853. if (Status == EFI_BUFFER_TOO_SMALL) {
  854. Attr |= EFI_VARIABLE_APPEND_WRITE;
  855. } else if (Status != EFI_NOT_FOUND) {
  856. goto ON_EXIT;
  857. }
  858. Status = gRT->SetVariable(
  859. VariableName,
  860. &gEfiImageSecurityDatabaseGuid,
  861. Attr,
  862. SigDBSize,
  863. Data
  864. );
  865. if (EFI_ERROR (Status)) {
  866. goto ON_EXIT;
  867. }
  868. ON_EXIT:
  869. CloseEnrolledFile(Private->FileContext);
  870. if (Private->SignatureGUID != NULL) {
  871. FreePool (Private->SignatureGUID);
  872. Private->SignatureGUID = NULL;
  873. }
  874. if (Data != NULL) {
  875. FreePool (Data);
  876. }
  877. if (X509Data != NULL) {
  878. FreePool (X509Data);
  879. }
  880. return Status;
  881. }
  882. /**
  883. Check whether signature is in specified database.
  884. @param[in] VariableName Name of database variable that is searched in.
  885. @param[in] Signature Pointer to signature that is searched for.
  886. @param[in] SignatureSize Size of Signature.
  887. @return TRUE Found the signature in the variable database.
  888. @return FALSE Not found the signature in the variable database.
  889. **/
  890. BOOLEAN
  891. IsSignatureFoundInDatabase (
  892. IN CHAR16 *VariableName,
  893. IN UINT8 *Signature,
  894. IN UINTN SignatureSize
  895. )
  896. {
  897. EFI_STATUS Status;
  898. EFI_SIGNATURE_LIST *CertList;
  899. EFI_SIGNATURE_DATA *Cert;
  900. UINTN DataSize;
  901. UINT8 *Data;
  902. UINTN Index;
  903. UINTN CertCount;
  904. BOOLEAN IsFound;
  905. //
  906. // Read signature database variable.
  907. //
  908. IsFound = FALSE;
  909. Data = NULL;
  910. DataSize = 0;
  911. Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
  912. if (Status != EFI_BUFFER_TOO_SMALL) {
  913. return FALSE;
  914. }
  915. Data = (UINT8 *) AllocateZeroPool (DataSize);
  916. if (Data == NULL) {
  917. return FALSE;
  918. }
  919. Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
  920. if (EFI_ERROR (Status)) {
  921. goto Done;
  922. }
  923. //
  924. // Enumerate all signature data in SigDB to check if signature exists for executable.
  925. //
  926. CertList = (EFI_SIGNATURE_LIST *) Data;
  927. while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
  928. CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
  929. Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
  930. if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &gEfiCertX509Guid))) {
  931. for (Index = 0; Index < CertCount; Index++) {
  932. if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {
  933. //
  934. // Find the signature in database.
  935. //
  936. IsFound = TRUE;
  937. break;
  938. }
  939. Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
  940. }
  941. if (IsFound) {
  942. break;
  943. }
  944. }
  945. DataSize -= CertList->SignatureListSize;
  946. CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
  947. }
  948. Done:
  949. if (Data != NULL) {
  950. FreePool (Data);
  951. }
  952. return IsFound;
  953. }
  954. /**
  955. Calculate the hash of a certificate data with the specified hash algorithm.
  956. @param[in] CertData The certificate data to be hashed.
  957. @param[in] CertSize The certificate size in bytes.
  958. @param[in] HashAlg The specified hash algorithm.
  959. @param[out] CertHash The output digest of the certificate
  960. @retval TRUE Successfully got the hash of the CertData.
  961. @retval FALSE Failed to get the hash of CertData.
  962. **/
  963. BOOLEAN
  964. CalculateCertHash (
  965. IN UINT8 *CertData,
  966. IN UINTN CertSize,
  967. IN UINT32 HashAlg,
  968. OUT UINT8 *CertHash
  969. )
  970. {
  971. BOOLEAN Status;
  972. VOID *HashCtx;
  973. UINTN CtxSize;
  974. UINT8 *TBSCert;
  975. UINTN TBSCertSize;
  976. HashCtx = NULL;
  977. Status = FALSE;
  978. if (HashAlg >= HASHALG_MAX) {
  979. return FALSE;
  980. }
  981. //
  982. // Retrieve the TBSCertificate for Hash Calculation.
  983. //
  984. if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) {
  985. return FALSE;
  986. }
  987. //
  988. // 1. Initialize context of hash.
  989. //
  990. CtxSize = mHash[HashAlg].GetContextSize ();
  991. HashCtx = AllocatePool (CtxSize);
  992. ASSERT (HashCtx != NULL);
  993. //
  994. // 2. Initialize a hash context.
  995. //
  996. Status = mHash[HashAlg].HashInit (HashCtx);
  997. if (!Status) {
  998. goto Done;
  999. }
  1000. //
  1001. // 3. Calculate the hash.
  1002. //
  1003. Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);
  1004. if (!Status) {
  1005. goto Done;
  1006. }
  1007. //
  1008. // 4. Get the hash result.
  1009. //
  1010. ZeroMem (CertHash, mHash[HashAlg].DigestLength);
  1011. Status = mHash[HashAlg].HashFinal (HashCtx, CertHash);
  1012. Done:
  1013. if (HashCtx != NULL) {
  1014. FreePool (HashCtx);
  1015. }
  1016. return Status;
  1017. }
  1018. /**
  1019. Check whether the hash of an X.509 certificate is in forbidden database (DBX).
  1020. @param[in] Certificate Pointer to X.509 Certificate that is searched for.
  1021. @param[in] CertSize Size of X.509 Certificate.
  1022. @return TRUE Found the certificate hash in the forbidden database.
  1023. @return FALSE Certificate hash is Not found in the forbidden database.
  1024. **/
  1025. BOOLEAN
  1026. IsCertHashFoundInDbx (
  1027. IN UINT8 *Certificate,
  1028. IN UINTN CertSize
  1029. )
  1030. {
  1031. BOOLEAN IsFound;
  1032. EFI_STATUS Status;
  1033. EFI_SIGNATURE_LIST *DbxList;
  1034. EFI_SIGNATURE_DATA *CertHash;
  1035. UINTN CertHashCount;
  1036. UINTN Index;
  1037. UINT32 HashAlg;
  1038. UINT8 CertDigest[MAX_DIGEST_SIZE];
  1039. UINT8 *DbxCertHash;
  1040. UINTN SiglistHeaderSize;
  1041. UINT8 *Data;
  1042. UINTN DataSize;
  1043. IsFound = FALSE;
  1044. HashAlg = HASHALG_MAX;
  1045. Data = NULL;
  1046. //
  1047. // Read signature database variable.
  1048. //
  1049. DataSize = 0;
  1050. Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
  1051. if (Status != EFI_BUFFER_TOO_SMALL) {
  1052. return FALSE;
  1053. }
  1054. Data = (UINT8 *) AllocateZeroPool (DataSize);
  1055. if (Data == NULL) {
  1056. return FALSE;
  1057. }
  1058. Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
  1059. if (EFI_ERROR (Status)) {
  1060. goto Done;
  1061. }
  1062. //
  1063. // Check whether the certificate hash exists in the forbidden database.
  1064. //
  1065. DbxList = (EFI_SIGNATURE_LIST *) Data;
  1066. while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) {
  1067. //
  1068. // Determine Hash Algorithm of Certificate in the forbidden database.
  1069. //
  1070. if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {
  1071. HashAlg = HASHALG_SHA256;
  1072. } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {
  1073. HashAlg = HASHALG_SHA384;
  1074. } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {
  1075. HashAlg = HASHALG_SHA512;
  1076. } else {
  1077. DataSize -= DbxList->SignatureListSize;
  1078. DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
  1079. continue;
  1080. }
  1081. //
  1082. // Calculate the hash value of current db certificate for comparision.
  1083. //
  1084. if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) {
  1085. goto Done;
  1086. }
  1087. SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;
  1088. CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);
  1089. CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;
  1090. for (Index = 0; Index < CertHashCount; Index++) {
  1091. //
  1092. // Iterate each Signature Data Node within this CertList for verify.
  1093. //
  1094. DbxCertHash = CertHash->SignatureData;
  1095. if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {
  1096. //
  1097. // Hash of Certificate is found in forbidden database.
  1098. //
  1099. IsFound = TRUE;
  1100. goto Done;
  1101. }
  1102. CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);
  1103. }
  1104. DataSize -= DbxList->SignatureListSize;
  1105. DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
  1106. }
  1107. Done:
  1108. if (Data != NULL) {
  1109. FreePool (Data);
  1110. }
  1111. return IsFound;
  1112. }
  1113. /**
  1114. Check whether the signature list exists in given variable data.
  1115. It searches the signature list for the certificate hash by CertType.
  1116. If the signature list is found, get the offset of Database for the
  1117. next hash of a certificate.
  1118. @param[in] Database Variable data to save signature list.
  1119. @param[in] DatabaseSize Variable size.
  1120. @param[in] SignatureType The type of the signature.
  1121. @param[out] Offset The offset to save a new hash of certificate.
  1122. @return TRUE The signature list is found in the forbidden database.
  1123. @return FALSE The signature list is not found in the forbidden database.
  1124. **/
  1125. BOOLEAN
  1126. GetSignaturelistOffset (
  1127. IN EFI_SIGNATURE_LIST *Database,
  1128. IN UINTN DatabaseSize,
  1129. IN EFI_GUID *SignatureType,
  1130. OUT UINTN *Offset
  1131. )
  1132. {
  1133. EFI_SIGNATURE_LIST *SigList;
  1134. UINTN SiglistSize;
  1135. if ((Database == NULL) || (DatabaseSize == 0)) {
  1136. *Offset = 0;
  1137. return FALSE;
  1138. }
  1139. SigList = Database;
  1140. SiglistSize = DatabaseSize;
  1141. while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) {
  1142. if (CompareGuid (&SigList->SignatureType, SignatureType)) {
  1143. *Offset = DatabaseSize - SiglistSize;
  1144. return TRUE;
  1145. }
  1146. SiglistSize -= SigList->SignatureListSize;
  1147. SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);
  1148. }
  1149. *Offset = 0;
  1150. return FALSE;
  1151. }
  1152. /**
  1153. Enroll a new X509 certificate hash into Signature Database (dbx) without
  1154. KEK's authentication.
  1155. @param[in] PrivateData The module's private data.
  1156. @param[in] HashAlg The hash algorithm to enroll the certificate.
  1157. @param[in] RevocationDate The revocation date of the certificate.
  1158. @param[in] RevocationTime The revocation time of the certificate.
  1159. @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
  1160. @retval EFI_SUCCESS New X509 is enrolled successfully.
  1161. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  1162. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  1163. **/
  1164. EFI_STATUS
  1165. EnrollX509HashtoSigDB (
  1166. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
  1167. IN UINT32 HashAlg,
  1168. IN EFI_HII_DATE *RevocationDate,
  1169. IN EFI_HII_TIME *RevocationTime,
  1170. IN BOOLEAN AlwaysRevocation
  1171. )
  1172. {
  1173. EFI_STATUS Status;
  1174. UINTN X509DataSize;
  1175. VOID *X509Data;
  1176. EFI_SIGNATURE_LIST *SignatureList;
  1177. UINTN SignatureListSize;
  1178. UINT8 *Data;
  1179. UINT8 *NewData;
  1180. UINTN DataSize;
  1181. UINTN DbSize;
  1182. UINT32 Attr;
  1183. EFI_SIGNATURE_DATA *SignatureData;
  1184. UINTN SignatureSize;
  1185. EFI_GUID SignatureType;
  1186. UINTN Offset;
  1187. UINT8 CertHash[MAX_DIGEST_SIZE];
  1188. UINT16* FilePostFix;
  1189. UINTN NameLength;
  1190. EFI_TIME *Time;
  1191. X509DataSize = 0;
  1192. DbSize = 0;
  1193. X509Data = NULL;
  1194. SignatureData = NULL;
  1195. SignatureList = NULL;
  1196. Data = NULL;
  1197. NewData = NULL;
  1198. if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
  1199. return EFI_INVALID_PARAMETER;
  1200. }
  1201. Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
  1202. if (EFI_ERROR (Status)) {
  1203. return Status;
  1204. }
  1205. //
  1206. // Parse the file's postfix.
  1207. //
  1208. NameLength = StrLen (Private->FileContext->FileName);
  1209. if (NameLength <= 4) {
  1210. return EFI_INVALID_PARAMETER;
  1211. }
  1212. FilePostFix = Private->FileContext->FileName + NameLength - 4;
  1213. if (!IsDerEncodeCertificate(FilePostFix)) {
  1214. //
  1215. // Only supports DER-encoded X509 certificate.
  1216. //
  1217. return EFI_INVALID_PARAMETER;
  1218. }
  1219. //
  1220. // Get the certificate from file and calculate its hash.
  1221. //
  1222. Status = ReadFileContent (
  1223. Private->FileContext->FHandle,
  1224. &X509Data,
  1225. &X509DataSize,
  1226. 0
  1227. );
  1228. if (EFI_ERROR (Status)) {
  1229. goto ON_EXIT;
  1230. }
  1231. ASSERT (X509Data != NULL);
  1232. if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) {
  1233. goto ON_EXIT;
  1234. }
  1235. //
  1236. // Get the variable for enrollment.
  1237. //
  1238. DataSize = 0;
  1239. Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
  1240. if (Status == EFI_BUFFER_TOO_SMALL) {
  1241. Data = (UINT8 *) AllocateZeroPool (DataSize);
  1242. if (Data == NULL) {
  1243. return EFI_OUT_OF_RESOURCES;
  1244. }
  1245. Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
  1246. if (EFI_ERROR (Status)) {
  1247. goto ON_EXIT;
  1248. }
  1249. }
  1250. //
  1251. // Allocate memory for Signature and fill the Signature
  1252. //
  1253. SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength;
  1254. SignatureData = (EFI_SIGNATURE_DATA *) AllocateZeroPool (SignatureSize);
  1255. if (SignatureData == NULL) {
  1256. return EFI_OUT_OF_RESOURCES;
  1257. }
  1258. CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID);
  1259. CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength);
  1260. //
  1261. // Fill the time.
  1262. //
  1263. if (!AlwaysRevocation) {
  1264. Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength);
  1265. Time->Year = RevocationDate->Year;
  1266. Time->Month = RevocationDate->Month;
  1267. Time->Day = RevocationDate->Day;
  1268. Time->Hour = RevocationTime->Hour;
  1269. Time->Minute = RevocationTime->Minute;
  1270. Time->Second = RevocationTime->Second;
  1271. }
  1272. //
  1273. // Determine the GUID for certificate hash.
  1274. //
  1275. switch (HashAlg) {
  1276. case HASHALG_SHA256:
  1277. SignatureType = gEfiCertX509Sha256Guid;
  1278. break;
  1279. case HASHALG_SHA384:
  1280. SignatureType = gEfiCertX509Sha384Guid;
  1281. break;
  1282. case HASHALG_SHA512:
  1283. SignatureType = gEfiCertX509Sha512Guid;
  1284. break;
  1285. default:
  1286. return FALSE;
  1287. }
  1288. //
  1289. // Add signature into the new variable data buffer
  1290. //
  1291. if (GetSignaturelistOffset((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) {
  1292. //
  1293. // Add the signature to the found signaturelist.
  1294. //
  1295. DbSize = DataSize + SignatureSize;
  1296. NewData = AllocateZeroPool (DbSize);
  1297. if (NewData == NULL) {
  1298. Status = EFI_OUT_OF_RESOURCES;
  1299. goto ON_EXIT;
  1300. }
  1301. SignatureList = (EFI_SIGNATURE_LIST *)(Data + Offset);
  1302. SignatureListSize = (UINTN) ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize);
  1303. CopyMem (NewData, Data, Offset + SignatureListSize);
  1304. SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset);
  1305. WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize));
  1306. Offset += SignatureListSize;
  1307. CopyMem (NewData + Offset, SignatureData, SignatureSize);
  1308. CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset);
  1309. FreePool (Data);
  1310. Data = NewData;
  1311. DataSize = DbSize;
  1312. } else {
  1313. //
  1314. // Create a new signaturelist, and add the signature into the signaturelist.
  1315. //
  1316. DbSize = DataSize + sizeof(EFI_SIGNATURE_LIST) + SignatureSize;
  1317. NewData = AllocateZeroPool (DbSize);
  1318. if (NewData == NULL) {
  1319. Status = EFI_OUT_OF_RESOURCES;
  1320. goto ON_EXIT;
  1321. }
  1322. //
  1323. // Fill Certificate Database parameters.
  1324. //
  1325. SignatureList = (EFI_SIGNATURE_LIST*) (NewData + DataSize);
  1326. SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + SignatureSize;
  1327. WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32) SignatureListSize);
  1328. WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureSize, (UINT32) SignatureSize);
  1329. CopyGuid (&SignatureList->SignatureType, &SignatureType);
  1330. CopyMem ((UINT8* ) SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize);
  1331. if ((DataSize != 0) && (Data != NULL)) {
  1332. CopyMem (NewData, Data, DataSize);
  1333. FreePool (Data);
  1334. }
  1335. Data = NewData;
  1336. DataSize = DbSize;
  1337. }
  1338. Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &Data);
  1339. if (EFI_ERROR (Status)) {
  1340. goto ON_EXIT;
  1341. }
  1342. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
  1343. | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  1344. Status = gRT->SetVariable(
  1345. EFI_IMAGE_SECURITY_DATABASE1,
  1346. &gEfiImageSecurityDatabaseGuid,
  1347. Attr,
  1348. DataSize,
  1349. Data
  1350. );
  1351. if (EFI_ERROR (Status)) {
  1352. goto ON_EXIT;
  1353. }
  1354. ON_EXIT:
  1355. CloseEnrolledFile(Private->FileContext);
  1356. if (Private->SignatureGUID != NULL) {
  1357. FreePool (Private->SignatureGUID);
  1358. Private->SignatureGUID = NULL;
  1359. }
  1360. if (Data != NULL) {
  1361. FreePool (Data);
  1362. }
  1363. if (SignatureData != NULL) {
  1364. FreePool (SignatureData);
  1365. }
  1366. if (X509Data != NULL) {
  1367. FreePool (X509Data);
  1368. }
  1369. return Status;
  1370. }
  1371. /**
  1372. Check whether a certificate from a file exists in dbx.
  1373. @param[in] PrivateData The module's private data.
  1374. @param[in] VariableName Variable name of signature database, must be
  1375. EFI_IMAGE_SECURITY_DATABASE1.
  1376. @retval TRUE The X509 certificate is found in dbx successfully.
  1377. @retval FALSE The X509 certificate is not found in dbx.
  1378. **/
  1379. BOOLEAN
  1380. IsX509CertInDbx (
  1381. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
  1382. IN CHAR16 *VariableName
  1383. )
  1384. {
  1385. EFI_STATUS Status;
  1386. UINTN X509DataSize;
  1387. VOID *X509Data;
  1388. BOOLEAN IsFound;
  1389. //
  1390. // Read the certificate from file
  1391. //
  1392. X509DataSize = 0;
  1393. X509Data = NULL;
  1394. Status = ReadFileContent (
  1395. Private->FileContext->FHandle,
  1396. &X509Data,
  1397. &X509DataSize,
  1398. 0
  1399. );
  1400. if (EFI_ERROR (Status)) {
  1401. return FALSE;
  1402. }
  1403. //
  1404. // Check the raw certificate.
  1405. //
  1406. IsFound = FALSE;
  1407. if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) {
  1408. IsFound = TRUE;
  1409. goto ON_EXIT;
  1410. }
  1411. //
  1412. // Check the hash of certificate.
  1413. //
  1414. if (IsCertHashFoundInDbx (X509Data, X509DataSize)) {
  1415. IsFound = TRUE;
  1416. goto ON_EXIT;
  1417. }
  1418. ON_EXIT:
  1419. if (X509Data != NULL) {
  1420. FreePool (X509Data);
  1421. }
  1422. return IsFound;
  1423. }
  1424. /**
  1425. Reads contents of a PE/COFF image in memory buffer.
  1426. Caution: This function may receive untrusted input.
  1427. PE/COFF image is external input, so this function will make sure the PE/COFF image content
  1428. read is within the image buffer.
  1429. @param FileHandle Pointer to the file handle to read the PE/COFF image.
  1430. @param FileOffset Offset into the PE/COFF image to begin the read operation.
  1431. @param ReadSize On input, the size in bytes of the requested read operation.
  1432. On output, the number of bytes actually read.
  1433. @param Buffer Output buffer that contains the data read from the PE/COFF image.
  1434. @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
  1435. **/
  1436. EFI_STATUS
  1437. EFIAPI
  1438. SecureBootConfigImageRead (
  1439. IN VOID *FileHandle,
  1440. IN UINTN FileOffset,
  1441. IN OUT UINTN *ReadSize,
  1442. OUT VOID *Buffer
  1443. )
  1444. {
  1445. UINTN EndPosition;
  1446. if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {
  1447. return EFI_INVALID_PARAMETER;
  1448. }
  1449. if (MAX_ADDRESS - FileOffset < *ReadSize) {
  1450. return EFI_INVALID_PARAMETER;
  1451. }
  1452. EndPosition = FileOffset + *ReadSize;
  1453. if (EndPosition > mImageSize) {
  1454. *ReadSize = (UINT32)(mImageSize - FileOffset);
  1455. }
  1456. if (FileOffset >= mImageSize) {
  1457. *ReadSize = 0;
  1458. }
  1459. CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
  1460. return EFI_SUCCESS;
  1461. }
  1462. /**
  1463. Load PE/COFF image information into internal buffer and check its validity.
  1464. @retval EFI_SUCCESS Successful
  1465. @retval EFI_UNSUPPORTED Invalid PE/COFF file
  1466. @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
  1467. **/
  1468. EFI_STATUS
  1469. LoadPeImage (
  1470. VOID
  1471. )
  1472. {
  1473. EFI_IMAGE_DOS_HEADER *DosHdr;
  1474. EFI_IMAGE_NT_HEADERS32 *NtHeader32;
  1475. EFI_IMAGE_NT_HEADERS64 *NtHeader64;
  1476. PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
  1477. EFI_STATUS Status;
  1478. NtHeader32 = NULL;
  1479. NtHeader64 = NULL;
  1480. ZeroMem (&ImageContext, sizeof (ImageContext));
  1481. ImageContext.Handle = (VOID *) mImageBase;
  1482. ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecureBootConfigImageRead;
  1483. //
  1484. // Get information about the image being loaded
  1485. //
  1486. Status = PeCoffLoaderGetImageInfo (&ImageContext);
  1487. if (EFI_ERROR (Status)) {
  1488. //
  1489. // The information can't be got from the invalid PeImage
  1490. //
  1491. DEBUG ((DEBUG_INFO, "SecureBootConfigDxe: PeImage invalid. \n"));
  1492. return Status;
  1493. }
  1494. //
  1495. // Read the Dos header
  1496. //
  1497. DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase);
  1498. if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
  1499. {
  1500. //
  1501. // DOS image header is present,
  1502. // So read the PE header after the DOS image header
  1503. //
  1504. mPeCoffHeaderOffset = DosHdr->e_lfanew;
  1505. }
  1506. else
  1507. {
  1508. mPeCoffHeaderOffset = 0;
  1509. }
  1510. //
  1511. // Read PE header and check the signature validity and machine compatibility
  1512. //
  1513. NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset);
  1514. if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE)
  1515. {
  1516. return EFI_UNSUPPORTED;
  1517. }
  1518. mNtHeader.Pe32 = NtHeader32;
  1519. //
  1520. // Check the architecture field of PE header and get the Certificate Data Directory data
  1521. // Note the size of FileHeader field is constant for both IA32 and X64 arch
  1522. //
  1523. if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)
  1524. || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)
  1525. || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)) {
  1526. //
  1527. // 32-bits Architecture
  1528. //
  1529. mImageType = ImageType_IA32;
  1530. mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
  1531. }
  1532. else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)
  1533. || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)
  1534. || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64)) {
  1535. //
  1536. // 64-bits Architecture
  1537. //
  1538. mImageType = ImageType_X64;
  1539. NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);
  1540. mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
  1541. } else {
  1542. return EFI_UNSUPPORTED;
  1543. }
  1544. return EFI_SUCCESS;
  1545. }
  1546. /**
  1547. Calculate hash of Pe/Coff image based on the authenticode image hashing in
  1548. PE/COFF Specification 8.0 Appendix A
  1549. Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
  1550. the function LoadPeImage ().
  1551. @param[in] HashAlg Hash algorithm type.
  1552. @retval TRUE Successfully hash image.
  1553. @retval FALSE Fail in hash image.
  1554. **/
  1555. BOOLEAN
  1556. HashPeImage (
  1557. IN UINT32 HashAlg
  1558. )
  1559. {
  1560. BOOLEAN Status;
  1561. EFI_IMAGE_SECTION_HEADER *Section;
  1562. VOID *HashCtx;
  1563. UINTN CtxSize;
  1564. UINT8 *HashBase;
  1565. UINTN HashSize;
  1566. UINTN SumOfBytesHashed;
  1567. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  1568. UINTN Index;
  1569. UINTN Pos;
  1570. HashCtx = NULL;
  1571. SectionHeader = NULL;
  1572. Status = FALSE;
  1573. if (HashAlg != HASHALG_SHA256) {
  1574. return FALSE;
  1575. }
  1576. //
  1577. // Initialize context of hash.
  1578. //
  1579. ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
  1580. mImageDigestSize = SHA256_DIGEST_SIZE;
  1581. mCertType = gEfiCertSha256Guid;
  1582. CtxSize = mHash[HashAlg].GetContextSize();
  1583. HashCtx = AllocatePool (CtxSize);
  1584. ASSERT (HashCtx != NULL);
  1585. // 1. Load the image header into memory.
  1586. // 2. Initialize a SHA hash context.
  1587. Status = mHash[HashAlg].HashInit(HashCtx);
  1588. if (!Status) {
  1589. goto Done;
  1590. }
  1591. //
  1592. // Measuring PE/COFF Image Header;
  1593. // But CheckSum field and SECURITY data directory (certificate) are excluded
  1594. //
  1595. //
  1596. // 3. Calculate the distance from the base of the image header to the image checksum address.
  1597. // 4. Hash the image header from its base to beginning of the image checksum.
  1598. //
  1599. HashBase = mImageBase;
  1600. if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  1601. //
  1602. // Use PE32 offset.
  1603. //
  1604. HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN) HashBase;
  1605. } else {
  1606. //
  1607. // Use PE32+ offset.
  1608. //
  1609. HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN) HashBase;
  1610. }
  1611. Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
  1612. if (!Status) {
  1613. goto Done;
  1614. }
  1615. //
  1616. // 5. Skip over the image checksum (it occupies a single ULONG).
  1617. // 6. Get the address of the beginning of the Cert Directory.
  1618. // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
  1619. //
  1620. if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  1621. //
  1622. // Use PE32 offset.
  1623. //
  1624. HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
  1625. HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;
  1626. } else {
  1627. //
  1628. // Use PE32+ offset.
  1629. //
  1630. HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
  1631. HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;
  1632. }
  1633. Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
  1634. if (!Status) {
  1635. goto Done;
  1636. }
  1637. //
  1638. // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
  1639. // 9. Hash everything from the end of the Cert Directory to the end of image header.
  1640. //
  1641. if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  1642. //
  1643. // Use PE32 offset
  1644. //
  1645. HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
  1646. HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase);
  1647. } else {
  1648. //
  1649. // Use PE32+ offset.
  1650. //
  1651. HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
  1652. HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase);
  1653. }
  1654. Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
  1655. if (!Status) {
  1656. goto Done;
  1657. }
  1658. //
  1659. // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
  1660. //
  1661. if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  1662. //
  1663. // Use PE32 offset.
  1664. //
  1665. SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
  1666. } else {
  1667. //
  1668. // Use PE32+ offset
  1669. //
  1670. SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
  1671. }
  1672. //
  1673. // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
  1674. // structures in the image. The 'NumberOfSections' field of the image
  1675. // header indicates how big the table should be. Do not include any
  1676. // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
  1677. //
  1678. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
  1679. ASSERT (SectionHeader != NULL);
  1680. //
  1681. // 12. Using the 'PointerToRawData' in the referenced section headers as
  1682. // a key, arrange the elements in the table in ascending order. In other
  1683. // words, sort the section headers according to the disk-file offset of
  1684. // the section.
  1685. //
  1686. Section = (EFI_IMAGE_SECTION_HEADER *) (
  1687. mImageBase +
  1688. mPeCoffHeaderOffset +
  1689. sizeof (UINT32) +
  1690. sizeof (EFI_IMAGE_FILE_HEADER) +
  1691. mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
  1692. );
  1693. for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
  1694. Pos = Index;
  1695. while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
  1696. CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
  1697. Pos--;
  1698. }
  1699. CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
  1700. Section += 1;
  1701. }
  1702. //
  1703. // 13. Walk through the sorted table, bring the corresponding section
  1704. // into memory, and hash the entire section (using the 'SizeOfRawData'
  1705. // field in the section header to determine the amount of data to hash).
  1706. // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
  1707. // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
  1708. //
  1709. for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
  1710. Section = &SectionHeader[Index];
  1711. if (Section->SizeOfRawData == 0) {
  1712. continue;
  1713. }
  1714. HashBase = mImageBase + Section->PointerToRawData;
  1715. HashSize = (UINTN) Section->SizeOfRawData;
  1716. Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
  1717. if (!Status) {
  1718. goto Done;
  1719. }
  1720. SumOfBytesHashed += HashSize;
  1721. }
  1722. //
  1723. // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
  1724. // data in the file that needs to be added to the hash. This data begins
  1725. // at file offset SUM_OF_BYTES_HASHED and its length is:
  1726. // FileSize - (CertDirectory->Size)
  1727. //
  1728. if (mImageSize > SumOfBytesHashed) {
  1729. HashBase = mImageBase + SumOfBytesHashed;
  1730. if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  1731. //
  1732. // Use PE32 offset.
  1733. //
  1734. HashSize = (UINTN)(
  1735. mImageSize -
  1736. mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
  1737. SumOfBytesHashed);
  1738. } else {
  1739. //
  1740. // Use PE32+ offset.
  1741. //
  1742. HashSize = (UINTN)(
  1743. mImageSize -
  1744. mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
  1745. SumOfBytesHashed);
  1746. }
  1747. Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
  1748. if (!Status) {
  1749. goto Done;
  1750. }
  1751. }
  1752. Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);
  1753. Done:
  1754. if (HashCtx != NULL) {
  1755. FreePool (HashCtx);
  1756. }
  1757. if (SectionHeader != NULL) {
  1758. FreePool (SectionHeader);
  1759. }
  1760. return Status;
  1761. }
  1762. /**
  1763. Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
  1764. Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
  1765. 8.0 Appendix A
  1766. @retval EFI_UNSUPPORTED Hash algorithm is not supported.
  1767. @retval EFI_SUCCESS Hash successfully.
  1768. **/
  1769. EFI_STATUS
  1770. HashPeImageByType (
  1771. VOID
  1772. )
  1773. {
  1774. UINT8 Index;
  1775. WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
  1776. PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);
  1777. for (Index = 0; Index < HASHALG_MAX; Index++) {
  1778. //
  1779. // Check the Hash algorithm in PE/COFF Authenticode.
  1780. // According to PKCS#7 Definition:
  1781. // SignedData ::= SEQUENCE {
  1782. // version Version,
  1783. // digestAlgorithms DigestAlgorithmIdentifiers,
  1784. // contentInfo ContentInfo,
  1785. // .... }
  1786. // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
  1787. // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
  1788. // Fixed offset (+32) is calculated based on two bytes of length encoding.
  1789. //
  1790. if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
  1791. //
  1792. // Only support two bytes of Long Form of Length Encoding.
  1793. //
  1794. continue;
  1795. }
  1796. //
  1797. if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
  1798. break;
  1799. }
  1800. }
  1801. if (Index == HASHALG_MAX) {
  1802. return EFI_UNSUPPORTED;
  1803. }
  1804. //
  1805. // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
  1806. //
  1807. if (!HashPeImage(Index)) {
  1808. return EFI_UNSUPPORTED;
  1809. }
  1810. return EFI_SUCCESS;
  1811. }
  1812. /**
  1813. Enroll a new signature of executable into Signature Database.
  1814. @param[in] PrivateData The module's private data.
  1815. @param[in] VariableName Variable name of signature database, must be
  1816. EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
  1817. or EFI_IMAGE_SECURITY_DATABASE2.
  1818. @retval EFI_SUCCESS New signature is enrolled successfully.
  1819. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  1820. @retval EFI_UNSUPPORTED Unsupported command.
  1821. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  1822. **/
  1823. EFI_STATUS
  1824. EnrollAuthentication2Descriptor (
  1825. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
  1826. IN CHAR16 *VariableName
  1827. )
  1828. {
  1829. EFI_STATUS Status;
  1830. VOID *Data;
  1831. UINTN DataSize;
  1832. UINT32 Attr;
  1833. Data = NULL;
  1834. //
  1835. // DBT only support DER-X509 Cert Enrollment
  1836. //
  1837. if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {
  1838. return EFI_UNSUPPORTED;
  1839. }
  1840. //
  1841. // Read the whole file content
  1842. //
  1843. Status = ReadFileContent(
  1844. Private->FileContext->FHandle,
  1845. (VOID **) &mImageBase,
  1846. &mImageSize,
  1847. 0
  1848. );
  1849. if (EFI_ERROR (Status)) {
  1850. goto ON_EXIT;
  1851. }
  1852. ASSERT (mImageBase != NULL);
  1853. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
  1854. | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  1855. //
  1856. // Check if SigDB variable has been already existed.
  1857. // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
  1858. // new signature data to original variable
  1859. //
  1860. DataSize = 0;
  1861. Status = gRT->GetVariable(
  1862. VariableName,
  1863. &gEfiImageSecurityDatabaseGuid,
  1864. NULL,
  1865. &DataSize,
  1866. NULL
  1867. );
  1868. if (Status == EFI_BUFFER_TOO_SMALL) {
  1869. Attr |= EFI_VARIABLE_APPEND_WRITE;
  1870. } else if (Status != EFI_NOT_FOUND) {
  1871. goto ON_EXIT;
  1872. }
  1873. //
  1874. // Directly set AUTHENTICATION_2 data to SetVariable
  1875. //
  1876. Status = gRT->SetVariable(
  1877. VariableName,
  1878. &gEfiImageSecurityDatabaseGuid,
  1879. Attr,
  1880. mImageSize,
  1881. mImageBase
  1882. );
  1883. DEBUG((DEBUG_INFO, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName, Status));
  1884. ON_EXIT:
  1885. CloseEnrolledFile(Private->FileContext);
  1886. if (Data != NULL) {
  1887. FreePool (Data);
  1888. }
  1889. if (mImageBase != NULL) {
  1890. FreePool (mImageBase);
  1891. mImageBase = NULL;
  1892. }
  1893. return Status;
  1894. }
  1895. /**
  1896. Enroll a new signature of executable into Signature Database.
  1897. @param[in] PrivateData The module's private data.
  1898. @param[in] VariableName Variable name of signature database, must be
  1899. EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
  1900. or EFI_IMAGE_SECURITY_DATABASE2.
  1901. @retval EFI_SUCCESS New signature is enrolled successfully.
  1902. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  1903. @retval EFI_UNSUPPORTED Unsupported command.
  1904. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  1905. **/
  1906. EFI_STATUS
  1907. EnrollImageSignatureToSigDB (
  1908. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
  1909. IN CHAR16 *VariableName
  1910. )
  1911. {
  1912. EFI_STATUS Status;
  1913. EFI_SIGNATURE_LIST *SigDBCert;
  1914. EFI_SIGNATURE_DATA *SigDBCertData;
  1915. VOID *Data;
  1916. UINTN DataSize;
  1917. UINTN SigDBSize;
  1918. UINT32 Attr;
  1919. WIN_CERTIFICATE_UEFI_GUID *GuidCertData;
  1920. Data = NULL;
  1921. GuidCertData = NULL;
  1922. if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {
  1923. return EFI_UNSUPPORTED;
  1924. }
  1925. //
  1926. // Form the SigDB certificate list.
  1927. // Format the data item into EFI_SIGNATURE_LIST type.
  1928. //
  1929. // We need to parse signature data of executable from specified signed executable file.
  1930. // In current implementation, we simply trust the pass-in signed executable file.
  1931. // In reality, it's OS's responsibility to verify the signed executable file.
  1932. //
  1933. //
  1934. // Read the whole file content
  1935. //
  1936. Status = ReadFileContent(
  1937. Private->FileContext->FHandle,
  1938. (VOID **) &mImageBase,
  1939. &mImageSize,
  1940. 0
  1941. );
  1942. if (EFI_ERROR (Status)) {
  1943. goto ON_EXIT;
  1944. }
  1945. ASSERT (mImageBase != NULL);
  1946. Status = LoadPeImage ();
  1947. if (EFI_ERROR (Status)) {
  1948. goto ON_EXIT;
  1949. }
  1950. if (mSecDataDir->SizeOfCert == 0) {
  1951. if (!HashPeImage (HASHALG_SHA256)) {
  1952. Status = EFI_SECURITY_VIOLATION;
  1953. goto ON_EXIT;
  1954. }
  1955. } else {
  1956. //
  1957. // Read the certificate data
  1958. //
  1959. mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);
  1960. if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
  1961. GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;
  1962. if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {
  1963. Status = EFI_ABORTED;
  1964. goto ON_EXIT;
  1965. }
  1966. if (!HashPeImage (HASHALG_SHA256)) {
  1967. Status = EFI_ABORTED;
  1968. goto ON_EXIT;;
  1969. }
  1970. } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
  1971. Status = HashPeImageByType ();
  1972. if (EFI_ERROR (Status)) {
  1973. goto ON_EXIT;;
  1974. }
  1975. } else {
  1976. Status = EFI_ABORTED;
  1977. goto ON_EXIT;
  1978. }
  1979. }
  1980. //
  1981. // Create a new SigDB entry.
  1982. //
  1983. SigDBSize = sizeof(EFI_SIGNATURE_LIST)
  1984. + sizeof(EFI_SIGNATURE_DATA) - 1
  1985. + (UINT32) mImageDigestSize;
  1986. Data = (UINT8*) AllocateZeroPool (SigDBSize);
  1987. if (Data == NULL) {
  1988. Status = EFI_OUT_OF_RESOURCES;
  1989. goto ON_EXIT;
  1990. }
  1991. //
  1992. // Adjust the Certificate Database parameters.
  1993. //
  1994. SigDBCert = (EFI_SIGNATURE_LIST*) Data;
  1995. SigDBCert->SignatureListSize = (UINT32) SigDBSize;
  1996. SigDBCert->SignatureHeaderSize = 0;
  1997. SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;
  1998. CopyGuid (&SigDBCert->SignatureType, &mCertType);
  1999. SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));
  2000. CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
  2001. CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);
  2002. Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
  2003. | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
  2004. Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);
  2005. if (EFI_ERROR (Status)) {
  2006. DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
  2007. goto ON_EXIT;
  2008. }
  2009. //
  2010. // Check if SigDB variable has been already existed.
  2011. // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
  2012. // new signature data to original variable
  2013. //
  2014. DataSize = 0;
  2015. Status = gRT->GetVariable(
  2016. VariableName,
  2017. &gEfiImageSecurityDatabaseGuid,
  2018. NULL,
  2019. &DataSize,
  2020. NULL
  2021. );
  2022. if (Status == EFI_BUFFER_TOO_SMALL) {
  2023. Attr |= EFI_VARIABLE_APPEND_WRITE;
  2024. } else if (Status != EFI_NOT_FOUND) {
  2025. goto ON_EXIT;
  2026. }
  2027. //
  2028. // Enroll the variable.
  2029. //
  2030. Status = gRT->SetVariable(
  2031. VariableName,
  2032. &gEfiImageSecurityDatabaseGuid,
  2033. Attr,
  2034. SigDBSize,
  2035. Data
  2036. );
  2037. if (EFI_ERROR (Status)) {
  2038. goto ON_EXIT;
  2039. }
  2040. ON_EXIT:
  2041. CloseEnrolledFile(Private->FileContext);
  2042. if (Private->SignatureGUID != NULL) {
  2043. FreePool (Private->SignatureGUID);
  2044. Private->SignatureGUID = NULL;
  2045. }
  2046. if (Data != NULL) {
  2047. FreePool (Data);
  2048. }
  2049. if (mImageBase != NULL) {
  2050. FreePool (mImageBase);
  2051. mImageBase = NULL;
  2052. }
  2053. return Status;
  2054. }
  2055. /**
  2056. Enroll signature into DB/DBX/DBT without KEK's authentication.
  2057. The SignatureOwner GUID will be Private->SignatureGUID.
  2058. @param[in] PrivateData The module's private data.
  2059. @param[in] VariableName Variable name of signature database, must be
  2060. EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
  2061. @retval EFI_SUCCESS New signature enrolled successfully.
  2062. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  2063. @retval others Fail to enroll signature data.
  2064. **/
  2065. EFI_STATUS
  2066. EnrollSignatureDatabase (
  2067. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
  2068. IN CHAR16 *VariableName
  2069. )
  2070. {
  2071. UINT16* FilePostFix;
  2072. EFI_STATUS Status;
  2073. UINTN NameLength;
  2074. if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
  2075. return EFI_INVALID_PARAMETER;
  2076. }
  2077. Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
  2078. if (EFI_ERROR (Status)) {
  2079. return Status;
  2080. }
  2081. //
  2082. // Parse the file's postfix.
  2083. //
  2084. NameLength = StrLen (Private->FileContext->FileName);
  2085. if (NameLength <= 4) {
  2086. return EFI_INVALID_PARAMETER;
  2087. }
  2088. FilePostFix = Private->FileContext->FileName + NameLength - 4;
  2089. if (IsDerEncodeCertificate (FilePostFix)) {
  2090. //
  2091. // Supports DER-encoded X509 certificate.
  2092. //
  2093. return EnrollX509toSigDB (Private, VariableName);
  2094. } else if (IsAuthentication2Format(Private->FileContext->FHandle)){
  2095. return EnrollAuthentication2Descriptor(Private, VariableName);
  2096. } else {
  2097. return EnrollImageSignatureToSigDB (Private, VariableName);
  2098. }
  2099. }
  2100. /**
  2101. List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
  2102. by GUID in the page for user to select and delete as needed.
  2103. @param[in] PrivateData Module's private data.
  2104. @param[in] VariableName The variable name of the vendor's signature database.
  2105. @param[in] VendorGuid A unique identifier for the vendor.
  2106. @param[in] LabelNumber Label number to insert opcodes.
  2107. @param[in] FormId Form ID of current page.
  2108. @param[in] QuestionIdBase Base question id of the signature list.
  2109. @retval EFI_SUCCESS Success to update the signature list page
  2110. @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
  2111. **/
  2112. EFI_STATUS
  2113. UpdateDeletePage (
  2114. IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
  2115. IN CHAR16 *VariableName,
  2116. IN EFI_GUID *VendorGuid,
  2117. IN UINT16 LabelNumber,
  2118. IN EFI_FORM_ID FormId,
  2119. IN EFI_QUESTION_ID QuestionIdBase
  2120. )
  2121. {
  2122. EFI_STATUS Status;
  2123. UINT32 Index;
  2124. UINTN CertCount;
  2125. UINTN GuidIndex;
  2126. VOID *StartOpCodeHandle;
  2127. VOID *EndOpCodeHandle;
  2128. EFI_IFR_GUID_LABEL *StartLabel;
  2129. EFI_IFR_GUID_LABEL *EndLabel;
  2130. UINTN DataSize;
  2131. UINT8 *Data;
  2132. EFI_SIGNATURE_LIST *CertList;
  2133. EFI_SIGNATURE_DATA *Cert;
  2134. UINT32 ItemDataSize;
  2135. CHAR16 *GuidStr;
  2136. EFI_STRING_ID GuidID;
  2137. EFI_STRING_ID Help;
  2138. Data = NULL;
  2139. CertList = NULL;
  2140. Cert = NULL;
  2141. GuidStr = NULL;
  2142. StartOpCodeHandle = NULL;
  2143. EndOpCodeHandle = NULL;
  2144. //
  2145. // Initialize the container for dynamic opcodes.
  2146. //
  2147. StartOpCodeHandle = HiiAllocateOpCodeHandle ();
  2148. if (StartOpCodeHandle == NULL) {
  2149. Status = EFI_OUT_OF_RESOURCES;
  2150. goto ON_EXIT;
  2151. }
  2152. EndOpCodeHandle = HiiAllocateOpCodeHandle ();
  2153. if (EndOpCodeHandle == NULL) {
  2154. Status = EFI_OUT_OF_RESOURCES;
  2155. goto ON_EXIT;
  2156. }
  2157. //
  2158. // Create Hii Extend Label OpCode.
  2159. //
  2160. StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
  2161. StartOpCodeHandle,
  2162. &gEfiIfrTianoGuid,
  2163. NULL,
  2164. sizeof (EFI_IFR_GUID_LABEL)
  2165. );
  2166. StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  2167. StartLabel->Number = LabelNumber;
  2168. EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
  2169. EndOpCodeHandle,
  2170. &gEfiIfrTianoGuid,
  2171. NULL,
  2172. sizeof (EFI_IFR_GUID_LABEL)
  2173. );
  2174. EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  2175. EndLabel->Number = LABEL_END;
  2176. //
  2177. // Read Variable.
  2178. //
  2179. DataSize = 0;
  2180. Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
  2181. if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
  2182. goto ON_EXIT;
  2183. }
  2184. Data = (UINT8 *) AllocateZeroPool (DataSize);
  2185. if (Data == NULL) {
  2186. Status = EFI_OUT_OF_RESOURCES;
  2187. goto ON_EXIT;
  2188. }
  2189. Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
  2190. if (EFI_ERROR (Status)) {
  2191. goto ON_EXIT;
  2192. }
  2193. GuidStr = AllocateZeroPool (100);
  2194. if (GuidStr == NULL) {
  2195. Status = EFI_OUT_OF_RESOURCES;
  2196. goto ON_EXIT;
  2197. }
  2198. //
  2199. // Enumerate all KEK pub data.
  2200. //
  2201. ItemDataSize = (UINT32) DataSize;
  2202. CertList = (EFI_SIGNATURE_LIST *) Data;
  2203. GuidIndex = 0;
  2204. while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
  2205. if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {
  2206. Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);
  2207. } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
  2208. Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);
  2209. } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {
  2210. Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);
  2211. } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {
  2212. Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);
  2213. } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) {
  2214. Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID);
  2215. } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) {
  2216. Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID);
  2217. } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) {
  2218. Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID);
  2219. } else {
  2220. //
  2221. // The signature type is not supported in current implementation.
  2222. //
  2223. ItemDataSize -= CertList->SignatureListSize;
  2224. CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
  2225. continue;
  2226. }
  2227. CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
  2228. for (Index = 0; Index < CertCount; Index++) {
  2229. Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList
  2230. + sizeof (EFI_SIGNATURE_LIST)
  2231. + CertList->SignatureHeaderSize
  2232. + Index * CertList->SignatureSize);
  2233. //
  2234. // Display GUID and help
  2235. //
  2236. GuidToString (&Cert->SignatureOwner, GuidStr, 100);
  2237. GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);
  2238. HiiCreateCheckBoxOpCode (
  2239. StartOpCodeHandle,
  2240. (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),
  2241. 0,
  2242. 0,
  2243. GuidID,
  2244. Help,
  2245. EFI_IFR_FLAG_CALLBACK,
  2246. 0,
  2247. NULL
  2248. );
  2249. }
  2250. ItemDataSize -= CertList->SignatureListSize;
  2251. CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
  2252. }
  2253. ON_EXIT:
  2254. HiiUpdateForm (
  2255. PrivateData->HiiHandle,
  2256. &gSecureBootConfigFormSetGuid,
  2257. FormId,
  2258. StartOpCodeHandle,
  2259. EndOpCodeHandle
  2260. );
  2261. if (StartOpCodeHandle != NULL) {
  2262. HiiFreeOpCodeHandle (StartOpCodeHandle);
  2263. }
  2264. if (EndOpCodeHandle != NULL) {
  2265. HiiFreeOpCodeHandle (EndOpCodeHandle);
  2266. }
  2267. if (Data != NULL) {
  2268. FreePool (Data);
  2269. }
  2270. if (GuidStr != NULL) {
  2271. FreePool (GuidStr);
  2272. }
  2273. return EFI_SUCCESS;
  2274. }
  2275. /**
  2276. Delete a KEK entry from KEK database.
  2277. @param[in] PrivateData Module's private data.
  2278. @param[in] QuestionId Question id of the KEK item to delete.
  2279. @retval EFI_SUCCESS Delete kek item successfully.
  2280. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  2281. **/
  2282. EFI_STATUS
  2283. DeleteKeyExchangeKey (
  2284. IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
  2285. IN EFI_QUESTION_ID QuestionId
  2286. )
  2287. {
  2288. EFI_STATUS Status;
  2289. UINTN DataSize;
  2290. UINT8 *Data;
  2291. UINT8 *OldData;
  2292. UINT32 Attr;
  2293. UINT32 Index;
  2294. EFI_SIGNATURE_LIST *CertList;
  2295. EFI_SIGNATURE_LIST *NewCertList;
  2296. EFI_SIGNATURE_DATA *Cert;
  2297. UINTN CertCount;
  2298. UINT32 Offset;
  2299. BOOLEAN IsKEKItemFound;
  2300. UINT32 KekDataSize;
  2301. UINTN DeleteKekIndex;
  2302. UINTN GuidIndex;
  2303. Data = NULL;
  2304. OldData = NULL;
  2305. CertList = NULL;
  2306. Cert = NULL;
  2307. Attr = 0;
  2308. DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID;
  2309. Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
  2310. if (EFI_ERROR (Status)) {
  2311. return Status;
  2312. }
  2313. //
  2314. // Get original KEK variable.
  2315. //
  2316. DataSize = 0;
  2317. Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);
  2318. if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
  2319. goto ON_EXIT;
  2320. }
  2321. OldData = (UINT8*)AllocateZeroPool(DataSize);
  2322. if (OldData == NULL) {
  2323. Status = EFI_OUT_OF_RESOURCES;
  2324. goto ON_EXIT;
  2325. }
  2326. Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);
  2327. if (EFI_ERROR(Status)) {
  2328. goto ON_EXIT;
  2329. }
  2330. //
  2331. // Allocate space for new variable.
  2332. //
  2333. Data = (UINT8*) AllocateZeroPool (DataSize);
  2334. if (Data == NULL) {
  2335. Status = EFI_OUT_OF_RESOURCES;
  2336. goto ON_EXIT;
  2337. }
  2338. //
  2339. // Enumerate all KEK pub data and erasing the target item.
  2340. //
  2341. IsKEKItemFound = FALSE;
  2342. KekDataSize = (UINT32) DataSize;
  2343. CertList = (EFI_SIGNATURE_LIST *) OldData;
  2344. Offset = 0;
  2345. GuidIndex = 0;
  2346. while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
  2347. if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
  2348. CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
  2349. CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
  2350. NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);
  2351. Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
  2352. Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
  2353. CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
  2354. for (Index = 0; Index < CertCount; Index++) {
  2355. if (GuidIndex == DeleteKekIndex ) {
  2356. //
  2357. // Find it! Skip it!
  2358. //
  2359. NewCertList->SignatureListSize -= CertList->SignatureSize;
  2360. IsKEKItemFound = TRUE;
  2361. } else {
  2362. //
  2363. // This item doesn't match. Copy it to the Data buffer.
  2364. //
  2365. CopyMem (Data + Offset, Cert, CertList->SignatureSize);
  2366. Offset += CertList->SignatureSize;
  2367. }
  2368. GuidIndex++;
  2369. Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);
  2370. }
  2371. } else {
  2372. //
  2373. // This List doesn't match. Copy it to the Data buffer.
  2374. //
  2375. CopyMem (Data + Offset, CertList, CertList->SignatureListSize);
  2376. Offset += CertList->SignatureListSize;
  2377. }
  2378. KekDataSize -= CertList->SignatureListSize;
  2379. CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);
  2380. }
  2381. if (!IsKEKItemFound) {
  2382. //
  2383. // Doesn't find the Kek Item!
  2384. //
  2385. Status = EFI_NOT_FOUND;
  2386. goto ON_EXIT;
  2387. }
  2388. //
  2389. // Delete the Signature header if there is no signature in the list.
  2390. //
  2391. KekDataSize = Offset;
  2392. CertList = (EFI_SIGNATURE_LIST*) Data;
  2393. Offset = 0;
  2394. ZeroMem (OldData, KekDataSize);
  2395. while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
  2396. CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
  2397. DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));
  2398. if (CertCount != 0) {
  2399. CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);
  2400. Offset += CertList->SignatureListSize;
  2401. }
  2402. KekDataSize -= CertList->SignatureListSize;
  2403. CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
  2404. }
  2405. DataSize = Offset;
  2406. if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
  2407. Status = CreateTimeBasedPayload (&DataSize, &OldData);
  2408. if (EFI_ERROR (Status)) {
  2409. DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
  2410. goto ON_EXIT;
  2411. }
  2412. }
  2413. Status = gRT->SetVariable(
  2414. EFI_KEY_EXCHANGE_KEY_NAME,
  2415. &gEfiGlobalVariableGuid,
  2416. Attr,
  2417. DataSize,
  2418. OldData
  2419. );
  2420. if (EFI_ERROR (Status)) {
  2421. DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
  2422. goto ON_EXIT;
  2423. }
  2424. ON_EXIT:
  2425. if (Data != NULL) {
  2426. FreePool(Data);
  2427. }
  2428. if (OldData != NULL) {
  2429. FreePool(OldData);
  2430. }
  2431. return UpdateDeletePage (
  2432. PrivateData,
  2433. EFI_KEY_EXCHANGE_KEY_NAME,
  2434. &gEfiGlobalVariableGuid,
  2435. LABEL_KEK_DELETE,
  2436. FORMID_DELETE_KEK_FORM,
  2437. OPTION_DEL_KEK_QUESTION_ID
  2438. );
  2439. }
  2440. /**
  2441. Delete a signature entry from signature database.
  2442. @param[in] PrivateData Module's private data.
  2443. @param[in] VariableName The variable name of the vendor's signature database.
  2444. @param[in] VendorGuid A unique identifier for the vendor.
  2445. @param[in] LabelNumber Label number to insert opcodes.
  2446. @param[in] FormId Form ID of current page.
  2447. @param[in] QuestionIdBase Base question id of the signature list.
  2448. @param[in] DeleteIndex Signature index to delete.
  2449. @retval EFI_SUCCESS Delete signature successfully.
  2450. @retval EFI_NOT_FOUND Can't find the signature item,
  2451. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
  2452. **/
  2453. EFI_STATUS
  2454. DeleteSignature (
  2455. IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
  2456. IN CHAR16 *VariableName,
  2457. IN EFI_GUID *VendorGuid,
  2458. IN UINT16 LabelNumber,
  2459. IN EFI_FORM_ID FormId,
  2460. IN EFI_QUESTION_ID QuestionIdBase,
  2461. IN UINTN DeleteIndex
  2462. )
  2463. {
  2464. EFI_STATUS Status;
  2465. UINTN DataSize;
  2466. UINT8 *Data;
  2467. UINT8 *OldData;
  2468. UINT32 Attr;
  2469. UINT32 Index;
  2470. EFI_SIGNATURE_LIST *CertList;
  2471. EFI_SIGNATURE_LIST *NewCertList;
  2472. EFI_SIGNATURE_DATA *Cert;
  2473. UINTN CertCount;
  2474. UINT32 Offset;
  2475. BOOLEAN IsItemFound;
  2476. UINT32 ItemDataSize;
  2477. UINTN GuidIndex;
  2478. Data = NULL;
  2479. OldData = NULL;
  2480. CertList = NULL;
  2481. Cert = NULL;
  2482. Attr = 0;
  2483. Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
  2484. if (EFI_ERROR (Status)) {
  2485. return Status;
  2486. }
  2487. //
  2488. // Get original signature list data.
  2489. //
  2490. DataSize = 0;
  2491. Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
  2492. if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
  2493. goto ON_EXIT;
  2494. }
  2495. OldData = (UINT8 *) AllocateZeroPool (DataSize);
  2496. if (OldData == NULL) {
  2497. Status = EFI_OUT_OF_RESOURCES;
  2498. goto ON_EXIT;
  2499. }
  2500. Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
  2501. if (EFI_ERROR(Status)) {
  2502. goto ON_EXIT;
  2503. }
  2504. //
  2505. // Allocate space for new variable.
  2506. //
  2507. Data = (UINT8*) AllocateZeroPool (DataSize);
  2508. if (Data == NULL) {
  2509. Status = EFI_OUT_OF_RESOURCES;
  2510. goto ON_EXIT;
  2511. }
  2512. //
  2513. // Enumerate all signature data and erasing the target item.
  2514. //
  2515. IsItemFound = FALSE;
  2516. ItemDataSize = (UINT32) DataSize;
  2517. CertList = (EFI_SIGNATURE_LIST *) OldData;
  2518. Offset = 0;
  2519. GuidIndex = 0;
  2520. while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
  2521. if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
  2522. CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||
  2523. CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||
  2524. CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) ||
  2525. CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) ||
  2526. CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) ||
  2527. CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)
  2528. ) {
  2529. //
  2530. // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
  2531. //
  2532. CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
  2533. NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
  2534. Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
  2535. Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
  2536. CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
  2537. for (Index = 0; Index < CertCount; Index++) {
  2538. if (GuidIndex == DeleteIndex) {
  2539. //
  2540. // Find it! Skip it!
  2541. //
  2542. NewCertList->SignatureListSize -= CertList->SignatureSize;
  2543. IsItemFound = TRUE;
  2544. } else {
  2545. //
  2546. // This item doesn't match. Copy it to the Data buffer.
  2547. //
  2548. CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
  2549. Offset += CertList->SignatureSize;
  2550. }
  2551. GuidIndex++;
  2552. Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
  2553. }
  2554. } else {
  2555. //
  2556. // This List doesn't match. Just copy it to the Data buffer.
  2557. //
  2558. CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
  2559. Offset += CertList->SignatureListSize;
  2560. }
  2561. ItemDataSize -= CertList->SignatureListSize;
  2562. CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
  2563. }
  2564. if (!IsItemFound) {
  2565. //
  2566. // Doesn't find the signature Item!
  2567. //
  2568. Status = EFI_NOT_FOUND;
  2569. goto ON_EXIT;
  2570. }
  2571. //
  2572. // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
  2573. //
  2574. ItemDataSize = Offset;
  2575. CertList = (EFI_SIGNATURE_LIST *) Data;
  2576. Offset = 0;
  2577. ZeroMem (OldData, ItemDataSize);
  2578. while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
  2579. CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
  2580. DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount));
  2581. if (CertCount != 0) {
  2582. CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
  2583. Offset += CertList->SignatureListSize;
  2584. }
  2585. ItemDataSize -= CertList->SignatureListSize;
  2586. CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
  2587. }
  2588. DataSize = Offset;
  2589. if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
  2590. Status = CreateTimeBasedPayload (&DataSize, &OldData);
  2591. if (EFI_ERROR (Status)) {
  2592. DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
  2593. goto ON_EXIT;
  2594. }
  2595. }
  2596. Status = gRT->SetVariable(
  2597. VariableName,
  2598. VendorGuid,
  2599. Attr,
  2600. DataSize,
  2601. OldData
  2602. );
  2603. if (EFI_ERROR (Status)) {
  2604. DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
  2605. goto ON_EXIT;
  2606. }
  2607. ON_EXIT:
  2608. if (Data != NULL) {
  2609. FreePool(Data);
  2610. }
  2611. if (OldData != NULL) {
  2612. FreePool(OldData);
  2613. }
  2614. return UpdateDeletePage (
  2615. PrivateData,
  2616. VariableName,
  2617. VendorGuid,
  2618. LabelNumber,
  2619. FormId,
  2620. QuestionIdBase
  2621. );
  2622. }
  2623. /**
  2624. This function to delete signature list or data, according by DelType.
  2625. @param[in] PrivateData Module's private data.
  2626. @param[in] DelType Indicate delete signature list or data.
  2627. @param[in] CheckedCount Indicate how many signature data have
  2628. been checked in current signature list.
  2629. @retval EFI_SUCCESS Success to update the signature list page
  2630. @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
  2631. **/
  2632. EFI_STATUS
  2633. DeleteSignatureEx (
  2634. IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
  2635. IN SIGNATURE_DELETE_TYPE DelType,
  2636. IN UINT32 CheckedCount
  2637. )
  2638. {
  2639. EFI_STATUS Status;
  2640. EFI_SIGNATURE_LIST *ListWalker;
  2641. EFI_SIGNATURE_LIST *NewCertList;
  2642. EFI_SIGNATURE_DATA *DataWalker;
  2643. CHAR16 VariableName[BUFFER_MAX_SIZE];
  2644. UINT32 VariableAttr;
  2645. UINTN VariableDataSize;
  2646. UINTN RemainingSize;
  2647. UINTN ListIndex;
  2648. UINTN Index;
  2649. UINTN Offset;
  2650. UINT8 *VariableData;
  2651. UINT8 *NewVariableData;
  2652. Status = EFI_SUCCESS;
  2653. VariableAttr = 0;
  2654. VariableDataSize = 0;
  2655. ListIndex = 0;
  2656. Offset = 0;
  2657. VariableData = NULL;
  2658. NewVariableData = NULL;
  2659. if (PrivateData->VariableName == Variable_DB) {
  2660. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);
  2661. } else if (PrivateData->VariableName == Variable_DBX) {
  2662. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);
  2663. } else if (PrivateData->VariableName == Variable_DBT) {
  2664. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);
  2665. } else {
  2666. goto ON_EXIT;
  2667. }
  2668. Status = gRT->GetVariable (
  2669. VariableName,
  2670. &gEfiImageSecurityDatabaseGuid,
  2671. &VariableAttr,
  2672. &VariableDataSize,
  2673. VariableData
  2674. );
  2675. if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
  2676. goto ON_EXIT;
  2677. }
  2678. VariableData = AllocateZeroPool (VariableDataSize);
  2679. if (VariableData == NULL) {
  2680. Status = EFI_OUT_OF_RESOURCES;
  2681. goto ON_EXIT;
  2682. }
  2683. Status = gRT->GetVariable (
  2684. VariableName,
  2685. &gEfiImageSecurityDatabaseGuid,
  2686. &VariableAttr,
  2687. &VariableDataSize,
  2688. VariableData
  2689. );
  2690. if (EFI_ERROR (Status)) {
  2691. goto ON_EXIT;
  2692. }
  2693. Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
  2694. if (EFI_ERROR (Status)) {
  2695. goto ON_EXIT;
  2696. }
  2697. NewVariableData = AllocateZeroPool (VariableDataSize);
  2698. if (NewVariableData == NULL) {
  2699. Status = EFI_OUT_OF_RESOURCES;
  2700. goto ON_EXIT;
  2701. }
  2702. RemainingSize = VariableDataSize;
  2703. ListWalker = (EFI_SIGNATURE_LIST *)(VariableData);
  2704. if (DelType == Delete_Signature_List_All) {
  2705. VariableDataSize = 0;
  2706. } else {
  2707. //
  2708. // Traverse to target EFI_SIGNATURE_LIST but others will be skipped.
  2709. //
  2710. while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex < PrivateData->ListIndex) {
  2711. CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, ListWalker->SignatureListSize);
  2712. Offset += ListWalker->SignatureListSize;
  2713. RemainingSize -= ListWalker->SignatureListSize;
  2714. ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);
  2715. ListIndex++;
  2716. }
  2717. //
  2718. // Handle the target EFI_SIGNATURE_LIST.
  2719. // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One
  2720. // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.
  2721. //
  2722. if (CheckedCount < SIGNATURE_DATA_COUNTS (ListWalker) && DelType == Delete_Signature_Data) {
  2723. NewCertList = (EFI_SIGNATURE_LIST *)(NewVariableData + Offset);
  2724. //
  2725. // Copy header.
  2726. //
  2727. CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);
  2728. Offset += sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize;
  2729. DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof(EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);
  2730. for (Index = 0; Index < SIGNATURE_DATA_COUNTS(ListWalker); Index = Index + 1) {
  2731. if (PrivateData->CheckArray[Index]) {
  2732. //
  2733. // Delete checked signature data, and update the size of whole signature list.
  2734. //
  2735. NewCertList->SignatureListSize -= NewCertList->SignatureSize;
  2736. } else {
  2737. //
  2738. // Remain the unchecked signature data.
  2739. //
  2740. CopyMem ((UINT8 *)NewVariableData + Offset, DataWalker, ListWalker->SignatureSize);
  2741. Offset += ListWalker->SignatureSize;
  2742. }
  2743. DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);
  2744. }
  2745. }
  2746. RemainingSize -= ListWalker->SignatureListSize;
  2747. ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);
  2748. //
  2749. // Copy remaining data, maybe 0.
  2750. //
  2751. CopyMem((UINT8 *)NewVariableData + Offset, ListWalker, RemainingSize);
  2752. Offset += RemainingSize;
  2753. VariableDataSize = Offset;
  2754. }
  2755. if ((VariableAttr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
  2756. Status = CreateTimeBasedPayload (&VariableDataSize, &NewVariableData);
  2757. if (EFI_ERROR (Status)) {
  2758. DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
  2759. goto ON_EXIT;
  2760. }
  2761. }
  2762. Status = gRT->SetVariable (
  2763. VariableName,
  2764. &gEfiImageSecurityDatabaseGuid,
  2765. VariableAttr,
  2766. VariableDataSize,
  2767. NewVariableData
  2768. );
  2769. if (EFI_ERROR (Status)) {
  2770. DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r", Status));
  2771. goto ON_EXIT;
  2772. }
  2773. ON_EXIT:
  2774. SECUREBOOT_FREE_NON_NULL (VariableData);
  2775. SECUREBOOT_FREE_NON_NULL (NewVariableData);
  2776. return Status;
  2777. }
  2778. /**
  2779. Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
  2780. and STR_CUR_SECURE_BOOT_MODE_CONTENT.
  2781. @param[in] PrivateData Module's private data.
  2782. @return EFI_SUCCESS Update secure boot strings successfully.
  2783. @return other Fail to update secure boot strings.
  2784. **/
  2785. EFI_STATUS
  2786. UpdateSecureBootString(
  2787. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
  2788. )
  2789. {
  2790. UINT8 *SecureBoot;
  2791. SecureBoot = NULL;
  2792. //
  2793. // Get current secure boot state.
  2794. //
  2795. GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);
  2796. if (SecureBoot == NULL) {
  2797. return EFI_NOT_FOUND;
  2798. }
  2799. if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) {
  2800. HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);
  2801. } else {
  2802. HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);
  2803. }
  2804. FreePool(SecureBoot);
  2805. return EFI_SUCCESS;
  2806. }
  2807. /**
  2808. This function extracts configuration from variable.
  2809. @param[in] Private Point to SecureBoot configuration driver private data.
  2810. @param[in, out] ConfigData Point to SecureBoot configuration private data.
  2811. **/
  2812. VOID
  2813. SecureBootExtractConfigFromVariable (
  2814. IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
  2815. IN OUT SECUREBOOT_CONFIGURATION *ConfigData
  2816. )
  2817. {
  2818. UINT8 *SecureBootEnable;
  2819. UINT8 *SetupMode;
  2820. UINT8 *SecureBootMode;
  2821. EFI_TIME CurrTime;
  2822. SecureBootEnable = NULL;
  2823. SetupMode = NULL;
  2824. SecureBootMode = NULL;
  2825. //
  2826. // Initialize the Date and Time using system time.
  2827. //
  2828. ConfigData->CertificateFormat = HASHALG_RAW;
  2829. ConfigData->AlwaysRevocation = TRUE;
  2830. gRT->GetTime (&CurrTime, NULL);
  2831. ConfigData->RevocationDate.Year = CurrTime.Year;
  2832. ConfigData->RevocationDate.Month = CurrTime.Month;
  2833. ConfigData->RevocationDate.Day = CurrTime.Day;
  2834. ConfigData->RevocationTime.Hour = CurrTime.Hour;
  2835. ConfigData->RevocationTime.Minute = CurrTime.Minute;
  2836. ConfigData->RevocationTime.Second = 0;
  2837. if (Private->FileContext->FHandle != NULL) {
  2838. ConfigData->FileEnrollType = Private->FileContext->FileType;
  2839. } else {
  2840. ConfigData->FileEnrollType = UNKNOWN_FILE_TYPE;
  2841. }
  2842. //
  2843. // If it is Physical Presence User, set the PhysicalPresent to true.
  2844. //
  2845. if (UserPhysicalPresent()) {
  2846. ConfigData->PhysicalPresent = TRUE;
  2847. } else {
  2848. ConfigData->PhysicalPresent = FALSE;
  2849. }
  2850. //
  2851. // If there is no PK then the Delete Pk button will be gray.
  2852. //
  2853. GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);
  2854. if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {
  2855. ConfigData->HasPk = FALSE;
  2856. } else {
  2857. ConfigData->HasPk = TRUE;
  2858. }
  2859. //
  2860. // Check SecureBootEnable & Pk status, fix the inconsistency.
  2861. // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
  2862. // Checkbox.
  2863. //
  2864. ConfigData->AttemptSecureBoot = FALSE;
  2865. GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
  2866. //
  2867. // Fix Pk and SecureBootEnable inconsistency
  2868. //
  2869. if ((SetupMode != NULL) && (*SetupMode) == USER_MODE) {
  2870. ConfigData->HideSecureBoot = FALSE;
  2871. if ((SecureBootEnable != NULL) && (*SecureBootEnable == SECURE_BOOT_ENABLE)) {
  2872. ConfigData->AttemptSecureBoot = TRUE;
  2873. }
  2874. } else {
  2875. ConfigData->HideSecureBoot = TRUE;
  2876. }
  2877. //
  2878. // Get the SecureBootMode from CustomMode variable.
  2879. //
  2880. GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
  2881. if (SecureBootMode == NULL) {
  2882. ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
  2883. } else {
  2884. ConfigData->SecureBootMode = *(SecureBootMode);
  2885. }
  2886. if (SecureBootEnable != NULL) {
  2887. FreePool (SecureBootEnable);
  2888. }
  2889. if (SetupMode != NULL) {
  2890. FreePool (SetupMode);
  2891. }
  2892. if (SecureBootMode != NULL) {
  2893. FreePool (SecureBootMode);
  2894. }
  2895. }
  2896. /**
  2897. This function allows a caller to extract the current configuration for one
  2898. or more named elements from the target driver.
  2899. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  2900. @param[in] Request A null-terminated Unicode string in
  2901. <ConfigRequest> format.
  2902. @param[out] Progress On return, points to a character in the Request
  2903. string. Points to the string's null terminator if
  2904. request was successful. Points to the most recent
  2905. '&' before the first failing name/value pair (or
  2906. the beginning of the string if the failure is in
  2907. the first name/value pair) if the request was not
  2908. successful.
  2909. @param[out] Results A null-terminated Unicode string in
  2910. <ConfigAltResp> format which has all values filled
  2911. in for the names in the Request string. String to
  2912. be allocated by the called function.
  2913. @retval EFI_SUCCESS The Results is filled with the requested values.
  2914. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
  2915. @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
  2916. @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
  2917. driver.
  2918. **/
  2919. EFI_STATUS
  2920. EFIAPI
  2921. SecureBootExtractConfig (
  2922. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  2923. IN CONST EFI_STRING Request,
  2924. OUT EFI_STRING *Progress,
  2925. OUT EFI_STRING *Results
  2926. )
  2927. {
  2928. EFI_STATUS Status;
  2929. UINTN BufferSize;
  2930. UINTN Size;
  2931. SECUREBOOT_CONFIGURATION Configuration;
  2932. EFI_STRING ConfigRequest;
  2933. EFI_STRING ConfigRequestHdr;
  2934. SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
  2935. BOOLEAN AllocatedRequest;
  2936. if (Progress == NULL || Results == NULL) {
  2937. return EFI_INVALID_PARAMETER;
  2938. }
  2939. AllocatedRequest = FALSE;
  2940. ConfigRequestHdr = NULL;
  2941. ConfigRequest = NULL;
  2942. Size = 0;
  2943. ZeroMem (&Configuration, sizeof (Configuration));
  2944. PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
  2945. *Progress = Request;
  2946. if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
  2947. return EFI_NOT_FOUND;
  2948. }
  2949. ZeroMem(&Configuration, sizeof(SECUREBOOT_CONFIGURATION));
  2950. //
  2951. // Get Configuration from Variable.
  2952. //
  2953. SecureBootExtractConfigFromVariable (PrivateData, &Configuration);
  2954. BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
  2955. ConfigRequest = Request;
  2956. if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
  2957. //
  2958. // Request is set to NULL or OFFSET is NULL, construct full request string.
  2959. //
  2960. // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
  2961. // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
  2962. //
  2963. ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);
  2964. Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
  2965. ConfigRequest = AllocateZeroPool (Size);
  2966. ASSERT (ConfigRequest != NULL);
  2967. AllocatedRequest = TRUE;
  2968. UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
  2969. FreePool (ConfigRequestHdr);
  2970. ConfigRequestHdr = NULL;
  2971. }
  2972. Status = gHiiConfigRouting->BlockToConfig (
  2973. gHiiConfigRouting,
  2974. ConfigRequest,
  2975. (UINT8 *) &Configuration,
  2976. BufferSize,
  2977. Results,
  2978. Progress
  2979. );
  2980. //
  2981. // Free the allocated config request string.
  2982. //
  2983. if (AllocatedRequest) {
  2984. FreePool (ConfigRequest);
  2985. }
  2986. //
  2987. // Set Progress string to the original request string.
  2988. //
  2989. if (Request == NULL) {
  2990. *Progress = NULL;
  2991. } else if (StrStr (Request, L"OFFSET") == NULL) {
  2992. *Progress = Request + StrLen (Request);
  2993. }
  2994. return Status;
  2995. }
  2996. /**
  2997. This function processes the results of changes in configuration.
  2998. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  2999. @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
  3000. format.
  3001. @param[out] Progress A pointer to a string filled in with the offset of
  3002. the most recent '&' before the first failing
  3003. name/value pair (or the beginning of the string if
  3004. the failure is in the first name/value pair) or
  3005. the terminating NULL if all was successful.
  3006. @retval EFI_SUCCESS The Results is processed successfully.
  3007. @retval EFI_INVALID_PARAMETER Configuration is NULL.
  3008. @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
  3009. driver.
  3010. **/
  3011. EFI_STATUS
  3012. EFIAPI
  3013. SecureBootRouteConfig (
  3014. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  3015. IN CONST EFI_STRING Configuration,
  3016. OUT EFI_STRING *Progress
  3017. )
  3018. {
  3019. SECUREBOOT_CONFIGURATION IfrNvData;
  3020. UINTN BufferSize;
  3021. SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
  3022. EFI_STATUS Status;
  3023. if (Configuration == NULL || Progress == NULL) {
  3024. return EFI_INVALID_PARAMETER;
  3025. }
  3026. *Progress = Configuration;
  3027. if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
  3028. return EFI_NOT_FOUND;
  3029. }
  3030. PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
  3031. //
  3032. // Get Configuration from Variable.
  3033. //
  3034. SecureBootExtractConfigFromVariable (PrivateData, &IfrNvData);
  3035. //
  3036. // Map the Configuration to the configuration block.
  3037. //
  3038. BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
  3039. Status = gHiiConfigRouting->ConfigToBlock (
  3040. gHiiConfigRouting,
  3041. Configuration,
  3042. (UINT8 *)&IfrNvData,
  3043. &BufferSize,
  3044. Progress
  3045. );
  3046. if (EFI_ERROR (Status)) {
  3047. return Status;
  3048. }
  3049. //
  3050. // Store Buffer Storage back to EFI variable if needed
  3051. //
  3052. if (!IfrNvData.HideSecureBoot) {
  3053. Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);
  3054. if (EFI_ERROR (Status)) {
  3055. return Status;
  3056. }
  3057. }
  3058. *Progress = Configuration + StrLen (Configuration);
  3059. return EFI_SUCCESS;
  3060. }
  3061. /**
  3062. This function to load signature list, the update the menu page.
  3063. @param[in] PrivateData Module's private data.
  3064. @param[in] LabelId Label number to insert opcodes.
  3065. @param[in] FormId Form ID of current page.
  3066. @param[in] QuestionIdBase Base question id of the signature list.
  3067. @retval EFI_SUCCESS Success to update the signature list page
  3068. @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
  3069. **/
  3070. EFI_STATUS
  3071. LoadSignatureList (
  3072. IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
  3073. IN UINT16 LabelId,
  3074. IN EFI_FORM_ID FormId,
  3075. IN EFI_QUESTION_ID QuestionIdBase
  3076. )
  3077. {
  3078. EFI_STATUS Status;
  3079. EFI_STRING_ID ListType;
  3080. EFI_STRING FormatNameString;
  3081. EFI_STRING FormatHelpString;
  3082. EFI_STRING FormatTypeString;
  3083. EFI_SIGNATURE_LIST *ListWalker;
  3084. EFI_IFR_GUID_LABEL *StartLabel;
  3085. EFI_IFR_GUID_LABEL *EndLabel;
  3086. EFI_IFR_GUID_LABEL *StartGoto;
  3087. EFI_IFR_GUID_LABEL *EndGoto;
  3088. EFI_FORM_ID DstFormId;
  3089. VOID *StartOpCodeHandle;
  3090. VOID *EndOpCodeHandle;
  3091. VOID *StartGotoHandle;
  3092. VOID *EndGotoHandle;
  3093. UINTN DataSize;
  3094. UINTN RemainingSize;
  3095. UINT16 Index;
  3096. UINT8 *VariableData;
  3097. CHAR16 VariableName[BUFFER_MAX_SIZE];
  3098. CHAR16 NameBuffer[BUFFER_MAX_SIZE];
  3099. CHAR16 HelpBuffer[BUFFER_MAX_SIZE];
  3100. Status = EFI_SUCCESS;
  3101. FormatNameString = NULL;
  3102. FormatHelpString = NULL;
  3103. StartOpCodeHandle = NULL;
  3104. EndOpCodeHandle = NULL;
  3105. StartGotoHandle = NULL;
  3106. EndGotoHandle = NULL;
  3107. Index = 0;
  3108. VariableData = NULL;
  3109. //
  3110. // Initialize the container for dynamic opcodes.
  3111. //
  3112. StartOpCodeHandle = HiiAllocateOpCodeHandle ();
  3113. if (StartOpCodeHandle == NULL) {
  3114. Status = EFI_OUT_OF_RESOURCES;
  3115. goto ON_EXIT;
  3116. }
  3117. EndOpCodeHandle = HiiAllocateOpCodeHandle ();
  3118. if (EndOpCodeHandle == NULL) {
  3119. Status = EFI_OUT_OF_RESOURCES;
  3120. goto ON_EXIT;
  3121. }
  3122. StartGotoHandle = HiiAllocateOpCodeHandle ();
  3123. if (StartGotoHandle == NULL) {
  3124. Status = EFI_OUT_OF_RESOURCES;
  3125. goto ON_EXIT;
  3126. }
  3127. EndGotoHandle = HiiAllocateOpCodeHandle ();
  3128. if (EndGotoHandle == NULL) {
  3129. Status = EFI_OUT_OF_RESOURCES;
  3130. goto ON_EXIT;
  3131. }
  3132. //
  3133. // Create Hii Extend Label OpCode.
  3134. //
  3135. StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
  3136. StartOpCodeHandle,
  3137. &gEfiIfrTianoGuid,
  3138. NULL,
  3139. sizeof (EFI_IFR_GUID_LABEL)
  3140. );
  3141. StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  3142. StartLabel->Number = LabelId;
  3143. EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
  3144. EndOpCodeHandle,
  3145. &gEfiIfrTianoGuid,
  3146. NULL,
  3147. sizeof (EFI_IFR_GUID_LABEL)
  3148. );
  3149. EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  3150. EndLabel->Number = LABEL_END;
  3151. StartGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode(
  3152. StartGotoHandle,
  3153. &gEfiIfrTianoGuid,
  3154. NULL,
  3155. sizeof(EFI_IFR_GUID_LABEL)
  3156. );
  3157. StartGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  3158. StartGoto->Number = LABEL_DELETE_ALL_LIST_BUTTON;
  3159. EndGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode(
  3160. EndGotoHandle,
  3161. &gEfiIfrTianoGuid,
  3162. NULL,
  3163. sizeof(EFI_IFR_GUID_LABEL)
  3164. );
  3165. EndGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  3166. EndGoto->Number = LABEL_END;
  3167. if (PrivateData->VariableName == Variable_DB) {
  3168. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);
  3169. DstFormId = FORMID_SECURE_BOOT_DB_OPTION_FORM;
  3170. } else if (PrivateData->VariableName == Variable_DBX) {
  3171. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);
  3172. DstFormId = FORMID_SECURE_BOOT_DBX_OPTION_FORM;
  3173. } else if (PrivateData->VariableName == Variable_DBT) {
  3174. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);
  3175. DstFormId = FORMID_SECURE_BOOT_DBT_OPTION_FORM;
  3176. } else {
  3177. goto ON_EXIT;
  3178. }
  3179. HiiCreateGotoOpCode (
  3180. StartGotoHandle,
  3181. DstFormId,
  3182. STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST),
  3183. STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST),
  3184. EFI_IFR_FLAG_CALLBACK,
  3185. KEY_SECURE_BOOT_DELETE_ALL_LIST
  3186. );
  3187. //
  3188. // Read Variable, the variable name save in the PrivateData->VariableName.
  3189. //
  3190. DataSize = 0;
  3191. Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);
  3192. if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
  3193. goto ON_EXIT;
  3194. }
  3195. VariableData = AllocateZeroPool (DataSize);
  3196. if (VariableData == NULL) {
  3197. Status = EFI_OUT_OF_RESOURCES;
  3198. goto ON_EXIT;
  3199. }
  3200. Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);
  3201. if (EFI_ERROR (Status)) {
  3202. goto ON_EXIT;
  3203. }
  3204. FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT), NULL);
  3205. FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT), NULL);
  3206. if (FormatNameString == NULL || FormatHelpString == NULL) {
  3207. goto ON_EXIT;
  3208. }
  3209. RemainingSize = DataSize;
  3210. ListWalker = (EFI_SIGNATURE_LIST *)VariableData;
  3211. while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) {
  3212. if (CompareGuid (&ListWalker->SignatureType, &gEfiCertRsa2048Guid)) {
  3213. ListType = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256);
  3214. } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Guid)) {
  3215. ListType = STRING_TOKEN (STR_LIST_TYPE_X509);
  3216. } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha1Guid)) {
  3217. ListType = STRING_TOKEN (STR_LIST_TYPE_SHA1);
  3218. } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha256Guid)) {
  3219. ListType = STRING_TOKEN (STR_LIST_TYPE_SHA256);
  3220. } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha256Guid)) {
  3221. ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256);
  3222. } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha384Guid)) {
  3223. ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA384);
  3224. } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha512Guid)) {
  3225. ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA512);
  3226. } else {
  3227. ListType = STRING_TOKEN (STR_LIST_TYPE_UNKNOWN);
  3228. }
  3229. FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListType, NULL);
  3230. if (FormatTypeString == NULL) {
  3231. goto ON_EXIT;
  3232. }
  3233. ZeroMem (NameBuffer, sizeof (NameBuffer));
  3234. UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1);
  3235. ZeroMem (HelpBuffer, sizeof (HelpBuffer));
  3236. UnicodeSPrint (HelpBuffer,
  3237. sizeof (HelpBuffer),
  3238. FormatHelpString,
  3239. FormatTypeString,
  3240. SIGNATURE_DATA_COUNTS (ListWalker)
  3241. );
  3242. SECUREBOOT_FREE_NON_NULL (FormatTypeString);
  3243. FormatTypeString = NULL;
  3244. HiiCreateGotoOpCode (
  3245. StartOpCodeHandle,
  3246. SECUREBOOT_DELETE_SIGNATURE_DATA_FORM,
  3247. HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL),
  3248. HiiSetString (PrivateData->HiiHandle, 0, HelpBuffer, NULL),
  3249. EFI_IFR_FLAG_CALLBACK,
  3250. QuestionIdBase + Index++
  3251. );
  3252. RemainingSize -= ListWalker->SignatureListSize;
  3253. ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);
  3254. }
  3255. ON_EXIT:
  3256. HiiUpdateForm (
  3257. PrivateData->HiiHandle,
  3258. &gSecureBootConfigFormSetGuid,
  3259. FormId,
  3260. StartOpCodeHandle,
  3261. EndOpCodeHandle
  3262. );
  3263. HiiUpdateForm (
  3264. PrivateData->HiiHandle,
  3265. &gSecureBootConfigFormSetGuid,
  3266. FormId,
  3267. StartGotoHandle,
  3268. EndGotoHandle
  3269. );
  3270. SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);
  3271. SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);
  3272. SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle);
  3273. SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle);
  3274. SECUREBOOT_FREE_NON_NULL (VariableData);
  3275. SECUREBOOT_FREE_NON_NULL (FormatNameString);
  3276. SECUREBOOT_FREE_NON_NULL (FormatHelpString);
  3277. PrivateData->ListCount = Index;
  3278. return Status;
  3279. }
  3280. /**
  3281. Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.
  3282. The buffer is callee allocated and should be freed by the caller.
  3283. @param[in] ListEntry The pointer point to the signature list.
  3284. @param[in] DataEntry The signature data we are processing.
  3285. @param[out] BufferToReturn Buffer to save the hash value.
  3286. @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
  3287. @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
  3288. @retval EFI_SUCCESS Operation success.
  3289. **/
  3290. EFI_STATUS
  3291. ParseHashValue (
  3292. IN EFI_SIGNATURE_LIST *ListEntry,
  3293. IN EFI_SIGNATURE_DATA *DataEntry,
  3294. OUT CHAR16 **BufferToReturn
  3295. )
  3296. {
  3297. UINTN Index;
  3298. UINTN BufferIndex;
  3299. UINTN TotalSize;
  3300. UINTN DataSize;
  3301. UINTN Line;
  3302. UINTN OneLineBytes;
  3303. //
  3304. // Assume that, display 8 bytes in one line.
  3305. //
  3306. OneLineBytes = 8;
  3307. if (ListEntry == NULL || DataEntry == NULL || BufferToReturn == NULL) {
  3308. return EFI_INVALID_PARAMETER;
  3309. }
  3310. DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);
  3311. Line = (DataSize + OneLineBytes - 1) / OneLineBytes;
  3312. //
  3313. // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.
  3314. //
  3315. TotalSize = ((DataSize + Line) * 2 * sizeof(CHAR16));
  3316. *BufferToReturn = AllocateZeroPool(TotalSize);
  3317. if (*BufferToReturn == NULL) {
  3318. return EFI_OUT_OF_RESOURCES;
  3319. }
  3320. for (Index = 0, BufferIndex = 0; Index < DataSize; Index = Index + 1) {
  3321. if ((Index > 0) && (Index % OneLineBytes == 0)) {
  3322. BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"\n");
  3323. }
  3324. BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"%02x", DataEntry->SignatureData[Index]);
  3325. }
  3326. BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"\n");
  3327. return EFI_SUCCESS;
  3328. }
  3329. /**
  3330. Function to get the common name from the X509 format certificate.
  3331. The buffer is callee allocated and should be freed by the caller.
  3332. @param[in] ListEntry The pointer point to the signature list.
  3333. @param[in] DataEntry The signature data we are processing.
  3334. @param[out] BufferToReturn Buffer to save the CN of X509 certificate.
  3335. @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer.
  3336. @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
  3337. @retval EFI_SUCCESS Operation success.
  3338. @retval EFI_NOT_FOUND Not found CN field in the X509 certificate.
  3339. **/
  3340. EFI_STATUS
  3341. GetCommonNameFromX509 (
  3342. IN EFI_SIGNATURE_LIST *ListEntry,
  3343. IN EFI_SIGNATURE_DATA *DataEntry,
  3344. OUT CHAR16 **BufferToReturn
  3345. )
  3346. {
  3347. EFI_STATUS Status;
  3348. CHAR8 *CNBuffer;
  3349. UINTN CNBufferSize;
  3350. Status = EFI_SUCCESS;
  3351. CNBuffer = NULL;
  3352. CNBuffer = AllocateZeroPool(256);
  3353. if (CNBuffer == NULL) {
  3354. Status = EFI_OUT_OF_RESOURCES;
  3355. goto ON_EXIT;
  3356. }
  3357. CNBufferSize = 256;
  3358. X509GetCommonName (
  3359. (UINT8 *)DataEntry + sizeof(EFI_GUID),
  3360. ListEntry->SignatureSize - sizeof(EFI_GUID),
  3361. CNBuffer,
  3362. &CNBufferSize
  3363. );
  3364. *BufferToReturn = AllocateZeroPool(256 * sizeof(CHAR16));
  3365. if (*BufferToReturn == NULL) {
  3366. Status = EFI_OUT_OF_RESOURCES;
  3367. goto ON_EXIT;
  3368. }
  3369. AsciiStrToUnicodeStrS (CNBuffer, *BufferToReturn, 256);
  3370. ON_EXIT:
  3371. SECUREBOOT_FREE_NON_NULL (CNBuffer);
  3372. return Status;
  3373. }
  3374. /**
  3375. Format the help info for the signature data, each help info contain 3 parts.
  3376. 1. Onwer Guid.
  3377. 2. Content, depends on the type of the signature list.
  3378. 3. Revocation time.
  3379. @param[in] PrivateData Module's private data.
  3380. @param[in] ListEntry Point to the signature list.
  3381. @param[in] DataEntry Point to the signature data we are processing.
  3382. @param[out] StringId Save the string id of help info.
  3383. @retval EFI_SUCCESS Operation success.
  3384. @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
  3385. **/
  3386. EFI_STATUS
  3387. FormatHelpInfo (
  3388. IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
  3389. IN EFI_SIGNATURE_LIST *ListEntry,
  3390. IN EFI_SIGNATURE_DATA *DataEntry,
  3391. OUT EFI_STRING_ID *StringId
  3392. )
  3393. {
  3394. EFI_STATUS Status;
  3395. EFI_TIME *Time;
  3396. EFI_STRING_ID ListTypeId;
  3397. EFI_STRING FormatHelpString;
  3398. EFI_STRING FormatTypeString;
  3399. UINTN DataSize;
  3400. UINTN HelpInfoIndex;
  3401. UINTN TotalSize;
  3402. CHAR16 GuidString[BUFFER_MAX_SIZE];
  3403. CHAR16 TimeString[BUFFER_MAX_SIZE];
  3404. CHAR16 *DataString;
  3405. CHAR16 *HelpInfoString;
  3406. BOOLEAN IsCert;
  3407. Status = EFI_SUCCESS;
  3408. Time = NULL;
  3409. FormatTypeString = NULL;
  3410. HelpInfoIndex = 0;
  3411. DataString = NULL;
  3412. HelpInfoString = NULL;
  3413. IsCert = FALSE;
  3414. if (CompareGuid(&ListEntry->SignatureType, &gEfiCertRsa2048Guid)) {
  3415. ListTypeId = STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256);
  3416. DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);
  3417. IsCert = TRUE;
  3418. } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Guid)) {
  3419. ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509);
  3420. DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);
  3421. IsCert = TRUE;
  3422. } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertSha1Guid)) {
  3423. ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA1);
  3424. DataSize = 20;
  3425. } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertSha256Guid)) {
  3426. ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA256);
  3427. DataSize = 32;
  3428. } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha256Guid)) {
  3429. ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA256);
  3430. DataSize = 32;
  3431. Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);
  3432. } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha384Guid)) {
  3433. ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA384);
  3434. DataSize = 48;
  3435. Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);
  3436. } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha512Guid)) {
  3437. ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA512);
  3438. DataSize = 64;
  3439. Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);
  3440. } else {
  3441. Status = EFI_UNSUPPORTED;
  3442. goto ON_EXIT;
  3443. }
  3444. FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListTypeId, NULL);
  3445. if (FormatTypeString == NULL) {
  3446. goto ON_EXIT;
  3447. }
  3448. TotalSize = 1024;
  3449. HelpInfoString = AllocateZeroPool (TotalSize);
  3450. if (HelpInfoString == NULL) {
  3451. Status = EFI_OUT_OF_RESOURCES;
  3452. goto ON_EXIT;
  3453. }
  3454. //
  3455. // Format GUID part.
  3456. //
  3457. ZeroMem (GuidString, sizeof (GuidString));
  3458. GuidToString(&DataEntry->SignatureOwner, GuidString, BUFFER_MAX_SIZE);
  3459. FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID), NULL);
  3460. if (FormatHelpString == NULL) {
  3461. goto ON_EXIT;
  3462. }
  3463. HelpInfoIndex += UnicodeSPrint (
  3464. &HelpInfoString[HelpInfoIndex],
  3465. TotalSize - sizeof(CHAR16) * HelpInfoIndex,
  3466. FormatHelpString,
  3467. GuidString
  3468. );
  3469. SECUREBOOT_FREE_NON_NULL (FormatHelpString);
  3470. FormatHelpString = NULL;
  3471. //
  3472. // Format content part, it depends on the type of signature list, hash value or CN.
  3473. //
  3474. if (IsCert) {
  3475. GetCommonNameFromX509 (ListEntry, DataEntry, &DataString);
  3476. FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN), NULL);
  3477. } else {
  3478. //
  3479. // Format hash value for each signature data entry.
  3480. //
  3481. ParseHashValue (ListEntry, DataEntry, &DataString);
  3482. FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH), NULL);
  3483. }
  3484. if (FormatHelpString == NULL) {
  3485. goto ON_EXIT;
  3486. }
  3487. HelpInfoIndex += UnicodeSPrint (
  3488. &HelpInfoString[HelpInfoIndex],
  3489. TotalSize - sizeof (CHAR16) * HelpInfoIndex,
  3490. FormatHelpString,
  3491. FormatTypeString,
  3492. DataSize,
  3493. DataString
  3494. );
  3495. SECUREBOOT_FREE_NON_NULL (FormatHelpString);
  3496. FormatHelpString = NULL;
  3497. //
  3498. // Format revocation time part.
  3499. //
  3500. if (Time != NULL) {
  3501. ZeroMem (TimeString, sizeof (TimeString));
  3502. UnicodeSPrint (
  3503. TimeString,
  3504. sizeof (TimeString),
  3505. L"%d-%d-%d %d:%d:%d",
  3506. Time->Year,
  3507. Time->Month,
  3508. Time->Day,
  3509. Time->Hour,
  3510. Time->Minute,
  3511. Time->Second
  3512. );
  3513. FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME), NULL);
  3514. if (FormatHelpString == NULL) {
  3515. goto ON_EXIT;
  3516. }
  3517. UnicodeSPrint (
  3518. &HelpInfoString[HelpInfoIndex],
  3519. TotalSize - sizeof (CHAR16) * HelpInfoIndex,
  3520. FormatHelpString,
  3521. TimeString
  3522. );
  3523. SECUREBOOT_FREE_NON_NULL (FormatHelpString);
  3524. FormatHelpString = NULL;
  3525. }
  3526. *StringId = HiiSetString (PrivateData->HiiHandle, 0, HelpInfoString, NULL);
  3527. ON_EXIT:
  3528. SECUREBOOT_FREE_NON_NULL (DataString);
  3529. SECUREBOOT_FREE_NON_NULL (HelpInfoString);
  3530. SECUREBOOT_FREE_NON_NULL (FormatTypeString);
  3531. return Status;
  3532. }
  3533. /**
  3534. This functino to load signature data under the signature list.
  3535. @param[in] PrivateData Module's private data.
  3536. @param[in] LabelId Label number to insert opcodes.
  3537. @param[in] FormId Form ID of current page.
  3538. @param[in] QuestionIdBase Base question id of the signature list.
  3539. @param[in] ListIndex Indicate to load which signature list.
  3540. @retval EFI_SUCCESS Success to update the signature list page
  3541. @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
  3542. **/
  3543. EFI_STATUS
  3544. LoadSignatureData (
  3545. IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,
  3546. IN UINT16 LabelId,
  3547. IN EFI_FORM_ID FormId,
  3548. IN EFI_QUESTION_ID QuestionIdBase,
  3549. IN UINT16 ListIndex
  3550. )
  3551. {
  3552. EFI_STATUS Status;
  3553. EFI_SIGNATURE_LIST *ListWalker;
  3554. EFI_SIGNATURE_DATA *DataWalker;
  3555. EFI_IFR_GUID_LABEL *StartLabel;
  3556. EFI_IFR_GUID_LABEL *EndLabel;
  3557. EFI_STRING_ID HelpStringId;
  3558. EFI_STRING FormatNameString;
  3559. VOID *StartOpCodeHandle;
  3560. VOID *EndOpCodeHandle;
  3561. UINTN DataSize;
  3562. UINTN RemainingSize;
  3563. UINT16 Index;
  3564. UINT8 *VariableData;
  3565. CHAR16 VariableName[BUFFER_MAX_SIZE];
  3566. CHAR16 NameBuffer[BUFFER_MAX_SIZE];
  3567. Status = EFI_SUCCESS;
  3568. FormatNameString = NULL;
  3569. StartOpCodeHandle = NULL;
  3570. EndOpCodeHandle = NULL;
  3571. Index = 0;
  3572. VariableData = NULL;
  3573. //
  3574. // Initialize the container for dynamic opcodes.
  3575. //
  3576. StartOpCodeHandle = HiiAllocateOpCodeHandle ();
  3577. if (StartOpCodeHandle == NULL) {
  3578. Status = EFI_OUT_OF_RESOURCES;
  3579. goto ON_EXIT;
  3580. }
  3581. EndOpCodeHandle = HiiAllocateOpCodeHandle ();
  3582. if (EndOpCodeHandle == NULL) {
  3583. Status = EFI_OUT_OF_RESOURCES;
  3584. goto ON_EXIT;
  3585. }
  3586. //
  3587. // Create Hii Extend Label OpCode.
  3588. //
  3589. StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
  3590. StartOpCodeHandle,
  3591. &gEfiIfrTianoGuid,
  3592. NULL,
  3593. sizeof (EFI_IFR_GUID_LABEL)
  3594. );
  3595. StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  3596. StartLabel->Number = LabelId;
  3597. EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
  3598. EndOpCodeHandle,
  3599. &gEfiIfrTianoGuid,
  3600. NULL,
  3601. sizeof (EFI_IFR_GUID_LABEL)
  3602. );
  3603. EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  3604. EndLabel->Number = LABEL_END;
  3605. if (PrivateData->VariableName == Variable_DB) {
  3606. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);
  3607. } else if (PrivateData->VariableName == Variable_DBX) {
  3608. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);
  3609. } else if (PrivateData->VariableName == Variable_DBT) {
  3610. UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);
  3611. } else {
  3612. goto ON_EXIT;
  3613. }
  3614. //
  3615. // Read Variable, the variable name save in the PrivateData->VariableName.
  3616. //
  3617. DataSize = 0;
  3618. Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);
  3619. if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
  3620. goto ON_EXIT;
  3621. }
  3622. VariableData = AllocateZeroPool (DataSize);
  3623. if (VariableData == NULL) {
  3624. Status = EFI_OUT_OF_RESOURCES;
  3625. goto ON_EXIT;
  3626. }
  3627. Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);
  3628. if (EFI_ERROR (Status)) {
  3629. goto ON_EXIT;
  3630. }
  3631. RemainingSize = DataSize;
  3632. ListWalker = (EFI_SIGNATURE_LIST *)VariableData;
  3633. //
  3634. // Skip signature list.
  3635. //
  3636. while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex-- > 0) {
  3637. RemainingSize -= ListWalker->SignatureListSize;
  3638. ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);
  3639. }
  3640. FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT), NULL);
  3641. if (FormatNameString == NULL) {
  3642. goto ON_EXIT;
  3643. }
  3644. DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof(EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);
  3645. for (Index = 0; Index < SIGNATURE_DATA_COUNTS(ListWalker); Index = Index + 1) {
  3646. //
  3647. // Format name buffer.
  3648. //
  3649. ZeroMem (NameBuffer, sizeof (NameBuffer));
  3650. UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1);
  3651. //
  3652. // Format help info buffer.
  3653. //
  3654. Status = FormatHelpInfo (PrivateData, ListWalker, DataWalker, &HelpStringId);
  3655. if (EFI_ERROR (Status)) {
  3656. goto ON_EXIT;
  3657. }
  3658. HiiCreateCheckBoxOpCode (
  3659. StartOpCodeHandle,
  3660. (EFI_QUESTION_ID)(QuestionIdBase + Index),
  3661. 0,
  3662. 0,
  3663. HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL),
  3664. HelpStringId,
  3665. EFI_IFR_FLAG_CALLBACK,
  3666. 0,
  3667. NULL
  3668. );
  3669. ZeroMem(NameBuffer, 100);
  3670. DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);
  3671. }
  3672. //
  3673. // Allocate a buffer to record which signature data will be checked.
  3674. // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
  3675. //
  3676. PrivateData->CheckArray = AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker) * sizeof (BOOLEAN));
  3677. ON_EXIT:
  3678. HiiUpdateForm (
  3679. PrivateData->HiiHandle,
  3680. &gSecureBootConfigFormSetGuid,
  3681. FormId,
  3682. StartOpCodeHandle,
  3683. EndOpCodeHandle
  3684. );
  3685. SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);
  3686. SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);
  3687. SECUREBOOT_FREE_NON_NULL (VariableData);
  3688. SECUREBOOT_FREE_NON_NULL (FormatNameString);
  3689. return Status;
  3690. }
  3691. /**
  3692. This function is called to provide results data to the driver.
  3693. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  3694. @param[in] Action Specifies the type of action taken by the browser.
  3695. @param[in] QuestionId A unique value which is sent to the original
  3696. exporting driver so that it can identify the type
  3697. of data to expect.
  3698. @param[in] Type The type of value for the question.
  3699. @param[in] Value A pointer to the data being sent to the original
  3700. exporting driver.
  3701. @param[out] ActionRequest On return, points to the action requested by the
  3702. callback function.
  3703. @retval EFI_SUCCESS The callback successfully handled the action.
  3704. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
  3705. variable and its data.
  3706. @retval EFI_DEVICE_ERROR The variable could not be saved.
  3707. @retval EFI_UNSUPPORTED The specified Action is not supported by the
  3708. callback.
  3709. **/
  3710. EFI_STATUS
  3711. EFIAPI
  3712. SecureBootCallback (
  3713. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  3714. IN EFI_BROWSER_ACTION Action,
  3715. IN EFI_QUESTION_ID QuestionId,
  3716. IN UINT8 Type,
  3717. IN EFI_IFR_TYPE_VALUE *Value,
  3718. OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
  3719. )
  3720. {
  3721. EFI_INPUT_KEY Key;
  3722. EFI_STATUS Status;
  3723. RETURN_STATUS RStatus;
  3724. SECUREBOOT_CONFIG_PRIVATE_DATA *Private;
  3725. UINTN BufferSize;
  3726. SECUREBOOT_CONFIGURATION *IfrNvData;
  3727. UINT16 LabelId;
  3728. UINT8 *SecureBootEnable;
  3729. UINT8 *Pk;
  3730. UINT8 *SecureBootMode;
  3731. UINT8 *SetupMode;
  3732. CHAR16 PromptString[100];
  3733. EFI_DEVICE_PATH_PROTOCOL *File;
  3734. UINTN NameLength;
  3735. UINT16 *FilePostFix;
  3736. SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
  3737. BOOLEAN GetBrowserDataResult;
  3738. Status = EFI_SUCCESS;
  3739. SecureBootEnable = NULL;
  3740. SecureBootMode = NULL;
  3741. SetupMode = NULL;
  3742. File = NULL;
  3743. if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
  3744. return EFI_INVALID_PARAMETER;
  3745. }
  3746. Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
  3747. gSecureBootPrivateData = Private;
  3748. //
  3749. // Retrieve uncommitted data from Browser
  3750. //
  3751. BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
  3752. IfrNvData = AllocateZeroPool (BufferSize);
  3753. if (IfrNvData == NULL) {
  3754. return EFI_OUT_OF_RESOURCES;
  3755. }
  3756. GetBrowserDataResult = HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);
  3757. if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
  3758. if (QuestionId == KEY_SECURE_BOOT_MODE) {
  3759. //
  3760. // Update secure boot strings when opening this form
  3761. //
  3762. Status = UpdateSecureBootString(Private);
  3763. SecureBootExtractConfigFromVariable (Private, IfrNvData);
  3764. mIsEnterSecureBootForm = TRUE;
  3765. } else {
  3766. //
  3767. // When entering SecureBoot OPTION Form
  3768. // always close opened file & free resource
  3769. //
  3770. if ((QuestionId == KEY_SECURE_BOOT_PK_OPTION) ||
  3771. (QuestionId == KEY_SECURE_BOOT_KEK_OPTION) ||
  3772. (QuestionId == KEY_SECURE_BOOT_DB_OPTION) ||
  3773. (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) ||
  3774. (QuestionId == KEY_SECURE_BOOT_DBT_OPTION)) {
  3775. CloseEnrolledFile(Private->FileContext);
  3776. } else if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_LIST) {
  3777. //
  3778. // Update ListCount field in varstore
  3779. // Button "Delete All Signature List" is
  3780. // enable when ListCount is greater than 0.
  3781. //
  3782. IfrNvData->ListCount = Private->ListCount;
  3783. }
  3784. }
  3785. goto EXIT;
  3786. }
  3787. if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
  3788. Status = EFI_UNSUPPORTED;
  3789. if (QuestionId == KEY_SECURE_BOOT_MODE) {
  3790. if (mIsEnterSecureBootForm) {
  3791. Value->u8 = SECURE_BOOT_MODE_STANDARD;
  3792. Status = EFI_SUCCESS;
  3793. }
  3794. }
  3795. goto EXIT;
  3796. }
  3797. if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
  3798. (Action != EFI_BROWSER_ACTION_CHANGING) &&
  3799. (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&
  3800. (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {
  3801. Status = EFI_UNSUPPORTED;
  3802. goto EXIT;
  3803. }
  3804. if (Action == EFI_BROWSER_ACTION_CHANGING) {
  3805. switch (QuestionId) {
  3806. case KEY_SECURE_BOOT_ENABLE:
  3807. GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
  3808. if (NULL != SecureBootEnable) {
  3809. FreePool (SecureBootEnable);
  3810. if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {
  3811. CreatePopUp (
  3812. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  3813. &Key,
  3814. L"Only Physical Presence User could disable secure boot!",
  3815. NULL
  3816. );
  3817. Status = EFI_UNSUPPORTED;
  3818. } else {
  3819. CreatePopUp (
  3820. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  3821. &Key,
  3822. L"Configuration changed, please reset the platform to take effect!",
  3823. NULL
  3824. );
  3825. }
  3826. }
  3827. break;
  3828. case KEY_SECURE_BOOT_KEK_OPTION:
  3829. case KEY_SECURE_BOOT_DB_OPTION:
  3830. case KEY_SECURE_BOOT_DBX_OPTION:
  3831. case KEY_SECURE_BOOT_DBT_OPTION:
  3832. PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
  3833. //
  3834. // Clear Signature GUID.
  3835. //
  3836. ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));
  3837. if (Private->SignatureGUID == NULL) {
  3838. Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));
  3839. if (Private->SignatureGUID == NULL) {
  3840. return EFI_OUT_OF_RESOURCES;
  3841. }
  3842. }
  3843. //
  3844. // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page
  3845. //
  3846. SecureBootExtractConfigFromVariable (PrivateData, IfrNvData);
  3847. if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {
  3848. LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
  3849. } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {
  3850. LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
  3851. } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) {
  3852. LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;
  3853. } else {
  3854. LabelId = FORMID_ENROLL_KEK_FORM;
  3855. }
  3856. //
  3857. // Refresh selected file.
  3858. //
  3859. CleanUpPage (LabelId, Private);
  3860. break;
  3861. case KEY_SECURE_BOOT_PK_OPTION:
  3862. LabelId = FORMID_ENROLL_PK_FORM;
  3863. //
  3864. // Refresh selected file.
  3865. //
  3866. CleanUpPage (LabelId, Private);
  3867. break;
  3868. case FORMID_ENROLL_PK_FORM:
  3869. ChooseFile (NULL, NULL, UpdatePKFromFile, &File);
  3870. break;
  3871. case FORMID_ENROLL_KEK_FORM:
  3872. ChooseFile (NULL, NULL, UpdateKEKFromFile, &File);
  3873. break;
  3874. case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:
  3875. ChooseFile (NULL, NULL, UpdateDBFromFile, &File);
  3876. break;
  3877. case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:
  3878. ChooseFile (NULL, NULL, UpdateDBXFromFile, &File);
  3879. if (Private->FileContext->FHandle != NULL) {
  3880. //
  3881. // Parse the file's postfix.
  3882. //
  3883. NameLength = StrLen (Private->FileContext->FileName);
  3884. if (NameLength <= 4) {
  3885. return FALSE;
  3886. }
  3887. FilePostFix = Private->FileContext->FileName + NameLength - 4;
  3888. if (IsDerEncodeCertificate (FilePostFix)) {
  3889. //
  3890. // Supports DER-encoded X509 certificate.
  3891. //
  3892. IfrNvData->FileEnrollType = X509_CERT_FILE_TYPE;
  3893. } else if (IsAuthentication2Format(Private->FileContext->FHandle)){
  3894. IfrNvData->FileEnrollType = AUTHENTICATION_2_FILE_TYPE;
  3895. } else {
  3896. IfrNvData->FileEnrollType = PE_IMAGE_FILE_TYPE;
  3897. }
  3898. Private->FileContext->FileType = IfrNvData->FileEnrollType;
  3899. //
  3900. // Clean up Certificate Format if File type is not X509 DER
  3901. //
  3902. if (IfrNvData->FileEnrollType != X509_CERT_FILE_TYPE) {
  3903. IfrNvData->CertificateFormat = HASHALG_RAW;
  3904. }
  3905. DEBUG((DEBUG_ERROR, "IfrNvData->FileEnrollType %d\n", Private->FileContext->FileType));
  3906. }
  3907. break;
  3908. case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT:
  3909. ChooseFile (NULL, NULL, UpdateDBTFromFile, &File);
  3910. break;
  3911. case KEY_SECURE_BOOT_DELETE_PK:
  3912. if (Value->u8) {
  3913. CreatePopUp (
  3914. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  3915. &Key,
  3916. L"Are you sure you want to delete PK? Secure boot will be disabled!",
  3917. L"Press 'Y' to delete PK and exit, 'N' to discard change and return",
  3918. NULL
  3919. );
  3920. if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {
  3921. Status = DeletePlatformKey ();
  3922. if (EFI_ERROR (Status)) {
  3923. CreatePopUp (
  3924. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  3925. &Key,
  3926. L"Only Physical Presence User could delete PK in custom mode!",
  3927. NULL
  3928. );
  3929. }
  3930. }
  3931. }
  3932. break;
  3933. case KEY_DELETE_KEK:
  3934. UpdateDeletePage (
  3935. Private,
  3936. EFI_KEY_EXCHANGE_KEY_NAME,
  3937. &gEfiGlobalVariableGuid,
  3938. LABEL_KEK_DELETE,
  3939. FORMID_DELETE_KEK_FORM,
  3940. OPTION_DEL_KEK_QUESTION_ID
  3941. );
  3942. break;
  3943. case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:
  3944. UpdateDeletePage (
  3945. Private,
  3946. EFI_IMAGE_SECURITY_DATABASE,
  3947. &gEfiImageSecurityDatabaseGuid,
  3948. LABEL_DB_DELETE,
  3949. SECUREBOOT_DELETE_SIGNATURE_FROM_DB,
  3950. OPTION_DEL_DB_QUESTION_ID
  3951. );
  3952. break;
  3953. //
  3954. // From DBX option to the level-1 form, display signature list.
  3955. //
  3956. case KEY_VALUE_FROM_DBX_TO_LIST_FORM:
  3957. Private->VariableName = Variable_DBX;
  3958. LoadSignatureList (
  3959. Private,
  3960. LABEL_SIGNATURE_LIST_START,
  3961. SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,
  3962. OPTION_SIGNATURE_LIST_QUESTION_ID
  3963. );
  3964. break;
  3965. //
  3966. // Delete all signature list and reload.
  3967. //
  3968. case KEY_SECURE_BOOT_DELETE_ALL_LIST:
  3969. CreatePopUp(
  3970. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  3971. &Key,
  3972. L"Press 'Y' to delete signature list.",
  3973. L"Press other key to cancel and exit.",
  3974. NULL
  3975. );
  3976. if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {
  3977. DeleteSignatureEx (Private, Delete_Signature_List_All, IfrNvData->CheckedDataCount);
  3978. }
  3979. LoadSignatureList (
  3980. Private,
  3981. LABEL_SIGNATURE_LIST_START,
  3982. SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,
  3983. OPTION_SIGNATURE_LIST_QUESTION_ID
  3984. );
  3985. break;
  3986. //
  3987. // Delete one signature list and reload.
  3988. //
  3989. case KEY_SECURE_BOOT_DELETE_ALL_DATA:
  3990. CreatePopUp(
  3991. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  3992. &Key,
  3993. L"Press 'Y' to delete signature data.",
  3994. L"Press other key to cancel and exit.",
  3995. NULL
  3996. );
  3997. if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {
  3998. DeleteSignatureEx (Private, Delete_Signature_List_One, IfrNvData->CheckedDataCount);
  3999. }
  4000. LoadSignatureList (
  4001. Private,
  4002. LABEL_SIGNATURE_LIST_START,
  4003. SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,
  4004. OPTION_SIGNATURE_LIST_QUESTION_ID
  4005. );
  4006. break;
  4007. //
  4008. // Delete checked signature data and reload.
  4009. //
  4010. case KEY_SECURE_BOOT_DELETE_CHECK_DATA:
  4011. CreatePopUp(
  4012. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  4013. &Key,
  4014. L"Press 'Y' to delete signature data.",
  4015. L"Press other key to cancel and exit.",
  4016. NULL
  4017. );
  4018. if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {
  4019. DeleteSignatureEx (Private, Delete_Signature_Data, IfrNvData->CheckedDataCount);
  4020. }
  4021. LoadSignatureList (
  4022. Private,
  4023. LABEL_SIGNATURE_LIST_START,
  4024. SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,
  4025. OPTION_SIGNATURE_LIST_QUESTION_ID
  4026. );
  4027. break;
  4028. case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT:
  4029. UpdateDeletePage (
  4030. Private,
  4031. EFI_IMAGE_SECURITY_DATABASE2,
  4032. &gEfiImageSecurityDatabaseGuid,
  4033. LABEL_DBT_DELETE,
  4034. SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
  4035. OPTION_DEL_DBT_QUESTION_ID
  4036. );
  4037. break;
  4038. case KEY_VALUE_SAVE_AND_EXIT_KEK:
  4039. Status = EnrollKeyExchangeKey (Private);
  4040. if (EFI_ERROR (Status)) {
  4041. CreatePopUp (
  4042. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  4043. &Key,
  4044. L"ERROR: Unsupported file type!",
  4045. L"Only supports DER-encoded X509 certificate",
  4046. NULL
  4047. );
  4048. }
  4049. break;
  4050. case KEY_VALUE_SAVE_AND_EXIT_DB:
  4051. Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);
  4052. if (EFI_ERROR (Status)) {
  4053. CreatePopUp (
  4054. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  4055. &Key,
  4056. L"ERROR: Unsupported file type!",
  4057. L"Only supports DER-encoded X509 certificate and executable EFI image",
  4058. NULL
  4059. );
  4060. }
  4061. break;
  4062. case KEY_VALUE_SAVE_AND_EXIT_DBX:
  4063. if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) {
  4064. CreatePopUp (
  4065. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  4066. &Key,
  4067. L"Enrollment failed! Same certificate had already been in the dbx!",
  4068. NULL
  4069. );
  4070. //
  4071. // Cert already exists in DBX. Close opened file before exit.
  4072. //
  4073. CloseEnrolledFile(Private->FileContext);
  4074. break;
  4075. }
  4076. if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) {
  4077. Status = EnrollX509HashtoSigDB (
  4078. Private,
  4079. IfrNvData->CertificateFormat,
  4080. &IfrNvData->RevocationDate,
  4081. &IfrNvData->RevocationTime,
  4082. IfrNvData->AlwaysRevocation
  4083. );
  4084. IfrNvData->CertificateFormat = HASHALG_RAW;
  4085. } else {
  4086. Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);
  4087. }
  4088. if (EFI_ERROR (Status)) {
  4089. CreatePopUp (
  4090. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  4091. &Key,
  4092. L"ERROR: Unsupported file type!",
  4093. L"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",
  4094. NULL
  4095. );
  4096. }
  4097. break;
  4098. case KEY_VALUE_SAVE_AND_EXIT_DBT:
  4099. Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2);
  4100. if (EFI_ERROR (Status)) {
  4101. CreatePopUp (
  4102. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  4103. &Key,
  4104. L"ERROR: Unsupported file type!",
  4105. L"Only supports DER-encoded X509 certificate.",
  4106. NULL
  4107. );
  4108. }
  4109. break;
  4110. case KEY_VALUE_SAVE_AND_EXIT_PK:
  4111. Status = EnrollPlatformKey (Private);
  4112. if (EFI_ERROR (Status)) {
  4113. UnicodeSPrint (
  4114. PromptString,
  4115. sizeof (PromptString),
  4116. L"Only DER encoded certificate file (%s) is supported.",
  4117. mSupportX509Suffix
  4118. );
  4119. CreatePopUp (
  4120. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  4121. &Key,
  4122. L"ERROR: Unsupported file type!",
  4123. PromptString,
  4124. NULL
  4125. );
  4126. }
  4127. break;
  4128. default:
  4129. if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&
  4130. (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {
  4131. DeleteKeyExchangeKey (Private, QuestionId);
  4132. } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&
  4133. (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {
  4134. DeleteSignature (
  4135. Private,
  4136. EFI_IMAGE_SECURITY_DATABASE,
  4137. &gEfiImageSecurityDatabaseGuid,
  4138. LABEL_DB_DELETE,
  4139. SECUREBOOT_DELETE_SIGNATURE_FROM_DB,
  4140. OPTION_DEL_DB_QUESTION_ID,
  4141. QuestionId - OPTION_DEL_DB_QUESTION_ID
  4142. );
  4143. } else if ((QuestionId >= OPTION_SIGNATURE_LIST_QUESTION_ID) &&
  4144. (QuestionId < (OPTION_SIGNATURE_LIST_QUESTION_ID + OPTION_CONFIG_RANGE))) {
  4145. LoadSignatureData (
  4146. Private,
  4147. LABEL_SIGNATURE_DATA_START,
  4148. SECUREBOOT_DELETE_SIGNATURE_DATA_FORM,
  4149. OPTION_SIGNATURE_DATA_QUESTION_ID,
  4150. QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID
  4151. );
  4152. Private->ListIndex = QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID;
  4153. } else if ((QuestionId >= OPTION_SIGNATURE_DATA_QUESTION_ID) &&
  4154. (QuestionId < (OPTION_SIGNATURE_DATA_QUESTION_ID + OPTION_CONFIG_RANGE))) {
  4155. if (Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID]) {
  4156. IfrNvData->CheckedDataCount--;
  4157. Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = FALSE;
  4158. } else {
  4159. IfrNvData->CheckedDataCount++;
  4160. Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = TRUE;
  4161. }
  4162. } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) &&
  4163. (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) {
  4164. DeleteSignature (
  4165. Private,
  4166. EFI_IMAGE_SECURITY_DATABASE2,
  4167. &gEfiImageSecurityDatabaseGuid,
  4168. LABEL_DBT_DELETE,
  4169. SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
  4170. OPTION_DEL_DBT_QUESTION_ID,
  4171. QuestionId - OPTION_DEL_DBT_QUESTION_ID
  4172. );
  4173. }
  4174. break;
  4175. case KEY_VALUE_NO_SAVE_AND_EXIT_PK:
  4176. case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:
  4177. case KEY_VALUE_NO_SAVE_AND_EXIT_DB:
  4178. case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:
  4179. case KEY_VALUE_NO_SAVE_AND_EXIT_DBT:
  4180. CloseEnrolledFile(Private->FileContext);
  4181. if (Private->SignatureGUID != NULL) {
  4182. FreePool (Private->SignatureGUID);
  4183. Private->SignatureGUID = NULL;
  4184. }
  4185. break;
  4186. }
  4187. } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
  4188. switch (QuestionId) {
  4189. case KEY_SECURE_BOOT_ENABLE:
  4190. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
  4191. break;
  4192. case KEY_SECURE_BOOT_MODE:
  4193. mIsEnterSecureBootForm = FALSE;
  4194. break;
  4195. case KEY_SECURE_BOOT_KEK_GUID:
  4196. case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:
  4197. case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:
  4198. case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT:
  4199. ASSERT (Private->SignatureGUID != NULL);
  4200. RStatus = StrToGuid (IfrNvData->SignatureGuid, Private->SignatureGUID);
  4201. if (RETURN_ERROR (RStatus) || (IfrNvData->SignatureGuid[GUID_STRING_LENGTH] != L'\0')) {
  4202. Status = EFI_INVALID_PARAMETER;
  4203. break;
  4204. }
  4205. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
  4206. break;
  4207. case KEY_SECURE_BOOT_DELETE_PK:
  4208. GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);
  4209. if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {
  4210. IfrNvData->DeletePk = TRUE;
  4211. IfrNvData->HasPk = FALSE;
  4212. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
  4213. } else {
  4214. IfrNvData->DeletePk = FALSE;
  4215. IfrNvData->HasPk = TRUE;
  4216. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
  4217. }
  4218. if (SetupMode != NULL) {
  4219. FreePool (SetupMode);
  4220. }
  4221. break;
  4222. default:
  4223. break;
  4224. }
  4225. } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {
  4226. if (QuestionId == KEY_HIDE_SECURE_BOOT) {
  4227. GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID**)&Pk, NULL);
  4228. if (Pk == NULL) {
  4229. IfrNvData->HideSecureBoot = TRUE;
  4230. } else {
  4231. FreePool (Pk);
  4232. IfrNvData->HideSecureBoot = FALSE;
  4233. }
  4234. Value->b = IfrNvData->HideSecureBoot;
  4235. }
  4236. } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
  4237. //
  4238. // Force the platform back to Standard Mode once user leave the setup screen.
  4239. //
  4240. GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
  4241. if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {
  4242. IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
  4243. SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);
  4244. }
  4245. if (SecureBootMode != NULL) {
  4246. FreePool (SecureBootMode);
  4247. }
  4248. if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_DATA) {
  4249. //
  4250. // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.
  4251. //
  4252. SECUREBOOT_FREE_NON_NULL (Private->CheckArray);
  4253. IfrNvData->CheckedDataCount = 0;
  4254. }
  4255. }
  4256. EXIT:
  4257. if (!EFI_ERROR (Status) && GetBrowserDataResult) {
  4258. BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
  4259. HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);
  4260. }
  4261. FreePool (IfrNvData);
  4262. if (File != NULL){
  4263. FreePool(File);
  4264. File = NULL;
  4265. }
  4266. return EFI_SUCCESS;
  4267. }
  4268. /**
  4269. This function publish the SecureBoot configuration Form.
  4270. @param[in, out] PrivateData Points to SecureBoot configuration private data.
  4271. @retval EFI_SUCCESS HII Form is installed successfully.
  4272. @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
  4273. @retval Others Other errors as indicated.
  4274. **/
  4275. EFI_STATUS
  4276. InstallSecureBootConfigForm (
  4277. IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData
  4278. )
  4279. {
  4280. EFI_STATUS Status;
  4281. EFI_HII_HANDLE HiiHandle;
  4282. EFI_HANDLE DriverHandle;
  4283. EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
  4284. DriverHandle = NULL;
  4285. ConfigAccess = &PrivateData->ConfigAccess;
  4286. Status = gBS->InstallMultipleProtocolInterfaces (
  4287. &DriverHandle,
  4288. &gEfiDevicePathProtocolGuid,
  4289. &mSecureBootHiiVendorDevicePath,
  4290. &gEfiHiiConfigAccessProtocolGuid,
  4291. ConfigAccess,
  4292. NULL
  4293. );
  4294. if (EFI_ERROR (Status)) {
  4295. return Status;
  4296. }
  4297. PrivateData->DriverHandle = DriverHandle;
  4298. //
  4299. // Publish the HII package list
  4300. //
  4301. HiiHandle = HiiAddPackages (
  4302. &gSecureBootConfigFormSetGuid,
  4303. DriverHandle,
  4304. SecureBootConfigDxeStrings,
  4305. SecureBootConfigBin,
  4306. NULL
  4307. );
  4308. if (HiiHandle == NULL) {
  4309. gBS->UninstallMultipleProtocolInterfaces (
  4310. DriverHandle,
  4311. &gEfiDevicePathProtocolGuid,
  4312. &mSecureBootHiiVendorDevicePath,
  4313. &gEfiHiiConfigAccessProtocolGuid,
  4314. ConfigAccess,
  4315. NULL
  4316. );
  4317. return EFI_OUT_OF_RESOURCES;
  4318. }
  4319. PrivateData->HiiHandle = HiiHandle;
  4320. PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));
  4321. if (PrivateData->FileContext == NULL) {
  4322. UninstallSecureBootConfigForm (PrivateData);
  4323. return EFI_OUT_OF_RESOURCES;
  4324. }
  4325. //
  4326. // Init OpCode Handle and Allocate space for creation of Buffer
  4327. //
  4328. mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
  4329. if (mStartOpCodeHandle == NULL) {
  4330. UninstallSecureBootConfigForm (PrivateData);
  4331. return EFI_OUT_OF_RESOURCES;
  4332. }
  4333. mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
  4334. if (mEndOpCodeHandle == NULL) {
  4335. UninstallSecureBootConfigForm (PrivateData);
  4336. return EFI_OUT_OF_RESOURCES;
  4337. }
  4338. //
  4339. // Create Hii Extend Label OpCode as the start opcode
  4340. //
  4341. mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
  4342. mStartOpCodeHandle,
  4343. &gEfiIfrTianoGuid,
  4344. NULL,
  4345. sizeof (EFI_IFR_GUID_LABEL)
  4346. );
  4347. mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  4348. //
  4349. // Create Hii Extend Label OpCode as the end opcode
  4350. //
  4351. mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
  4352. mEndOpCodeHandle,
  4353. &gEfiIfrTianoGuid,
  4354. NULL,
  4355. sizeof (EFI_IFR_GUID_LABEL)
  4356. );
  4357. mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  4358. mEndLabel->Number = LABEL_END;
  4359. return EFI_SUCCESS;
  4360. }
  4361. /**
  4362. This function removes SecureBoot configuration Form.
  4363. @param[in, out] PrivateData Points to SecureBoot configuration private data.
  4364. **/
  4365. VOID
  4366. UninstallSecureBootConfigForm (
  4367. IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData
  4368. )
  4369. {
  4370. //
  4371. // Uninstall HII package list
  4372. //
  4373. if (PrivateData->HiiHandle != NULL) {
  4374. HiiRemovePackages (PrivateData->HiiHandle);
  4375. PrivateData->HiiHandle = NULL;
  4376. }
  4377. //
  4378. // Uninstall HII Config Access Protocol
  4379. //
  4380. if (PrivateData->DriverHandle != NULL) {
  4381. gBS->UninstallMultipleProtocolInterfaces (
  4382. PrivateData->DriverHandle,
  4383. &gEfiDevicePathProtocolGuid,
  4384. &mSecureBootHiiVendorDevicePath,
  4385. &gEfiHiiConfigAccessProtocolGuid,
  4386. &PrivateData->ConfigAccess,
  4387. NULL
  4388. );
  4389. PrivateData->DriverHandle = NULL;
  4390. }
  4391. if (PrivateData->SignatureGUID != NULL) {
  4392. FreePool (PrivateData->SignatureGUID);
  4393. }
  4394. if (PrivateData->FileContext != NULL) {
  4395. FreePool (PrivateData->FileContext);
  4396. }
  4397. FreePool (PrivateData);
  4398. if (mStartOpCodeHandle != NULL) {
  4399. HiiFreeOpCodeHandle (mStartOpCodeHandle);
  4400. }
  4401. if (mEndOpCodeHandle != NULL) {
  4402. HiiFreeOpCodeHandle (mEndOpCodeHandle);
  4403. }
  4404. }