From 73a153c122e7947208a79b3098891e14565bcf31 Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 10 May 2024 18:38:38 +0200 Subject: [PATCH 1/2] Added KeeLoq decoder --- decoders/keeloq/README.md | 90 +++++++++++ decoders/keeloq/__init__.py | 31 ++++ decoders/keeloq/hcs300_sample.sr | Bin 0 -> 1354 bytes decoders/keeloq/keeloq1_pv.png | Bin 0 -> 65333 bytes decoders/keeloq/keeloq2_pv.png | Bin 0 -> 30098 bytes decoders/keeloq/pd.py | 266 +++++++++++++++++++++++++++++++ 6 files changed, 387 insertions(+) create mode 100755 decoders/keeloq/README.md create mode 100755 decoders/keeloq/__init__.py create mode 100755 decoders/keeloq/hcs300_sample.sr create mode 100755 decoders/keeloq/keeloq1_pv.png create mode 100755 decoders/keeloq/keeloq2_pv.png create mode 100755 decoders/keeloq/pd.py diff --git a/decoders/keeloq/README.md b/decoders/keeloq/README.md new file mode 100755 index 00000000..2bc28afb --- /dev/null +++ b/decoders/keeloq/README.md @@ -0,0 +1,90 @@ +# KeeLoq decoder for PulseView +This decoder has been developed for [PulseView](https://sigrok.org/wiki/PulseView) using [Sigrok API](http://sigrok.org/wiki/Protocol_decoder_API) . +The following output has been obtained connecting a Logic Analizer to the PWM pin of an IC implementing the KeyLoq algorithm. + +A Code Word +![KeeLoq output](keeloq1_pv.png) +Detail +![KeeLoq output](keeloq2_pv.png) + +## KeeLoq in a nutshell +KeeLoq is proprietary block cypher widely used in industry as secure Remote Keyless Entry (RKE) systems. +It has been designed to be easily implemented at hardware level in Integrated Circuit for secure wireless transmissions. Typical applications for KeeLoq are remote controllers for gates, car immobilizers and anti-theft systems. Each remote control, known as an encoder, relies on the internal IC to transmit a command to the receiver using _Keeloq_ as a cryptographic algorithm. After information has been deciphered on the receiver side, it reacts to the command by opening a door or unlocking a system. +*** +## Code Word Structure +KeeLoq uses PWM (_Pulse Width Modulation_) to encode logical bits. In particular the documentation +states the TE as the _'Basic Pulse Element'_ and it is considered the minimum information visibile within a _'Code Word'_. + +Each transmission is organized in a logical structure named _'Code Word'_ described below : +### Preamble + Header + +----------+--------+---------------+ + | Preamble | Header | Data Portion | + +----------+--------+---------------+ + 0 TE 23 0 TE 10 0 Bits 65 + +- **Preamble** = 23 TE with 50% Duty Cycle. +- **Header** = 10 TE at Low level. + +### Data Portion + + Bits: + 0 31 32 59 60 63 64 65 + +-------------------+---------------+----+----+----+----+-------+-----+ + | Encrypted Portion | Serial Number | Button Code | Status | + +-------------------+---------------*----+----+----+----+-------+-----+ + | S3 | S0 | S1 | S2 | V-Low | RPT | + *----+----+----+----+-------+-----+ + ++ **Encrypted Portion** : This data changes everytime a button is pressed according to the encryption algorithm. ++ **Serial Number** : Unique value present in each encoder. ++ **Button Code** : Button pressed. ++ **V-Low** : Indicates encoder battery voltage : High/Low. ++ **RPT** : Reports if the button is kept pressed. + +*** + +## What this decoder does: +- It is able to recognise a sequence of _'Code Words'_ genederated by an econder that uses KeeLoq encryption algorithm. +- It decodes the PWM signals into a human readble format for each _'Code Word'_. +- it shows data in the same format as described in the official documentation. +- It shows '_Encrypted Portion_' just as transmitted by the encoder. + +## What this decoder does NOT do: +- Decrypt the '_Encrytped Portion_' +- Extract the Master encryption key. + +## Installation +Depending of your Operating System create a new directory named keeloq + +**Windows**: %LOCALAPPDATA%\libsigrokdecode\decoders\\**keeloq** + +**Linux**: ~/.local/share/libsigrokdecode/decoders/**keeloq** + + $ git clone https://github.com/rzondr/KeeLoq_decoder.git + $ cd KeeLoq_decoder + $ cp __init__.py pd.py + +- Run Pulseview. +- Add decoder selecting KeeLoq. +- Click on the decoder and select the acquisition channel. +- Run signal acquisition. +- Enjoy the reading. + +Please note that it is present also a sample file named **hcs300_sample.sr** for your convenience. + +## Tested Integrated circuits +At the writing time the only IC tested with this software is +- **HCS300** [Datasheet](https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/21137G.pdf) + +Looking forward to seeing this list longer. + +### How to contribute +I aim to write a KeeLoq decoder able to recognise _'Code Words'_ generated by as much as possible encoders. +If you want to contribute to this, please send an email to : as follows: +- Subject : KeeLoq Encoder - IC name - (ex. hcs300) +- Body : Whatever you think is worth adding about the IC and the application it is used for'. +- Att'achment : A PulseView sample containing a good number of _Code Words_ in **.sr** format. +*** +# Change Log: +- Version 0.1 : + * Recognise a sequence of _Code Words_ genederated by an econder and shows their content in human readble format. diff --git a/decoders/keeloq/__init__.py b/decoders/keeloq/__init__.py new file mode 100755 index 00000000..8b1d188d --- /dev/null +++ b/decoders/keeloq/__init__.py @@ -0,0 +1,31 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2012 Uwe Hermann +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see . +## + +''' +KeeLoq is a block-cypher which is widely used as an industry standards in +in secure wireless Keyless Entry (RKE) systems such as anti-theft, gates and car immobilizers. +Transmitter or encoder sends commands to the receiver using a sequence of PWM bits organized +in structured known as 'Code Word'. This decoder inteprets the bits and shows the 'Code Word' in +a human readable form. + +A typical KeeLoq implementation is for IC HCS300 : +https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/21137G.pdf +''' + +from .pd import Decoder diff --git a/decoders/keeloq/hcs300_sample.sr b/decoders/keeloq/hcs300_sample.sr new file mode 100755 index 0000000000000000000000000000000000000000..263658d6d0c50a90a2345c1b82920a1498a2b27b GIT binary patch literal 1354 zcmWIWW@h1H0D;EEOCxyqU6o=4vO$;~h|5xoiZk=`i~@kFL>QPDIKZkN{@LhM1(fXv zVh$kAO)W`GNi0d!J-w0dkb(fig}?in>ryO=UKak zW|iIfz}I_EwP@+NjIFokJ(mwy^xlEjKJ#N@g8!x2b9&h9P~G?Kw$Hnz%nS^tb}=z< z0^OIBpPrelYp84Z_D*-+YzG0>3;+MW=-B3!8X5Rn+}K*&!hO{hA#vg4GJWIhd}*Kt zEMV@wf4ly&f+ZT{wqH9FJNene!~bpGT)Xn~Z+i8;%R8%o)Ox@8{XaK;S29d{0ay9z zR)&Vo&L7pK?{>AGu%CCU{AfcqC~#q*;q}MDS^ROE=gaf{d2S#7r|{*ud4G3&`Tqa@ z=}$i<#8rR!_C)pl4bPLocK7z|-TFTFx?kMwm@1>_@}Nq&uzhR2`kw4HKb76Dw>QE2 zp5WT>+LO{tpR9U+r_VTO! z=Obb7sJAB}+~xYgiVa1@$5%d|@-ji%hn?|zdg0dQ+T`@-D$?=R99)?|USq+8$(E13 z*+1S~P`+(Pnwdlom%QC|Q!aMy#RvD@O2{$ku(w{SoaJ{n;eprbO5Z8G*Y-^`6+N_y zZL(?Gv;-0BKVEFU-=C;!OC3>bK6tY5k!hgG1RlMKJWNf8pJXxrZDIZ{EW+#3oGixs zMR=99=bIVQ)|(topYxOBWmEIL_#nGv=86mjsTb-iq*~mYRdpK=yEJF(nsV%#@?45b z*j0A5!1Zq{i`HE~7hiWh?WTj-jvwkGR*!4^%&ni7nc7M5%#jUc2EmgGI+AN<{PMod z+r_qdwE*)wWA?o7`hms*JYD_2SEx20JS%&cGxsiwD6?pDb0`nrS#vxzN;+zumPKB3FdNbqMmmP~` zkFdI@KVzSXkcp6v-JS@Y6K5H($%UPt(JUNv(ni$2>G*Qvod?>5PMIC&S6_3ERanzW z??z3OVKImPTD8^UbC$&wyo;G&Jm&=Kf!&f4u(V7KTH*_LfHxzPJu~hy31-cay@m*(2%(4_Y0@E~DHwW@KoAH; zrAP?~0RjYql!OujN|kOQ+%U;Jdt;@F_*evV@yn?i)l^roX@8rLcxrSQT6R#7; zxwvXYExl{%VgVt*RMgV%56@~Ie?~>!Jg@x)C3ID!SI<{2S1(YS`O*jFzZ9@oV>^lx z@@n2N3*GFTpD!)#kRyrP%Y1zNLgb;&jHR{pn*W_U>PcxL(QZryphN%l5s}lA|F0(& z7UhZW*Kx2TXE3if^+(4WHdz1uaxe8>F8ALP(!ZSrIPqVfuTP%OasRytkPzqmU+-C1 z?tgr&0Qy_PLk@nd%Ypx%po9K<6-|fP`;PuC1B=mv)XWqAJ%P*ZrzrmOBcl56MA-%D z{O4QXi}HlsFGBvskpG_~k~tdZ%w(4QT@_fu`u|;rMFN6!Y>)pvQZzI9fHKFBV-?`3vkDk_et@(#2(X*(TFeAS7JvqW>@N`ybqI9&!N-{U{ zd+PNxWxlISYN|4vw`hByfw~W4dYp5zugs)OMvD=z#kvu4dwDr#R(Xxens;9Nd@ak` z^FRzAw`KeBf}g{dEqHR#xZe{Rv#!QJCA4FmOVfk|7+k+>&(5VB0k1-k`6aVnc^4g^lXe?$~vWt6G=ya}~A{ zmYzDYrH8J#B{?K!Q!+6r?w#9u)0*L28+9+}4@IycR~>CxbOe_|Ch8SoAU=Mi2;6F8mnrT>?=t_G|mI5#;D#OB_MAq+aQ{8cllw@?yHT4Sq>Xn*KO8q+FN|iXDc0j@bO6CQuf!StPPA z7YFSKFHToq+jL}W-dugVPJNrs!S`4RZ1cG%9J?Exv|?#-580FeU7OZqSZrJ0w6|EN zK)%t4p1cY1AO|V^_V9Oeu={8@Y197A&VYQFlLe}f^5ciKKmZx*n%0P8uDYfv3p_ZV z1`-IGzKSimv>UuPz`1|1deQYqS6JC_E2=S(5T?d_M)IVdua-^(<*9~UKSw8}q`Qrn z+FxJMrzdj8%Nn9QGjj(_)`6lNd48|ep3%}>hsmBsfwCG{r}CiDHY=ZG7)^XwwpJY< zRkdjm17o&2vhB1V3A<@3+}##C0{PsIVORYgj^3KN${r#b2NeijeVpdkZyQFXYf2z) zfveWAGelHY0bKrv@`?{C^wTzZ&mTFTvciaw1$P%tKk@n6KNBw-Ju|djmq>84CDTiC z(9of&^mwQw%7Q?~D-#nIlseX~OtrYAnc5ad!=?&JhL*-Y+k$zv0YP5We12DMGh&4C z=yz{qhZ)X6{TmDenmPyjrYQ%uNWP7vwvDUrRo9SX!y4AI3@JnIMueq;k!`aoUd%Rg zNxouCv?Dw~V|x*u+PKqai%#BK9oKBT(N5UbuaZ?q<8^&L(wpkCilR4%KmsK&9dC<; z-Tk_(vgple=DG#fW`j46G*1Esy0q6(XGqdqOHB_Y&P5PljPiOL=V@Y|*S4b@VnF>uIbJi zBE?`fsPM9IOlSDv0rdh>nfe%EyJaD@@kgI+D*f;PVYA;w-OXtCI-D8>yR;ml7Cc=V zJ56uWU901IG2QfO6ZWnB(n7sfm?C(ux@Um?a6Y{CvSn<_IG78bm|UHxoU(7U@+T{SbAmbfv|kyfDUu0*i}aaq$mBUzWM z5dXJbPY#0?s~WEQQcRvbbHA#>k*~){ODM75dK(b;s~sl0%-2>BvNO!xS4MLE!G9c2?&0%hR3WOKo$r zqQmKWJ*=`JTeng`Z*QKRc{$w#@Qt}-A8wB%R110U{{2V8 z^{9XgI$?;h+5zjFK6RI^Rky{B)BN(xsZ#4p%q7A4F_nNt$VS~UhnJO>Ngxk$X+b+H zUqW|xd^O?s(z!WU_Bfys{ru*H2PW=O^MCMFyBef|++-s;!5h}STp_l6b>%>Uc@4H! z1`YBaEVEr237V+67!SI<3&WkvQIX07ZCRgc50?>k#Vy?Tv$X(n+Zn_`z63^)K^@_x zrEG}6xD-&WzbN=k;He(gfwe+#g^wZgjdHZj#VN3 zfgCxqvol|o-s@slo#stxfo0* z^2$;0@PhUTV93^>Qe<=*wP~7nsI!@O8%tz#{AwF)??g3Zjr`HO8}VlR^T(%0F3wcv z<#kqJd{skeYr`FZv_LLXV)$8|HlvyAuvf`Ym35Uvy@cMSE8FN~=$1j1S>L=O6W6db z^iC~_YpijeOH9Y_VW>#0R~|Fv_b`38z#NqujoxF7=d$xNCTzJs>63gxk1I{FW6K|V zus(cgOx9p~?@C)By(=vV@&e~W^Qm6yP5-jlU;l<`7Lq+4(T()2Gg-}?H{+8IiCL`i z%i`W`@UDb2EiI_C@AG4g8uPvld1NJmUiNO++FTUCg?gy0cd)kn&bM+}{ElO*7P6@t z(E%Gk^*X$95dBCnA(T?g19L*i2sufxFP|x!R&0(b{+ZBZ2U{&%H>-HUQv4!RE4C z*7?y~ds2@eL#b$wt^EhvXBWuVBTd+51NtbIC6|(=ZSSQ(9X`DkvJ21)SbFrLTMQ^|n?8_|PFEIG#pj?|VuSxXEp zs#VWto*2|Gbnx3f7G`_o%z?(d*`+&V!GWcVIpfU5vAR)&axwCiGym%DtwU~iw8xLR zJyW=f79_I7T+oxxHCH=JeB}&$N$b`p@ZVr_^ed&)So$QmAOD%@mGcOGT~ZR^YxQR) z^OL#Unjum73X#S=`5m^rY++9d`(HU%&Hk9Z!jWut@NMe1-LD@X0Yz{3ZfXII0C0cq zX9H^w|5cre^!Ff5*sFmWbP7lh=XkX5=%3wjql{En5_-Ka|5@f5P;5>1O`pWeKMIz~ z&prvfzNnaME~%nk`{fDk_GK~QV2$_XKdZg%s~-2W^W2&$|B#lmMAg}Q`IA4}eKYN+ zDTeryPVS~z5YVq8a4z?s9VGoV$cwuN2oO#51&6;f^%+nG8{X2QV~+fpN&k@oC_nZ@ zlCwe23x&v>rN7t=kkSTlt*@B>KMKuUuwfSkSE!h+_^`MoNBu>zo;=)gI~f>OQa{P* zlQ`UWG+SNg7Fydx@b=!w{U1WN-U9v6ZqwyNmlH0Ewmew^bDsHG?aOYFKU)Xsf&W>L z*>lstd`E8s?t)zNL;{;A?bu)SafSSI!9~q+$2ohij{S?|qhIg-)QJJmpEX}a&k>p# ztibd$<8H%tmKZPlC&@?MuyBv@zGa=ZgMX^Th0AEx{8g6qj=q&!f|hJ2p4B6hOo zn#&#flVm~Se@th84ocj4J^6=QTqbU3w4dJE^!PLpdn1XbulNj~fVJz#<-+V!91Q|i zcYjuUQ6=jy9-igq+Rd#mC9Sa9-K7cF#4Z@|yV=BFY& zbO4mv?GF2YNPFdE88{JSo>3GCd#Iq_`X|Z2JcKU^(eLEt;{*sf>Xv-K?a&PYp^L;f z`L8a9!IgJT6y5|B>CIHm5yQJSrxWczZahBnbNJoSp5geDhpf3jXRd#sYT&-E$866o z@&oNkT(XK6GE=r)JHw{!7}vHj`@)ea;pk6{W$i zoZGqnB>9;F315W(?B&$YF(XKf2V67r4q9)`Po2I=D?9dFoZ}+p>!r9<+e=*wkANE)i9r)$Ljh3Gb)NW@yyh;5_CJ%eT|6Fi@pVIA&?*EY0 zd2^+3r)uJxZvORSZg(PMVx<)90&m}Vd3c;%N&?`q`RNSfKY4iQ727}Tv7S7;3RmHS zp9~ZYR{=ME}QPk-QDwru|sfiNFP5sDmQ~Jh%V1BeSMb^>Nb0YQt8_Yp3MD%{3Op zIZJ2x#!n3zhmBZwJ>`Mfs;%{Rpxms+Ml2%IT*S`-M-X*uYcI-r`^qft=Y<(GFDx8U z$!{+8u8-IVDds6Va&KAw30r^4-lX(NS)8iVRWBHW6tQd@*n@KK81--Ej*#=t+%0M> zjEH!%v_JG*BmG6-B&#%@r_?UQUtaM#BfY6$6M?0L9 z-5-YBg(nP{2^%SZoe)=p zl_D3#rBC5X#5Z@}04Ho<-k~VVb94<1$otev8p%k%d3pe}5jY=iJ=Gf6`CN6eJ$wMR z)+C=f-ty(^y|-NhC6W;vQ=%fmF4IHeQ;l6ydC8L;+OYd&#PJ7gs%|U6?l2u#$T;xAD^qnnE;h9w zZZv3ecc~}3W+O}Ec7%5$pYbKNZb_Gn+Yu&ggl~&GsFb2a5G_@?gVmOwuM(bINr2TM zilNRZ9X3b>TxopMTJei5F`O+dvpLO<()*qHeAJ%e`yD<_YZ}8dxirj-DYfUKyaSiN z@6=v_9ghy|!rS>EznW$#klw()r6_@Y?7gbSWznFX#_chxk4YkMq$Yj9Kg(8?mZ;Sw zh!Qvf9C%{|=)JU{cp++75np|yYhI77xn>k!-8ebi`f4nzyzBOQ(B?pTPvC^{UT!>8 z1)2q0i5j&6&T}{{ny^hbt9nridQ~pI#D9ORQDwkvBLvht z%`Php6gV*BL(0?0_>AEk-?ot#kB554j3`}IjZFmA=Jjr?gauF-+BQ^Cu(QrG-ELb& z8nIYiqbMW<&fLUl=r@o0Z_P>R_%-?AjlS&~O#(XTh|Npyx$SS+6F46)v_6ua>_OSu zCam>jW_rmFG?e*IP3^BW(gz>gU(H>7fpoLPKt<@39`d$3G;~gF=^8;m7bcUJ4vq9& zNIBA+4~LpQ8Pzs#M1Yw)bpf}ewiGeURd8w2 z%6?a&u-51W=x?poRMe!AxR)4 z@YtfdwYQ&~&&gj7Ck~74DtAOm@1^X=y9$ijZI}g40jFhDR~j}35;>s?G1rI~+IqSg zBci6+CemeSqjD)=e@cUHgKP=4Ov$4^ED_3FnVzBhj7>z=}jKPRb9h$`z~|c#%sR$tHsXH_>Ld3YUmoS%`C%H z3gcbD9X2=)GdYv>-!EGD8k?5DZ{=N46{LwtjTK=O%Gw0uLZ(#Y>)_g5MQhoSn z=vGhtM}r@a{(dH&WiM6PZ89zFPn-Sw-`|Lw6lr;C4*9=M-T(VN4&Sc>k@bIX@F7P8 zaHiiO=+fV7W7*3G4p96prRlKo;%ZdG*}o;RJk${WfA!jkXKHE=Q%!eC-rZ~@yocqZ z7^FX1mZMeJ;m|h8VSPcyVXHPl*7T5}TaQ1&V5YRhxoar*i$|I~(bC3uVJKZxdL&u$ zTQVn~B^l*#opI+uXJp^jZE9+aA%j5U>*U;Yz$2DZsw=xQ=3-$K+lG)0Hj)BdhT9=F zM7P6RiaG4YBeE`HKi?VNU^k;_>dfX@Bm~Bv?})7RxySs5%&vr~fk(`aYJf-RyLLX= zCa`jpBQl$mIn%nAsbyddlkq65Cg>5v-pd9?MwV#cO}?=&kKv)DKhCacW(qgxuu}RBQNDSytGp z&|@;@=HO3(7jzj}wk~>XC;LQ=CF6%11Rsnw)Q#bvE^P1?wPIraQ+ ztB|Yv4y~wCvxGx^Woqj|1q^3ZY~a>;L}0JC|MfaQssyU5ddtCcY$?*s@}06Gwlc5; zigg&f4rFL>uF-JT*Qpz@k*}BKCKn|SlTOM;ulqfpL0`CzhYu+Xki4qk2l`rX?bNS?i`37FrPdaksy+UfrGj!ps9tWi)TnGP!X`IY%M~sC)^K^ zeUy@Z9g%%$bF^~MlKLIo!CJqlOvwT%xYw0DF%9odzoC~b9GTFi8Rn|WAoypdEktto+h zH%_fvSe}XQ3~vW1(yXI=&eFC6MpCg6A?>LjLQR(wIXjMxuU&=R==jV!zLw+knXY-= zIv?__#gX2Wyhi03*eH-y0td^!jrIVPb^g;g+6eyG-g0s!MD%SxUq`qODrAkOIp-Nh z^&Q$KW80?^vK)HM++1|ne$2-l4#BF?s1~p<%7W$r?;&~xWZx{R@)yhtw={YAOJLPC zLrVN+fvgn37^X)un+8~^*r*IRvAEvmX}u&VZQ;8=--%)F)qWZP)uyb`n!2MPsd9p8 zp!K0V+Qa!6VH6X%I-)Z?k!#KFXwW>{_At|J8w>f?&nJn*V(^KzUuX|S5Edz2`aKx9 z7_2<#nhsm>a%+DQh@1JjAL!1de&K*!?gq%vMA;=PwtT+1&hW~q;-3|Cgs)oR{1VF= zC7|GVKV4_Gp(WrYz6Az59%-U+d)2CtIXYe7z^Vg^4k`5L&+A>>(nkwZ#+y5&wlU>p z8$)DMzmm$bfJ%xS9P9KtwC92)IY0JOGOUiYR+TvDM;X_ygEtOuhzzGHu7_+}?8<)P zcN?s=kKo?=_{o{F|0Cr9GAp>hveYX6g)L3ORpIPOFlB(QFSr{pKL#0j$E{q zCnC(h%cn^s8qL`yM_Q~U@+P1`cyEQ(&F2K!j&S^dK8LJ1OlD;-2OBtX<6JAP32M9C zYCsSZ0*8K+L>P>}<;*HgY)~-bl+STP zy^J*WuF5sD_DTsiC^9qEA?y=|NsNh38?s|8df{jRmJ5hnM_wI1EE16ynYNmC4NnzK zTVKm?{(wBvH6l=^m@(rEix>>JmNoos<=6)$;S__ViFZ=irHW9JLWv_nRfX7BCaKtI zYwM*F;73uZb!@d!?oQ%%aaglBR^q2&?Q*D;ryTm@17l#^5`HGk>0OCFbEfNJ+F`QM zec2IRrez)c6?~8BOhV?875lE&U3Z>p^i)7*p*?s*GO%to?FMzo+DNesQ=c}?XwCY? zA(st50(@vLb;qkH&3pW)Wy**{MX@7eRuDI53q3gA=2gADI;LV+SpyPaBDy4_yQ zL2J27@mjkk7PP&QMd?de*Lg%-?Q;QBw`~m#>n%7fZEV zbV;ibr5RNN9JqBbVyFjpiQA!Uf&Ed+Hg=omB5}KBa&J*+`q< zj*Pk=HExzw{axFWLR79Qm$lGyz=XNnhochG{HuxKPctDyUKEM(pq4BU)avxK<_>Zp zz?XT)xa++>Ti#3)MdMl`=h#dZCKH4&nTVWICTC*qilmLGjjdB#IH!E>jW14bRx-tz zIB6Z&m$^=ixf0lm(1(GF+k}ZdxY3saTBm;C#LbEugPDVOqZSRHWr2#|89yqa&Rb*E zY0297vHA9J8iKGu#9T)0kEn`>u~`F0(*XLfcb`i2cv43)lMjq`;nIRV^G-KAM3Xu_kO*VQ-;` zJ3|g)m$_rz@P6gp;Xqfv@&`rDG`(zbF0BvvP9u&=tMjO89*-1*-*q~pzMlvMJC6qR zS4yRMIM~l189KNfhIEjF?^2(tf*LUA2A6K`F{qH)x}7T|RiO*u(9K<~z+Tjcz*7F$ z%-T3Mt->#XpC)!2$X}Ag* zy0e3dShio#o}u79i&w_^W7l!jL-^N?i?b?Wh%59bu<|+Eutd?uO|k}Fc3r(jBN@2H zM+n@7wY}glxcftr+~5j%L2K#)fcQX45Ymu5P>Ku?Ue;8g|Ua zb}|sCC`o!7`4tB}xN-73q zn;_J7Nd!7Y%&F&*@h$q;{Yh5b1ShZI{^|Ldca1qE%=J*u67DeK1CpvfMRa&;2+x{j zsT}Mk+}XG&viCCZQ%{2fq9dNK5srVyD3WL{thPZyk0{FGKgK-(u2m>xSz9$w&@p~A zcV$Ujy5Fv^c0}o!kZh2T;pvDnLaLqgBgshkRZ$)XgugJ=x1^eox|+sdUMr8D&@<@# zSmWFZ(ygayXVnY7)VMZW+d&;wTT87b%zE=}RzbCxm_hUfeB7+Kv{jp4vD_`8kO9lG zpiacQB)>Yil`ddwQR?J8-(}!_uWhNZ;%!9#e0TVeX!$6l{Mc)yvE$nIzN2l{@tGib z0m7v;5H1h%0aLb~%((~oT_rG>ragX|b0p*)R4Xo(@KfT_X&?-_miM4--~@wf?p5|3 z-K;!9C+k?TP6q%w@x6>lZ`l19V%6QK&hYUcmjdsEY%>;hN`-~HSdBrN`6q5xL_cwj z%3O_~H2`vE^S;rGQpxRaPdFpL@)~8(8NXR2YsZ$`Y)}zBL4VDyC~GIugAdbB<_s~j zS?CFuR-KfTu4Sj_xSt1KJgHh?Yt)5$0%>y1_I?BZJ%bEK@Z-@`AqVEM+qc)d!u%WD zEC<|1p#JECJ<{cYjl{(DHeZUWN^R6)4-^Jc%3RAxypBI{jT|1oi{3XOyJ;cWlI> z-*zeB(SXaEdS%(8pRLwTHxIl-l*nY%d3Npi%QF|}oEeR9zxdMLMU1*Fh3maf6SD~a znjC3sv!L^;N|3PIK{T3zotqAd)wVN=#~^n z(BHD=j!+6Pkox_}crlnMYwoz=pqpp@op{?0&008eFPbo90bNEoPVT{y%ph{-% z<5Rq$>tpCzc}He!15M?(lhACuVf>)i?dK2j>JOJiyn}vscX-<(;mw|1TohsQ+_|hi zCaTZzCqb8=kPXP~fQWSYy8t#zFuk39U#SR=t`em!A#&sW(YSDW5aaz-t8GZvI<{f8>!0!=*eCykiL3@z}WU)1rLZHvRVRBA+dJ#SEQOzuLDyyHZ zr@LM0;j6=9Zmp%XK`K3^`{7Z+<$#$>;Lqo3}1C+W) zIZp9d))_CM;B}#UAEgyI)i(}8k7y|%Zl%Ojk#A>xIfWCb8?W@xyb1#=U@%YoD+!Jv zvGe*pv$_wbGO%+ONMUmiw(Evxx9(bS2B7iGa2AaB{!vnGR|C~VuBZ_=(u*o5uN^e3 zb*ez=1%AUuV4X5cIQ^3s>L-K9OC&jsq1LUe;(%T48j^hNYc!3o?^uJ^gEtz@%4+k? z(W=9_KUgXG>q*DFq3`4VxEj6QUTw1^$@}JYu3ezuyVu=tTl04x?x>#(?d1x1y#KZb z)fqW3zFCXu5aOBg`o?_PZDu1;bvpamX>#)ruOhq?cr4%k%JZq0%Q6CcyTX1wXG2(J z`GQFGTLq<-#2)IY(c?*-jDoXjn+$PYx%&ebN)xar9eDjdb+e)#k3+j4t`*Rwuvy3# z4n^E&-{$RURsm!?jwu$kh}Qo zn++kjG3i(Zrn)17=THLa5DR37Ah|?!a#bkMd`3 z#PWtHiL$OE!d*#>`@ZBIX(ANvaVdkvayzGLed8U`Cd{+W!MhHAm*^{-v3+UGwZtvJ z5LxD;p+d2-9m(h#SuHYL7xs+g{XXEhaUsfk((M{b`=J=tFJjklk?lY#j~#ll+)w*C z_txaA$X=51h|b2QT4~ob1)GX}%EWqvoo!zAO~3|9z~>br8!A4BG=@e8;heUljvW|k zN}9@e!5d(5KkEF*M~8~Z=+jcz?R&A2X}+ZMW?0=f#L&hFGWa9n1MWz=t2i?T!Vytb zgExRVQxjH3^Q(J>iKE0^z;WjH@%MnMe1Si*-C9p!JW__1GN_sJ$^ikJ`8Hn)02fF#zc*3p1^i-`1)pRM&%B2W zS&BPbv8nnXg4lLeFJVpDFKHv2@BnP`_ppfa(KNNuby$6s=5tmOkvy_)U_}=N1E9!* z8}_ZHxiZGc2pbi2T%NxImhJDsl>;fynnF!#oS*%iMQaaVO$`^9mNiMsfqbdgzY_%o zml8zfb>u`s_f=@?yrxJ)*l~f^Gd^D@P&bkA-JS;CsNW)egWR?H2`(BbXi!mO38Wl8 z<~;zo>(*8CS|o1kHjI??LWTq{@4CBFyY`o79?yNwsd4U^smqIagB8rf60HI2)TQ&OqVB)o5&h%Z=P~a^$o`_aRNj|l)7Stf+Sd>qY*w3kA~d0zo;!2Q4lcZZXqP6TXC6v z6njlr_Q7rvHqd|V^;v-HLwVPPO#)NZ;z2yxSxFxCx(jPUeKCpInZ7HE1vOa6?90RT zgW6ZU*56k4Ht{Bb;$gk1%fHW8)?Sr6{|Yw1C6aIZ;NqG})dH{WVMikcgeR{_&b}$~ z>t^2QEEW9|+6Rwo_}uK;9DR%pS*t+TmJiU;Tb?1bmQ|EjHB*oB?000gEv$TCZRtlx zRl6~6YtaoZ#s8S&A3Hxbn%rg{)D+$P}+e<4&)>=h5 z%eh+*yHR>G7OVJEyZPMw+kneg7hdtyAo&~1=+C)a);ZWmcv&c1Qf-xtL;IW3L7mSG z>R05k*PvQ7E}{!z!Q*FAR3lxEl;3(Erepd(A4xG&YWADf&GaIzy1N;(J@uV;YtcJ6 z*_@bXbqXq%XVrf34&__Yk>MX@8igl<77vZzv1+Ig47z?%MNW4`m3@f!fbH;cs38UK zuG>&oQ#a*|7=ESQqcNAcbJ)Q`F@5vhZ?J5;dD>44H!6c{vPoa@x%W{qh5Zt^)y5U6 zXXns~jUV`Q*yt>;DF2RmJTRIp_a`!7ZXA2zb$5ZiMPFnJdhLtmsUfyLjB2DwUkW4O-`lZP9OUqDeq0XjL3o!EfGig2dp+BB)xU{~9yy)jE z)D0&2y8iKy$NUeO>tB4I0fJf{7Q;FPqGW128wN>NGElYdjkbYJDCSzg8 zCyR4s@CN4y>mmbre$p$@Vv^^5m zqREtf*Ou?(RF@WNd*9%<{kD}Nkly%b-NC~A^v%-c# zpRWe_Cf8@q)t<4zQOIRVM{I*H$~!N^p@Y8DMPs#AriWdc^*$=N1-)Hvm$Ir~MH6LW`q5QND3@hm?fNdVg$%Fet2WJ;$bo#EDRyfg`eiTU;rP=Gl%IT=_t|)HQ#D@_`xvY7H z+Q%yMN!TmFuvN93M|Xr&6q4-kbRD92y)>%M_fJ~HRRG)887L3ry&c6AXF7WEpo;$; zCtxq*5~95ea}Zx&ux9p=Yb>EFa3OpFQof;7I%d(%dU#&ixz+W0{_L$1bh0tKp%abx z00sExiY_7_LG(ELub5UT6$ymK`}b;WrS4@D;+XRAYY;_4sfvOL%N++t0+rm$063&gYs(3PuL!5dONxUPZhJVQji8d_m@+52W|q!|j$@2gj*g!50H4~4v?=~u zap_&hb*>1leq1SFyzn_It^>1d&<6L~ zg%B^UoZjA`_e$c3N(rs!yM}j`o!f&crS;Z>GB{ZDZ5D!uEK!5eY8u{V2z zpYED7*=U+QAM~OCnVBRX@PmED&K~WC?{MQan*lq(v@*Z z>CUpwqo7t$fHOVXIp_;dwjH(7{Xo^UV=G7mh( za^v1W7vzR*)`(G3?I$`Bz0?>7?AFau*EC;rH^RpY5z?7GyXfzt71j@XuXIkv!^esK zzZtM|2V{;pP}0VX9=HV_1-2e|f0reeuo&8!wpqtRT|+QBZ(a6yO0oE~W!J zZVBpoZW&+<)l$O7gJ7~B&>kOnlumv`FP@cdHN1VJn^i4XX8SvsKznn5u{aF5KOUB{ zA;0?d5oYj{7w0{NUe(62uJ_W%p*VpoxCOZylSU)+hSl^^yC}8N=bEsi>I0QtUe!?5 z@Gi6uZ(n-o-O4lm*H$nUar$qvBFsp84;h4#N1BFK=ex`MBNH@}HwHBVB zCTt8gRWIH1+Du)L9Om7*XM17L>hW^gS!bH1xZ#W!YK+UN&%ji^R)p%{XMak~b4rJv zh&V;*raI$yRDji70poKu{0#5Z8NqR!5Duv|yR|TH*K%~duKN*zYeNA)Qu0zvV-C%k zv#z6j@hUm{18*sQGcgn-^=K~X5%|WVx%cWAUitMmj~96gQwNjutwpZd7?3xEST4BY z4j2q$+K`RkZiGYfJ0QFKXBzXxhJAd_0`m@V74Tp&q4(2$ zF9laFhn|GGfOa5|(O0|Ku8tUPxQ~_;S(^@VB38+On`G#>+DoCq@3x1q=1xSD^zx#cvL4}T7JA1BhW>x zx`*!078*b7ZV9E+44 zO6R*qrND*M%eP8S_M661(=i?vNXdoIWd`lZrn+nV1>M(44MrZ%fMr(O`|S)Lmq3(q zkdhEWX>Yy_Ye`P`ajCJCU$_J?iplOlw(`IQCMeY-UzA=0#+KS;V0DHyAaYeS+iZ`{ z+R!x3Z_KPExf1U~KT-gYK`>)z)AYV@ZwM%s(Bfc#r48JKnUL1zFL%m-7vGDSW=4kV zJ+G?^3z?>l66Wf^-IKXp6z$E>4iU37`UBcmxTE<3OGDTc53H0PWFRdeVM4xAZ zkKXipw`Nz|!V7DN>jR<%4c=`ibI#Dwj*gw9n)G}Dj}9hunhy9uq!kVAct3_xi=QvG zmmq#i<7f|esi5V4={sd;$M%GD$z?kF3EHyzT-3Y9x}@=r;j?Hbkr`RvP3?|Q) z>@7En@W!|61pf5bYurLPKY$P=^kvsQ`6CO8E|Hc24K872bM7+KpK{pfRfA27acUoX?W{KD?BFY*5P&PQI%UY2 zy_V`*j2k=}*%#m@V^D8$I#U#Y3&#cvpne}3KfM1k(@YRT9l?;;t`|wnq z>k8Mg{<4u<#(m~O9O$6E)h8u1@b5b9P+li1YGqNJLp%C>^laY-`Pg113bBzKIq8$F zs-0tbO4Wf_ew=7l8W**woRWwCmK1rixQ^3+Q~>!BT?Nokz5d4Qg=f@sE-I+YRO%(q zC*nHx?y=ir$G2mUXJv~fIqp?{sV%-pP?#+8_0QvVFC)7*yRP18qZYDYR+=F>1)Q8A zipOnm0vI@h#AYc1_VFM!dde|T`s>d5)hFedvkD@;m6<6WdX?8&VKq+Uc zKS)NE$eo0ryf>kACO9x$JjdaU9NO#VF%7;186A%b?bwKz@Qx=!qm`u?4~dZ;l81-@ zd^7XvfP);34RzGtqj&UeY1A1qbI618B1aEBcg<{UmG0LZQ7$xY*y6i+a9!Ck;Oooy z!7DiUnQ9}0Rg3v}A_hdB5pcrflwT);XdOuq6SzIuA~X9v&0uKKjUeNQn<=#U%pPp zjT07(wkmT4drBsSz-HBpoVAj7wr}hVSEp%)6Al9)a-_t9<023daJ&P;2ll%O{MJCJ z4_oC$@WSpDn<&)r5(#9b&8;}d-JJoKF;Q+#oI`^7cb!l+y+k}L%>mhz*;8e~P|9&I zF+c*?!QUel1gp?|@3-;Hv(7IV@d|WsSs1W4u(Ow~&jYTwr6WG~M$SVk^7IVa8q@|L z?>Et-R!CTOs`uDsw$T6uC}MDLR+3b+C zf7jy~ZQQIT?v4`lw(+r%ZL;d&!fqF6RbHvUk!Pcy(gJJn-E>W}K%!y_$o7FU5H}IZ zxNR1o9G4?DoSxm?%{p+Jj{-fodw`;Zb~@P)ldTPtEIBr4g(NM9XjmG(Ok*E)q6Az9 zm)I|>gtSasBJQ(4$v3s|kt>_BeUc+Ln&`RhKXYAJP)t(r_10B(#hLcsP88QD4bmR+ zrxQCBX}8}4>p$C!?Cy46V3<0_M0@+(G_9abNBcBIcfFHk@}3tVk&hlRcSmL;pJV4L z$ySyExqt#_=Y0QZY0%TTd8XW@4RJiHRq5b9Vd)A0eO7Xj!c{H#R;?fxE|& z#M7S4?_&!(!Y|7&{#L@BoaKR@xAZ7gB=)22QfBDUPi`uYy|GN#>9+J)aUL^ngi{p4 z4;(%4f5`gou%@=ROBKCb8(cx@V4*5V4In`TMFJ{KkzS<2Xi9Fm;uoSeL6y=$$#v0D>RzCa)zV<;}9 z5ZGb8bnD!t#_hEEvUb`GhF@(b2stU$hlP_eyf!e?@4@5O|H+vT99v=ph|T z3H|MDye{^H5@MGqv2fmNNe9PLz_}(A{*OhS>8$Op8IoKg@b2<>k+Yj7==~a`ls%Nj zrihl*wh-=)4%f}P8Q^;#i~iZt=5ll+O?!phpnsV)a6PM`LFU0&pZFR?zN~A{FHyV^ zedXzo#7*)7#mtTLM<3BwiEJ7E4R5R4JH7F3U5F3Pc=|Eo5P#^zQQAuBf@Pt*VC4`g z*)%1CrJ;C5GpAEzw6>Sw)#Wo+X|K=sn|XN6piUjR7w|KR&x?y=ckL(pnzZvPJ%`U* z^mA(~^f|-lt}ZLeuWaS%OYOz-A9c$4$ESXsu_ElArWaMByUj7D>FfFT$Z?G1)bM%J zlpzD%vX#uoHj4X{aYdh``EC2@^2zE?82iEr6A7Y7#rKtCE6PNE`P`AvOcnoH*V0g? z+L;mO8P!DvnbfN1D_PaSoA-wIN2dDhd))d$7O#Z*6cN z4x|Y}><8S#Dv9a_mG#6oIa{6gER~L~Er!sc9;w$X*6tZ7-RaR8_}$rZUsDHes&ljl zy?q=!5?_e~ZHhNTtKp9mINUY0nMS&gV;^lk`zp!VZtb#oIyRaaeuVq+yZjBv(o>lF zj3S=^$t%AMJE=ht3g~M2n>N9(&-Q|`oc~CsbOyWz;B7~hYqm(ljifi6bd9c0{?}NM zP5t!dsLpszAa58y9ouj@X?W1+1~~ZS%k-%ir35>Dua1@;d+VuUm?f+Q;4)0^QQsc& zb5E75+;fU2zWr%Y|g+}l6?Gj63({?@GrJKyVu4+#(}JQj=omc1i(y2|#?-3y_E zujiq}uDy&x;byMJl0Kj16?sV;_M<5<58q`*g|Fs?suxsYMw53IM~*8`WpOH3)DRp) zf8gLYVeowZbY*lZ?2&8ZqAcumzF(c-RcIlN@0;i^d_ajPQ6%-O0;9j+5P!X2U&T`X z30X`a1rqb_5DK0$LgRS!jmc=pqAi8;lrJ*6#+ei!mMg-)hMa6)9np0X8HI32N16W| zKSBvWnmWC}QDqqwnZo_K%$J+KUkiQ>Ijq)PG==Tt(MHt;tNKOA7D+uaMD9e}nA+S@ zZusO{qH_qy9{1O8H{!#O<2m#}85{xn6Pl!Q`nvxBEi&Remxw=ttD|dCd{Pr4S^-r} zOOWVu96-F6qu7*6^?)ul!4>>W`BK3pgs|_|`M?is#|YfUBCzyow{l1? zZi!me$*AXC%Lp7Nm=?@eJF9#9ze`CaA##)=yAD@5n}rGd?%u#_sn{`l_1cZU25s7g zymK{STdY_zLGMb(u>@krXEbiATpov(K4LrTQa<-lHCdT++nw!fd_1Fqj)l>O1-@7+ zNI52g=|cB?Z4w@P9(QvXGP4}W9hkWkn8_q^yIj`i36B1QVf}|7% z$OVkkcrB*15^GwT)LZ54Nzf4;Ur2M^x)s=Y@6=qQM{rMq`$a6~R{1|i;o(mH1;=Ne zQVmclcD?swc|d^m)>Fw+{Ok?&dUEgB7xIJ` zj|cz?oX4Q%YxITNDt0KsYuSNXH1fryU1ps@4|Y@Pw#rwk6%IQ0UjIzTdp2K8cfZ_R z)1pqX)IWUYcvq<6wyPmS>)aRq<41e}w?lTVQT4hrvj4cF z1-%!rc2YefrpdqI&t0LP&kSmK+a{HqH&?OU0XvH zcPBr2{gMhnAZ2Ik)yWz1V9v*fgurUQ{*wk=ZrXYv^rP^q9q;=YTHaZ`dp20S{weRT zXd-uANJ8$s52Nke+xX5YY2{19B-KTa;@5-VLb|aYRVk@^>u9k%K^!Zat)99$rNw%3 z<^a&T@wm=%Kod?q*TIi*22aIi7*X=MI&dQf*TH3jmplGj_)JvQ=38vMedfG%IZl~R zDjR*Az&{J?<@$pA31|wK=tu7u?JsBR7=usA=QG`@EHVuiEK@czLClAT+9eT|_egrB zqkC+SfzWb<46{~LO{89FuM39TY1phXKWAqYqknokptH-YX!nuX&jxx%0 zEE$`+q(OBvqgp+%vQpb&n~J?Gri*?{YaIt>i`RJ+OTHrekj@$O7gE24;i#GNATZ{bNn_ZeNhGC>1({1SM>hAL^I^U-Bodc z2~p_cj*+_RkYe$=#pj=*FGSkcEe7ri4}Z!(@$&t^V*6uLdy&y>cv_A8Y|@pSucSXA zk-KSZ%JNbP=7G=hDa)ZeIrlx%Sqp@lsk@Hp=!V5gr$jI>X4PHMGCoY&+=1)S!laoG z6FRFEyWOLx{*;~US)CZ(P{edfP)?9;C!^8zZpT1lbi_~2KwHcgS?6z&CnuQ4`BRF! z1Jdzc&-Ski#^}gSgIm9Bz=k$>CWm1h%OCs=>Q&_dvEZ-NnSGtIzc@P{XjzNou94#^ zcSma&orr0;fF_qn1pa+TIA3we{*3vBzZMm7|1WL)BhWAC19^$q&9>c6|5hEeMrM z3zyP`KdHT_=%+f7c5NVSAmNuwutxZNJyEHa$ihOiGP$N+NlF+!Z{&`vayfurD!VY$ zqmmgcXsh;Y{td$muuBE+*IZEmbGj5zZUcg+Ly;f+zDms~{b|N6TKDMy_(Zr=Jp5%*6*DsqG{Gl2?@avg8377T_um0>Hwp8BqNq{D zBgIc;IXZU-k}63VotdDBW=eB>TsS0iDfIn!0__E(jmC|LE@6N#W7~}6wQ0}n z*4;z8AE5UOV$+v4Q4xO&m;QX2I}S;&Z9IobU8{Lz#ea*PayItZt*#d?@3))Jai8ny z{m4)BS&FV#{G2`a?t)&a^4dq$ld~A_n&8iTV}2n;W|PCHe&3%~;(WHH0$c6{26CRK`-bP zWBu&6)iNt*oomo8xh}=?A7y8rI!j!^D(@!SPH&4ozTv6;t^R(~E9yR$Ii2&lP}QBy zC2;oA5`Q{7Muf%!M}h;DpTRhm*%ja5EO?V`kzjr$rVhb>OXaPyqQjSL;te}#|ur$ky z{$*CBU;iR`8_{M1rK+70I3e3W^DU`u8=>2JDE*KYoK1S)$M={&q~>E(gJY5T??1QD zS5GF@dJgDD?ar93bv)0M&((8Z*YD-ojhF7ZlvA-OsOZrYJb232|ClggvgCA0II26? zgMV$a|DD}Y>f5Uh_cBABpQlQ~H~H_BiCGr6F7DuMq)TS53zIY63Q!<#+v+Qb*Rfrg zzjkU>-1mc>KSNOl>!>TjpL*m4Y3Kb07L`dpwUD(aNcohLjb^4w*YV2ziShZ#$VAkX zICQnUaetukmN2;mFzu8qUZeFs>I=Q|Jqc;G=?{-j@m!i&c5Y_c@HxZ?_y`I%G6(v| z7)zPXH5eRJ|>l!>HT;QfD9JN1_u3ZJ-$;rH^v_-qy1}gVFz)U4+YIU z2(0G;zJMfc%<`t)_%$xU$`;2#Aom> z#bOiVv{_}H-sAak?WEgulHm`xZ>W=!au(-{7=O%occ232a%t(a{#Ym5!V@LD%wA7S z2{z^RAxiyd+%pj8<(^PLarF7c-EMr9vPyuliWuqRZ1fw%*Ozi`zgKL~8*ZPtOq zZPQb_Cw-gUjuJCCu6nab`=AP0uSXQ|a(x%lD5cq`Em^()Y%q7n>P^ih@RQ5qG^K=I z-KTdcosVqQNzlp>5+@`HLx63E%r&3nRRwEC42x4VapBe+CCwKs4e;mUeY zC0KjL9EjHJ=ZbTZLVpzE$3ilX9iyH)dEDDBra{`7$j_}sX}L_J2CeYFL}|c_^Y^5- z4bxLR53+HDU)zcFdo#_R_7HoRmlkaFrOz-bXIJvdNl5lBBZz)ElL#WQN){B+!^zH7 zoMXi%Fw77tz6wG%N>2`Xm-H+^0cgU~vZSC3H|Hj`HfFb<3Fo~`^5`4<^0_8t9f%5c zi(hf(u=x?tHV?U8_pE{1*APNWV2NulV2`9@@JpuJTZ`H&GHJ>My^7B!vY=;P2C|_rMOo$0= zx2tUdyiTDzDBQ?U8PE+a`;hwn!B+1|rtBI&pYB>EF$G~zRG?E9tS|BAB5Hl9 z?6+IO(`}4OZQmZcyV1_N;=^e=WJ;%8oSrN?QZ-J3Zc6(+TQJ^HAEmk?MMgr0Q~shn zSt=flb%170SR<>oC{Vool5$Q<%7(|utoY2nhrAtKJAKCT; z?lU-m<){xMp< zV-LKtUG0=qNDVaoUCU^*@z6ZqkPFt+ z+W6t|H+fD|MF3H_z+eAJ_P%qgW!NDUQATJM7XEStKD-LfrTl7hjsL5=n>A*1SH_Pb{a1107rmK> z6`u{F>ZXsBFILVjdPxdVP`@sgFN_gSOTtdliMw8<`7bmBrLQ&hL2h4UgsdWV#$q8- zfXbQFuv$-!zZZTk$93f|kLo}(Ig6H{&c`0S)U7n1ozt6DM(%EHZ@~}2kKuhbG5!|A z#%1uE=PE363f?gOZMu0llIzDPwA!hGqfgq;=5!vNtm#-xCCqX#hZ!|uB(DorzF*Lg&I0QWLrgj z^4*-&qM+D>J+`HrzDP-5+rE5T7?lK{sQxyMQBy7q{YiLalgoy~>_7Ok=Sz`knx*VeSi!|NXF7h1-1&!0D$T(=GI zl2x0PU4}+PU0@B5&7>^X41p!z{`~@1tcZFgw|yt7X+gfq@2h7qq7&ydC84C~@VW;B zYh}w_o~v8ERK7ghdaSbRaGi%16?4-37gf^v>u49b?a^!4@nC|rrO(kcp1|)n6Wap^?GB8bv6q? zZHPJ(8rpUyIRia+x>Xdq)q}TvRvOMV|7sJzo0~fMyb^Fp_~BR4$7LIYLMNUmGxUF7 z`1vQ7KDP5bpM)&zsm_s?Y^?mWm+?$Kkg(DBX^&f+TsyfS|9HYbX)8B1v*?WT4c8=f zHHT~4cSAv`#xfRV312MB$3L2)J;$`{)raUk$H3)wY~<)PK0(q7*nE9AFLkO9*%K9! zZ-})Xw9r+Hc3V&DxdoIa`=q5S8lQ zm7II?`of;YV?Ml$tV7U1k^I0SKhiSSV6JRTCmIqz?KUn)Y0O3Z!A<0r>#o({$n)Fv zqM9ngi_$5Xdx#JR;0$T?HZBi$|SyJj%7aS?gngs{)9ha#>Zb!B&a zEz7B9&v~KSaVoVxPAG(|=u$ibWufFZm3x0t7VsufnC$}3;Y5Oa*YN^Rz4AnQ@!V`R zbB}zdq&$f&@x!Pr4IVh zUrfcKkw5Q|Rz1>`I@ZU+BLLh!@im#`E=xw?xid0)C&ou$hHKdeNXLq%A{QycQw(IpNyWvbRx_veb!K($r3NQ^9qEFw8)*PfNk{&L!|OqUli7eF2vSzB zGYt3tf$gU#jRA;n0zB0V92Cd|y}5_rJcJ`Y>1v6U^;NNpsY2J1jl`m1sTf{~S&fgd zbl@_A#IdNJP$YpGvy4ylow#*m3*dNUQfj^5q%sE`CgpD#IJ(-_a|=BEk+6wLPwcn6 z*F+lhNgqRSH9bg&8FCP2J!2XUU+K!==EC;uT06Hg!X9Gx7lSA@L<;q^alhD2>iN_R z!y~#m1-JT@cKS!~4j!+}nH0Ox+Z~WQwm6$;mB*_AbdwHdPKJn*S`a8FN@o{~}kq1NAgEuE_Vwm;aWh zyp$P@P>pBJLvAF^9i|sM?m4L95J=rhT^tT+d zAIyKxNJNgChPIQ;PqgGYh`5vwUzhxSyAk@053!R&4$+TgdwCVOGGI!V(vJTa$Dsd% z#`}yi?*2$Pj;E0dBPuYEL{hP-ocB@jqLDO*{17pb=_Br8VTmb5?QrDN>>z~&PQwSZ`^)j0TCM)0QuD$z$J3!QwaMrrL^ z9b)U4G%Ii_cmmoXFeFgEhoc>%tN}n>%`88#qyklL{x15@rHy8-S)3SXt1=lU^eOqV zu9(il2MdvN-%ST>OY#9)FD;MA@Ye7y^IFK7r{*;tk&8>2*xY{S&=)!qdrNRJaM;wl zEMQMc;mMlfOK&|R=|Yq_?O7^w;=Y6js9rOHuM9xm>t${{knn(5+jac`coSE{Z{2tG z0Qr+G&^)43o_ZF*+%J$=d6!YdWYN|~{+HfamNa%W!lOLX$ZU1V`)wX#lWu9N&eASY21a*@w1Ej> z4dxb^-H15Nhhbs-t&S$D6)L+hzY zyo_!4vrU`m&5dIY%7@jc5GvK;q#3z z;XRPY5apEc9)2=o^vjBkJTCX%iw2>3w*5a%`&|N!evz)@koGicpWU;M<~zEwA0Cx7 zU{{xWJ;O{OjCTc2%ywbUnl5A5P1yMy!t_!%*_q&tX zGo7l`+8~Nn&Qm*0-On|Hk?%)qGymAma7>j?{Sc?`%$R=6w8f#Lbrs3+JzavX_#R}( zvGga34`}n@UjW$#8h~ADHJ1y#q_3-`aSxnhuta8wlE{#!ovU7tv12OWB&|z`T{UB(ssKnK6E)~6h`h;UUllZjz;0d-&g~>QHgR`Tq<%Z zf#n#|^Rs}90Br_Ok{bA`Kdli9tA%c7s{jnxUOW9dxO=MyEX5-DxcC%vSEkDBqH*{> zQ|XAVFf~={sEkh;J1?~XRW;8@Gd*qjnj~xEYDJaR**ogK+0_6)wrd5xF-eix{Oi<8 zNvkNwyzr@=POa2mU#;;0AX+p{#vVF}v?ud#vH(sAQ{gGW8 zm47DZ%p%pvv^YHcA%2gY>HXp6%-SUhDrr<1h?Vo5$ZNj@q-$RNYdDmy~lr zJlD;ke7f%u_jHuT>(npyYv@taRQIdGY`r5z2vg$<*J*6$i)_7T1P4=3-A_Dv+PrFF z(7M!QfrO#%fYNSLPaxlX1)feD0d`T-E})i<`L6Rp*#01 zsjPCUN~z~Ore~YSWkvuL5X6M@AXB;kb+bE(}3{g z^{h6HW#NlVoN^$?#7uL=9i(91B{{*J&4;M3bhtN)JoD7P&6ichbE<#5-h3ygN_V#L z>&IM@ajk!Vh&t=!lMzhNag+w-_{0t9#n)TZ8xGEQrltH!ZA#nyX)@)Wm)qTOnvjJ!_ z4-Qw5I~bcut0{;M(c`2aaFV)#Vyu^}sArAOH{$;+@cYx}nt+^FXCL}YfC+uU?3%ZR z?@L%?b;vUW|4BmChaK9$XreUh=+cG*A}rqmpz_IpqEBo&JD-pl1ZL#{d+z9~bBar( zWr+dvWuc-pmDb}d$FY~b8&YbO^fJCK#CUNFde3%&pBqeHNuP%Sl#-S78SLuaUANlV zplT2r8oc?t$aU#IF;mtS^C<7CW{F^rZ2;#y>nm`+7#e z7sh$~7&co@ohBlV6N^G!GV8LNp219~GbBr=KD5#|Du6(SjPq6BC80|!fbLPKNnP1v z-LOU^N!6KQ3XM(kPq)}!K;gTDY?GBq)?e{%bb0lsXLJ8zk|=^!w@PmTzrG6fE*XTPlSSY83yxSEUP0BvCu;oAA%04&dsyn)Ttf}*^2}41{z9V;u&{eg zYL!ug*RI!91$?i|J#x*)b*ktF#_oz1xqyOxQbb_3{|}1NO{PV#zz-szu&S8^!xITP zq}ma5AlrIvBl{agvc+JqO$=HCdKMwRb=%x0uuU~%-`nZcppLI*f`fY56?SaKUt`y- zoBGlwJ!@5R3P;lN&zMq_M)#{i4W{gCH~iDy?C9;(=F=;}0meu3cHZ14!O3#Ri_At& zu;`Z!?M*#YSUO#I-s31E(sA+i)ms8~k?x8R|F@aVW}QC{-xlOo%l;d5<8pKX3y zbzehsIynH*gpQStT{X{`PCxm@!HMKMwcnB~P`cpk<2O0hIRe+688 zZ{@y-eu|;dO8t+p2LdOU7z!;9e%&e1v$k<@3kzek5O6`9e58xv!1z_? z3n^j7Q51O0LQY)l4#NkOPe4=xaW*~YMn zaXw@ZdwlaR;%7Zdo;-HBv?8Z`6=bWss;WyEH{aVhn0KPPu0%#sJ*lP5C$;h3ky4X@ zU{{c4TFhKcbIrG$WxwCc`8ulXpK?c;HT!CiTInAPCz0m6bs!;u{{w+V6zk)o?IN2N z!jnK#zESmYR=+X0O!Y79l%VIpsKZf;53WlhZ@%K_PU9dt$o* zzk6@>7UPTGDCs_raB4iwtMofi_6p(eM?tv}V-iFb)Vt~FHpLl%Ih4WlEYMb%)m*!l z354t&X^R4VK2{4+#ObGqc=`xSttAm)_0kPwr+%yDOjvfjsirDn+T;b0%Zt(pTl z`CFC`n8N4xc~u1A7EB2&i=<7}5;aPoFTohw*eJ&84RZqIqpP+&KcF)xsA(b#--cm4 zi;7?h2$^{Zpj>CXnrU@`7MrM1*m$&#mE)7Y?5W*Q$DNb^N{(@M)tScS~kj-ZN$(oM!cG&GoO~ z$&*bzK-4%6?d<62VEO1}(^U4hyI&LcP2%+?Vc|>YMOD_t0M89Q6`(hWSG(dc!9L|F z3<1r2pJnF3ET3=dyZxdHqKa7-kUqmPm_DXdUEePuYhAu7@^xJNyl>9q4c^*NLG ztK)O9ei`e3rk^g`5*s1P>MS?aaA4o2G*jo}Jk2~p`sQm;5LX0;-Am>aV!&~UY0QQl- zKHGZr4Xzoz3`g@nansXc$;uqXZqKJ%=Psf#83cOs-Z&$H|7JrymgNVrRz#U5l4nUL zd&_O3fzX0Z$54NHFX^CfJioukq*ImMwC@_eQjy(H7563@sVS}a){k$E*Y`+~%~6Oo zB7$uWYt+N9cBkj`gE3A_g%#)rQT0(1sZ$HNOZ-6c7ozZsKZTcijuh3X(CqRKfymvp zJ_=7#IZSGzMK#zJS(fV(>v{_tP0njieF!dAckbxAhX^ijB~MZ+bH{AXi&yi$_(WSc ze?kjqiq-0`@A$^%8jM$onKE5tiBuSy9G|!6ZL1FNTN_~@=KtC+dhpye1wB}gu#w;C zahJ7LZkhv*B`P$2UoYvC}OYg&uUW)4X zfrGT2=2({46j@qYEIei;?U;iwbH!HwR9HXzlrJ8L$7^eh9vkvdAP!}`)e8?iM*iuD z9U$o?@~D+6&qU)IoHV&c_<6zft}Rb~sP-6mfi!E9DM|yyUnsXI$)7FYGSFHh@B^>9 zZQ;k}a{s5jilNiuOV%st*R##o7K^PQt)8eXFS{b#YMZI_Z45WJ(Owi#j)!xaJ&K|h z4siPZd&Whr>ro)1{9k(Vg=yDHW&KCG?*ytDCdz|1qK@P1J3GP{#FD8xEXx8mUPd5@Us|%6crFP&>n?)CUX`qQc|*{;qB-5h^*ISAX#3yHq%BDU5TjTKLNd1Lw>4 z%bxJkC&*>7G1Ov4-_>Lmo~sb@mDG>?;!rQ)i`26EiBpsR)Kj50>2Ydxz^_TmZSa(p z$|QvN*5#zg08o}I;T`c)suK;=x#H-hO=oA*I=IzkJX440YHcZx>dMx;rAt&qn zT=1^e=JLVG>orWpeZPCt8wY#<<^FX2;g?2|`oPs|Hw584p!e}_rQ>qJ>i$uS@T#^{ zAS_>~VA(Z2H7LZ1jgtL%J^WWc%Qsn|i%?)0L%Y9^#7?IazoKPgES&dX> z39HwU2hd>+Hu*;R0+dELe3_5SLZ)EAxm0<1p@qEgI<7=Q>qRWi{1XXXW>4M!Q-^eG zlZ8>V<}bc4iax2FSW@iuC<^+sxbBhy%xGxtuuR91);t!EQR@+SvFjBv|CI+fl-(lp z^y1FtDCsfEH1w|k%hQwK!TjB#+|Qp=q7h20jlh|bSMCR~u^S@E`l-GYXhV(4?AvUf zlqi8-$cFU|yu1ZmeoppxwxCh_pf|iQCPY%x4@SuP?;|i0I&AQmrlir zlRk?N*^YubdAZvLrN_9gdeb_(U+oQaRRPsJIacil7iD#?+voyIs1cvsFtmPhqYBw= zjY8Bn_`7DD^O3Fth9w|#CIX;Ip6sMDZ|{ffSc;-Nbp7@`5z5A)VJ*8+9TTaK8(?^f!wSQoh z{48LG*B{@JM*(I46X$n)!8;1?Hk21tq#rQR6z=^%j*n2YSP24MS{7B)_fdB=xkhk{ zV~|X7XM3^b+WUAi?-XH&^TdKI>#E4ThmeIvZOVqTZ;~YIxK3S}W8BexpE7d}L*EQo z@Jsv719BL=Gb|#lLhdT+akZ;l`KoiQ(8K=ciI1WhdU^wYFL&4XL)@`RGTny>EFbPa zG!Mv`p9D!&)B|{<%mgY%kGwp0b7_-I$KVphgvHX53}$={ z7Vz`ku~LB-l&@#jMoX|B2>p@a@Afq0Yi^vf+;@D#JJGc8F7_^)Zl?QR(oKEtJzsjA zruwjtoK##LARnwJvGBkwt7o-w%J=AFeoNM=0m3(}|J9Vo4XtH#CaG`?V!zkLvEZmR zv8v{@%W77I*V)FD_36_^HTe8s&Hr8xD^M)O4~CZjH!J>lAR)XLmoIgCqe>{e*Uevo zHINMkRtD6VB3Yp9O&gq>1m>e(x)m|m?9-0_fX>KU!JP7C;V`2|kY6$&hxItb$jD@J z?qbQn=()uDeqBRk0rk`wfxj2*){E>b^l?I`x(ZY)R^Fxg$XP0<%n%>PET7iyHCbT8 zDZ?B0Va^lxg~bs&Cc)@mLCa06-?2+aqPQ%$lHGTZBm}UbW4{jM zsy5ub_odqM$FBhfWdB{Eh5gHj1#jU&5h`6>ZK`ouNo|J4he(nnTeVtEUZlN&^V{{G zH%s#*WXZyQSv(muRl0rak*-JN2r-}6R@Ft{!$q-S^U@p$?BZdcd;dWe;9f2NN;r+T z{Da@x$Ev=vAoE%e@hIDFCEr+ibNp|>r4Nbb`)tA4X=*d~mu>nku#kL5L~M0N9#Bc@&W=;?@VYSenxZwph1?9(V#)LnfXG zc#C!;&+Z0HrY@#UI`4ggOq9R1jm^Ww1|;|z^WAJzPdKm1*Y zU3>mpuL9ju3tZw4QQ&&Hc|3ZL^TgvISM4Q6D>BU2zAwC1(t9&pUoss&!>ELzDuIN9*>%g`hAm#cV50@g;wia zsP;6-N>WX<(yifCX5bZ5l4Pn6`^%vo*D!#G6!q`R=_ry~$VW`6XL@zaR3=}}hEmQY z&5D}nKkJG#lg14T*#UKLO5x_~QBhZ#El3HYQn5UQsu>}TJ8$~qi%VUM+ergQ0P|e1aNF;t?LR~T~B+Y+ZRjpWj+9!(5ZZ0Me%V>9VA&X z6f_Wk@8@tg@RDtg{DYp{3~KUvWE-e#8`B$?GoW!}G*Q$A_`|lSR~0r1h^lZ9Fm_bT z1@Bw5OJB(=RCz0;;5j1-gNGa2yR(5xlTHqk1Wj3B6wY2Ij%E2K#CJOPU$I(B#BB3t z=6m|+c4jb*oc)jA*9gBcWIA(k_5sRnqbiYw2xVh>gJm$OnnF;yXaX&kv0i_k zBJopyxik#SU4oNRj^}P-=o(X^+VUteCM~K$SP@Z$XXpX3p++)HUaR;#Au>EI=pNee zQ4Ub_raOqj7^(N@?*|17n|AalgjX(?hB6CB)Jm;iZJYrLEJh;3bxb^XHq!0xYlrZ}!0+^MlC zr~#5(dFnWi{*q+}E+0Gp&5*7MU*0~`d50gE3%3LP0U(yfTe$e!}`-&{BuHw-cqFZwSQen*3#@I0y+r5xfQ-*u<_Qg zW23=kD`L~vnv_0*Tq&fD?F^nq?v_y#1&dc;*?R0Ig`s#xnnsap@HRCu9qG!}Ks_4+ z>=oPm?+Wu$cU$%yDdCyMAPHngFI7aAbFonMsHqNox}Q_%Usu{psu~lC^}xi*l1d8- zhrSr{)JtN=KUl0|TtYc(8et$Pqlw{gLwPX`__6#moV#gw6-svtu6QGfJN|})$4`VP zFUHmU8m+tJ^hMi%`!(0J?IA;$aJ!w(lgf_QyuG;G{@#LiYeFl;ZcW>Z`Ji(6FWGKg zB^^P;bR6M!=*@+qg5+FP`WoSN4Ou&qYqG3v_KU|L%B+j6Dtz%7EQc4SV=ugEo2!l~ zKRCbK+Q+(hV3KcJdkDNiD4WZ~GZ3oA2e~K(&n%{Ap2FX^qwLBNrykEdh1%MyWVy1WbZ|@`nm*+>(QO51au($KjsAul$SWFu! zXxmx_0JgdEM8D`OBL@-tAE1U|xhxky*rDLa?-F}ZNXn%tX+6x$`1xx_qYVq6;24Y* z@I+;gwVC)deW$>WfLtSAOlsqn2e( zcQ@%`Z*>GoMK&>&rGOMvZ^4zM>x#ZGns#W+!NL7GJp1<83aR$;8UDwKFq`x7_jPkdV-pLWjdzvWiwdF6uIXo&ElRAaOPY6c+ zj63CCvBMQX0%DHwMmPSztA|ZSM`vJh`DgM{me=a^C{b+8s?PPhPe)REf~}V~{^Tyo znR5!nzm$iPl9XU<~Xw{oYf>v#T;cK%oN^(7NsC+A5?@K)op5S++Ss_(BIc37HDJy+64^ z2Eg*dvjuoIS`Oh2$cG87-#fx8e3^qIXVbBz91fsRTDHE904fCj-LsL$VUM@Q2$B=n zM??2fY{@J@2N>D}j36F!dJh08N)^5pL|7UU)27Ss!z8)}g)FbaIK2Bc&Zh zLA#nWuPPOxxVlg8Cg?_I>tAzYM`5UXwQf`9wcZ9i9N`O^yGJE4Dz9#)gkBi;bfB zq$&m|pt0b}5o^S5E;$EZjtSuat>c#a!b9{A;#Gqcfv&^AdO1$nK}OnOiJzdl$h2G! z+J>YrFhK+JDBzudjwP_d{EA0K4GG4n6gJHQZ1y=q{F(}Hq}MH(nVZf8^fF8z=J1ex zcw0>G2=r!yB%rrP9oOEfI8-?S~AGrola$Z?pdS(HV^?y8n z`}27v_?m!HYtE)BN3^zu~X5_PP*8S-^&IY zYyC=hvj!&gwoj_*?L65vN#F*_&O4Zy$h48GtZihj+`S{XMQmEcq(1pEw49y!dL+G( zZs7xTUK~eU4Sa6XA`ALxP7VW3(a^0NZn1X=mk@W`0NT5ySdLLs#TP+xZo`E)g<@Q> zimiI4vytXobjjuKf-(6%WoUb!p7Hvf(iE_%)N{nC+@hK!EQ`hK>x!%e46UIS$LXgT z9BzYyT%{=vu`HmdM6=9F5>IZIc7{a@b_lrGWX(taVJv^3H?OuLCyv-gd1vVf2A8H3 z3G|%~Dd%%31-ChNwUd+6TA@e`n3|R?+hj84)@GWc2LX=t9Bq$aA;hs{v?WR8b1Gd0 z`vHMHf$Z;{ephjTa<$k))Z$>qx4T%4ypw1rkMcM{HW|u-Iv;v=H~&K3>ZnMcpxZF+ zT)_B5Gc4_>drt_! z*sx2f8k*KJARAPL=@3=cwUrCzn@}V;LP@^0^MaKc?z6>6xOfu;y8GVtDq8Q z*$rz7_P|M7wugMuYu8|u%~u{Z`|$*=kn6BoM{sTnRv4G4Npcdk)Mi(CG}{<6QOt>G zns6Isl33f{OPyE5>bAc}XudLE|8(gl(rrSZuksd*uaB~0`D##Yqq+5n(_LY82sWwp>1My< ztEPWcJU<)XWNT4x57DL}H(GAfP62zF3m=|ab4V+)K7eKiu|EU_{9;3-j2MV`ek}=x z+Krnd+&KcT^=HlAq<-*a7Ow;4hy8>0Y*6|%JePq99)!Yvo(UY-3(aH<+CLRb6rZ%@ z8ama|VNpL+B&gvw@j_U!e@EbX_wvKO-h_4YU#2EpkuA%xmsttZrRTo!Ha_@ntUcie37V>duIhgxK~J7eVIUVNqsZhpdvd@WpH>u0I_pRn-28z;No3;H;YTMt)BT? zBriv9^U1+O3^uhOft73QsAloQl{N{SSO7Ih0vth@wVuOsB4+A}K^J#dSn52yc)oVj zce&>_$e4J+hE|+%AdluVs1R@nQ4}P4Jj{f7BvEOdch2Y!E$|O=tG4N++dQWBcx z{@(X{&-t$FoWHWOlRdL$_RLyq)|$ER57MVaJefb!GX8}simbi(N8Neu;LCt)sor$s z#5iA!<6iDkHG`Km$d>n_M_<@ZX&ZH3bK3co-xYaD?NUQk99GG)#RhImohIiVJau%S zj_1<;AB-n2Jo)}Vx|3!b1eZqR)4dTR?#IRpg^(Y=7FoSIE0Ts{fO+~H>dZ1<-7;p(yl_2TW6sPw|G+^&rjaoXE* zmIbG)^h?railsusFWKF+z>GEND%TP|q)x2*t}SOjcit9{Q2)(k?2Aqf`d^hwg_Zo1 zin+iN1RV8;TJRW5b~BlK&32K@o%Hbp6jdoAXy(CD4C>}i$~>X^*cISEswc3$2AIRp zMF9KZD1UXFs8iT*O?_}F{zEzc;#*_%mB*$W#V2~KNI(0J&4%_4G>g7){liY!$?FEy zy^$kdnp0N*3YEMD<}=8Jhx9X@dPQJc!yc}KQoTOts>`mfvkaJzgM8<>Bxsd(w5mu) z@b*Y=jMj+XB6JLQ#QWp{Y>Mj6es$a@X))sk!L7^!gV@4HqbrGpY=1jVLmR5jI>w|Z zm#VIHOv0bK2T#e(m6D5GQyU3t4>t5T?Jgf~oIQO}8Q_LAEObwS3kW7D?4nk&I`J>meLJ=SW7JH+KT!$+u* zY6rCOd$_C}p~|WS9PTPtX(gG(2M$djHqJB9jq-(5&i^2V8>#%kUxN_f{JpNIu4@JRVy*rLL2D|N7`!3_@K6Sa zc>zmBCz2cGuFp*~VepDBBFwOC99Zr>#|Js>8vuqpaFwtL^#PHXfMW-2lX-Q#4i13ncq|j&NOZ~R;}ZT!&Y=Aa0EHOr%u{wHGx>$Y3Ep1 zEF_+#v}=ER0#0#I|A%i(%s=3&RP47s(kQ^tsFjD{%m(-#RkN|CjL5pSn40X_h8vU! zvD0cndMg=ACa=R?Kb^>GgV@PQtNV@kI|o^+S7Z6|g0z5&cqS4?`6sDEeD(cvH`1d3 z8pD-n)$EH;%mwqoj+S%^3l3me3wwli$V3m z0*{yUJ-wwhhxItk@xWMtT1FD{vsFn*izF=gIu{$;=UXir4ZEHd?W^7q~;VqMVCCL$s09>~3%1DA`F%n-ib z#G~LfZ=ZV`SAZTxY1>84#hqqjyY;o%8{sJuNK=YyS0{PL0gr$#Ib9(eu|Qj!~CSpX%zV@;#58lTdYbU-3e^lDhd-f z7@nxduUc;y`>k&DbnIx#G6m{4#q(Ren{7ZecG4Z$l7$bD2{TH7R z2<;>5shF&lRY%X1!KNX8;sMN0jg9T@BdT!=@l%V!^eYxB&x9{X#~*);?app_IxBW* zW%h&EOM}?}{L7NYDHyh~eWRC;!0@72y@ffq(B3LnZ={l%E~AA&>gwWRdF!?Z?8m2w>*tmytHcj__k&P(16d~wBZ^ErLzj!`>1nx~K9|n&BpQh2y zXDG&)qj7U0hK&yv1w8{oVKEd zI@hg=-c7C>2IoOO*}V0uvk9PwPWLJMkWKw?C1$M{?~t9=kkv{aU!huOtcS6kl|K{o zeE6?CT)a9UNqo_NNp!^>7+eU?5#4lI>^U~)d3`>p;uO#Wdw|d@GvM9I{YdJG0<#_m zbH}0So>z=Vef#MY_m$_K-r&?rt0Vjz!ujg6vwuCfP64 zrS{4_B>KRX@Pyvn*_9uawdq(#o=8)|v!H@JVjZj%#_Gbh`lJ2UO+>{6s(^x_PqL;# z&=v;0XOnz@*=ui^-@eqiF1qoxlw)LMzmiY(Uaeu>yi+3e60Ojc?LjU z=kuwv@`zO*!O+UvrId@vUf*% zQ?{exRwQ8zT`U)OAJ!MAhN`PxavJv+SiYMgagI-3pZ@6LKL=mKhV_t~NPDroU%aE72qeWCWs@ zsK=S)=>+8Eiq4u359~H3S>6}cAE8|)wd4#k8DTS5!vYhPZ)2C}Fzn@=;WWOckz1ROBryU4mdV+!<5et+W$H@d6ve;QmM81Y{*^ ztqKRbj_Cr4M)abR4_!{17l zr^kjc4Huw$_j7S6-O|VxHL8~gn#W^Lz0t(3o*^)}Sz~QVo2{Bl7+)oED<+PA_mi~z zh{R!%^kD8LMV|2e*~jKpVOLVef(oc4N9C7oaB!uAfa1Ch0l zGNp#NI~?ioJk;14nbyNoZMyb-_*_Yf zdb39ix_HNh71%0^#%M`;qJ5s}o1M=0YORgw-CD7K9_;*+6a4u}Y?3zyIQ}m$FQv5h z4(gqK{Aa^=K>`}fn)r3(=oapc)up3@5%GQG9$^ke0HsZtZqoZVSlQ&H5e62wnsK`sF0#k-L!j30zNGv-~TpYK$qLxh;@1eJZgj~u&tM!kB{a_Qn;S|Eei%6;)3>+-IbuDVIfhar88p4fH(#qyQP?n>>R2N7EAeU8UvM90G8$8>z@G zr6a>%aP?w!$V?}8$^%e9KNEnqtSE7U;k~QUEXN^1&9TF7q*A(oH%q}XIPDKaL$}Q> z{1KjCK&4Bfl@4`vjQnbR+dA3B52-XTJ(5j}+_fc;sz>>mak8wVNe-H^IO+wtkNQjTjiLL{mHI_}`Sbyg{o#r{|JFZ86@{^Y!Lo42|*bfN^bbQ4#G2u7J z8$NkRr7*!{!(hyX2GpCuwP4L%q!o@;H|;CqkuP|mU-nE5OXdPi)mBiMj=>q1FqED>`QIuOP$3Hif9XM)9VkbX_a^@NjFY##69 zF6>0$?PcKl?mDkw0&y{^6~u()TV*JCDw{vqjy6qGcgg(53Ij&cQ9TYzR`}#FASELd zX|)F@e4CuW<=c zQWcd7$grs27fFMPGWf&Rmh-)cNqO#hGz*SeV`RgEM;RLBY~;h8}XjNWN?{Qhw+-;lgOu z6yAeQ#NLgGd+gmr$iPsJu7a`mwmzBxy9q?ijOGxk-4RWymy}!!!swd(igt=*58K&Y z?(POw5Qy@M1}bV3Ka7)Ko*kVUT#*Ea0<+Eo%F{p?bkXtVpt7X^u@MR|XEqH7%Z z0L$5J9ofA94VIdI(i;Kc*e8WNu(r_4%~aUXqXMa$$6Pj?Lm(m8Q1(~jR9W=v2wQSh)U3keKcLy z(Qo9$Wp@ad^a@Gbk8aAEX=`nxWeXm@P##)qJtFs(Xx?dCcJV16NlI5_KyAa zIuEbX!W}*?7t>#P*$Rm`B3uS%C4nI>t305kJcI`+#9)sv-Ffh^iUy*Uv}FlAP-?8u zY-}!NsS;utC(bCuDSFeg+)wpprK$or3gFqrl_{^3q3}CFZm4+|GaoTSfcEcTT+Yw{ z&2DM$ZNlii0bVO@HA*F|X!afwvYGYmDTB8()LpktTka%16icv9{2az8=HVp>ln+qc zMw_WG0N6mr;)kS1=d}~>NF!erDWrwzA;b;cx#YJe{VRO`8uLr|FVLx(?ROJb@Rrs* zXGGH7I(((7SsGXE4!Jf(ilAv&}`+cSW7#4NbGMlK z7+5zvSg1m6y$0O#U+sT@VFLq)5Yhj68}1$%UM3n$!GO>*CfxAln9;=EdC!RqeVDW5++tlp} z_vU|7?GD=L#HLz%e=V^V>5udXmvXJmcK7Tf&Vc2mU?D}rz4l)DXgS{=u~tn(+*e~v zLv~IReLSMd*$zSgO(8Ih_I@a|uGfaL3KLc0Kd;-^OsmC7_|r}@{`zgg8LK$Gp!)={ zm+vpe%EN{jblpO&aya5Zk2Mlex5a~Yk}J`zO)i)u>$z$-Q;=DYYG^S%y4_ZvmSHhN z%SvWkCAg>g#O!o4);r^nL#v|vmklGhH&VEOSelZ6V)-A8fqSPIYcPZ#i4R%%3Tgm4O4W6cz6|d?38Lte{RF67IC#Gva`unoV;CAwL}ytaGF<> z=-c`vdmqIVg09r@E(Mu{Wn-s5$fIRT2p}n2UlXC0f%X1IeAs!x7oWC>2k`*7NHg6_ zld+AXk?qhzerZv0=fR7WEXajj4Ljdh@T zN#L6T(U$^6za8P%UomlDV;D~cJ1a6?5h8;9g;Vdob~7GJ8+%(>z1oV+tIVwxi_knm zgbR>^ZOc9Q2&tbYtYT8=aNUpe_n#yYjl9i;bQiMS@#0HL2gn)Nw^iGtmIZbA#8Y|e zyFtci3E7mLEO_Pzw{Xqt!$+K}_B$!asSqSHq-iZeQ6iLt%X(VD3<<{(#Yr-A;fi6> ziU7>&iCK?yZ9eillUqY5aFKr6lF}!+vlY5VCx4ZO*-m+)3v1=yV=Jrer@YCqqBOA5 zdx=fQ<&HLV9=N#4N4Pscg2;IZ}-P) zZ+_F{*LKP4#>$)QCo9(}NR3{vO4a{dkL>JzCVM&M-4SA&g=Gc1+&-XH+uy3V`T06+ z?15bJc^#VpbGu;3VY{`DJNYZnc&ibUO{~7Ee(hqg)&^y|@JRYTYV1MnChYRNLPYN` zFUJ%7eBf;duLjS56({&_8QElH@{i|uAdmJnL8mQ3gmrUIUcwtMG!aGnezA%shKIqy z(9}mdcwCnvO5T?v!RImh%EUS40q;B*@G!MDLWk;cgv19*)3f9gJ(sO z{1h&Q@BkgAdAs-6zaIT{FkIpiy+;>$roW<20bl#gdK|VJq?NeDe5+GNjQ$C7{c#rU zv18ZOLdC6OrdFL8W;B?~+KhDCI;p#`rg0i(%JH;qcvRh4WJgE_SdTO-6%jVdA-no# z05A2*Sp|ljBzt{`b9m3wZ;3~W)V0>&D~%1~pO$(m2$cOT>d#Yr+_6%OI9-i3*cjl} ze$JWApd=|LF(?5o6CW5e*8=FY`Lvsrxg+BLhMkQ1zTD-TPprZt?ktV-3qexo z#C6qWbQk^WkcQ+Iqn9$91)&V>uc_|_45Fv2;|gUfsO6wHIBg8;0xW_rmV@9|pJij_ zLDdlcmiNthIWk@sVmT0>1y0{{eIygvu@}4AS!e^jxghKi`H5^BuL4 zad-LT{J!U|FT77RIoI@cL3=!gJNd~+dSTJpfT}2dSrC%aQk8i6g$(2A#6VA6`Ic{) z27u|)oAuB$3Mjq3Z>84R*8HN;Mw;z0a~=mp=>0G+U8W<}UA*?zm3FF*wf*DfA@)MK z*k1rv$9j^(@S1LaXq6n)ZO<@5t z;0h(gK^9$Pc?l3v4Z`&|I^h#GZ!}k~yjVWqMn?}ypB*@UP3Atzp0|`&1V)qNBM8?; zSAxQ_L|Uz^fz189IBnFu%zp(T)I#%Bxf9L*yE_nFxV>HssDhKV^#^f?&En|c4SXVv z@&H}8#Dk7P{!JOcsFnou+$+N4W)1m_wC8jE<7-_Fu zCoCo@vvVgm?!1|{gt1&&w_{S6RsB z*FKNztbL{`xO-Qda5t;uVhASK%;D%D*${7YJ_bMEb62XP&FS%GBXxa$Dq5M?dn58( z(BWfxz_uYs)F8vCmK8iAp)w+2V6W1BBz=)jk`}X*jINsXL<{rO*h~xf5{u&iOpvsAD&k!QLqM_Jw?6;^q{1xVD2{t7AP5Xrru; zU=y8!)d5wVS#MMnV>#VlR?Rn=egt4MDd3&mip@~XAHl=J4jXA{Y+~#sXNuZe)fDm~ zW1c|@CvM-sU&{M({ibeCw~IH{qb+ssT(WyU&*8JLDB$JhNL0vA`Md#Yy!*Kz8NhC) zOg1M^7N3hbQjLxC%R3}V#3|aj464*u93nJixjJ^+t;|tNL1FpGBycdf-8-4+{{U3{ z>PZEJ>c~ol1n2#?M%Yok^G7ze(!mmoPYzo3I`$p{p?! zAzb@M3XH2+GIM-ASE4Y?-6|+fj4-+N+J?-D?QVRfFt;k}c&D{x5apNsQUQN`1oy79 zj>!)&aS{G$S-Nn8C8}>>Q)HA^b=@0f6TB@U+qoV0Z0TQyrV@bW1{WP3d2R7&57zm2 zwU>{ZP8uAcXKL6JjCSlLm0fi2^f1@!UkXUEoV)p4Y?{Bl=@B?n)gg*FqCO0oDnE4a zc1u+UuLrFy%4D8y6tTaLx-Xo@s*kUNIoue2xn@Z!uC#%pmZ4QH0+j)7o;nJ>7Gm5NgKtP8D0J7JnGMz(5 zR-0&2bqGS;w)DM-sw4#P|Zg(iSC=W*SfXe0J0%OCEuLnkCLn4T9@< z_;39Bqly++oXyh^#-QYP?4R$x&5RiN+P7G@xvOPko?_X_xb*PjPIny>6*N$1Ib{HH zFPV=hFP}DPQbf7r75mJCIBD&@5lv->JisaQU(XIOeJ$?mLANlg7&6mw>*wHP!x3w3 z77}Pr$z0fYeqIE*o{@#rND{e82=J$FUyIUKiiehPCFdu)Ran?c*rZ6u5h_^0;c8xA*){+k?`->;oNWBm2S>zj9aKCE+twsIG`+YX1e)aayA zyT&X#3q{2gdnZbSNy)O!y5z;O%4I9oLjO8M*YnLlZ;9NrD7#nE@{X*qVWOFNdX9Yi z;V-AmM0k3{glJ34YEtwJ9GgM8f`*|=cGpVIkJS89N@VZQ(n4E=UqGkHhpnj`wv11M zR@JmXbpFcrDZ8oRW=zvsYAs?w$W5>Go<;;-tI_zh6ZaJqQXSv+8CRk*unr)tc&A3$*6yipzR#LpWv|taezas|-b!0>VmYkqoA!O_Bcrg=NwXQ_j8NmgH>(ky zRUs6UF(t(f5ND*a6HA0lEbGb(8YxTwZFq+bK|d0tA2=4+41YHoK9+^T1g&iO_aLt^ zb_UE;uEaj5-%xU5%wuaePppu$X4L9}PM#K=oX>>jcYxoV4DFEd@r%lO!92_Cg> zSISTs#QOEwsP9I>ZWfl2aYMIP7jlMf)5+hI;|V}m-!Yr06|KE5d>EDNu42Dg?{Pwb z37m`tou*`io7QJVM7pfEEPl(O(NWbCI$Bn*)PMeU zfBZX6&XRV%Vdq(+=@Yj6RL=|$nVl#xr&)JZdU48;JGB{%9Hsc~q;eEQFj=d2eQ)3A z{M0<4q?iss-vcuW*<HpK(RKuT8)zI5K*J2NvIu`|H9ozMos@Et4Y%`FzLZa67f0y%y6XzR9)m8--Q`Xx3AR+Sbh)kwz(Ej_o zkrh(XpdoD{L&xR8xCAr2Uzj(f0)8L0vfKaFEh!8EVf8egJ@9dOX3M+MfRq_zz%Hao z4g!wx_1EAd3eUg=oV-BK;`eSu*(>xJh+N}z{v-0Kr5_&ij>C+nnQAMmU6=LMDTCaL z>B+J`Eq=>#?xh)svF2KA@m7#RL3W3%VKW&$6Ys_fym|v)6Gh)-o~8EE==bG29dgLQ z;@#Nox;u?wLlxlk0PjeXj^3@%-feQr7Pq=-;{};l`(-$_T`x4T6X@rxn2vu&7$1lS z2a+Yqo*L>qM7MT%;oVZr!n4^7>I<5_oGgltJ`PSYG=si*dRO4mh&KiZc#mU-n%DT*YmoGl|*2CGXcD7-36V0oOxad9^^+JqTcqKKy)&bE|_ zja1QzDw1YO+-J~(>4^S5n}+SH&mVS*ffC?;Xr!dId!b}GByoHSGA0;#uL!`@e6WgD zr%y@|F&h&nnJJCx*DcO4^(SWzzxV_|b``Z{fk#b$lEA4>)mWT1(1=?t%cag2#W#Z-HykCT(v+Bx7~L&8T%nO!71Rn?dGd3U&Wf#u01E>EZwQdxH0gb`n7#h zSEu(1gJK(67FI5qo^xkR2rKrF=MYXZZ4;x%*!5jWGhckP>xria{yg<=4BQ|Fx-bTA zdi<{xzW5^Qn9xnTWMs4#h^^_+#{!&1w1obVee|Yf|5S%x)KMH7Ht&>Qzk4^hs@5~t z)G{#gwzQ0z+)-uSD8FnO*Z#sOaJr!d)Y3mpclxtor#Y%13rm_huuuCyIdcqW`{YlN z=1?#&N=9$Kai6U%s+g-ApMMhcB8j~#_njjTHsdk0nf)$P4_1m|;-0#Ho?3my`A1Uy zF);A3U@5S7gWJ&hzeSArT8dLcS4;stP$*dnNog4U_+6OSiXNez*gr;e=jIl+&2PVk zVa@lIjXZAD^lELUR#t~xX^VU#{|sH2#zmPi zKeioBzd>BzdAHFP`Niix&}Vr-#iCZw;6at%(W-|JU3yYc7f#e%#s+i9?el&GA9X`8O zvAoxCWUCkO^I6Z>kmzJpi7e&i|F3QT;Ya7*_idhAblk2t(pN_K_P~97Wng_9b6;{? z_H^p_gX{l{EX7ni2#jr#w4;~`@QsUY4`WJ|3tKqHWoc?n79wNHe@R;|k9LoKJW>gh z{_X^u8+=48kXk)-T^8p$AYu{}3jc;NS#DcHb@T=#p|ZzUQ&PfsBak%A1i|dHrqTAKFlX=1w5s@!fxC9OKiad;d*RrlEwRm~d(ZYnJkd@Mlzi8( z<%EEG>lrzAK;zmN4}Ye?qSFfsWJR*i$MSerrA(NXH+DD$MqCvRIzPP1xO)&57otO% zp!?u<_erClW5Hf-&wd;pyYn}m4X2`V=;d?kFse{GewTi;ocsJ#KoYaIMG_IqF&tmQ z{=Qn)w3IzZBk0kb5Mk;{^6Bx0*YW%5LC{2BtPr7sy0@7!_+3`iQvQMK4^BPp<=pip zhkQrHyu~&PWrPwynW!MGG8+Y2@6@B9#^_|jP2IMtBRzN zM}*SKin;NLj3DTj0~F4Ri3o7 zdpKNQUtwDx$F)7-Xc1t1vPYsc2CJiIMB0opi_}zUGiV5zFi55yZb#RJgiQ3=(S2*< z!y>)zD*lya1{V{HW|(cJe~=|ll5U9G&Jq9lKF%5&itE!D2sriQR#N_Yw2Vt`pCZUo4>wk^-q# zW8E(*FnUg-i|*&zWmO5o-%YnecY}mCcOOlUIbLp&&-0LTNS4g50$xGZVCb-{Um1H% zzfom`MoD~;bnN@M{ceF3HxH4Nae#`53$bACw*b@VP5;J%&PZJ(_;&rrR<*{mT!`eRj}eC7?!mfxjj# zt!{_j%D=#FUg%tpJPO2_Td4)^YY!2YwH`>rihCD-uf8Rnz>N&i2GT(zb5g@iI&sag zQ2l<{3zd+Mib}=U;%RB$)mzHIyb0HDHk6mLTG)$QGpt}9a%|tc`A8^f`QW$ndaKz9 zYC@>GG@JRQQXF7>(*bi^CMUl8MuP3ftBd7|(<2v?5FA7hE{}d%^+(wt?@DpX1dU(v zKx1$K(1o*x-USA6Hr9L!Pb?=#VzYzwZMR+oI#!|JXZR8DF|5kg9 zyInd5R`6rU*j~VpiQPeJq9*w?H)_e1ifG?{7~^)m;3a0@S%+2eQoh9D_vm@;o`|p+ zwGM;$2!mOc`D4d(+X%Ibp%DWS%~(F6RUuDC4ZTT)dY!hhDhn^4lamWfR_c+h6PA&Z zp}8JC)NXX|Jw5d>5i@1vS9lPTE;k+-=|^h67hI4jD~`*00tdcpsy6hP*DT5A2@Hxx z`!Ek9L!UlSYdr#6TNuO4KUkv8!R|xogFzqlOP&mNWtlztX1w4u@tRN; zNYpR(B2gMMEeBPn(hTDn(W}Z8nW|2Or!f?MafbbKhkY3-kQIW{T>?-;+GNt2;jX}eYgS8dTK<*94=fK3W^*$3j55``Mf68Xe@yK zsTtba_DE2%H?TMD8T)3Bx_3{|K#yjY=mb(Wo>ad=sbIk8UT%?U9z{Bt@cq`%YFS|e006;?JZ(uj-QA={QH*5LmIEdTqTQ5Oyz_qv|Epmm%me^G$@_@HyN_ zGy1l&q{n=IBuBVCO&?%2Zuig~W2T*RTNo(H*1LH}QD>>N-hlermH1mf+Jg9F0Ae@U zC^pUN?pTq0ffU{rn@ah3EvSYnKw$q_`vRp}DKk2fL)`Iqn`)<>ayvN8_tClivq~)&Y;?e9*>|70$XwLuvGtBnJVD>Zd4B7kV?*Cjxh78bhSfyTiN13oX`}hQIH#u~nLz zBcFf+j#niM_@<2!uT9KW51z+lG?elRxG3k)G{@k&RCvTqO@2bowCMHP-=%z%58OUT zMS=ITHwh%y7V=DU?f2I%;T?Bdm9mu<@X?f5KJe0Fo^PMfaDr zT*}S+5M`^tnMO)KCPQ?qa@-HK{5<~qIrJ;cA5CqqW^zZdEwcTPdMpTW$hB{(G~U#i zO5j>?6u}&{ZP6DEU$Kmj=B0nV_~O&SSGT`lVdM<-m_4F8A=`Xu98xcQJ(U70D2@W%;#?6^u5_YuR^O~>eviBDC zG)bsxs=W2KNCFq21!?Kisn~~hT9)-a6g$=M7%BYX{zzfnwtTO9ox0SJ>G^*pUU&wu zP?iv@g?eFuR3YQ4!~pk*AHU-7c?{Lp1R6OqXC4d#CPR<0jKk{nMx)A)eLniUdvB~4 z8x{qahR~2rf7? zV8qgktmHK{!0>&gM1xIkDLxw_Z2GOM<;L&#sNa64lPLE@IX-mENkx7|9n#Y-f0+xl zAK%=4W`fH!)AEMNK;4-(lYSN`fZDOW)u;1jUN*DR9pjk9+InhD{-l;1V(*3&LmyuC z%F$fhY&^|4b)r%2{?yASs56+huoyhg-*|b%mlUN07)vaOze@5-Qy7$Fe@ovgyVaZ4@^j${j zU8fKZ0nhtM2uV$&L8V5=FW~dtGyfP`p)}*aRwlq zhGRYPpy4kIaMK;5WTL1WYyJFY1D{TT#wJhLH};mpHNuMy5%YkTw>X<9_%-h>tCtYp zw3G@d(9cv<$m5~1p8YOKR+FhmQeif?*E9zb2sXOmH%K6l*1?bM>`W=gYVa=arrr0g$<+J8#_Xo2+C4aOt$E3S2>s@Ds`y-bO_& zh=1=*S{vAm%PEX`?M8Af6!Y#lcd|>Ok*2lN)Tnc}!6Ewb6KJ;<+GWls2ifYDx8&M$ z@KOd&Uh(U=02vsJdK_3!j1M&GxHIJoZQL(t*&}AYLz-SBPC*@2T5NZNd++k38x_`!=13A`wzzGG; ze!qTVV(8)YS%KBx7RjzZG(KrwyHzPqaO&0u3EXLRTFCm4{PAsFnlQKb z@t=v~;-W)MofCMo&D=vrlif0!CP-NGBibK8Yss#$KrQ_<@Y;>#Nwsa1E1_beY?aF9 z+VYO*p?*5Nx~TGG*X~r0bAp63CxRZ(b5V#Fys13RrjCRmS;kI$#$zV;d|Z&&uT{8T z${8(CtMhaB6cdSaNw`bz-x)=oOyF5rS;;Q5PCwIl_Jkrq$t?qI?)vV#L{$}`VPwUr zTvC-A`>d|Y(y=9Ia*9jWNe$SJyrkZBxNSS;u`cf5MGIpb$tq9T*###fcQ-4%=XWV3 zTfAGd@PVB`$61gtiIAEumEo?>Px3r4xDjl+B5?#*N*{iMXimb_ zO!kGfQ)kpiulkWLACV>q%gs{W#(i3)_~&Y=&SAP$BL?L68OrsKagHusF~V{?FG2c0 zR+Jj=kKQS2S|yij(*-je7>8^lRS988>bhrCiv& zp?qc7)#sYEY|7CK1N4LW;{A^5#5IxTZp~n8t8Y;|k_+}?qk+xI;EA%{ExOXy%i_Z? zlA2#?8{B&j$ZCIIXspdi+wXYb3I3`SWaL-gLEBLxN7uP8Xx%nP0XmHBo;m7Ck9h0I zDxvmAX;}p0qcT*)2*h~4UyRYt_@^S{d%1Z5l7M*jqv=S|LyG0vVF2Q6Dp^S4e!1j~ zCbuk6)%Aa_CbyvPCmit`)`zX(oFx1lXQezYMveB0b zVaHOW{~ahhhpt-~UVHMwW->93l;OB&apeQkY!-jbP(7RpsI}JWA|9z0=LeP&I_&EZ zE`INqvW*7D(dJK}ogWNNdn%3h1%yCT0({dbtA5njt(UcpLUpgftB^N5uhsFBgma;q z*h+bEfi%d`mnD&RI$VH}0I6&h`@CCx>hmxQJMArTy_UUqq(#Obn`#ujiXuM7p^FG;rk>Q*nHOM z^SWl~I%5jGMZPJ!bGXw^Fgw_XxkBM*@LwwuZydE_XV_NmJEdbqJ3?xP!dRH zOa(sAncfs1vKLw06wq|b2ny2;DW8~N0p2p=idEft%6AJe=kj%JmK>i|qjVXgA@W`{ z!%NskC^-|E*7j`Tly~;$b_dy#$K01%RZ8bGPh%OctmzKs+{v>`);8RB2QCmf&g9oB zjVILmYkLk4_uj5P9D)}Mi;zj}xG6nC&M%iBsZMSnQ2F=~^bJz7I^V@3+CHR9W&g#Q zPiN`Ok$Yop2?=-BRM-Zj@Sf??|GY<*RyB8c)w|@_Y<$6a4^_!+3DTp$BKeFu{#%!F zDFABls!J)(%W@!h>h-s=dIo9zCJ@E{`wam9O6{+1v_h7Mm3>@TCrK>KG+2jJwyYL( zvP2M@+|QgCLBwE!qVzAzRLT@d!gEW2{MxFcfOn^9e}C>MkJkf81PPRtkx6Z)+2rbs zhpsyTvarufch`DetCe*%mo}*632wt>_O%S_m2}UtPU6w$3Z&?E=&IVQri7*du)%Ar2e?$;UV$P|9?;9Frk;XjM z7U*bKZ@2W8v|(3W)nA*;6XNCnJCLv=n*N_a0v(9_l{_c7HhBC361?L>G;vplk=C1H z_+_odjt_9Wqo%A_tBPywU3}TXspkgHrFfMR#V#Z2Uk?LtLC#677$j$;Lx9;+ArO6I z1?E1m6W~@O{cvmkWqntzEuL@2Ndj@Z`>Q&hYw@$htkj=)0nog36;cvH*|d_m$7@(` z{WIf89lzZaHvY^v9Z}M+iKd?bU#i0T+^Yy^$5cuJxjd;$9!uZCs3E_K;5id&`wt|l z6Oepw;PYmWli(+LHq)~J4(It-qR^5ho5`Idnd4?Bewd5xwY!h zDo<6ob5v}Q2>$f9R|vyn$(8e)v6Rzb6h}tjm3hoqr;Wila{APQ;w@xKwxD4QDRp&T z*~6*!K_f}2Pr$FpJaVd-Ag z8ud#>!gT8Qb4^c=#6Xgzj`Kw=bK~FpXh;Wmp_pMpi5a(6xbnBhu7Ucnp-Ub{=$7X# zuw?a&O_(z@rmmzT+^Dd`wxdbb!5_Clxea-m`p~{o>UBqR-gcJv>6Gy_Y+Z3}k@%Ae z69V5ze6i;IP8-`p{bI!vZ1z4teYBl7K#ng>`9Hb&?G%o7xnWeUp?pW=Lb&qe%3o&T zIBQsaxKG_8;|>r#z5z=aH%R71S4)Y^c^Q>ZxSa0XxjE-x^6;|7TyU_+XxguzGXbp( z_nVm??t2+Q#l%jhjHRACmd#H~d6Dv3xvByPd+zK8ogDiUFHLl>7;J`VinGNhCWDU< zMyVravlri;%lJg!9*J$7{94X_c``3n_~Hxkml!NAudLItT|L4{dTrc2=zlHf`R&`; z=~i0#Q+M3BaeeB98NZxwNN-*Z>>*w1ocwat8@E-VrGYmuOX^!ad;8mL_EO2cSq6J+ zmi$u*+-SIeNAlb^XO3)6{!;w&>)lrIjQEKAYO=jLXE_#p0!_{CxX}ceUwrWCbNI~4 z{qw75Cx5yT5q^>1?1k;&uuj4%D?e^?!UQ0&mzvkCgtt=zZF$eb4sVD zeaQ(f-czGfbAIdd?|dhsN;f`{->fV=)m&F`#`D+0w#$^xzTWRR_xelc*5{=w%r#B- zUEpWX;=BqP1wRU$cm25P?5UgP>``oVhq3ZhHNu#8h|l)KAkIuRJeuncE$=_2g`E2S4B>U%ePNxo>&B=4i>E#8_GZuAy1#6Pe|zH2e{)~WSZ?1@@p7Rm=|lEWmv!i znlJ}8LH;~CQuR7QcH7GdIu>c+yQ1##-K_Y!V0ZeA{rmOy-oF|syQ}2UJD)8Hz8QO; z-w4@Wd)_csDW7{AuqbeM`W6G8IlMaax69?y))5Pvy>XF<0{8s1JYu~$p zCH9hairfFT*Tp@S4g9%P|IBaj{NEc!PI8-d7I0!~>#DP6Y0g%EEKc8kle}$J@wTtmFP&{YpKcTUqk6aJ zU!SJG3=1Z0xng#@Zx!RsNK+2rT(*o3PCEXj zwO4-Cb(-CjJpJzfQ~AaA9EKD5D*IO&>v5iL-;{kd`LXQPYrsjg85s$!ifgxODhlU* zGyF9t_iBQ7w9uxtckR+9O9hKc7+;zfu-65Seq@7;eOZN1#3u6aY14AaRa=>Ve5H ztf&YgY70~sUgClCMEfrw zbDm1VZ3y_d!h{*7&fzF9!67)wm2NN&Lx>G9wZlNbN8nsA3FVdQ&MBb@06>wz$p8QV literal 0 HcmV?d00001 diff --git a/decoders/keeloq/keeloq2_pv.png b/decoders/keeloq/keeloq2_pv.png new file mode 100755 index 0000000000000000000000000000000000000000..dfbc1c3a108a84095f3ce0fd04c4e7de2c89af2c GIT binary patch literal 30098 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 Q7Ob6Db)Z*@F4^7tAO8jIFaQ7m literal 0 HcmV?d00001 diff --git a/decoders/keeloq/pd.py b/decoders/keeloq/pd.py new file mode 100755 index 00000000..a3fed414 --- /dev/null +++ b/decoders/keeloq/pd.py @@ -0,0 +1,266 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2024 Andrea Orazi +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see . +## + +import sigrokdecode as srd + +class Ann: + TE, LOGICAL_BIT, CODE_WORD, ENCRYP_DATA, FIXED_DATA = range(5) + +class Decoder(srd.Decoder): + api_version = 3 + id = 'keyloq' + name = 'KeyLoq' + longname = 'KeeLoq CodeWord Decoder' + desc = 'Keeloq CodeWord Decoder for Pulseview' + license = 'gplv2+' + inputs = ['logic'] + outputs = [] + tags = ['Security/crypto'] + channels = ( + {'id': 'pwm', 'name': 'PWM', 'desc': 'Code Word Channel'}, + ) + options = ( + + ) + + annotations = ( + ('te', 'TE'), + ('logical_bit', 'Logical Bit'), + ('Code_Word', 'Code Word'), + ('encryp_data', 'Encrypted Data'), + ('fixed_data', 'Fixed Data'), + ) + annotation_rows = ( + ('bits', 'Bits', (Ann.TE,Ann.LOGICAL_BIT)), + ('code word', 'Code Word', (Ann.CODE_WORD, )), + ('data', 'Data', (Ann.ENCRYP_DATA, Ann.FIXED_DATA )), + ) + + def __init__(self): + self.reset() + + def reset(self): + self.samplerate = None + self.TEcnt = 0 #TE counter + self.Block_Init = 0 #Flag for each block of info + #TE Timing - According to documentation a TE is typically 400 usecs + #[0][1] - TE/Logical Bit 1 | [2][3] - Logical Bit 0 | [4][5] - Header Lenght + self.TE_Timing = [ 300e-6, 500e-6, 700e-6, 1000e-6, 3e-3, 6e-3 ] + self.ssBlock = 0 #Sample number of a block of intormation + self.Header_Completed = 0 #[ 0 = Not Complete 1 = Complete] + self.n = 0 # Current Sample number + self.prevN = 0 # Previous sample number + self.Bitcnt = 0 # Bit counter in Data Portion + self.trig_cond = '' #Wait - trigger condition + self.BitString = '' # A string of Logical Bit Code Word + self.KeyLoq = { "Encrypted" : "", "Serial-Number" : "", "S3" : "", "S0" : "", "S1" : "", "S2" : "", + "V-Low" : "", "RPT" : ""} #KeyLoq Code Word + + def start(self): + self.out_ann = self.register(srd.OUTPUT_ANN) + + def metadata(self, key, value): + if key == srd.SRD_CONF_SAMPLERATE: + self.samplerate = value + + #Define the beginning of each useful block of information saving the Sample Number + def Start_Block(self): + if (self.Block_Init == 0): + self.Block_Init = 1 + self.ssBlock = self.prevN + + #Shows Preable + Header + def Decode_Preable(self,t): + #According to documentation a TE is typically 400 usecs + if ((t >= self.TE_Timing[0] and t <= self.TE_Timing[1] )): + if (self.TEcnt < 23): + self.put(self.prevN, self.samplenum, self.out_ann, [Ann.TE, [str(self.TEcnt)]]) + self.Start_Block() + + #Shows Preamble + elif (self.TEcnt == 23): + self.put(self.ssBlock, self.n, self.out_ann, [Ann.CODE_WORD, ['Preamble']]) + self.put(self.prevN, self.samplenum, self.out_ann, [0, [str(self.TEcnt)]]) + + # We have reached the last Rising Edge on TEcnt == 24 + # This is not technically a TE . It is actually a period of 10 TEs known as Header + # Header has usually a lenth of 3-6 msec + elif ( (t >= self.TE_Timing[4] and t <= self.TE_Timing[5] ) and (self.TEcnt == 24 ) ): + self.put(self.prevN, self.n, self.out_ann, [Ann.CODE_WORD, ['Header']]) + self.TEcnt = 0 + self.Block_Init = 0 + self.Header_Completed = 1 #Is 1 when the decoder successfully reached the end of Preable + Header + + else: #Reset Counters because this is not a TE + self.TEcnt = 0 + self.Block_Init = 0 + + #In Data Portion bits are encoded using PWM technique + def Decode_LogicalBit(self,t): + # Logic Bit 0 = 2 TE at High Level + 1 TE at low level >> Tipically 800 usec (H) + 400 usec (L) << + # Logic Bit 1 = 1 TE at High Level + 2 TE at Low Level >> Tipically 400 usec (H) + 800 usec (L) << + # Thus, To recognise a logical bit we have to read two subsequent Edges (or HalfBits) + + LogicalBit = '' #Either '0' or '1' encoded using PWM + Valid_Bit = 0 + + #Check timing validity first + if (( t >= self.TE_Timing[0] and t <= self.TE_Timing[1] ) or (t >= self.TE_Timing[2] and t <= self.TE_Timing[3] ) ): + Valid_Bit = 1 + + #Having got the next edge pointer n = first half of the Logical bit + if (Valid_Bit): + self.Start_Block() + + #Gets the the next second half of the Logical bit to fully decode it + if (self.Bitcnt == 65): #Last bit needs special care as definitely there is no valid edge nearby + self.n = self.samplenum + 8 #Arbitrary value after last sample# to complete this Logical Bit + else: + self.wait(self.trig_cond) + self.n = self.samplenum + + #After time validity, it check wether it is '1' or '0' + if ( t >= self.TE_Timing[0] and t <= self.TE_Timing[1] ) : + LogicalBit = '1' + else: + LogicalBit = '0' + + self.put(self.prevN, self.n, self.out_ann, [Ann.LOGICAL_BIT, ['Bit ' + LogicalBit ]]) + return (LogicalBit) + + else : #In case of Invalid bit, Reset all counters and conditions + self.put(self.prevN, self.n, self.out_ann, [Ann.LOGICAL_BIT, ['>>> Invalid Bit <<< ' + LogicalBit ]]) + self.Reset_DP_Cnts() + self.Header_Completed = 0 + self.Bitcnt = -1 #Will be set to 0 in the Main Cycle + return("0") + + + #Reset Data Portion counters at the end of each decoded block + def Reset_DP_Cnts(self): + self.Block_Init = 0 + self.BitString ='' + + #Convert a Binary string into the equivalent value in Hex 0x in string format + def Bin2Hex (self): + decimal_value = int(self.BitString, 2) + # Convert integer to hexadecimal + hex_value = hex(decimal_value) + return ( hex_value.upper() ) + + #Decode all Logical PWM Bit from 0 to 65 completing the CodeWord + def Decode_DataPortion(self, t): + # Bits 0-31 : Encrypted Portion. It comes from the algorithm. + if (self.Bitcnt <= 31 ): + self.BitString = self.BitString + self.Decode_LogicalBit(t) + + if (self.Bitcnt == 31): + self.put(self.ssBlock, self.n, self.out_ann, [Ann.CODE_WORD, ['Encrypted Portion']]) + self.KeyLoq["Encrypted"] = self.Bin2Hex () + self.put(self.ssBlock, self.n, self.out_ann, [Ann.ENCRYP_DATA, [ self.KeyLoq["Encrypted"] ]]) + self.Reset_DP_Cnts() + + # Here begins the cleartext portion known as Fixed Portion + # it is made by Serial Number + Button Code + Status (V-Low + Repeat\) + elif (self.Bitcnt >= 32 and self.Bitcnt <= 59 ): # Bits 32-59 : Serial Number + self.BitString = self.BitString + self.Decode_LogicalBit(t) + + if (self.Bitcnt == 59): + self.put(self.ssBlock, self.n, self.out_ann, [Ann.CODE_WORD, ['Serial Number']]) + self.KeyLoq["Serial-Number"] = self.Bin2Hex () + self.put(self.ssBlock, self.n, self.out_ann, [Ann.FIXED_DATA, [ self.KeyLoq["Serial-Number"] ]]) + self.Reset_DP_Cnts() + + elif (self.Bitcnt >= 60 and self.Bitcnt <= 63 ): # Bits 60-63 : Button Code + LogicalBit = self.Decode_LogicalBit(t) + + if ( self.Bitcnt == 60 ): + self.KeyLoq["S3"] = LogicalBit + self.put(self.prevN, self.n, self.out_ann, [Ann.FIXED_DATA, [ 'S3 = ' + self.KeyLoq["S3"] ]]) + elif ( self.Bitcnt == 61 ): + self.KeyLoq["S0"] = LogicalBit + self.put(self.prevN, self.n, self.out_ann, [Ann.FIXED_DATA, [ 'S0 = ' + self.KeyLoq["S0"] ]]) + elif ( self.Bitcnt == 62 ): + self.KeyLoq["S1"] = LogicalBit + self.put(self.prevN, self.n, self.out_ann, [Ann.FIXED_DATA, [ 'S1 = ' + self.KeyLoq["S1"] ]]) + elif (self.Bitcnt == 63): + self.KeyLoq["S2"] = LogicalBit + self.put(self.ssBlock, self.n, self.out_ann, [Ann.CODE_WORD, ['Button Code']]) + self.put(self.prevN, self.n, self.out_ann, [Ann.FIXED_DATA, [ 'S2 = ' + self.KeyLoq["S2"] ]]) + self.Reset_DP_Cnts() + + #Status + elif (self.Bitcnt == 64 ): # Bits 64 : V-Low + LogicalBit = self.Decode_LogicalBit(t) + + self.put(self.ssBlock, self.n, self.out_ann, [Ann.CODE_WORD, ['V-Low']]) + if (LogicalBit == '0'): + self.KeyLoq["V-Low"] = "Battery High" + else: + self.KeyLoq["V-Low"] = "Battery Low" + + self.put(self.prevN, self.n, self.out_ann, [Ann.FIXED_DATA, [ self.KeyLoq["V-Low"] ]]) + self.Reset_DP_Cnts() + + elif (self.Bitcnt == 65 ): # Bits 65 : Repeat + LogicalBit = self.Decode_LogicalBit(t) + + self.put(self.ssBlock, self.n, self.out_ann, [Ann.CODE_WORD, ['RPT']]) + if (LogicalBit == '0'): + self.KeyLoq["RPT"] = "No" + else: + self.KeyLoq["RPT"] = "Yes" + + self.put(self.prevN, self.n, self.out_ann, [Ann.FIXED_DATA, [ self.KeyLoq["RPT"] ]]) + self.Reset_DP_Cnts() + self.Header_Completed = 0 #Looks for another new CodeWord + self.Bitcnt = -1 #To start from 0 in the Main - decode() it needs to be negative + + # Main Loop + def decode(self): + if self.samplerate is None: + raise Exception('Cannot decode without samplerate.') + + t = 0 #Time between two edges + + #Each CodeWord begins with a Rising Edge. + self.trig_cond = [{0: 'r'}] # Go and look for it + self.wait(self.trig_cond) + self.prevN = self.samplenum + + self.trig_cond = [{0: 'e'}] # Go to the next Edge + + while True: + + self.wait(self.trig_cond) + self.n = self.samplenum + + #Get time (usec) between the current and the previous sample + t = (self.n - self.prevN) / self.samplerate + + #CodeWord decoding subfunctions + if (self.Header_Completed == 0): + self.TEcnt += 1 + self.Decode_Preable(t) + else: + self.Decode_DataPortion (t) + self.Bitcnt += 1 + + #Ready for the next cycle + self.prevN = self.samplenum From 8c5fccf584b7d54bbc00620adcacb538b89dd91a Mon Sep 17 00:00:00 2001 From: Andrea Date: Mon, 30 Sep 2024 08:10:03 +0200 Subject: [PATCH 2/2] keeloq: Release 0.2 --- decoders/keeloq/README.md | 15 +++++++++++++-- decoders/keeloq/pd.py | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/decoders/keeloq/README.md b/decoders/keeloq/README.md index 2bc28afb..44cd449a 100755 --- a/decoders/keeloq/README.md +++ b/decoders/keeloq/README.md @@ -34,6 +34,8 @@ Each transmission is organized in a logical structure named _'Code Word'_ descri +-------------------+---------------*----+----+----+----+-------+-----+ | S3 | S0 | S1 | S2 | V-Low | RPT | *----+----+----+----+-------+-----+ + LSB MSB +Please note that **LSB** is transmitted **first** . This means that Encrypted Portion is sent out before any other parts. + **Encrypted Portion** : This data changes everytime a button is pressed according to the encryption algorithm. + **Serial Number** : Unique value present in each encoder. @@ -41,6 +43,7 @@ Each transmission is organized in a logical structure named _'Code Word'_ descri + **V-Low** : Indicates encoder battery voltage : High/Low. + **RPT** : Reports if the button is kept pressed. + *** ## What this decoder does: @@ -73,8 +76,9 @@ Depending of your Operating System create a new directory named keeloq Please note that it is present also a sample file named **hcs300_sample.sr** for your convenience. ## Tested Integrated circuits -At the writing time the only IC tested with this software is +At the writing time here the ICs succesfully tested with this decorder - **HCS300** [Datasheet](https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/21137G.pdf) +- **HCS301** [Datasheet](https://ww1.microchip.com/downloads/en/devicedoc/21143b.pdf) Looking forward to seeing this list longer. @@ -86,5 +90,12 @@ If you want to contribute to this, please send an email to : Att'achment : A PulseView sample containing a good number of _Code Words_ in **.sr** format. *** # Change Log: -- Version 0.1 : +- Version 0.2 - [29th September 2024] + * TEs timing review + * Bug-Fix regarding LSB-MSB interpretation for the Encrypted Portion and Fixed Part + * Minor code changes + * IC: HCS301 Succesfully tested (Contribution Tobias Rothfelder) + +- Version 0.1 - [09th May 2024]: * Recognise a sequence of _Code Words_ genederated by an econder and shows their content in human readble format. + * IC: HCS300 Succesfully tested diff --git a/decoders/keeloq/pd.py b/decoders/keeloq/pd.py index a3fed414..b6b6c7e2 100755 --- a/decoders/keeloq/pd.py +++ b/decoders/keeloq/pd.py @@ -17,6 +17,7 @@ ## along with this program; if not, see . ## + import sigrokdecode as srd class Ann: @@ -61,7 +62,7 @@ def reset(self): self.Block_Init = 0 #Flag for each block of info #TE Timing - According to documentation a TE is typically 400 usecs #[0][1] - TE/Logical Bit 1 | [2][3] - Logical Bit 0 | [4][5] - Header Lenght - self.TE_Timing = [ 300e-6, 500e-6, 700e-6, 1000e-6, 3e-3, 6e-3 ] + self.TE_Timing = [ 280e-6, 580e-6, 700e-6, 1000e-6, 3e-3, 6e-3 ] self.ssBlock = 0 #Sample number of a block of intormation self.Header_Completed = 0 #[ 0 = Not Complete 1 = Complete] self.n = 0 # Current Sample number @@ -160,15 +161,21 @@ def Reset_DP_Cnts(self): #Convert a Binary string into the equivalent value in Hex 0x in string format def Bin2Hex (self): decimal_value = int(self.BitString, 2) - # Convert integer to hexadecimal - hex_value = hex(decimal_value) - return ( hex_value.upper() ) + # Convert integer to hexadecimal with leading zeroes + hex_value = "0x{0:0{1}X}".format(decimal_value,7) + return ( hex_value ) #Decode all Logical PWM Bit from 0 to 65 completing the CodeWord def Decode_DataPortion(self, t): # Bits 0-31 : Encrypted Portion. It comes from the algorithm. if (self.Bitcnt <= 31 ): - self.BitString = self.BitString + self.Decode_LogicalBit(t) + # According to the documentation LSB is transmitted first. + # However, decoding a bit string to Hex, requires that LSB must be the last bit in the string sequence + # to preserve bit significance. + # That's why --self.BitString-- is appended always as LSB, whereas the last transmitted bit + # is considered as MSB. This ensures the right interpretation and conversion to Hex + # for both Encrypted and Fixed portion + self.BitString = self.Decode_LogicalBit(t) + self.BitString if (self.Bitcnt == 31): self.put(self.ssBlock, self.n, self.out_ann, [Ann.CODE_WORD, ['Encrypted Portion']]) @@ -179,7 +186,7 @@ def Decode_DataPortion(self, t): # Here begins the cleartext portion known as Fixed Portion # it is made by Serial Number + Button Code + Status (V-Low + Repeat\) elif (self.Bitcnt >= 32 and self.Bitcnt <= 59 ): # Bits 32-59 : Serial Number - self.BitString = self.BitString + self.Decode_LogicalBit(t) + self.BitString = self.Decode_LogicalBit(t) + self.BitString if (self.Bitcnt == 59): self.put(self.ssBlock, self.n, self.out_ann, [Ann.CODE_WORD, ['Serial Number']])