SessionFactory
.
+ * The factory is used for an in-memory database that is used for testing.
+ */
+ @BeforeAll
+ public static final void setup() {
+ LOGGER.debug("retrieving session factory");
+ }
+
+ /**
+ * Closes the SessionFactory
from setup.
+ */
+ @AfterAll
+ public static final void tearDown() {
+ LOGGER.debug("closing session factory");
+ }
+
+ /**
+ * Tests the processing of UEFI Variables.
+ *
+ * @throws IOException when processing the test fails.
+ * @throws NoSuchAlgorithmException if non TCG Algorithm is encountered.
+ * @throws CertificateException if parsing issue for X509 cert is encountered.
+ * @throws URISyntaxException File location exception
+ */
+ @Test
+ public final void testUefiVariables() throws IOException,
+ CertificateException, NoSuchAlgorithmException, URISyntaxException {
+ LOGGER.debug("Testing the parsing of UEFI Variables");
+ Path jsonPath = Paths.get(this.getClass()
+ .getResource(JSON_FILE).toURI());
+ String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_VARIABLE_BOOT),
+ "UTF-8");
+ byte[] uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
+ UefiVariable uefiVariable = new UefiVariable(uefiVariableBytes);
+ UefiGuid guid = uefiVariable.getUefiVarGuid();
+ String varName = uefiVariable.getEfiVarName();
+ JsonObject jsonObject = JsonUtils.getSpecificJsonObject(jsonPath, "VendorTable");
+ String guidStr = jsonObject.getString(
+ guid.toStringNoLookup().toLowerCase(), "Unknown GUID reference");
+ Assertions.assertEquals("EFI_Global_Variable", guidStr);
+ Assertions.assertEquals("BootOrder", varName);
+
+ uefiTxt = IOUtils.toString(this.getClass()
+ .getResourceAsStream(UEFI_VARIABLE_BOOT_SECURE_BOOT),
+ "UTF-8");
+ uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
+ uefiVariable = new UefiVariable(uefiVariableBytes);
+ guid = uefiVariable.getUefiVarGuid();
+ varName = uefiVariable.getEfiVarName();
+ guidStr = jsonObject.getString(
+ guid.toStringNoLookup().toLowerCase(), "Unknown GUID reference");
+ Assertions.assertEquals("EFI_Global_Variable", guidStr);
+ Assertions.assertEquals("SecureBoot", varName);
+
+ uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(
+ UEFI_VARIABLE_BOOT_DRIVER_CONFIG_KEK), "UTF-8");
+ uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
+ uefiVariable = new UefiVariable(uefiVariableBytes);
+ varName = uefiVariable.getEfiVarName();
+ Assertions.assertEquals("KEK", varName);
+ }
+
+ /**
+ * Tests the processing of a UEFI defined GPT Partition event.
+ *
+ * @throws IOException when processing the test fails.
+ * @throws NoSuchAlgorithmException if non TCG Algorithm is encountered.
+ * @throws CertificateException if parsing issue for X509 cert is encountered.
+ * @throws URISyntaxException File location exception
+ */
+ @Test
+ public final void testUefiPartiton() throws IOException,
+ CertificateException, NoSuchAlgorithmException, URISyntaxException {
+ LOGGER.debug("Testing the parsing of GPT Data");
+ Path jsonPath = Paths.get(this.getClass()
+ .getResource(JSON_FILE).toURI());
+ String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_GPT_EVENT),
+ "UTF-8");
+ byte[] uefiPartitionBytes = HexUtils.hexStringToByteArray(uefiTxt);
+ UefiPartition gptPart = new UefiPartition(uefiPartitionBytes);
+ String gptPartName = gptPart.getPartitionName();
+ UefiGuid gptTypeuid = gptPart.getPartitionTypeGUID();
+ UefiGuid gptUniqueGuid = gptPart.getUniquePartitionGUID();
+ JsonObject jsonObject = JsonUtils.getSpecificJsonObject(jsonPath, "VendorTable");
+ String guidStr = jsonObject.getString(
+ gptTypeuid.toStringNoLookup().toLowerCase(), "Unknown GUID reference");
+ Assertions.assertEquals("EFI System Partition", guidStr);
+ Assertions.assertEquals("8ca7623c-041e-4fab-8c12-f49a86b85d73 : Unknown GUID reference",
+ gptUniqueGuid.toString());
+ Assertions.assertEquals("EFI system partition", gptPartName);
+ }
+
+ /**
+ * Tests the processing of a UEFI defined GPT Partition event.
+ *
+ * @throws IOException when processing the test fails.
+ * @throws NoSuchAlgorithmException if non TCG Algorithm is encountered.
+ * @throws CertificateException if parsing issue for X509 cert is encountered.
+ */
+ @Test
+ public final void testUefiFirmwareBlob() throws IOException,
+ CertificateException, NoSuchAlgorithmException {
+ LOGGER.debug("Testing the parsing of Uefi Firmware Blob");
+ String uefiTxt = IOUtils.toString(this.getClass()
+ .getResourceAsStream(UEFI_FW_BLOB), "UTF-8");
+ byte[] uefiFwBlobBytes = HexUtils.hexStringToByteArray(uefiTxt);
+ UefiFirmware uefiFWBlob = new UefiFirmware(uefiFwBlobBytes);
+ int fwAddress = uefiFWBlob.getPhysicalBlobAddress();
+ int fwLength = uefiFWBlob.getBlobLength();
+ Assertions.assertEquals(1797287936, fwAddress);
+ Assertions.assertEquals(851968, fwLength);
+ }
+
+ /**
+ * Tests the processing of a UEFI defined Device Path.
+ *
+ * @throws IOException when processing the test fails.
+ * @throws URISyntaxException File location exception
+ */
+ @Test
+ public final void testUefiDevicePath() throws IOException, URISyntaxException {
+ LOGGER.debug("Testing the parsing of Uefi Device Path");
+ String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_DEVICE_PATH),
+ "UTF-8");
+ byte[] uefiFwBlobBytes = HexUtils.hexStringToByteArray(uefiTxt);
+ UefiDevicePath uefiDevPath = new UefiDevicePath(uefiFwBlobBytes);
+ String devPathType = uefiDevPath.getType();
+ Assertions.assertEquals("Media Device Path", devPathType);
+ }
+}
\ No newline at end of file
From dbc11f15c45304f7b68fa05120b4c866bdc3b4fd Mon Sep 17 00:00:00 2001
From: iadgovuser59 <133057011+iadgovuser59@users.noreply.github.com>
Date: Mon, 17 Jul 2023 16:17:24 -0400
Subject: [PATCH 2/2] Adding resources for unit tests
---
.../src/test/resources/tcgeventlog/TpmLog.bin | Bin 0 -> 7549 bytes
.../tcgeventlog/TpmLogExpectedPcrs.txt | 24 ++
.../test/resources/tcgeventlog/TpmLogSHA1.bin | Bin 0 -> 18675 bytes
.../tcgeventlog/TpmLogSHA1ExpectedPcrs.txt | 24 ++
.../events/EvBootServicesApplication.txt | 1 +
.../tcgeventlog/events/EvEfiGptPartition.txt | 1 +
.../tcgeventlog/events/EvEfiSpecId.txt | 1 +
.../tcgeventlog/events/EvHandoffTables.txt | 1 +
.../tcgeventlog/events/EvPostCode.txt | 1 +
.../tcgeventlog/uefi/EFI_DEVICE_PATH.txt | 1 +
.../uefi/EFI_PLATFORM_FIRMWARE_BLOB.txt | 1 +
.../tcgeventlog/uefi/EV_EFI_GPT_EVENT.txt | 1 +
.../tcgeventlog/uefi/EV_EFI_VARIABLE_BOOT.txt | 1 +
.../EV_EFI_VARIABLE_DRIVER_CONFIG_KEK.txt | 1 +
.../uefi/EV_EFI_VAR_SECURE_BOOT.txt | 1 +
.../tcgeventlog/uefi/vendor-table.json | 233 ++++++++++++++++++
16 files changed, 292 insertions(+)
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/TpmLog.bin
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/TpmLogExpectedPcrs.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/TpmLogSHA1.bin
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/TpmLogSHA1ExpectedPcrs.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/events/EvBootServicesApplication.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/events/EvEfiGptPartition.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/events/EvEfiSpecId.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/events/EvHandoffTables.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/events/EvPostCode.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/uefi/EFI_DEVICE_PATH.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/uefi/EFI_PLATFORM_FIRMWARE_BLOB.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/uefi/EV_EFI_GPT_EVENT.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/uefi/EV_EFI_VARIABLE_BOOT.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/uefi/EV_EFI_VARIABLE_DRIVER_CONFIG_KEK.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/uefi/EV_EFI_VAR_SECURE_BOOT.txt
create mode 100644 HIRS_Utils/src/test/resources/tcgeventlog/uefi/vendor-table.json
diff --git a/HIRS_Utils/src/test/resources/tcgeventlog/TpmLog.bin b/HIRS_Utils/src/test/resources/tcgeventlog/TpmLog.bin
new file mode 100644
index 0000000000000000000000000000000000000000..0b8f1f398d51035bc91afbe8400d4888a28d5669
GIT binary patch
literal 7549
zcmds53p`a>+h2!6H)=?dq+LukI^;4cmCNBAxieB{D&BHAZX@U9mIif5nUNZairneu
zQp}Wyq6@02K{H)mgj^eyq^o4S&)WN_P+#Ny=J)&heQW>rUhAyAp6CC6*7K~jo_!EP
zNEGf5m08fag3om(Oj!gwfa~q2u0;(KK_WD0O+Wz##hT8$R=`I6GBE!Wm1&Tw#Q?-Q_Z-`p$_r5PlqRxw_i{8mX# zB`rj`gDaOZjUlvfG?@iPe|I+VS>4W}ZPv%U^smcLlA;HT-WWHA#n10wZ!D35w#+-c z07lz#{rr8r@##dKMxQ#Oh64PPhaV2Le|8HV>WW`~lsR@IAyJ!_cq`y6qo>KCcb9Th zJiX{IkvM0c%jbhgSL6kft`O{=D4cw%`jjg^lqd~FzwPAberwLf^arPs0(iDD`YIW2 ziM7$z{eN+S%K7E1UPJ+qTvHDD$!uUU1e{FKaL@2iA52nknB&>g7mA%P?IK&Do94&} zyU2=0qtoZW(P9T5LT>Pxz=G6u18m|Juywl)`~3R<#9nb5D}L%s-sV=`e9oK0C%gVi z3=3>8^byR|zn}4A$*dl7?hUB9FZ=A~o^7~7?BLy8fu6g1Gpnt=qBXLEkgwH9rt^5V zQZb&7NcQSN_NMRq8+`_m6WgPgoSD6f%iQWvwf>I^uZpsXU2j&ZBuS@FPw^f2DS(Rm zY%1{QS^bl^mm>T03`hPRRT0n=C%J$l2ZT*k3zvZo;8X+x=BqN+RFoiyf*k Z3Uxc}%4JljeszIlpGQT``p bIpsYM;7r7Mol zn?S-5b0Fd1s9Z!a0vL>^k=GIxw^-LK#o6oMKjM%F!A3!6i&luwbzoV(BQaXo~WaKl|SP;p+1PCo=<7;r5diOMB3N<-oghqNW_~T zGgg$2#lfouOgDNQ&1E~xMKIo9&S~|ypO*K&WomDLP{!*as<@<%4~e#7Y$|EJ&OAni zjfZ?3lxsP^&;4$?tkC0AXn0 oZWS593&DXqHEA3Dm+@P3_apCkz)lig+ZUsg?}DsK-z$T zMgVE;)& G3nq@*(z1%cF*vV7G`$(OD$$9mrElz`6JQ|***${91JnNYnUV!x*79s zAHw3Ny?HXtWiBOXy`y8ji95nuu$Uh(QT*n#ktuGL&G|#w7)ue;u2FBRg$O~@*y&iu z01fD?b8#SQ+Gs^VLz__P{@g~yS1pzlv3em4-2Am*Oc2j_wbbsnofwK(q=-qr&5VG{ zZ5*=3G8`_`$Sw*Dtt4r}lDd?N$s(_7Y$d-`5?_| OM-kzt>s8)ob2s9wt( )Atya^=H7bIBGTTdK{ctzw-}fZ`StaoD3j->Fm+yy4;N=%Gf;j&V=_UpU z-MMa}_?vD5R1&S6zqNy mTAYC%@;Q}u!*m@6J-4{ zsp|9c>C8Jjh%shDV)(3X_uN7Geeu)Kledm{zO3yHNSU+L&O@`6HWQ?!o@KP%=hI#< zRB%s0Di-usGPJ_ku6cNyXKUByb{Hi}o_}+`KW#*++BRAN1O;~|bF!T;s#F>${m?7% zd701Dp^1WnBIS17$^EK#Z@%43P}{v`7(o=5-{TaJY<_^c`B~5X5!V-<(;d%LipkDP z&Rw}1re ;Z>Q>N%W~N(zky~_sZU*oy`Jd3EWyqv%6D D?qn+E% zm=wiCo)Md+e(nMx)!m|z @krj=h<;gGcA$v(e8W4PI zHcvzSueJ=SFTQ+Pk(Mhns~lOXy$ #ruFz%68D+_1@Oo zPW;NJamsfTQDktU^%ZU`l~!<|>ZCgh!jk|plyib`gbV_;WFGh#BJ!%XSg>p_Ci*Kw z!jZoKL}2LriN~ +#yBfqQ1yX8ozgs57! zHm*=N8=gxLD%cZ+K}f9XXzdC0g4%i0%0fNep`MoBj=&LO5RtPdj*$14^|U$;jsU;Y zu=Ml}pjEZ>bhh<&cd@j#1?UCT`-~|7)PR?t7sAiOD*{ss0C9j71z<%;Sm?i`&ukEu z^FGu4y3fjT%Cxf5w7d`=9)K(SV-C^vr8cg$T%W0msq@?7q5k!&U{h4=DWwH(w$D|# z%dShyAq}65ta$_RN!4*aVLlQjPQBf|GZ$H%nZ>cV^DKD`{lmvLq~bCN)vUr6ibkf* zBh8SWDD_0z=z$aN4-Zbm+g85z4{U2YS&3rGHhg3}K0)4p(?#?c|0BcA1ovl!)T+xB z3)u%G9pmkNZ@zSKFJ!D ?laQOr5!$`B|HQ+kA?jR zLh(~ZbZ!UVYp0Fs&)=1Muo;vd;*11H%xBq(y=G;5aO7#2zf_U3wktpw+6`WwH-DYu z+rMU=(q0)L6&Vl{@=2@sOU?~c$3)_DWf6{`4vdsCz!uTjQ4o+2!i9(t049L|`V(ug zI+E?rl`QPDCm1oF)GfR5x-QNfLjK1AL|`PWOBevN_5oReWI@spOqkxlg%J{jXb3K> za7IXwA&3AW`HR|-v(u9O5Nv?oI;M7?K^IL-l-{WrVgfsY21ys94bjY1&sB|9cJTIg z7v<)*_H^NLy^v)tYp5%?yR#!~FSolV)W*l!+lw0z3qZyJ(FNod5L!T1%>iM6a034j z0WJUvu|PosE)*FV6#)TB2ciYhxF|!w(N}+*$j{I3S0}Rd{3p)f4fpsWh6987CNg%1 zD2)u<%O-xvmO_O!o;$qpMa!;uHNV#9dJ?FVv(VS*TfnmhAt%incs9EqY&OC6&-aQc z{aYFbVhwDt#`Js03(S$nrn`q62NaZfpDme=Kz7=8>Kpx03)oMxrup?Em&1E2q#50_ zoxh$W;f|-%EG(wc)UaVCD4(*h;@#LA4}3W6+ko5?u!5VElHGAK3k`O`z44}9ZiZho zT?BW*OmBh=Iei w&e9|>(u`o*eiG5i^+dk~(V^E6vwvX7O zlFLUL(oz9)oaz`(%)V|~E9s6mDslH>kcZ?t%C(8YXbvGrr9y(1Q%a7M{1Xl h)&C{A(5^U8o&&;Ty-BUjle7S|`dL(i187wofQ81zph>sQIk!^R&tW zkzTtZIe>aBOPYo_TF1TSJ+=UDU=_b-<6R4}^?;@P8Y4@{JfQlCR?)P4z3eb4hRvQtXk28NRWo?GVmPyqMeKo-m-pJPb7kqNqN_V8} zIby_B!_rfN&ZyWFDoY Z=_R U$zRoA^o^Yi^~6 zLbxwM04tOrsI2Bhl_!KVWPTrIZ6K?6hYF?Az (6M4vxT?~(Y z-my9f@_ZV2C0*|81CPGUDf-fEI%g%;8=Oi!qVhDUxBP`mrH?-)y<6p=vmesMRyR4q zuBnKaKIAt=-%}1vMqA@4yFZ8gU6-du!bSsQixJ!2(M#!0tAuh5E7`D8Qm^|Iub4G$ zg6&aSVp=#R$4K%+O7B6n59H-(g$hHc44awqnyuvM=eEHfV*6Jji5dzagehl6BrFKV zh2BI&{EJHeB~| -MqY`Mlx zcn1_pVoX*&i$BUeGSd~djfe6)(A1hrFV7qR9fD7U@DBu5WbMDWA&`zg-6+7U%uBD` z=UuP}{bbcO@lG-6zy$GS;H}&ao1PNk6I0oycejadCWcLl#pk@(A48967BX9(^(?ea z^m!smQxpZ3z4{$jj(t2WNrFl|%JWj4TMv{k&8w#zBYax3#vu9GW(#2_i&M@ml7ytI zHSg)Kd?8%1w}U>HDz2&3Kpua};U%$rYl#Sz%B{gu?X`VevD8h?-Du{C?9B48#5O|% zaSUm01$usxPfUw9Dj4Xi(Qq5^d>39+&BghKmQs>H>Q~#Nhv1)fsUJ-8GO+%cNuuBZ zO!E5$lSCWsI%ASZa0C0lnn?=r^6>KV3tTWspvVU+Lc+rSst^8$*e^ST^-Mbu(*K%C zo@t7ImP$TEb5VIIhwh||RoE62g5rZEi=bmOM-qa%k`jbj iD85TZ__RLSF0Y)bn2OLfu~omBqZ|IFey~{ z)ULi#xuirMJRhD(?eC|GRn@YKJ4!Oze8B!tQ`mIpuyNWSJbk*1L7DzGqMn@aYhBw7 zsT&_?SeRcOtm&CieGX0wZd<=v6CkoMRbv&e+A8e+(cv=DE51TBp|=K(W}|^C?MT{a zi)vMDG1h37P-|ktZ#C=z<5-sVamL4H 1D3wZG!-N$K33a!=8t@m9V1}2PmWNM;Mo6P1KBeA7Y}leOrQFa++JB-ODZ@fV z+fq}ZN%W$v?Cu>ps-$V$BftB1ypm&kTUxXlkTtMp_3!6eu3#^?GEPe2l1lXq6exA5 zR%Q}Vqv<5Jylie@mr!J<;XQJqb5zgj36|kM5=0@5Po$M iM!`%N0v0&G9cu`R2 zdV@yoD8VplYm@ivyGx0oZ&%2+xrs=ex!>E}s$y7p89A}?t(`BtTu+&dbHm{dYX9K6 z=XyocOmx&e4muS+_H|sPb%&VR6kT4QJg0Cc@d8Ht!j 8=?DZ|{z;X5i;$@CQ7 z)VCz$ajq84S7q@FR3Fr77juLy7b1J~ pSG04pEVOIwN-v)4X&Vg$ek|Li(pDV{yqV zP4Xn3x*r+ot0!+PBBHPr>|IK_)(OHMBft3xM}XN1(Sx{XZHPHH*HFmfyKq|loWJ|` zMwRH8wB5N1u-vL`M_oa%BZ&`cO4d$Mvtfh*y!}A^VLz6B?THu%>__W`{Xq5AJF_2X zKiQAie~B&zzBQcdV%ERuVwjhKRu*{Ua ;fkx$HJUpRaK|GYRes?}Tc-ucfmX$5=3Mw7!#nXuqe)eBW~kwdhsDB{6M*z=hFe z=7t!mlZICe=+NS8$?b0G;?kpi1y@YLPO8g}G>j}Jf~Uu_#29IF
5iAXk!YvH=FU%?~vIw^J-QYhkAjY~&nTIIQxWEn7a zD$FJ4yxq3IQa?qV7&nbRPVrI&L(tCY)-vTdQc^J)X<=5wM=4%G->!C}?$&vvwr?b( zWt|RdR%J6fE*cPnqNTu-v`1>Ux0eH>z4SY@=)CxiwhH3(dXT12(O165e;U{hzFo1t ziy4P@c;ywfXNY$F(sS#%PZB(~RbdO8W&I?D4 f>wE{ zNk5Q!V7`#YR)e4H6-URiKJea4#9Z>RiN*3PB3|(*`q%B<^r*TJ%~(5m@`U^<0*Np- z2V}pdWEHC$b?vAx8?VRkBjPAqUC;R1do-XV^op}kKalD~;$1zi(ZN{P6L1t*^xKn3 zw|Pf8q4#0KyFTQ|_M@r#W~`JVJ*%7_`sd}mjE6=Bu0JLr55HzGWR?^5#JbtMG<6ACO~{$ zIJwE$xSy6IwL&JhF%W0sEcqC5)SZkC!)eZ3e)z352JdF&xF8LiyU~J-A)1G>eq(S% z*gBo~HdXtJhNM)SSh>{buhp~}&+qlUxKn6qHI{3QM%&_p=NBZgCD-ua?t?!4P$*vs z(x6|V6_sJ|h2!D=Q|dg~egUpQ=?Z9J(&3f2_jFZNiGOxH{O~D&n1MQ2f;k@ie{wx! z{V*mWKi22i^BfY6;tUB#(!MYzSWe_;6+gd>{O>X*!1r#zfeqn@@bbZoiNJYL09J$q z{7Y=f#V0R9ieK20a{~hTt*4?bph>iP9XGPR+=k7E#A~PtbypHQhiJa~L3>YHm2e=< z5TEW&BZJ)z7mI@SOOlAj9nG@fvN@&@T<;^pJMUg~=kIB`8*xylJtl9hyc1Mumj}(V za&uK~<`!^yU+83QWPZ4Xt!nuiBbaB&1!G9{F79!N@U_ozFTEUnbsf`H<|o$qml~^S z23Ui;)N=@l9}`k~8d&MM#Dx{u_}#l^%bF8G^iTyYH)5QDX3KmQ$}u=aGJ)fX#4_P5 z`JJ#jFrPF)J@}pIe2zP_bL;fcrI)A^ZO<`NFR{#dxsK?3Wl?E$Hhpkv%10n{htZPX zNv1C_N3vA>_0Rh!|Ek*sAvP*m&xuefKIo@0;q+W|6@R4 zj`1JH$r}=u1G9RxNMUy%VJVQX#6MozxDbK&aEQc(tpX#E@cdm{rJ=0IZ3DIT;+ECW z=C-l5v-ENC=5p|Mg-HEzI2giziI =iMlh!$*SCn-7WIl7- zbq9J|JHe=Ut77_^%kvOw9X(2MYL6~WVx8dD)rWUv_>QrYE?@q%|1Q1vsJ^UqyF)~; zzG=nl3F%C5v<5@G-sRq=BI?W-Zsw@PygH0*Y|2|(AS>xc1@D;fV~tnaF|3`4rR=j5 ztN~vLE@wus3~`N0h3%l4^P%XNO4aUFTOF$^?72zHYf&{(cIb;1XXvHA>3+{tY~d5# zv}{$hPK_itEBPpL*!U`gHKU*(w8Hou{aYdiC+UzOnWE`6#v4eVM$(0>P%6Ju;@*BD zlG$`~M*wA^(75x~eIax0;R2!KLiI0{IL^NF^@&v--;RCuIHaFt7ks#cd~!FXFT@bh zwOB1dEtK@lThCp+d4&fB42>wcZMTPG)l+FV-OVSQJqu_RkNmJqU%dPP#ub*q! N~HG%Q)O9h;ruW|zzW_^7W#D3k*5_Ke4Jc# ziF{a{x=`!0YmL;cVhdGiniSgy81VQV?udee?8C7XTu+wE)ANXO{3FIusF$6^?gW*& zQ4U;($G@1I$cz5i!--y5$_5SL@`}NhwAtfOLtC>CaEipmZGp!N@ m!0%WCz7$5Sjv)+@W%J|v(mdF~OGt_7jPwi+81SIEeAW;J5R zK!L}9?sfPoea$L!{fcA9cQ@xXt9{6mKxlK1|FeYsTZsG%@c7P>%xl<%Ho5wp2CfkU zJKGg#&+tS7R&MfobFQywW7)yu4Gz;N*6!pR%04+XXT-~$y)v(2@X8FM9w~;^$Kml^ z4|u$Ga%cV_J{`EI^wK-V3cn8zOrhxg=&Lmv8T76FhAH3R@ncNH!PHJ3@$Hu%C*%h< z*`jjfir#Q$3~K3XvDh`+8ivOYSueBf1~+PN*l@N6o$_@Tu+2n2upm4k;o{)k=v#1w z$Fp`XX+0Ge&5P%lSaB=12wW3C_|SNQZ|h^S`I#tE=_))v>2MLpag0wYL6Q{9fp@xQ z1bvQ~k$JXGLUH7dXVJC_JRa5T8w&DGo%mdfnv)g0DRJ7DCt0NZVCS?iMG^J*TEai! zKX(@!*g&h-x&shTSgJ`7Xc+8IQa(Rt7tFYSDl&8*9*;h2uBJ(Vw(Q^FN-z}0cwC1V zo$%=a)HB6j%P`9}n+YC|*(94XRd&5T3sP8S>%-G< =@J3OAlYm$$#(Y0^k=9|K9apP27!?l#db&VB`u8(M1C>ufWcrN#3`{<%Q zFHM?9WHgU)soiV!yLq`v7;1_~8`w1~f5JoTSPpdjAo?tgO4ouGhlH=|>^P44J{U0b zS-v@vK%5HSz98C4<4!rQbRkim-}P4RN;7*zetWad3^PZ8@cUS$Bk*`(=@B}?1mcKs z6AbWYItvk17c~rfi@IIZ21KjoC}S`@{>nhsgIUS-938EyeY5$nj%Vwx-lARs9=f;P z37rNcz2Nb(cc*$I?uS^T2G(Mw%*r-%a@Q2^JYYJyj-&i$(uX7k9xwkI&64>eN@nz& zsPh`f8@%r?j9i_k1?e0*DLFo|8O_4uHDh^ByuxdVh9rr*>FDF*>U08Huv!aVv=413 zWJ4?k;PFOZ6~D#mE~U nRXB<~v=V zhsTFciw!*8MUx%Kx!XA$)1PH1-7oP4561w?KBXt5Z*C8dziD(gYL~Q^I{1xxd!9U| z$JPeDu+`*g&TG++vneDJmGJnuF$KeoJGDCrm8EHzPL}p%W7lKd60fD&kb2U+FqCV6 z$H#B;KfMony+;hr?@vOr?L$}=lgJepc&=eSd*iM34jnu`;dcJb!9@%z)W=@7eJrb* zE2H9@8m?br56j1JT0<46;PDyvMy P z_mvz;c`O~cbdSHB>{u+tF4LU6t3(3P*tPZUq1HU(hsPJy64MCkj^
$)KqBVyb--I3Fv*ULsozi|f 9e3UO}PVdf*86GB1L-xRv#$}n+R2}L*?{5wk|xre%*gEB44SCkIp(ZR)DBKm4mO6 zY;ndtRwZ0un^|8F9^Y^s?Iv {_(dP|b+;`%e9r2T236bFD@`MNZ-TH2z)aEoJgP rS!GW$PRC% e64+wqhA?Ivw6u3lveqhhHorc{X-e-&?x#mqu&2}WJ|oYIjV0^grkxO{e` z^^5xvcXbF~-QB?ST4D;B$ir&*)Y95*|9Cnc9^dC26)!cKd(YQ^xHhF-Q%TW6y>bkV zd@6SQk=tGW6Cm3DuMw03Vh7I+#{$2UB^)b}>~%@*cU;!I(rjy}KQ3^ Ip00GQ5flVJT8`O;gWT#0h}C8+kK{YmmZuT)ZW*-PrN>7Vr5iFL8M zKgX-lqs`a*NBD E&{)RqZ*VQ;}#^vDgaxZ%-d@u%^ z6pn =fc`w+0 zSV906*d&3rVQ8C%GsaS%BTA1srmCNc+p%ROus {@V2ct4c?}#3?uRuH2m>R) zw)|mRLa ^WU)X_e@frX-I9;5L7q>T-5pJB0P8q!)iz|etA z0IY!b*HU2h$5gaR-a%?unI4t_>GqHEBHMeUNih=Xds&lj-;NpyUIYV%0vOn0jR2{< z*vI0<)=u+%1iw)kl>18ZmDoEZ3gPeI45_CdPwxe-VXU3a#RHBxMg0*;2yDZW9OxQI z5kw34*#babKm2U8fDg_Rm>A~`c;R3R6!5$KE>%i&<3>b!%HIx~R9dA~e9?XnXKlL;{mz9Y;4;$FOGi;uT?_ z4t}Bz`i~R9?k_A|OaW8}uG 3>^=nXMYb~680A!Ekqc|n z6#>V=w+ox{2ur@_t3TR>fM9<-XYE;?1xWjxc{6 JN0g@yOVgYgukRH$nR^Vtb0v2dU z8u4s86at`NP-qY_89{|AJv2`Vel-586(SaFdg(9I+4Uf~f!5@0IA4k7N|%wVY7SAV ze1@HsALxbR*|^#QK4cb<7SIP;V7$D6v4P!FHz4;0_Q;;eG^}L(hlJAtc!4v#B8V5b zQz9Tvz%LD(YzjLgAR+1qKn{}yW*#i--r%|nqHWuJL6oK!1~c@<8R^8%0vsfk3*D zv2$7AI~&EXzZpfr|Ep2N7C%4p?{g`5$UhopL0|~~wZjZNo}us6NM7hXHu0H-Tz#Eh zLn(NoDNsubbo0k(f_OM{mSQ$9B?e`QzyK|2R>&0C$bV2@bcf7SM;CA%Kt=G{=Ynz=Rc8^ z|9?kT!bkz|DiS*Md0%7$q7-r0od485;h|RryX3-sppJ}o<^`|<(V7v#R)3`6A6xL$ z2t rk}JH>-492k(B#{BW2XG2F1@WV;`ZBg1S6^VAlVCZOJ-U} ze*J3o<|4~IX05fB=v9~6Sv%k?8jnpauFZjDAJ<7t;LXG{z)lQH!ap{&fACfyR)`-6 zKBYR37eWU$NMFt+<4CcG``G{2fKGWC9-_0KIskqJ15?q<#g-Oo2TW4^+ca1#)T>Y* zdl%r>F-RfAFaw5xg(GX}26Y31NnL1FyluF6fJh%$1tJ#vUn_uiyu58ae;s^!7I%6! z=aq+thgX0H2o*Y;0t=MRivL@>`Mb%lt;V7x-m7$`6_zVGdSxx|-+OM&1aqob;g+?z zDxl#HCd40F(lEcqcbn9e5YbtZ602_d7{wpZyLY3t@p=y)CwWl0;b765uWGnc6 5H&q;5Wm-vPsf?1BQ1cZPnh7+%!;C+6#Olt z#Nm pSLz)Un mG|5i6LgqD<=9HHqe5)|lwf#uMW60Z=1W{6t zLEx>fyfFo}bjK)x%DdAFjFfCE3{r$_uQ{{o