From c29b8b1cfbb379419469a8827354b4d926a97395 Mon Sep 17 00:00:00 2001 From: Stephen Kapp Date: Thu, 22 Apr 2010 08:52:17 +0100 Subject: [PATCH] Initial 1.03 Import --- demo/mdemo.c | 0 demo/randemo.c | 0 demo/redemo.c | 0 docs/asm.inf | 0 docs/bugs.txt | 16 +- docs/history | 72 +- docs/licence.txt | 13 +- docs/redemo.ps | Bin 86870 -> 85269 bytes docs/redemo.txt | 0 docs/rsaedoc.doc | Bin 0 -> 677188 bytes docs/rsaedoc.htm | 3191 ++++++++++++++++++++++++++++++++++++ docs/rsaedoc.ps | Bin 0 -> 718764 bytes docs/rsaeuro.asc | 0 docs/rsaeuro.ps | Bin 266231 -> 0 bytes docs/rsaread.me | 38 +- docs/scripts.ps | Bin 84006 -> 82689 bytes docs/scripts.txt | 0 docs/todo | 2 +- install/msdos/makefile.bcc | 188 +-- install/msdos/makefile.wat | 152 ++ install/readme.txt | 13 + install/unix/makefile | 0 install/win32/makefile.wat | 152 ++ readme | 36 +- scripts/1024-1.env | 0 scripts/1024-1.iv | 0 scripts/1024-1.key | 0 scripts/1024-5.sig | Bin scripts/1024.in | 0 scripts/1024.key | Bin scripts/508-1.env | 0 scripts/508-1.iv | 0 scripts/508-1.key | Bin scripts/508-5.sig | 0 scripts/508.in | 0 scripts/508.key | Bin scripts/512a.in | 0 scripts/512a1.env | 0 scripts/512a1.iv | 0 scripts/512a1.key | 0 scripts/512a1big.env | Bin scripts/512a1big.iv | 0 scripts/512a1big.key | 0 scripts/512a2.env | 0 scripts/512a2.iv | 0 scripts/512a2.key | 0 scripts/512a2.sig | 0 scripts/512a3.env | 0 scripts/512a3.iv | 0 scripts/512a3.key | 0 scripts/512a5.sig | 0 scripts/512a5big.sig | Bin scripts/512ax.env | 0 scripts/512ax.iv | 0 scripts/512ax.key | 0 scripts/767-1.env | 0 scripts/767-1.iv | 0 scripts/767-1.key | 0 scripts/767-5.sig | Bin scripts/767.in | 0 scripts/767.key | Bin scripts/bigfile | 194 +-- scripts/file | 2 +- source/des.h | 12 +- source/des386.s | 4 +- source/desc.c | 1594 +++++++++--------- source/global.h | 12 +- source/md2.h | 2 +- source/md2c.c | 2 +- source/md4.h | 2 +- source/md4c.c | 2 +- source/md5.h | 2 +- source/md5c.c | 4 +- source/nn.c | 1367 +++++++-------- source/nn.h | 14 +- source/prime.c | 570 +++---- source/prime.h | 14 +- source/r_dh.c | 5 +- source/r_encode.c | 438 ++--- source/r_enhanc.c | 1861 ++++++++++----------- source/r_keygen.c | 2 +- source/r_random.c | 444 ++--- source/r_random.h | 14 +- source/r_stdlib.c | 8 +- source/rsa.c | 720 ++++---- source/rsa.h | 14 +- source/rsa386.s | 4 +- source/rsa68k.s | 4 +- source/rsaeuro.h | 622 +++---- source/rsaref.h | 16 +- source/rsasparc.s | 4 +- source/shs.h | 20 +- source/shsc.c | 51 +- source/targets.mak | 0 94 files changed, 7716 insertions(+), 4181 deletions(-) mode change 100755 => 100644 demo/mdemo.c mode change 100755 => 100644 demo/randemo.c mode change 100755 => 100644 demo/redemo.c mode change 100755 => 100644 docs/asm.inf mode change 100755 => 100644 docs/bugs.txt mode change 100755 => 100644 docs/history mode change 100755 => 100644 docs/licence.txt mode change 100755 => 100644 docs/redemo.ps mode change 100755 => 100644 docs/redemo.txt create mode 100644 docs/rsaedoc.doc create mode 100644 docs/rsaedoc.htm create mode 100644 docs/rsaedoc.ps mode change 100755 => 100644 docs/rsaeuro.asc delete mode 100755 docs/rsaeuro.ps mode change 100755 => 100644 docs/rsaread.me mode change 100755 => 100644 docs/scripts.ps mode change 100755 => 100644 docs/scripts.txt mode change 100755 => 100644 docs/todo mode change 100755 => 100644 install/msdos/makefile.bcc create mode 100644 install/msdos/makefile.wat create mode 100644 install/readme.txt mode change 100755 => 100644 install/unix/makefile create mode 100644 install/win32/makefile.wat mode change 100755 => 100644 readme mode change 100755 => 100644 scripts/1024-1.env mode change 100755 => 100644 scripts/1024-1.iv mode change 100755 => 100644 scripts/1024-1.key mode change 100755 => 100644 scripts/1024-5.sig mode change 100755 => 100644 scripts/1024.in mode change 100755 => 100644 scripts/1024.key mode change 100755 => 100644 scripts/508-1.env mode change 100755 => 100644 scripts/508-1.iv mode change 100755 => 100644 scripts/508-1.key mode change 100755 => 100644 scripts/508-5.sig mode change 100755 => 100644 scripts/508.in mode change 100755 => 100644 scripts/508.key mode change 100755 => 100644 scripts/512a.in mode change 100755 => 100644 scripts/512a1.env mode change 100755 => 100644 scripts/512a1.iv mode change 100755 => 100644 scripts/512a1.key mode change 100755 => 100644 scripts/512a1big.env mode change 100755 => 100644 scripts/512a1big.iv mode change 100755 => 100644 scripts/512a1big.key mode change 100755 => 100644 scripts/512a2.env mode change 100755 => 100644 scripts/512a2.iv mode change 100755 => 100644 scripts/512a2.key mode change 100755 => 100644 scripts/512a2.sig mode change 100755 => 100644 scripts/512a3.env mode change 100755 => 100644 scripts/512a3.iv mode change 100755 => 100644 scripts/512a3.key mode change 100755 => 100644 scripts/512a5.sig mode change 100755 => 100644 scripts/512a5big.sig mode change 100755 => 100644 scripts/512ax.env mode change 100755 => 100644 scripts/512ax.iv mode change 100755 => 100644 scripts/512ax.key mode change 100755 => 100644 scripts/767-1.env mode change 100755 => 100644 scripts/767-1.iv mode change 100755 => 100644 scripts/767-1.key mode change 100755 => 100644 scripts/767-5.sig mode change 100755 => 100644 scripts/767.in mode change 100755 => 100644 scripts/767.key mode change 100755 => 100644 scripts/bigfile mode change 100755 => 100644 scripts/file mode change 100755 => 100644 source/des.h mode change 100755 => 100644 source/des386.s mode change 100755 => 100644 source/desc.c mode change 100755 => 100644 source/global.h mode change 100755 => 100644 source/md2.h mode change 100755 => 100644 source/md2c.c mode change 100755 => 100644 source/md4.h mode change 100755 => 100644 source/md4c.c mode change 100755 => 100644 source/md5.h mode change 100755 => 100644 source/md5c.c mode change 100755 => 100644 source/nn.c mode change 100755 => 100644 source/nn.h mode change 100755 => 100644 source/prime.c mode change 100755 => 100644 source/prime.h mode change 100755 => 100644 source/r_dh.c mode change 100755 => 100644 source/r_encode.c mode change 100755 => 100644 source/r_enhanc.c mode change 100755 => 100644 source/r_keygen.c mode change 100755 => 100644 source/r_random.c mode change 100755 => 100644 source/r_random.h mode change 100755 => 100644 source/r_stdlib.c mode change 100755 => 100644 source/rsa.c mode change 100755 => 100644 source/rsa.h mode change 100755 => 100644 source/rsa386.s mode change 100755 => 100644 source/rsa68k.s mode change 100755 => 100644 source/rsaeuro.h mode change 100755 => 100644 source/rsaref.h mode change 100755 => 100644 source/rsasparc.s mode change 100755 => 100644 source/shs.h mode change 100755 => 100644 source/shsc.c mode change 100755 => 100644 source/targets.mak diff --git a/demo/mdemo.c b/demo/mdemo.c old mode 100755 new mode 100644 diff --git a/demo/randemo.c b/demo/randemo.c old mode 100755 new mode 100644 diff --git a/demo/redemo.c b/demo/redemo.c old mode 100755 new mode 100644 diff --git a/docs/asm.inf b/docs/asm.inf old mode 100755 new mode 100644 diff --git a/docs/bugs.txt b/docs/bugs.txt old mode 100755 new mode 100644 index 077799d..78bc979 --- a/docs/bugs.txt +++ b/docs/bugs.txt @@ -2,13 +2,13 @@ Version 1.0 -This is the RSAEURO Beta testers bug report form, please complete -this if during your use you encounter a problem. Once complete -please either e-mail or post a copy to me. This can also be used -for comments and suggestions. +This is the RSAEURO report form, please complete this if during +your use you encounter a problem. Once complete please either +e-mail or post a copy to me. This can also be used for comments +and suggestions. -You may also contact me by telephone but only after 7pm weekdays -or anytime weekends, on +44 (1200) 448241 and ask for Stephen. +You may also contact me by telephone on +44 (468) 286034 weekdays +or weekends, on +44 (1200) 448241 and ask for Stephen. Bug Report: @@ -64,5 +64,5 @@ Details:- Please write "RSAEURO BUGS" in top left of envelope. - 3. Phone: +44 (1200) 448241 - After 7pm Weekdays, Anytime Weekends. \ No newline at end of file + 3. Phone: +44 (468) 286034 Daytime during weekdays. + +44 (1200) 448241 After 7pm Weekdays, Anytime Weekends. diff --git a/docs/history b/docs/history old mode 100755 new mode 100644 index d2cd84f..c57ac22 --- a/docs/history +++ b/docs/history @@ -1,36 +1,36 @@ -Revision History of RSAEURO - -0.90 - July 1994. - First Alpha Versions, most functions implemented. - -0.91 - Sept. 1994. - Bulk of Code complete, Math functions partly complete. - -0.92 - Oct. 1994. - Some assembler support added for Intel x86 processors. - Math routines problems on PC and Sun SPARC. - -0.93 - Feb. 1995. - Math routines complete, 680x0 assembler support added. - In house testing started. - -0.93 - April 1995. - Goes to Beta.. - -1.00 - June 1995. - Fixed Documentation and produced distribution for release. - RSAEURO Released. - -1.01 - August 1995. - Documentation updated with new rsaeuro e-mail addresses. - Random Objects code for R_RandomCreate and R_RandomMix - modified. - -1.02 - October 1995. - Fixed a number of minor bugs and fixed problem with Math - library caused it not to work that well with 16-bit - compilers. - ----- -J.S.Kapp - Sun 08/10/95 15:51:35 - +Revision History of RSAEURO + +0.90 - July 1994. + First Alpha Versions, most functions implemented. + +0.91 - Sept. 1994. + Bulk of Code complete, Math functions partly complete. + +0.92 - Oct. 1994. + Some assembler support added for Intel x86 processors. + Math routines problems on PC and Sun SPARC. + +0.93 - Feb. 1995. + Math routines complete, 680x0 assembler support added. + In house testing started. + +0.93 - April 1995. + Goes to Beta.. + +1.00 - June 1995. + Fixed Documentation and produced distribution for release. + RSAEURO Released. + +1.01 - August 1995. + Documentation updated with new rsaeuro e-mail addresses. + Random Objects code for R_RandomCreate and R_RandomMix + modified. + +1.02 - October 1995. + Fixed a number of minor bugs and fixed problem with Math + library caused it not to work that well with 16-bit + compilers. + +---- +J.S.Kapp - Sun 08/10/95 15:51:35 + diff --git a/docs/licence.txt b/docs/licence.txt old mode 100755 new mode 100644 index b0f0dd7..c20cfdd --- a/docs/licence.txt +++ b/docs/licence.txt @@ -1,8 +1,8 @@ - RSAEURO - TOOLKIT LICENSE AGREEMENT - June 23rd, 1995. + RSAEURO + TOOLKIT LICENSE AGREEMENT + 17th April 1996. - Copyright (c) J.S.A.Kapp, 1994-1995. + Copyright (c) J.S.A.Kapp, 1994-1996. 1. LICENSE. J.S.A.Kapp grants you a nonexclusive, non-transferable, perpetual (subject to the conditions of section 7) license for the @@ -82,8 +82,8 @@ on distribution media, is co-located or stored with the Toolkit. developed with RSAEURO may be subject to export controls in some countries. If you are located in the United States and develop such applications using RSAEURO, you are advised to obtain a copy of RSAREF - from RSADSI, as you may using RSAEURO infringe on Patents held by - Public Key Partners of Sunnydale California. + from RSADSI, as you may using RSAEURO infringe on Patents held by RSA + Data Security and Cylink. 7. The license granted hereunder is effective until terminated. You may terminate it at anytime by destroying all components of the Toolkit and @@ -106,6 +106,7 @@ on distribution media, is co-located or stored with the Toolkit. BB7 3BB. Tel. (+44) 1200-448241 + Tel. (+44) 468-286034 ii. For details of Export Controls and other controls regarding the use of cryptographic techniques please contact your country's diff --git a/docs/redemo.ps b/docs/redemo.ps old mode 100755 new mode 100644 index c3ba7f871da6dabdc6a0d6794e22f67a63a666b1..b153b49b8a07eb0bbbfd3edd0adb572df6adda8d GIT binary patch delta 17185 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 delta 19323 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 z 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
  • p#?ea&G+}we=sZ`)2WV zHtk-KCoPo1f}~Pw*2U5@wzdl+wc#8r41 +RSAEURO Version 1.03 Documentation + +
    +

    RSAEURO

    +
    Version 1.03
    +
    +
      +
    1. INTRODUCTION
    2. +
    3. RANDOM NUMBERS
    4. +
    5. MESSAGE DIGESTS
    6. +
    7. DIGITAL SIGNATURE ROUTINES
    8. +
    9. ENVELOPE PROCESSING
    10. +
    11. PEM FUNCTIONS
    12. +
    13. KEY GENERATION AND EXCHANGE
    14. +
    15. RSA
    16. +
    17. DES
    18. +
    19. NATURAL NUMBER ARITHMETIC
    20. +
    21. MEMORY MANIPULATION
    22. +
    23. TECHNICAL INFORMATION
    24. +
    25. APPENDIX A: FUNCTION CROSS-REFERENCE
    +

    + + +

    +
    +

    +INTRODUCTION

    +
      +
    1. What is RSAEURO? +
    2. +
    3. What is covered by this document? +
    4. +
    5. Contact information +
    6. +
    7. Typographic conventions +
    8. +
    9. Licence +
    10. +
    11. Patents and trademarks
        +
      1. RSADSI +
      2. +
      3. Cylink
      4. +
    12. +
    13. Release history
        +
      1. Release 1.00 +
      2. +
      3. Release 1.01 +
      4. +
      5. Release 1.02 +
      6. +
      7. Release 1.03
    14. +
    +

    +What is RSAEURO? +

    +

    RSAEURO is a cryptographic toolkit providing various functions for the use +of digital signatures, data encryption and supporting areas (PEM encoding, +random number generation etc). To aid compatibility with existing +software, RSAEURO is call-compatible with RSADSI's "RSAREF" toolkit. +RSAEURO allows non-US residents to make use of much of the cryptographic +software previously only (legally) available in the US. +

    +
    +

    IMPORTANT NOTICE: Please do not distribute or use this +software in the US-it is illegal to use this toolkit in the US, as +public-key cryptography is covered by US patents (see the Patents and Trademarks +section below for details). If you are a US resident, please use the RSAREF +toolkit instead. +

    +
    +

    RSAEURO contains support for the following: +

    +
      +
    • RSA encryption, decryption and key generation. Compatible with RSA +Laboratories' Public-Key Cryptography Standard (PKCS) #1. +
    • +
    • Generation and verification of message digests using MD2, MD4, MD5 and SHS +(SHS currently not implemented in higher-level functions to maintain +compatibility with PKCS). +
    • +
    • DES encryption and decryption using CBC (1, 2 or 3 keys using +Encrypt-Decrypt-Encrypt) and DESX, RSADSI's secure DES enhancement. +
    • +
    • Diffie-Hellman key agreement as defined in PKCS #3. +
    • +
    • PEM support - support for RFC&nbsp;1421 encoded ASCII data with all +main functions. +
    • +
    • Key routines implemented in assembler for speed (80386 and 680x0 currently +supported). +
    +

    +What is covered by this document? +

    +

    This document provides a function-by-function description of the RSAEURO +toolkit, at a sufficient level of detail to allow the use of the toolkit within +other software. The internal workings of the functions are not described. For +full details of the internal workings of the RSAEURO routines, please consult +the (well commented) source code.

    +

    +It is assumed that the reader is familiar with C programming and basic +cryptography, although a detailed knowledge is not required.

    +

    +This document is divided into the following sections: +

    +
    Introduction (This section).
    +
    General introduction to RSAEURO.
    +
    Random numbers
    +
    Routines for generating cryptographically-secure random numbers, for use by +various other cryptographic functions.
    +
    Message digests
    +
    Routines for the creation and verification of message digests.
    +
    Digital signatures
    +
    Routines for the creation and verification of digital signatures.
    +
    Envelope processing
    +
    Routines for the creation and use of digital "envelopes" (an "envelope" +is a structure containing encrypted data and an optional digital signature).
    +
    PEM functions
    +
    Routines for processing Interned privacy-enhanced mail (PEM) encoded +messages.
    +
    Key generation and exchange
    +
    Routines for generating key material for RSA encryption, and exchanging +keys via Diffie-Hellman agreement.
    +
    RSA
    +
    Routines for public key encryption and decryption using RSA and PKCS#1.
    +
    DES
    +
    Routines for secret-key encryption and decryption using DES in CBC mode, +with either single or triple-key operation.
    +
    Natural number arithmetic
    +
    Low-level routines for performing natural number arithmetic.
    +
    Memory manipulation
    +
    Platform-specific memory manipulation routines.
    +
    Technical information
    +
    "Technical" programming information, including descriptions of +RSAEURO data structures, defined values and references to further information.
    +
    Appendix A: Function cross-reference +
    +
    An alphabetical list of functions with brief details and a reference to +coverage in the main documentation.
    +

    +Contact information +

    +

    All general comments should be sent to +rsaeuro@sourcery.demon.co.uk. + Bug reports should be sent to +rsaeuro-bugs@sourcery.demon.co.uk. + Comments or corrections regarding the documentation should be sent to +nikb@cix.compulink.co.uk.

    +

    +As a last resort, the author may be contacted by "snail-mail" at the +following address:

    +

    +Stephen Kapp
    The Post Office
    Nr. Clitheroe
    Lancashire
    BB7 3BB
    UNITED +KINDOM + +

    +

    +Typographic conventions +

    +

    Throughout this document, blocks of C source code are set in +courier , and in-text references to functions, constants and the +like are set in bold. Conventional C-style mathematical operators are +used throughout (e.g. * for "times", / for "divided by" +etc) + +

    +

    +Licence

    +

    RSAEURO TOOLKIT LICENSE AGREEMENT 15th December 1995

    +

    + Copyright (c) J.S.A.Kapp, 1994-1995. 1. LICENSE. J.S.A.Kapp grants you a +nonexclusive, non-transferable, perpetual (subject to the conditions of section +7) license for the "RSAEURO" toolkit (the "Toolkit") and its +associated documentation, subject to all of the following terms and conditions:

    +

    +i. To use the Toolkit on any computer in your possession.

    +

    +ii. to make copies of the Toolkit for back-up purposes.

    +

    +iii. to modify the Toolkit in any manner for porting or performance improvement +purposes (subject to Section 2) or to incorporate the Toolkit into other +computer programs for your own personal or internal use, provided that you +provide J.S.A.Kapp with a copy of any such modification or Application Program +by electronic mail, and grant J.S.A.Kapp a perpetual, royalty-free license to +use and distribute such modifications and Application Programs on the terms set +forth in this Agreement.

    +

    +iv. To copy and distribute the Toolkit and Application Programs in accordance +with the limitations set forth in Section 2.

    +

    + "Application Programs" are programs that incorporate all or any +portion of the Toolkit in any form. The restrictions imposed on Application +Programs in this Agreement shall not apply to any software which through the +mere aggregation on distribution media, is co-located or stored with the +Toolkit.

    +

    +2. LIMITATIONS ON LICENSE.

    +

    +i. J.S.A.Kapp owns the Toolkit and its associated documentation and all +copyrights therein. You may only use, copy, modify and distribute the Toolkit as +expressly provided for in this Agreement. You must reproduce and include this +Agreement, J.S.A.Kapp's copyright notices and disclaimer of warranty on any copy +and its associated documentation.

    +

    +ii. The Toolkit and its associated documentation are freeware for noncommercial +purposes, however for commercial purposes please contact J.S.A.Kapp for +licensing details.

    +

    +iii. The Toolkit and Application Programs are to be used for noncommercial +purposes. However, media costs associated with the distribution of the Program +or Application Programs may be recovered.

    +

    +iv. The Toolkit, if modified, must carry prominent notices stating that changes +have been made, and the dates of any such changes. v. Prior permission from +J.S.A.Kapp is required for any modifications that access the Toolkit through +ways other than the published Toolkit interface or for modifications to the +Toolkit interface, and structures. J.S.A.Kapp will grant all reasonable requests +for permission to make such modifications.

    +

    +3. You are solely responsible for all of your costs and expenses incurred in +connection with the distribution of the Toolkit or any Application Program +hereunder, and J.S.A.Kapp shall have no liability, obligation or responsibility +there of. J.S.A.Kapp shall have no obligation to provide maintenance, support, +upgrades or new releases to you or to any distributee of the Toolkit or any +Application Program.

    +

    +4. THE TOOLKIT AND ITS ASSOCIATED DOCUMENTATION ARE LICENSED "AS IS" +WITHOUT WARRANTY AS TO THEIR PERFORMANCE, MERCHANTABILITY OR FITNESS FOR ANY +PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE RESULTS AND PERFORMANCE OF THE +TOOLKIT IS ASSUMED BY YOU AND YOUR DISTRIBUTEES. SHOULD THE TOOLKIT PROVE +DEFECTIVE, YOU AND YOUR DISTRIBUTEES (AND NOT J.S.A.KAPP) ASSUME THE ENTIRE COST +OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

    +

    +5. LIMITATION OF LIABILITY, NEITHER J.S.A.KAPP NOR ANY OTHER PERSON WHO HAS BEEN +INVOLVED IN THE CREATION, PRODUCTION, OR DELIVERY OF THE TOOLKIT SHALL BE LIABLE +TO YOU OR TO ANY OTHER PERSON FOR ANY DIRECT, INCIDENTAL OR CONSEQUENTIAL +DAMAGES, EVEN IF J.S.A.KAPP HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

    +

    +6. RSAEURO is a publication of cryptographic techniques. Applications developed +with RSAEURO may be subject to export controls in some countries. If you are +located in the United States and develop such applications using RSAEURO, you +are advised to obtain a copy of RSAREF from RSADSI, as you may using RSAEURO +infringe on Patents held by RSA Data Security and Cylink.

    +

    +7. The license granted hereunder is effective until terminated. You may +terminate it at anytime by destroying all components of the Toolkit and its +associated documentation. The termination of your license will not result in the +termination of the licenses of any distributees who have received rights to the +Toolkit through you so long as they are in compliance with the provisions of +this license.

    +

    +8. GENERAL

    +

    +i. Address all correspondence regarding this license to J.S.A.Kapp's electronic +mail address <rsaeuro@sourcery.demon.co.uk>, +or to

    +

    + Mr J.S.A.Kapp.
    The Post Office,
    Dunsop Bridge,
    Clitheroe, +
    Lancashire,
    England.
    BB7 3BB.

    Tel. (+44) 1200-448241

    +

    +ii. For details of Export Controls and other controls regarding the use of +cryptographic techniques please contact your country's relevant authority. + +

    +

    +Patents and trademarks +

    +

    The following terms are registered trademarks as indicated. All other +trademarks acknowledged. To the author's knowledge, all relevant trademarks have +been duly acknowledged. If there are any omissions, please provide the relevant +details and the documentation will be amended accordingly. + +

    +

    +RSADSI

    +

    RSA Data Security Inc (RSADSI) provide consultancy and software engineering +service in the field of cryptography. The RSAREF toolkit, on which RSAEURO is +modelled, is available free of charge from RSADSI with the USA and Canada, +subject to their licensing agreement. For information regarding licensing +RSADSI's toolkits, contact Paul Gordon (paul@rsa.com) +at RSADSI.

    +

    +Following a recent arbitration between RSADSI and Cylink, it has been determined +that RSADSI hold patent rights to the RSA public-key cryptographic algorithm. +For details of licensing the RSA algorithm contact Paul Livesay (pol@rsa.com)at RSADSI.

    +

    +RSADSI can be contacted at:

    RSA Data Security Inc,
    10 Twin Dolphin +Drive
    Redwood City
    CA 94065

    Tel. (415) 595-8782.

    +

    +DESX and RSAREF are registered trademarks of RSADSI. + +

    +

    +Cylink

    +

    At the time of writing it was not possible to determine the legal situation +regarding patents regarding cryptography held by Cylink. Interested parties +should contact Bob Fougner on (+1) 408 735 5893, e-mail: +fougner@cylink.com. + +

    +

    +Release history +

    +

    This section describes the changes made at each release of the software.

    +

    + +

    +

    +Release 1.00 +

    +

    First major release. + +

    +

    +Release 1.01 +

    +

    Modifications: +

    +
      +
    • R_RandomCreate and R_RandomMix modified to improve random +number generation. R_RandomMix had a minor flaw as it didn't flush the +old output from the object. +
    +

    +Release 1.02 +

    +

    Bug fixes: +

    +
      +
    • Fixed bug in R_EncodePEMBlock reported by Wang Wei Jun <wang@iti.gov.sg>. +
    • +
    • Fixed bug in R_SealUpdate reported by Anders Heerfordt <i3683@dc.dk>. +
    • +
    • Fixed bug in dmult, reported by Anders Heerfordt <i3683@dc.dk>. +
    • +
    • Fixed PADDING[] bug for R_ENHANC.C, reported by Anders Heerfordt. +
    +

    +Release 1.03 +

    +

    Bug fixes: +

    +
      +
    • RSAPublicEncrypt, checks that RandomStruct has been initialised +prior to use. +
    • +
    • SHSFinal, digest now output "directly" to a passed +parameter, context cleared on exit.
    • +
    +

    +

    +
    +

    +RANDOM NUMBERS +

    +
      +
    1. Introduction +
    2. +
    3. Functions
        +
      1. R_RandomInit +
      2. +
      3. R_RandomUpdate +
      4. +
      5. R_GetRandomBytesNeeded +
      6. +
      7. R_GenerateBytes +
      8. +
      9. R_RandomFinal +
      10. +
      11. R_RandomCreate +
      12. +
      13. R_RandomMix
    4. +
    +

    RSAEURO Full documentation, revision 0.90. 18/08/95. + +

    +

    +Introduction

    +

    Various functions within RSAEURO require random data (primarily for key +generation). A stream of random (strictly, pseudo-random) data is generated +using the MD5 digest algorithm and a "seed" value, which is provided +in the form of the random structure.

    +

    +Before use, the random structure must be initialised and "seeded" +itself, by "mixing in" an amount of genuine random data. The +procedure for preparing a new random structure is as follows: +

    +
      +
    1. Reserve sizeof(R_RANDOM_STRUCT) memory. +
    2. +
    3. Initialise the new structure using R_RandomInit. This sets +random- + >bytesNeeded, the number of random bytes required to "seed" +the structure before use, to RANDOM_BYTES_RQ, and zeroes the data. +
    4. +
    5. "Mix in" a suitable quantity of random data using R_RandomUpdate. +R_RandomUpdate takes a caller-supplied block of data and combines it +with the existing random structure using MD5. R_RandomUpdate also +decrements random->bytesNeeded, which indicates the amount of random +data still required (the R_GetRandomBytesNeeded function returns the +bytesNeeded value of a given random structure). +R_RandomUpdate should be called repeatedly until +R_GetRandomBytesNeeded returns zero.
    +

    R_RandomUpdate may be called once the structure has been initialised +(i.e. bytesNeeded equals zero). RANDOM_BYTES_RQ should be +adjusted according to the "purity" of the random data source.

    +

    +An additional function, R_RandomCreate, creates and initialises a "fresh" +random structure using data from the current system clock, via the ANSI +gmtime function (this function uses a separate variable, +RANDOM_BYTES_INT, to indicate the amount of mix-in bytes, currently set to 512). + On ANSI-compliant systems, R_RandomCreate can be used as a "one-stop +shop" for producing a ready-to-use random structure. Other sources +of random data, such as keyboard timings, disk latency and so on are highly +system-dependant, and have not yet been implemented.

    +

    +Once a random structure has been created, initialised and seeded, it may +be used by R_GenerateBytes to produce a stream of pseudo-random data. +R_GenerateBytes returns an error if an invalid (non-seeded) +random structure is referenced.

    +

    +The function R_RandomMix uses the ANSI clock and time +functions to randomise the current state of an existing, initialised random +structure. Then flush any pending output from the output state.

    +

    +The function R_RandomFinal clears a random structure. + +

    +

    +Functions

    +

    +R_RandomInit

    +

    int R_RandomInit(random)R_RANDOM_STRUCT *random; /* random structure +*/

    +

    +Initialises a new random structure. Zeroes the data area and sets +random->bytesNeeded to the system default (RANDOM_BYTES_RQ). Always +returns IDOK. + +

    +

    +R_RandomUpdate

    +

    int R_RandomUpdate(random, block, len)
    R_RANDOM_STRUCT +*random; /* random structure */
    unsigned char *block; /* block of data */
    unsigned +int len; /* length of block */

    +

    +Updates a previously initialised random structure by mixing in a block +of caller-supplied data using MD5. Updates random->bytesNeeded as +appropriate. Always returns IDOK. + +

    +

    +R_GetRandomBytesNeeded

    +

    int R_GetRandomBytesNeeded(bytesNeeded, random)
    unsigned int +*bytesNeeded /* number of mix-in bytes needed */
    R_RANDOM_STRUCT *random /* +random structure */

    +

    +Returns the number of seed bytes still required for the random +structure. On exit, bytesNeeded contains the number of bytes +required by the structure random. Always returns IDOK. + +

    +

    +R_GenerateBytes

    +

    int R_GenerateBytes(block, len, random)
    unsigned char *block; /* +block */
    unsigned int len; /* length of block */
    R_RANDOM_STRUCT +*random; /* random structure */

    +

    +Populates block with len pseudo-random bytes derived from +random using MD5. Returns RE_NEED_RANDOM if random has not been fully +initialised, IDOK otherwise. + +

    +

    +R_RandomFinal

    +

    void R_RandomFinal(random)
    R_RANDOM_STRUCT *random; /* random +structure */

    +

    +Clears a random structure, setting all values and data to zero. + +

    +

    +R_RandomCreate

    +

    void R_RandomCreate(random)
    R_RANDOM_STRUCT *random; /* random +structure */

    +

    +Initialises a random structure and seeds it with data derived using the +ANSI gmtime and clock function. The quantity of seeding data is +defined by RANDOM_BYTES_RQINT. + +

    +

    +R_RandomMix

    +

    void R_RandomMix(random)
    R_RANDOM_STRUCT *random;

    +

    +Randomises the internal state of the supplied random structure, using +data from the ANSI clock and time functions, then flushes any +pending output. + +

    +
    +

    +MESSAGE DIGESTS +

    +
      +
    1. Introduction +
    2. +
    3. Functions
        +
      1. R_DigestInit +
      2. +
      3. R_DigestUpdate +
      4. +
      5. R_DigestFinal +
      6. +
      7. R_DigestBlock +
      8. +
      9. MD2Init +
      10. +
      11. MD2Update +
      12. +
      13. MD2Final +
      14. +
      15. MD4Init +
      16. +
      17. MD4Update +
      18. +
      19. MD4Final +
      20. +
      21. MD5Init +
      22. +
      23. MD5Update +
      24. +
      25. MD5Final +
      26. +
      27. SHSInit +
      28. +
      29. SHSUpdate +
      30. +
      31. SHSFinal
    4. +
    +

    +Introduction

    +

    RSAEURO supports four different message digest algorithms: MD2, MD4, MD5 and +Secure Hash Standard (SHS). The current MD2, MD4 and MD5 routines are based on +source code made available by RSADSI.

    +

    +Support for each digest method consists of three basic functions: init, +which initialises the relevant structures and contexts; update, which +adds data to the digest, and final which "tidies up" and +returns the final digest value. To simplify implementation, the digest and +signature routines are called via "parent" routines, with the +algorithm to be used passed as a parameter.

    +

    +High-level functions are provided for processing data which is memory-resident. +These functions handle all memory allocation, initialisation and processing +internally, providing a "one-stop shop" solution. However, as the +data to be processed must be resident in memory, the run-time resource +requirements of these functions are larger than the init-update-final method.

    +

    +The procedure for producing a message digest is as follows: +

    +
      +
    1. Initialise the digest "context", containing the digest generator +state, input buffer etc, by calling R_DigestInit. The digest +type (MD2, MD4, MD5 or SHS) is specified as a parameter to R_DigestInit. +
    2. +
    3. Process the source data a block at a time, using R_DigestUpdate. +
    4. +
    5. Produce the final digest value using R_DigestFinal.
    +

    The +R_Digest functions act as "wrappers" for the +algorithm-specific message digest routines. An additional function, R_DigestBlock, +may be used for memory-resident data. + +

    +

    +Functions

    +

    +R_DigestInit

    +

    int R_DigestInit(context, digesttype)
    R_DIGEST_CTX *context; /* +new context */
    int digesttype; /* message-digest algorithm */

    +

    +Initialises a context ready for digest production. The R_DIGEST_CTX type is a +union structure supporting the different context types required for each message +digest algorithm. context is a pointer to a "blank" +R_DIGEST_CTX structure, digesttype indicates the digest algorithm to be +used. Currently supported digest types are DA_MD2, DA_MD4, DA_MD5 and DA_SHS. +Returns RE_DIGEST_ALGORITHM if an invalid (unsupported) digest algorithm is +selected, IDOK otherwise. + +

    +

    +R_DigestUpdate

    +

    int R_DigestUpdate(context, partIn, partInLen)
    R_DIGEST_CTX +*context; /* context */
    unsigned char *partIn; /* next data part */
    unsigned +int partInLen; /* length of next data part */

    +

    +Updates context using the appropriate digest algorithm (as indicated by +the context) with the supplied data. partIn points to the data block, +partInLen indicates the length of the block in bytes. Returns +RE_DIGEST_ALGORITHM if an invalid (unsupported) digest algorithm is selected, +IDOK otherwise. + +

    +

    +R_DigestFinal

    +

    int R_DigestFinal(context, digest, digestLen)
    R_DIGEST_CTX +*context; /* context */
    unsigned char *digest; /* message digest */
    unsigned +int *digestLen; /* length of message digest */

    +

    +Produces the final digest value from context. On exit, digest +contains the message digest and digestLen indicates length of the digest +in bytes. R_DigestFinal also zeroes the context to remove any sensitive +data from memory. Returns RE_DIGEST_ALGORITHM if an invalid (unsupported) +digest algorithm is selected, IDOK otherwise. + +

    +

    +R_DigestBlock

    +

    int R_DigestBlock(digest, digestLen, block, blockLen, +digestAlgorithm)
    unsigned char *digest; /* message digest */
    unsigned +int *digestLen; /* length of message digest */
    unsigned char *block; /* +block */
    unsigned int blockLen; /* length of block */
    int +digestAlgorithm; /* message-digest algorithm */

    +

    +Produces a digest of the data block supplied (pointed to by block, +blockLen bytes long), using the digest algorithm indicated by +digestAlgorithm. On success, the digest is returned in digest, +and the length of the digest is indicated by digestLen. Context +creation, initialisation and clearing is handled internally.

    +

    +Returns RE_DIGEST_ALGORITHM if an invalid (unsupported) digest algorithm is +selected, IDOK otherwise. + +

    +

    +MD2Init

    +

    void MD2Init(context)
    MD2_CTX *context; /* context */

    +

    +Initialises a new MD2 context, ready for digest production. context is +a pointer to a "blank" MD2_CTX structure. + +

    +

    +MD2Update

    +

    void MD2Update(context, input, inputLen)
    MD2_CTX *context; /* +context */
    unsigned char *input; /* input block */
    unsigned int +inputLen; /* length of input block */

    +

    +Updates the MD2 context from the supplied data block (pointed to by +input, inputLen bytes long). context must be an MD2_CTX +structure which has been initialised using MD2_init. No checks are made +for context validity.

    +

    + +

    +

    +MD2Final

    +

    void MD2Final(digest, context)
    unsigned char digest[16]; /* +message digest */
    MD2_CTX *context; /* context */

    +

    +Produces the final MD2 digest value from context. context must +be an MD2_CTX structure which has been initialised using MD2_init. No +checks are made for context validity. On exit, digest contains the MD2 +message digest. MD2Final zeroes the context to remove any sensitive data +from memory. + +

    +

    +MD4Init

    +

    void MD4Init(context)
    MD4_CTX *context; /* context */

    +

    +Initialises a new MD4 context, ready for digest production. context is +a pointer to a "blank" MD4_CTX structure. + +

    +

    +MD4Update

    +

    void MD4Update(context, input, inputLen)
    MD4_CTX *context; /* +context */
    unsigned char *input; /* input block */
    unsigned int +inputLen; /* length of input block */

    +

    +Updates the MD4 context from the supplied data block (pointed to by +input, inputLen bytes long). context must be an MD4_CTX +structure which has been initialised using MD4_init. No checks are made +for context validity. + +

    +

    +MD4Final

    +

    void MD4Final(digest, context)
    unsigned char digest[16]; /* +message digest */
    MD4_CTX *context; /* context */

    +

    +Produces the final MD4 digest value from context. context must +be an MD4_CTX structure which has been initialised using MD4_init. No +checks are made for context validity. On exit, digest contains the MD4 +message digest. MD4Final zeroes the context to remove any sensitive data +from memory. + +

    +

    +MD5Init

    +

    void MD5Init (context)
    MD5_CTX *context; /* context */

    +

    +Initialises a new MD5 context, ready for digest production. context is +a pointer to a "blank" MD5_CTX structure. + +

    +

    +MD5Update

    +

    void MD5Update(context, input, inputLen)
    MD5_CTX *context; /* +context */
    unsigned char *input; /* input block */
    unsigned int +inputLen; /* length of input block */

    +

    +Updates the MD5 context from the supplied data block (pointed to by +input, inputLen bytes long). context must be an MD5_CTX +structure which has been initialised using MD5_init. No checks are made +for context validity. + +

    +

    +MD5Final

    +

    void MD5Final (digest, context)
    unsigned char digest[16]; /* +message digest */
    MD5_CTX *context; /* context */

    +

    +Produces the final MD5 digest value from context. context must +be an MD5_CTX structure which has been initialised using MD5_init. No +checks are made for context validity. On exit, digest contains the MD5 +message digest. MD5Final zeroes the context to remove any sensitive data +from memory. + +

    +

    +SHSInit

    +

    void SHSInit(context)
    SHS_CTX *context; /* context */

    +

    +Initialises a new SHS context, ready for digest production. context is +a pointer to a "blank" SHS_CTX structure. + +

    +

    +SHSUpdate

    +

    void SHSUpdate(context, buffer, count)
    SHS_CTX *context; /* +context */
    BYTE *buffer; /* input block */
    int count; /* length of +input block */

    +

    +Updates the SHS context from the supplied data block (pointed to by +buffer, count bytes long). context must be an SHS_CTX +structure which has been initialised using SHS_init. No checks are made +for context validity.

    +

    + +

    +

    +SHSFinal

    +

    void SHSFinal(digest, context)
    char *digest /* digest */
    SHS_CTX +*context; /* context */

    +

    +Produces the final SHS digest value from context, returning the digest +in digest. context must be an SHS_CTX structure which has been +initialised using SHS_init. No checks are made for context validity. On +exit, digest contains the SHS message digest, and context is +cleared.

    +

    + +

    +
    +

    +DIGITAL SIGNATURE ROUTINES +

    +
      +
    1. Introduction +
    2. +
    3. Functions
        +
      1. R_SignInit +
      2. +
      3. R_SignUpdate +
      4. +
      5. R_SignFinal +
      6. +
      7. R_SignBlock +
      8. +
      9. R_VerifyInit +
      10. +
      11. R_VerifyUpdate +
      12. +
      13. R_VerifyFinal +
      14. +
      15. R_VerifyBlockSignature
    4. +
    +

    +Introduction

    +

    RSAEURO provides support for digital signatures using MD2, MD4 and MD5 +digests (to maintain compliance with PKCS #1, SHS cannot be used for digital +signatures, as it produces a 160 bit digest).

    +

    +Signature generation consists of three basic functions: init, which +initialises the relevant structures and contexts; update, which adds +data to the digest, and final which "tidies up", generates the +final digest value, and encrypts it using the sender's secret key to produce the +signature. To simplify implementation, the signature routines are called via "parent" +routines, with the digest algorithm required passed as a parameter.

    +

    +High-level functions are provided for processing data which is memory-resident. +These functions handle all memory allocation, initialisation and processing +internally, providing a "one-stop shop" solution. However, as the +data to be processed must be resident in memory, the run-time resource +requirements of these functions are larger than the init-update-final method.

    +

    +The procedure for producing a digital signature is as follows: +

    +
      +
    1. Initialise the signature context by calling R_SignInit. The +message digest type required is passed as a parameter. To maintain PKCS #1 +compatibility, SHS is rejected by R_SignInit as a digest type. +
    2. +
    3. Process the source data a block at a time using R_SignUpdate. +
    4. +
    5. Produce the final signature using R_SignFinal. The sender's +private key is passed as a parameter. RSA is the only algorithm supported for +signatures.
    +

    An additional function, R_SignBlock, may be used to produce a +signature for memory-resident data.

    +

    +RSAEURO also provides routines for verifying a supplied signature. The +procedure is as follows: +

    +
      +
    1. Initialise the signature context by calling R_VerifyInit. The +message digest type required is passed as a parameter. To maintain PKCS #1 +compatibility, SHS is rejected by R_SignInit as a digest type. +
    2. +
    3. Process the source data a block at a time using R_VerifyUpdate. +
    4. +
    5. Produce the final digest and verify it against a supplied signature using +R_VerifyFinal. The sender's public key is passed as a parameter, to +allow the decryption of the supplied signature. RSA is the only algorithm +supported for signatures.
    +

    An additional function, R_VerifyBlock, may be used to verify a +signature for memory-resident data. + +

    +

    +Functions

    +

    +R_SignInit

    +

    int R_SignInit(context, digesttype)
    R_SIGNATURE_CTX *context; /* +new context */
    int digesttype; /* message-digest algorithm */

    +

    +Initialises a digest context ready for signature production. The +R_SIGNATURE_CTX type is a union structure supporting the different context types +required for each message digest algorithm. context is a pointer to a "blank" +R_SIGNATURE_CTX structure, digesttype indicates the digest algorithm to +be used. Returns RE_DIGEST_ALGORITHM if an invalid digest type is specified +(such as SHS), IDOK otherwise. + +

    +

    +R_SignUpdate

    +

    int R_SignUpdate(context, partIn, partInLen)
    R_SIGNATURE_CTX +*context; /* context */
    unsigned char *partIn; /* next data part */
    unsigned +int partInLen; /* length of next data part */

    +

    +Updates context using the appropriate digest algorithm (as indicated by +the context) with the supplied data (partInLen bytes from +partIn). Returns RE_DIGEST_ALGORITHM if an invalid digest type is +specified (such as SHS), IDOK otherwise. + +

    +

    +R_SignFinal

    +

    int R_SignFinal(context, signature, signatureLen, privateKey)
    R_SIGNATURE_CTX +*context; /* context */
    unsigned char *signature; /* signature */
    unsigned +int *signatureLen; /* length of signature */
    R_RSA_PRIVATE_KEY +*privateKey; /* signer's RSA private key */

    +

    +Produces a signature from the supplied context and private key. The digest +value is first calculated using R_DigestFinal and the context, +and this value is then encrypted using RSA with privatekey. The +encrypted value is returned in signature, and the length of the +signature is returned in signatureLen. Returns RE_PRIVATE_KEY if the +private key is invalid, RE_DIGEST_ALGORITHM if an invalid digest type is +specified (such as SHS), IDOK otherwise.

    +

    +R_SignFinal "restarts" the signature context, ready for +re-use, and clears all sensitive information. + +

    +

    +R_SignBlock

    +

    int R_SignBlock(signature, signatureLen, block, +blockLen,digestAlgorithm, privateKey)
    unsigned char *signature; /* signature +*/
    unsigned int *signatureLen; /* length of signature */
    unsigned char +*block; /* block */
    unsigned int blockLen; /* length of block */
    int +digestAlgorithm; /* message-digest algorithm */
    R_RSA_PRIVATE_KEY +*privateKey; /* signer's RSA private key */

    +

    +Produces a signature for the data block supplied (pointed to by block, +blockLen bytes long). digestAlgorithm indicates the required +message digest algorithm, privateKey is the sender's RSA private key. On +success, returns IDOK, signature contains the generated signature, +signatureLen indicates the length in bytes of the signature. On error, +returns RE_DIGEST_ALGORITHM if an invalid digest algorithm is selected or +RE_PRIVATE_KEY if the private key is invalid. + +

    +

    +R_VerifyInit

    +

    int R_VerifyInit(context, digesttype)
    R_SIGNATURE_CTX +*context; /* new context */
    int digesttype; /* message-digest algorithm */

    +

    +Initialises context ready for signature verification. The +R_SIGNATURE_CTX type is a union structure supporting the different context types +required for each message digest algorithm. context is a pointer to a "blank" +R_SIGNATURE_CTX structure, digesttype indicates the digest algorithm to +be used. Returns RE_DIGEST_ALGORITHM if an invalid digest type is specified +(such as SHS), IDOK otherwise. + +

    +

    +R_VerifyUpdate

    +

    int R_VerifyUpdate(context, partIn, partInLen)
    R_SIGNATURE_CTX +*context; /* context */
    unsigned char *partIn; /* next data part */
    unsigned +int partInLen; /* length of next data part */

    +

    +Updates context using the appropriate digest algorithm (as indicated by +the context) with the supplied data (partInLen bytes from +partIn). Returns RE_DIGEST_ALGORITHM if an invalid digest type is +specified (such as SHS), IDOK otherwise. + +

    +

    +R_VerifyFinal

    +

    int R_VerifyFinal(context, signature, signatureLen, publicKey)
    R_SIGNATURE_CTX +*context; /* context */
    unsigned char *signature; /* signature */
    unsigned +int *signatureLen; /* length of signature */
    R_RSA_PRIVATE_KEY +*privateKey; /* signer's RSA public key */

    +

    +Verifies the supplied signature against the digest produced from the supplied +context. Returns zero for success, RE_LEN if the supplied signature is too long +(greater than MAX_SIGNATURE_LEN), RE_PUBLIC_KEY if the supplied public key +cannot decrypt the signature correctly, RE_SIGNATURE if the message digests do +not match or RE_DIGEST_ALGORITHM if an invalid digest type is specified (such as +SHS). + +

    +

    +R_VerifyBlockSignature

    +

    int R_VerifyBlockSignature( block, blockLen, signature, signatureLen,
    + digestAlgorithm, publicKey)
    unsigned char *block; +/* block */
    unsigned int blockLen; /* length of block */
    unsigned char +*signature; /* signature */
    unsigned int signatureLen; /* length of +signature */
    int digestAlgorithm; /* message-digest algorithm */
    R_RSA_PUBLIC_KEY +*publicKey; /* signer's RSA public key */

    +

    +Verifies the signature of a memory-resident data block (pointed to by +block, blockLen bytes long). digestAlgorithm indicates +the required message digest algorithm, publicKey is the sender's RSA +public key, signature points to the signature to verify and +signatureLen indicates the length of the signature in bytes. +RE_DIGEST_ALGORITHM if an invalid digest algorithm is selected. On success, +returns zero. On error, returns RE_DIGEST_ALGORITHM if an invalid digest +algorithm is selected, RE_LEN if the supplied signature is too long (greater +than MAX_SIGNATURE_LEN), RE_PUBLIC_KEY if the supplied public key cannot decrypt +the signature correctly or RE_SIGNATURE if the message digests do not match. + +

    +
    +

    +ENVELOPE PROCESSING +

    +
      +
    1. Introduction +
    2. +
    3. Sealing data in digital envelopes +
    4. +
    5. Opening digital envelopes +
    6. +
    7. Functions
        +
      1. R_SealInit +
      2. +
      3. R_SealUpdate +
      4. +
      5. R_SealFinal +
      6. +
      7. R_OpenInit +
      8. +
      9. R_OpenUpdate +
      10. +
      11. R_OpenFinal
    8. +
    +

    +Introduction

    +

    RSAEURO uses the concept of a "digital envelope" for handling +encrypted data. Data is first encrypted using a secret-key algorithm, using a +random session key. The session key is then encrypted using the public keys of +the intended recipients. The encrypted versions of the session key and the +secret-key encrypted message form the digital envelope. "Opening" a +digital envelope requires the decryption of the session key, using the +recipient's private key (assuming the recipient is one of the intended +recipients!), then using the session key to decrypt the message.

    +

    +RSAEURO provides four varieties of secret-key encryption, all based on the US +Data Encryption Standard (DES): +

    +
    • EA_DES_CBC DES in cipher-block chaining (CBC) mode, using a +single key.
    • +
    • EA_DESX_CBC RSADSI's "enhanced" DES (CBC with an +additional XOR with a secret value).
    • +
    • EA_DES_EDE3_CBC Triple-DES, using three keys, in CBC mode. EDE is +"Encrypt-Decrypt-Encrypt", where data is encrypted with key1, +decrypted with key2, then encrypted with key3. EDE avoids certain weaknesses of +"plain" multiple encryption.
    • +
    • EA_DES_EDE2_CBC Triple-DES using two keys (key1 and key 3 are +identical).
    +

    EA_DES_EDE3_CBC is the most secure, and the slowest, method of encryption +supported by RSAEURO. + +

    +

    +Sealing data in digital envelopes +

    +

    The procedure for "sealing" data in a digital envelope is as +follows: +

    +
      +
    1. Initialise the envelope context, by calling R_SealInit. +R_SealInit generates the random session key and returns the public-key +encrypted versions of the session key (the session key itself, together with +other intermediate data, is stored in the context). The secret-key encryption +method to use is specified as a parameter to R_SealInit. +
    2. +
    3. Process the source data a block at a time, using R_SealUpdate. +
    4. +
    5. "Close" the envelope using R_SealFinal, and clear the +encryption context. +
    +

    +Opening digital envelopes +

    +

    The procedure for "opening" a digital envelope is as follows: +

    +
      +
    1. Initialise a new envelope context using R_OpenInit. This decrypts +the session key using the recipient's private key, and sets up the context ready +for decryption of the main message. +
    2. +
    3. Process the encrypted data a block at a time using R_OpenUpdate. +
    4. +
    5. Process the final encrypted data block using R_OpenFinal, which +also removes any padding data. +
    +

    +Functions

    +

    +R_SealInit

    +

    int R_SealInit(context, encryptedKeys, encryptedKeyLens, iv, +publicKeyCount,
    publicKeys, encryptionAlgorithm, randomStruct
    R_ENVELOPE_CTX +*context; /* new context */
    unsigned char **encryptedKeys; /* encrypted keys +*/
    unsigned int *encryptedKeyLens; /* lengths of encrypted keys */
    unsigned +char iv[8]; /* initialization vector */
    unsigned int publicKeyCount; /* +number of public keys */
    R_RSA_PUBLIC_KEY **publicKeys; /* public keys */
    int +encryptionAlgorithm; /* data encryption algorithm */
    R_RANDOM_STRUCT +*randomStruct; /* random structure */

    +

    +Initialises an envelope sealing operation. context points to an +allocated blank R_ENVELOPE_CTX structure and randomStruct points to a +pre-initialised R_RANDOM_STRUCT. encryptionAlgorithm indicates which +method of secret encryption is required (EA_DES_CBC, EA_DES_EDE2_CBC, +EA_DES_EDE3_CBC or EA_DESX_CBC).

    +

    +R_SealInit uses the random structure to generate a session key +and initialisation vector for the secret-key encryption (DES in CBC mode +requires a 64-bit initialisation vector).

    +

    +The public keys of the intended recipients are placed in the publicKeys +array, with the total number of public keys indicated by publicKeyCount +(at least one public key must be supplied). An invalid public key results in an +RE_PUBLIC_KEY error, and no further keys will be processed.

    +

    +On success, returns zero, the encryptedKeys array contains the +public-key encrypted session key (for each supplied public key) and +encryptedKeyLens contains the respective encrypted key lengths. +iv contains the DES initialisation vector.

    +

    +On error, returns RE_NEED_RANDOM if randomStruct has not been +initialised, RE_PUBLIC_KEY if an invalid public key has been supplied or +RE_ENCRYPTION_ALGORITHM if an invalid encryption algorithm has been selected. + +

    +

    +R_SealUpdate

    +

    int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen)
    R_ENVELOPE_CTX +*context; /* context */
    unsigned char *partOut; /* next encrypted data part +*/
    unsigned int *partOutLen; /* length of next encrypted data part */
    unsigned +char *partIn; /* next data part */
    unsigned int partInLen; /* length of next +data part */

    +

    +Continues a sealing operation, encrypting a block of data using the supplied +context. context is a R_ENVELOPE_CTX structure which has been +successfully initialised using R_SealInit. partInLen bytes of +partIn are encrypted and returned in partOut. Due to data +padding, some expansion may occur, and partOut should be at least eight +bytes larger than partIn.

    +

    +Always returns IDOK. + +

    +

    +R_SealFinal

    +

    int R_SealFinal(context, partOut, partOutLen)
    R_ENVELOPE_CTX +*context; /* context */
    unsigned char *partOut; /* last encrypted data part +*/
    unsigned int *partOutLen; /* length of last encrypted data part */

    +

    +Finalises a sealing operation, flushing the context buffer and resetting the +context (to allow further use of the session key if required). context +is the R_ENVELOPE_CTX structure in use for the current sealing operation. On +exit, partOut contains partOutLen bytes to be appended to the +encrypted data (the contents of the context buffer). partOutLen will be +no more than eight. Always returns IDOK.

    +

    +Note that although the context is restarted, sensitive information is not +cleared. If the context is no longer required, it is the caller's +responsibility to clear it for security. + +

    +

    +R_OpenInit

    +

    int R_OpenInit(context, encryptionAlgorithm, encryptedKey, +encryptedKeyLen, iv,
    privateKey)
    R_ENVELOPE_CTX *context; +/* new context */
    int encryptionAlgorithm; /* data encryption algorithm */
    unsigned +char *encryptedKey; /* encrypted data encryption key */
    unsigned int +encryptedKeyLen; /* length of encrypted key */
    unsigned char iv[8]; /* +initialization vector */
    R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA +private key */

    +

    +Initialises an envelope context ready for an "opening" (decryption) +operation. The encrypted session key is decrypted using privateKey, and +placed in the context. The context is then initialised with the initialisation +vector (supplied unencrypted "in" the envelope, and passed to R_OpenInit +as +iv), ready for decryption. encryptionAlgorithm indicates the +encryption algorithm to be used.

    +

    +On success, returns zero. On error, returns RE_LEN if encryptedKey is +too long (encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN), RE_PRIVATE_KEY if +the private key is invalid (i.e. the correct session key cannot be +retrieved) or RE_ENCRYPTION_ALGORITHM if an invalid encryption algorithm is +selected. + +

    +

    +R_OpenUpdate

    +

    int R_OpenUpdate(context, partOut, partOutLen, partIn, partInLen)
    R_ENVELOPE_CTX +*context; /* context */
    unsigned char *partOut; /* next recovered data part +*/
    unsigned int *partOutLen; /* length of next recovered data part */
    unsigned +char *partIn; /* next encrypted data part */
    unsigned int partInLen; /* +length of next encrypted data part */

    +

    +Continues an opening operation, decrypting a block of data using the supplied +context. context is a R_ENVELOPE_CTX structure which has been +successfully initialised using R_OpenInit. partInLen bytes of +partIn are decrypted and returned in partOut. Due to data +padding, some expansion may occur, and partOut should be at least eight +bytes larger than partIn.

    +

    +Always returns IDOK. + +

    +

    +R_OpenFinal

    +

    int R_OpenFinal(context, partOut, partOutLen)
    R_ENVELOPE_CTX +*context; /* context */
    unsigned char *partOut; /* last recovered data part +*/
    unsigned int *partOutLen; /* length of last recovered data part */

    +

    +Finalises an opening operation, flushing the context buffer and re-initialising +the context. context is the R_ENVELOPE_CTX structure in use for the +current opening operation.

    +

    +On success, returns zero and partOut contains partOutLen bytes +to be appended to the decrypted data (the contents of the context buffer). +partOutLen will be no more than eight. On error, returns RE_KEY if the +session key is invalid.

    +

    +Note that although the context is restarted, sensitive information is not +cleared. If the context is no longer required, it is the caller's +responsibility to clear it for security. + +

    +
    +

    +PEM FUNCTIONS +

    +
      +
    1. Introduction +
    2. +
    3. Functions
        +
      1. R_EncodePEMBlock +
      2. +
      3. R_DecodePEMBlock +
      4. +
      5. R_SignPEMBlock +
      6. +
      7. R_VerifyPEMSignature +
      8. +
      9. R_SealPEMBlock +
      10. +
      11. R_OpenPEMBlock +
      12. +
      13. R_EncryptOpenPEMBlock +
      14. +
      15. R_DecryptOpenPEMBlock
    4. +
    +

    +Introduction

    +

    RSAEURO provides a number functions to process data in Privacy Enhanced Mail +(PEM) format, ASCII-encoded according to RFC 1421. In addition to simple +encoding and decoding functions, PEM "versions" of several other +functions are also provided. The following list of PEM functions provides brief +details, and the function descriptions which follow provide more detailed +information. +

    +
    • R_EncodePEMBlock Encodes data into ASCII according to RFC +1421.
    • +
    • R_DecodePEMBlock Decodes data in RFC 1421 format into "raw" +data.
    • +
    • R_SignPEMBlock Produces an RFC 1421 encoded signature of a data +block, optionally RFC 1421 encoding the data following signature generation.
    • +
    • R_VerifyPEMSignature Verifies an RFC 1421 encoded signature, +optionally decoding the content prior to signature generation.
    • +
    • R_SealPEMBlock Signs and seals a block of data in and RFC 1421 +encoded "envelope", using single-key DES CBC. Only supports single +recipients.
    • +
    • R_OpenPEMBlock "Opens" an RFC 1421 encoded "envelope", +verifying the signature and decrypting the data.
    • +
    • R_EncryptOpenPEMBlock Encrypts a data block, returning encrypted +RFC 1421 encoded data.
    • +
    • R_DecryptOpenPEMBlock Decrypts and decodes an encrypted, RFC 1421 +encoded data block.
    +

    Throughout this section, any reference to "ASCII encoded" should +be read as "ASCII encoded according to RFC 1421", and so on. + +

    +

    +Functions

    +

    +R_EncodePEMBlock

    +

    int R_EncodePEMBlock(encodedBlock, encodedBlockLen, block, blockLen)
    unsigned +char *encodedBlock; /* encoded block */
    unsigned int *encodedBlockLen; /* +length of encoded block */
    unsigned char *block; /* block */
    unsigned +int blockLen; /* length of block */

    +

    +Encodes a block of binary data into ASCII for transmission through 7-bit +channels such as Internet electronic mail. blockLen bytes of +block are encoded and returned in encodedBlock, of length +encodedBlock (in bytes).

    +

    +Data expansion occurs as four ASCII characters are used to encode three data +bytes. Therefore, the encodedBlock buffer should be allocated at least +33% larger than block.

    +

    +Always returns IDOK. + +

    +

    +R_DecodePEMBlock

    +

    int R_DecodePEMBlock (outbuf, outlength, inbuf, inlength)
    unsigned +char *outbuf; /* block */
    unsigned int *outlength; /* length of block */
    unsigned +char *inbuf; /* encoded block */
    unsigned int inlength; /* length of encoded +block */

    +

    +Decodes a block of ASCII into binary data. Inbuf holds the input data, +inlength indicates the number of ASCII bytes to process, and therefore +must be an integer multiple of four.

    +

    +On success, returns IDOK and outbuf contains outlength bytes of +decoded data. On error, returns RE_ENCODING in the event of an encoding error +(or if inlength is not an integer multiple of four). + +

    +

    +R_SignPEMBlock

    +

    int R_SignPEMBlock( encodedContent, encodedContentLen, +encodedSignature,
    encodedSignatureLen, content, +contentLen, recode, digestAlgorithm,
    privateKey)
    unsigned char +*encodedContent; /* encoded content */
    unsigned int *encodedContentLen; /* +length of encoded content */
    unsigned char *encodedSignature; /* encoded +signature */
    unsigned int *encodedSignatureLen; /* length of encoded +signature */
    unsigned char *content; /* content */
    unsigned int +contentLen; /* length of content */
    int recode; /* recoding flag */
    int +digestAlgorithm; /* digest algorithm */
    R_RSA_PRIVATE_KEY *privateKey; /* +signer's RSA private key */

    +

    +Produces a digital signature of the supplied data, and returns a ASCII-encoded +version of the signature. Optionally ASCII-encodes the data block.

    +

    +Content contains the data to be signed, contentLen indicates the +length of the data. digestAlgorithm indicates the message digest +algorithm to use, privateKey is the signer's RSA private key, used to +encrypt the digest to produce a signature.

    +

    +If recode is TRUE, the data block (content) is ASCII encoded +following the message digest generation, and the encoded data is returned in +encodedContent, and its length is returned in +encodedContentLen.

    +

    +On success, returns IDOK, encodedSignature contains the ASCII encoded +signature and encodedSignatureLen indicates the length of the encoded +signature. On error, returns RE_DIGEST_ALGORITHM if an invalid digest algorithm +is specified or RE_PRIVATE_KEY if the private key is invalid. + +

    +

    +R_VerifyPEMSignature

    +

    int R_VerifyPEMSignature( content, contentLen, encodedContent, +encodedContentLen,
    encodedSignature, +encodedSignatureLen, recode,
    digestAlgorithm, +publicKey)
    unsigned char *content; /* content */
    unsigned int +*contentLen; /* length of content */
    unsigned char *encodedContent; /* +(possibly) encoded content */
    unsigned int encodedContentLen; /* length of +encoded content */
    unsigned char *encodedSignature; /* encoded signature */
    unsigned +int encodedSignatureLen; /* length of encoded signature */
    int recode; /* +recoding flag */
    int digestAlgorithm; /* digest algorithm */
    R_RSA_PUBLIC_KEY +*publicKey; /* signer's public key */

    +

    +Decodes and verifies an ASCII-encoded signature. Optionally decodes the data +block prior to message digest generation and verification.

    +

    +content contains the data against which the signature is to be verified, +contentLen indicates the length of the data. If recode is TRUE, +encodedContent (encodedContentLen bytes long) is decoded into +content prior to signature verification.

    +

    +publicKey is used to decrypt the signature, and the resulting message +digest is compared with the digest generated from content using the +digest algorithm indicated by digestAlgorithm (it is the caller's +responsibility to identify the appropriate digest algorithm).

    +

    +Returns zero for success (the digests match), RE_SIGNATURE_ENCODING if the +signature cannot be decoded correctly, RE_CONTENT_ENCODING if the content cannot +be decoded correctly, RE_LEN if the signature length is invalid, +RE_DIGEST_ALGORITHM if an invalid digest algorithm is selected, RE_PUBLIC_KEY if +the supplied public key is invalid or RE_SIGNATURE if the signature is incorrect +(i.e. the digests do not match). + +

    +

    +R_SealPEMBlock

    +

    int R_SealPEMBlock( encryptedContent, encryptedContentLen, +encryptedKey, +
    encryptedKeyLen, encryptedSignature, +encryptedSignatureLen, iv,
    content, contentLen, +digestAlgorithm, publicKey, privateKey,
    randomStruct)
    unsigned char +*encryptedContent; /* encoded, encrypted content */
    unsigned int +*encryptedContentLen; /* length */
    unsigned char *encryptedKey; /* encoded, +encrypted key */
    unsigned int *encryptedKeyLen; /* length */
    unsigned +char *encryptedSignature; /* encoded, encrypted signature */
    unsigned int +*encryptedSignatureLen; /* length */
    unsigned char iv[8]; /* DES +initialization vector */
    unsigned char *content; /* content */
    unsigned +int contentLen; /* length of content */
    int digestAlgorithm; /* +message-digest algorithms */
    R_RSA_PUBLIC_KEY *publicKey; /* recipient's +RSA public key */
    R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key +*/
    R_RANDOM_STRUCT *randomStruct; /* random structure */

    +

    +Seals data in a digital envelope, with EA_DES_CBC encryption and digital +signature, and returns PEM ASCII-encoded data.

    +

    +content contains the data to be sealed, contentLen indicates the +length of the data. A signature of content is produced using the digest +algorithm indicated by digestAlgorithm and the sender's private key, +privateKey. content is then encrypted using EA_DES_CBC, with a +random session key generated from randomStruct (it is the caller's +responsibility to ensure that randomStruct has been initialised).

    +

    +On success, returns zero, encryptedContent contains +encryptedContentLen bytes of ASCII encoded encrypted content, +encryptedKey contains the ASCII encoded session key (encryptedKeyLen +bytes long), encrypted with publicKey, and encryptedSignature +contains the ASCII encoded signature. All secret-key encryption is performed +using EA_DES_CBC and the session key.

    +

    +It is the caller's responsibility to clear the context if it is no longer +required.

    +

    +On error, returns RE_DIGEST_ALGORITHM if an invalid digest algorithm is +selected, RE_PRIVATE_KEY if the private key is invalid, RE_PUBLIC_KEY if the +public key is invalid or RE_NEED_RANDOM if the random structure is not +initialised. + +

    +

    +R_OpenPEMBlock

    +

    int R_OpenPEMBlock( content, contentLen, encryptedContent,
    + encryptedContentLen, encryptedKey, encryptedKeyLen,
    +encryptedSignature, encryptedSignatureLen, iv,
    digestAlgorithm, +privateKey, publicKey)
    unsigned char *content; /* content */
    unsigned +int *contentLen; /* length of content */
    unsigned char *encryptedContent; /* +encoded, encrypted content */
    unsigned int encryptedContentLen; /* length */
    unsigned +char *encryptedKey; /* encoded, encrypted key */
    unsigned int +encryptedKeyLen; /* length */
    unsigned char *encryptedSignature; /* encoded, +encrypted signature */
    unsigned int encryptedSignatureLen; /* length */
    unsigned +char iv[8]; /* DES initialization vector */
    int digestAlgorithm; /* +message-digest algorithms */
    R_RSA_PRIVATE_KEY *privateKey; /* recipient's +RSA private key */
    R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key +*/

    +

    +"Opens" a ASCII encoded digital envelope, verifies the signature, +decodes and decrypts the content of the envelope.

    +

    +encryptedContent contains the encoded, encrypted content, and +encryptedContent indicates its length in bytes. The session key is +retrieved from encryptedKey (encryptedKeyLen bytes long) using +publicKey, then used to decrypt the encryptedContent. Once the +content has been decrypted, the signature is retrieved, decoded and verified +against the content using the recipient's private key (privateKey) and +the message digest algorithm indicated by digestAlgorithm.

    +

    +On success, returns zero and content contains contentLen bytes +of plaintext data.

    +

    +On error, returns RE_KEY_ENCODING if the key cannot be decoded, +RE_SIGNATURE_ENCODING if the signature cannot be decoded, RE_CONTENT_ENCODING if +the content cannot be decoded, RE_LEN if the encrypted session key is too long, +RE_PRIVATE_KEY if the private key is invalid, RE_KEY if the retrieved session +key is invalid, RE_DIGEST_ALGORTIHM if an invalid digest algorithm is selected, +RE_PUBLIC_KEY if the public key is invalid or RE_SIGNATURE if the signature is +incorrect (i.e. the message digests do not match). + +

    +

    +R_EncryptOpenPEMBlock

    +

    int R_EncryptOpenPEMBlock(context, output, outputLen, input, +inputLen)
    R_ENVELOPE_CTX *context; /* context */
    unsigned char *output; +/* encrypted, encoded block */
    unsigned int *outputLen; /* length of output +*/
    unsigned char *input; /* block to encrypt */
    unsigned int +inputLen; /* length */

    +

    +Encrypts a block of data and returns the ciphertext in ASCII encoded format. +context is the current envelope context, which must have been +initialised correctly by the caller. inputLen bytes from input are +encrypted and encoded into ASCII, then returned in output. On exit, +outputLen may be up to 33% larger than inputLen (three source +bytes become four output bytes), so output should be allocated to +account for the data expansion. Always returns IDOK. + +

    +

    +R_DecryptOpenPEMBlock

    +

    int R_DecryptOpenPEMBlock(context, output, outputLen, input, +inputLen)
    R_ENVELOPE_CTX *context; /* context */
    unsigned char *output; +/* decoded, decrypted block */
    unsigned int *outputLen; /* length of output +*/
    unsigned char *input; /* encrypted, encoded block */
    unsigned int +inputLen; /* length */

    +

    +Decrypts a block of ASCII encoded ciphertext and returns the plaintext in +output. context is the current envelope context, which must +have been initialised correctly by the caller. inputLen bytes from +input are decoded, decrypted, then returned in output. Always +returns IDOK. + +

    +
    +

    +KEY GENERATION AND EXCHANGE +

    +
      +
    1. Introduction +
    2. +
    3. RSA Key Generation +
    4. +
    5. Diffie-Hellman key agreement +
    6. +
    7. Functions
        +
      1. R_GeneratePEMKeys +
      2. +
      3. R_GenerateDHParams +
      4. +
      5. R_SetupDHAgreement +
      6. +
      7. R_ComputeDHAgreedKey
    8. +
    +

    +Introduction

    +

    RSAEURO contains functions for the generation of RSA key pairs, and for the +exchange of keys using the Diffie-Hellman agreement protocol. This section +describes these functions and their use. + +

    +

    +RSA Key Generation +

    +

    A single function, R_GeneratePEMKeys, provides RSA key generation +for RSAEURO. A "prototype key" is passed to the function, indicating +the length of the modulus in bits and the public exponent. Two values are +supported for the public exponent: 3 or "Fermat 4" (65537). A +pre-initialised random structure is required for key generation. + +

    +

    +Diffie-Hellman key agreement +

    +

    Diffie-Hellman key agreement provides a method for exchanging session keys +without using RSA. Diffie-Hellman gains its security form the difficulty of +calculating discrete logarithms in a finite field. The procedure for generating +a session key using Diffie-Hellman is as follows: +

    +
      +
    1. The Diffie-Hellman parameters are generated using +R_GenerateDHParams, and passed to the relevant parties (this exchange +can take place over an insecure communications path, as knowledge of the +Diffie-Hellman parameters does not assist an attacker). +
    2. +
    3. The two parties wishing to communicate each generate public and private +values using R_SetupDHAgreement, using the agreed on parameters. +
    4. +
    5. Both parties exchange public values, and compute the session key using +R_ComputeDHAgreedKey. +
    +

    +Functions

    +

    +R_GeneratePEMKeys

    +

    int R_GeneratePEMKeys(publicKey, privateKey, protoKey, randomStruct)
    R_RSA_PUBLIC_KEY +*publicKey; /* new RSA public key */
    R_RSA_PRIVATE_KEY *privateKey; /* new +RSA private key */
    R_RSA_PROTO_KEY *protoKey; /* RSA prototype key */
    R_RANDOM_STRUCT +*randomStruct; /* random structure */

    +

    +Generates an RSA public/private key pair, based on the supplied prototype key.

    +

    +On success, returns zero, with the new public and private keys returned in +publicKey and privateKey.

    +

    +On error, returns RE_MODULUS_LEN if the modulus length specified in +protoKey is invalid (either less than MIN_RSA_MODULUS_BITS or greater +than MAX_RSA_MODULUS_BITS), RE_NEED_RANDOM if randomStruct has not been +initialised or RE_DATA if a problem occurred generating primes. + +

    +

    +R_GenerateDHParams

    +

    int R_GenerateDHParams(params, primeBits, subPrimeBits, randomStruct)
    R_DH_PARAMS +*params; /* new Diffie-Hellman parameters */
    unsigned int primeBits; /* +length of prime in bits */
    unsigned int subPrimeBits; /* length of subprime +in bits */
    R_RANDOM_STRUCT *randomStruct; /* random structure */

    +

    +Generates a set of Diffie-Hellman parameters (prime/modulus and generator). +primeBits indicates the length of the prime required (in bits), and +subPrimeBits indicates the length of a prime "q" that divides +p-1. The resulting Diffie-Hellman "generator" is of order q. randomStruct +points to an initialised random structure.

    +

    +It is the caller's responsibility to use sensible values for primeBits; +there are no sanity checks.

    +

    +On success, returns zero, and the Diffie-Hellman parameters in params.

    +

    +On error, returns RE_NEED_RANDOM if randomStruct has not been +initialised or RE_DATA if a problem occurred generating primes. + +

    +

    +R_SetupDHAgreement

    +

    int R_SetupDHAgreement(publicValue, privateValue, privateValueLen, +params,
    randomStruct)
    unsigned char +*publicValue; /* new public value */
    unsigned char *privateValue; /* new +private value */
    unsigned int privateValueLen; /* length of private value */
    R_DH_PARAMS +*params; /* Diffie-Hellman parameters */
    R_RANDOM_STRUCT *randomStruct; /* +random structure */

    +

    +Generates a set of public and private Diffie-Hellman values, using the supplied +prime and generator (from params).

    +

    +params is a previously initialised R_DH_PARAMS structure, +randomStruct points to an initialised random structure. +privateValueLen indicates the length of the required private value in +bytes (typically, the same size as the subPrimeBits value supplied to +R_GenerateDHParameters).

    +

    +On success, returns IDOK, with the Diffie-Hellman private and public values in +privateValue and publicValue respectively (publicValue +is the same length as params->prime).

    +

    +On error, returns RE_NEED_RANDOM if randomStruct has not been +initialised or RE_DATA if a problem occurred generating primes. + +

    +

    +R_ComputeDHAgreedKey

    +

    int R_ComputeDHAgreedKey(agreedKey, otherPublicValue, privateValue, +
    privateValueLen, params)
    unsigned char +*agreedKey; /* new agreed key */
    unsigned char *otherPublicValue; /* other's +public value */
    unsigned char *privateValue; /* private value */
    unsigned +int privateValueLen; /* length of private value */
    R_DH_PARAMS *params; /* +Diffie-Hellman parameters */

    +

    +Computes a session key from supplied Diffie-Hellman parameters.

    +

    +params is a previously initialised R_DH_PARAMS structure, +randomStruct points to an initialised random structure. +privateValue points to the caller's Diffie-Hellman private value (privateValueLen +bytes long). OtherPublicValue points to the other party's Diffie-Hellman +public value (which is params->primeLen +long).

    +

    +On success, returns IDOK, with the generated session key in agreedKey (params->primeLen +bytes long).

    +

    +On error, returns RE_DATA for a mathematical error (such as incorrect public +values or invalid params structure). + +

    +
    +

    +RSA

    +
      +
    1. Introduction +
    2. +
    3. Functions
        +
      1. RSAPrivateEncrypt +
      2. +
      3. RSAPrivateDecrypt +
      4. +
      5. RSAPublicEncrypt +
      6. +
      7. RSAPublicDecrypt
    4. +
    +

    +Introduction

    +

    This section describes the RSA processing routines provided by RSAEURO for +RSA encryption and decryption. The RSA functions are listed below: +

    +
    • RSAPrivateEncrypt Encrypts a block of data using an RSA +private key, according to PKCS#1: RSA Encryption Standard.
    • +
    • +RSAPrivateDecrypt Decrypts a block of data using an RSA private key, +according to PKCS#1: RSA Encryption Standard.
    • +
    • RSAPublicEncrypt Encrypts a block of data using an RSA public key, +according to PKCS#1: RSA Encryption Standard.
    • +
    • RSAPublicDecrypt Decrypts a block of data using an RSA public key, +according to PKCS#1: RSA Encryption Standard.
    +
    +

    NOTE: Paul Kocher recently published a timing-based attack which +could be used against RSA encryption providing the attacker has access to the +machine performing the encryption - this is not usually the case with +email encryption. Future versions of RSAEURO will incorporate protection +against such attacks. For further details, see the preliminary draft of the +paper, available on the Internet at http://www.cryptography.com +and RSADSI's response at http://www.rsa.com. + +

    +
    +

    +Functions

    +

    +RSAPrivateEncrypt

    +

    int RSAPrivateEncrypt(output, outputLen, input, inputLen, privateKey)
    unsigned +char *output; /* output block */
    unsigned int *outputLen; /* length of +output block */
    unsigned char *input; /* input block */
    unsigned int +inputLen; /* length of input block */
    R_RSA_PRIVATE_KEY *privateKey; /* RSA +private key */

    +

    +Performs a PKCS#1-compliant RSA private-key encryption. inputLen bytes +from input are encrypted using privateKey, and the result +returned in ouput, outputLen bytes long. output should +be large enough to hold the result of the calculation, which will be one byte +longer than the private key (i.e. not larger than MAX_RSA_MODULUS_LEN + +1). inputLen must be at least eleven bytes smaller than the modulus +size (the additional eleven bytes are required for PKCS#1 encoding).

    +

    +On exit, outputLen bytes of encrypted data are returned in +output. Returns RE_LEN if the input block is too large for the supplied +key, IDOK otherwise. + +

    +

    +RSAPrivateDecrypt

    +

    int RSAPrivateDecrypt(output, outputLen, input, inputLen, privateKey)
    unsigned +char *output; /* output block */
    unsigned int *outputLen; /* length of +output block *
    unsigned char *input; /* input block */
    unsigned int +inputLen; /* length of input block */
    R_RSA_PRIVATE_KEY *privateKey; /* RSA +private key */

    +

    +Performs an RSA private-key decryption of a PKCS#1-compliant input block. +inputLen bytes from input are decrypted using privateKey, +and the result returned in output, outputLen bytes long. +outputLen will be no larger than MAX_RSA_MODULUS_LEN + 1.

    +

    +On exit, outputLen bytes of decrypted data are returned in +output. Returns RE_LEN if the input block size is incorrect for the +supplied key, RE_DATA if the decrypted data is not a valid PKCS#1 data block, +IDOK otherwise. + +

    +

    +RSAPublicEncrypt

    +

    int RSAPublicEncrypt(output, outputLen, input, inputLen, publicKey,
    + randomStruct)
    unsigned char *output; /* output block */
    unsigned +int *outputLen; /* length of output block */
    unsigned char *input; /* input +block */
    unsigned int inputLen; /* length of input block */
    R_RSA_PUBLIC_KEY +*publicKey; /* RSA public key */
    R_RANDOM_STRUCT *randomStruct; /* random +structure */

    +

    +Performs a PKCS#1 compliant RSA public key encryption. inputLen bytes +from input are encrypted using publicKey, and the result +returned in ouput, outputLen bytes long. output should +be large enough to hold the result of the calculation, which will be one byte +longer than the public key (i.e. not larger than MAX_RSA_MODULUS_LEN + +1). +inputLen must be at least eleven bytes smaller than the modulus size +(the additional eleven bytes are required for PKCS#1 encoding). +randomStruct must be an initialised random structure (random data is +required for the PKCS#1 data block).

    +

    +On exit, outputLen bytes of encrypted data are returned in +output. Returns RE_LEN if the input block size is incorrect for the +supplied key, IDOK otherwise.

    +

    + +

    +

    +RSAPublicDecrypt

    +

    int RSAPublicDecrypt(output, outputLen, input, inputLen, publicKey)
    unsigned +char *output; /* output block */
    unsigned int *outputLen; /* length of +output block */
    unsigned char *input; /* input block */
    unsigned int +inputLen; /* length of input block */
    R_RSA_PUBLIC_KEY *publicKey; /* RSA +public key */

    +

    +Performs an RSA public-key decryption of a PKCS#1-compliant input block. +inputLen bytes from input are decrypted using publicKey, +and the result returned in output, outputLen bytes long. +outputLen will be no larger than MAX_RSA_MODULUS_LEN + 1.

    +

    +On exit, outputLen bytes of decrypted data are returned in +output. Returns RE_LEN if the input block size is incorrect for the +supplied key, RE_DATA if the decrypted data is not a valid PKCS#1 data block, +IDOK otherwise.

    +

    + +

    +
    +

    +DES

    +
      +
    1. Introduction +
    2. +
    3. Functions
        +
      1. DES_CBCInit +
      2. +
      3. DES_CBCUpdate +
      4. +
      5. DES_CBCRestart +
      6. +
      7. DES3_CBCInit +
      8. +
      9. DES3_CBCRestart +
      10. +
      11. DES3_CBCUpdate +
      12. +
      13. DESX_CBCInit +
      14. +
      15. DESX_CBCRestart +
      16. +
      17. DESX_CBCUpdate
    4. +
    +

    +Introduction

    +

    This section describes the core DES processing routines provided by RSAEURO +for DES encryption and decryption in various modes of operation.

    +

    +RSAEURO supports three different DES modes: single-key DES in +cipher-block-chaining (CBC) mode, three-key DES in CBC mode using "encrypt-decrypt-encrypt" +and DESX, RSADSI's "enhanced" DES (CBC with an additional XOR with a +secret value). Dual-key DES is provided for envelope processing by using +three-key DES with key1 equal to key3.

    +

    +DES support in each mode consists of three basic functions: init, which +initialises the relevant structure and loads the key (as supplied to the +init function); update, which processes a block of input data +using an initialised context, either encrypting or decrypting, and +restart which restarts a context, resetting the initialisation vector, +allowing the re-use of the same key for further CBC operations.

    +

    +The context contains the key (in the form of subkeys) during the DES operation, +and as such should be treated as sensitive data. It is the caller's +responsibility to clear the context once the DES operation is complete.

    +

    + +

    +

    +Functions

    +

    +DES_CBCInit

    +

    void DES_CBCInit(context, key, iv, encrypt)
    DES_CBC_CTX +*context; /* context */
    unsigned char *key; /* key */
    unsigned char +*iv; /* initializing vector */
    int encrypt; /* encrypt flag (1 = encrypt, 0 += decrypt) */

    +

    +Initialises a DES CBC context, loading the context with the subkeys. +context is a blank DES_CBC_CTX structure, key is the DES key, +iv is the initialising vector and encrypt is a flag indicating +encryption or decryption (zero for decryption, any other value for encryption). +Both key and iv are unsigned char arrays of eight bytes each.

    +

    +Note that on exit context contains the key supplied, and should be +handled as security sensitive data. It is the caller's responsibility to clear +context once the encryption or decryption operation has been completed.

    +

    + +

    +

    +DES_CBCUpdate

    +

    int DES_CBCUpdate(context, output, input, len)
    DES_CBC_CTX +*context; /* context */
    unsigned char *output; /* output block */
    unsigned +char *input; /* input block */
    unsigned int len;

    +

    +Continues a DES_CBC operation, encrypting len bytes from input +using the supplied context, placing the results in output. +context must be a DES_CBC_CTX structure which has been initialised using +DES_CBCInit. len must be a multiple of eight bytes. +output must have at least len bytes available.

    +

    +On exit, output contains len bytes of encrypted data. Returns +RE_LEN if len is not an integer multiple of eight bytes, IDOK otherwise. + +

    +

    +DES_CBCRestart

    +

    void DES_CBCRestart(context)
    DES_CBC_CTX *context;

    +

    +Restarts the supplied DES_CBC context, resetting the initialisation vector to +the original value, allowing the use of the same context (and, consequently, the +same DES key) on a new block of data. Note that the key information is not +cleared, so context should be handled as security sensitive data.

    +

    + +

    +

    +DES3_CBCInit

    +

    void DES3_CBCInit(context, key, iv, encrypt)
    DES3_CBC_CTX +*context; /* context */
    unsigned char *key; /* key */
    unsigned char +*iv; /* initializing vector */
    int encrypt; /* encrypt flag (1 = encrypt, 0 += decrypt) */

    +

    +Initialises an Encrypt-Decrypt-Encrypt (EDE) DES CBC context, loading the +context with the subkeys from the three supplied DES keys. context is a +blank DES3_CBC_CTX structure, key is the DES key, iv is the +initialising vector and encrypt is a flag indicating encryption or +decryption (zero for decryption, any other value for encryption). Both +key and iv are unsigned byte arrays, of twenty-four and eight +bytes respectively (the key array consists of the three DES keys +concatenated).

    +

    +Note that on exit context contains the key supplied, and should be +handled as security sensitive data. It is the caller's responsibility to clear +context once the encryption or decryption operation has been completed. + +

    +

    +DES3_CBCRestart

    +

    void DES3_CBCRestart (context)
    DES3_CBC_CTX *context; /* context +*/

    +

    +Restarts the supplied DES3_CBC context, resetting the initialisation vector to +the original value, allowing the use of the same context (and, consequently, the +same DES key) on a new block of data. Note that the key information is not +cleared, so context should be handled as security sensitive data. + +

    +

    +DES3_CBCUpdate +

    +

    int DES3_CBCUpdate(context, output, input, len)
    DES3_CBC_CTX +*context; /* context */
    unsigned char *output; /* output block */
    unsigned +char *input; /* input block */
    unsigned int len; /* length of input and +output blocks */

    +

    +Continues a DES3_CBC operation, encrypting len bytes from input +using the supplied context, placing the results in output. +context must be a DES3_CBC_CTX structure which has been initialised +using DES3_CBCInit. len must be a multiple of eight bytes. +output must have at least len bytes available.

    +

    +On exit, output contains len bytes of encrypted data. Returns +RE_LEN if len is not an integer multiple of eight bytes, IDOK otherwise. + +

    +

    +DESX_CBCInit

    +

    void DESX_CBCInit(context, key, iv, encrypt)
    DESX_CBC_CTX +*context; /* context */
    unsigned char *key; /* DES key and whiteners */
    unsigned +char *iv; /* DES initializing vector */
    int encrypt; /* encrypt flag (1 = +encrypt, 0 = decrypt) */

    +

    +Initialises an DESX CBC context, loading the context with the subkeys and "whiteners" +from the supplied key. context is a blank DESX_CBC_CTX structure, key +is the DESX key (the DES key, input whitener and output whitener concatenated), +iv is the initialising vector and encrypt is a flag indicating +encryption or decryption (zero for decryption, any other value for encryption). +Both key and iv are unsigned byte arrays, of twenty-four and +eight bytes respectively (the key array consists of the three DES keys +concatenated).

    +

    +Note that on exit context contains the key supplied, and should be +handled as security sensitive data. It is the caller's responsibility to clear +context once the encryption or decryption operation has been completed. + +

    +

    +DESX_CBCRestart

    +

    void DESX_CBCRestart(context)
    DESX_CBC_CTX *context; /* context +*/

    +

    +Restarts the supplied DESX_CBC context, resetting the initialisation vector to +the original value, allowing the use of the same context (and, consequently, the +same DES key) on a new block of data. Note that the key information is not +cleared, so context should be handled as security sensitive data. + +

    +

    +DESX_CBCUpdate +

    +

    int DESX_CBCUpdate (context, output, input, len)
    DESX_CBC_CTX +*context; /* context */
    unsigned char *output; /* output block */
    unsigned +char *input; /* input block */
    unsigned int len; /* length of input and +output blocks */

    +

    +Continues a DESX_CBC operation, encrypting len bytes from input +using the supplied context, placing the results in output. +context must be a DESX_CBC_CTX structure which has been initialised +using DESX_CBCInit. len must be a multiple of eight bytes. +output must have at least len bytes available.

    +

    +On exit, output contains len bytes of encrypted data. Returns +RE_LEN if len is not an integer multiple of eight bytes, IDOK otherwise.

    +

    + +

    +
    +

    +NATURAL NUMBER ARITHMETIC +

    +
      +
    1. Introduction +
    2. +
    3. Representation of natural numbers +
    4. +
    5. Functions
        +
      1. NN_Decode +
      2. +
      3. NN_Encode +
      4. +
      5. NN_Assign +
      6. +
      7. NN_AssignZero +
      8. +
      9. NN_Assign2Exp +
      10. +
      11. NN_Add +
      12. +
      13. NN_Sub +
      14. +
      15. NN_Mult +
      16. +
      17. NN_LShift +
      18. +
      19. NN_RShift +
      20. +
      21. NN_Div +
      22. +
      23. NN_Mod +
      24. +
      25. NN_ModMult +
      26. +
      27. NN_ModExp +
      28. +
      29. NN_ModInv +
      30. +
      31. NN_Gcd +
      32. +
      33. NN_Cmp +
      34. +
      35. NN_Zero +
      36. +
      37. NN_Digits +
      38. +
      39. NN_Bits +
      40. +
      41. GeneratePrime
    6. +
    +

    +Introduction

    +

    This section describes the natural number arithmetic "primitives" +used by various functions within RSAEURO. The following table provides brief +details, and the function descriptions which follow provide more detailed +information. +

    +
    • NN_Decode(a, digits, b, len) Decodes a character array +representation `a' into a "raw" value b
    • +
    • NN_Encode(a, len, b, digits) Encodes a "raw" value a +into a character array 'b'
    • +
    • NN_Assign(a, b, digits) Assigns a = b
    • +
    • NN_AssignZero(a, digits) Zeroises a
    • +
    • NN_Assign2Exp(a, b, digits) Assigns a = 2 ** b
    • +
    • NN_Add(a, b, c, digits) Computes a = b + c
    • +
    • NN_Sub(a, b, c, digits) Computes a = b - c
    • +
    • NN_Mult(a, b, c, digits) Computes a = b * c
    • +
    • +NN_LShift(a, b, c, digits) Computes a = b * 2 ** c (i.e. shifts b left +c bits, returning the result in a)
    • +
    • NN_RShift(a, b, c, digits) Computes a = b / 2 ** c (i.e. shifts b +right c bits, returning the result in a)
    • +
    • NN_Div(a, b, c, cDigits, d, dDigits) Computes a = c div d and b = +c mod d
    • +
    • NN_Mod(a, b, bDigits, c, cDigits) Computes a = b mod c
    • +
    • NN_ModMult(a, b, c, d, digits) Computes a = b * c mod d
    • +
    • NN_ModExp(a, b, c, cDigits, d, dDigits) Computes a = b ** c mod d
    • +
    • NN_ModInv(a, b, c, digits) Computes a = 1/b mod c
    • +
    • NN_Gcd(a, b, c, digits) Assigns a to the greatest common divisor +of b and c
    • +
    • NN_Cmp(a, b, digits) Returns the sign of a - b
    • +
    • +NN_Zero(a, digits) Returns 1 iff a = 0
    • +
    • NN_Digits(a, digits) Returns the significant length of natural +number a in digits
    • +
    • NN_Bits(a, bits) Returns the significant length of the natural +number a in bits
    • +
    • NN_DigitBits (a) Returns the significant length of the digit a in +bits
    +
    +                                                
    +
    +
    +

    +Representation of natural numbers +

    +

    Natural numbers are represented internally in RSAEURO as arbitrary-length +NN_DIGIT arrays, where the NN_DIGIT type is by default an unsigned 32-bit value +(UINT4). The maximum size of an NN_DIGIT array is set by MAX_NN_DIGITS which is +derived from MAX_RSA_MODULUS_LEN, to ensure that all values are generated within +an appropriate range. The mathematical functions effectively treat NN_DIGIT +arrays as integers of an arbitrary length. In the context of natural numbers +within RSAEURO, a "digit" is an NN_DIGIT element of a natural number, +as opposed to the normal meaning (i.e. a single numerical digit). For +example, a ten-digit NN_DIGIT array consists of forty bytes of data (ten +UINT4s).

    +

    +NN_DIGIT arrays are packed into unsigned character arrays, most significant bit +first, when values are returned to higher-level functions. This behaviour is +primarily to maintain compatibility with existing RSAREF code.

    +

    +For the remainder of this section, the term "natural number" is used +to describe an NN_DIGIT array. + +

    +

    +Functions

    +

    +NN_Decode

    +

    void NN_Decode (a, digits, b, len)
    NN_DIGIT *a;
    unsigned char +*b;
    unsigned int digits, len;

    +

    +Decodes a character array into a natural number. b is a pointer to the +character array, which is len bytes long. a is a pointer to the +destination natural number, which is digits digits long.

    +

    +digits must be large enough to accommodate len bytes; if it is +not, the most significant bytes of a are truncated. + +

    +

    +NN_Encode

    +

    void NN_Encode (a, len, b, digits)
    NN_DIGIT *b;
    unsigned char +*a;
    unsigned int digits, len;

    +

    +Encodes a natural number into a character array. b is a pointer to the +natural number, which is digits digits long. a points to the +destination character array, which is len bytes long.

    +

    +len must be long enough to accommodate digits digits of b; +if it is not, the most significant digits of the natural number are truncated. + +

    +

    +NN_Assign

    +

    void NN_Assign (a, b, digits)
    NN_DIGIT *a, *b;
    unsigned int +digits;

    +

    +Assigns a = b, where a and b are natural numbers. Note that +only +digits digits of a are assigned, so if NNDigits(a) > +NNDigits(b), the most significant digits of a will not be cleared. + +

    +

    +NN_AssignZero

    +

    void NN_AssignZero (a, digits)
    NN_DIGIT *a;
    unsigned int +digits;

    +

    +Zeroises digits digits of the natural number a. + +

    +

    +NN_Assign2Exp

    +

    void NN_Assign2Exp (a, b, digits)
    NN_DIGIT *a;
    unsigned int +b, digits;

    +

    +Assigns a = 2b. a is the destination natural number which has +digits digits and b is the exponent. The result is undefined if +b is greater than digits&nbsp;*&nbsp;NN_DIGIT_BITS. + +

    +

    +NN_Add

    +

    NN_DIGIT NN_Add (a, b, c, digits)
    NN_DIGIT *a, *b, *c;
    unsigned +int digits;

    +

    +Computes a = b + c, and returns the carry. a, b, c and +the return value are natural numbers, all digits digits long. + +

    +

    +NN_Sub

    +

    NN_DIGIT NN_Sub (a, b, c, digits)
    NN_DIGIT *a, *b, *c;
    unsigned +int digits;

    +

    +Computes a = b - c, and returns the borrow. a, b, c and +the return value are natural numbers, all digits digits long. + +

    +

    +NN_Mult

    +

    void NN_Mult (a, b, c, digits)
    NN_DIGIT *a, *b, *c;
    unsigned +int digits;

    +

    +Computes a = b * c. a, b, c and the return value are +natural numbers, all digits digits long. The result is undefined if +digits > MAX_NN_DIGITS. + +

    +

    +NN_LShift

    +

    NN_DIGIT NN_LShift (a, b, c, digits)
    NN_DIGIT *a, *b;
    unsigned +int c, digits;

    +

    +Computes a = b * 2c (i.e. shifts b left c bits, +returning the result in a). a, b, c and the +return value are natural numbers, all digits digits long. The result is +undefined if +c > NN_DIGIT_BITS. + +

    +

    +NN_RShift

    +

    NN_DIGIT NN_RShift (a, b, c, digits)
    NN_DIGIT *a, *b;
    unsigned +int c, digits;

    +

    +Computes a = b div 2c (i.e. shifts b right c bits, returning the result +in a). Returns the carry. a, b, c and the return value +are natural numbers, all digits digits long. The result is undefined if +c > NN_DIGIT_BITS. + +

    +

    +NN_Div

    +

    void NN_Div (a, b, c, cDigits, d, dDigits)
    NN_DIGIT *a, *b, *c, +*d;
    unsigned int cDigits, dDigits;

    +

    +Computes a = c div d and b = c mod d. a, b, c and d +are natural numbers. a and c are cDigits digits long, +b and d are dDigits digits long. The result is +undefined if d = 0, cDigits >= 2&nbsp;*&nbsp;MAX_NN_DIGITS +or +dDigits > MAX_NN_DIGITS. + +

    +

    +NN_Mod

    +

    void NN_Mod (a, b, bDigits, c, cDigits)
    NN_DIGIT *a, *b, *c;
    unsigned +int bDigits, cDigits;

    +

    +Computes a = b mod c. a, b, and c are natural numbers. +a and c are cDigits long, b is bDigits +long. The result is undefined if c = 0, bDigits >= 2&nbsp;*&nbsp;MAX_NN_DIGITS +or cDigits > MAX_NN_DIGITS + +

    +

    +NN_ModMult

    +

    void NN_ModMult (a, b, c, d, digits)
    NN_DIGIT *a, *b, *c, *d;
    unsigned +int digits;

    +

    +Computes a = b * c mod d. a, b, c and d are +natural numbers, all digits digits long. The result is undefined if +d = 0 or digits > MAX_NN_DIGITS. + +

    +

    +NN_ModExp

    +

    void NN_ModExp (a, b, c, cDigits, d, dDigits)
    NN_DIGIT *a, *b, +*c, *d;
    unsigned int cDigits, dDigits;

    +

    +Computes a = bc mod d. a, b, c and d are natural +numbers. a, b and d are dDigits digits long, +c is cDigits digits long.. The result is undefined if d += 0, cDigits = 0 or dDigits > MAX_NN_DIGITS. + +

    +

    +NN_ModInv

    +

    void NN_ModInv (a, b, c, digits)
    NN_DIGIT *a, *b, *c;
    unsigned +int digits;

    +

    +Computes a = 1/b mod c. a, b and c are natural numbers, +all digits digits long. The result is undefined if b and +c are not relatively prime (e.g. gcd(b, c) is not 1) or +digits > MAX_NN_DIGITS. + +

    +

    +NN_Gcd

    +

    void NN_Gcd(a ,b ,c, digits)
    NN_DIGIT *a, *b, *c;
    unsigned +int digits;

    +

    +Calculates the greatest common divisor of b and c, returning the +result in a. a, b and c are natural numbers, all +digits digits long. The result is undefined if c < b +or digits > MAX_NN_DIGITS.

    +

    + +

    +

    +NN_Cmp

    +

    int NN_Cmp (a, b, digits)
    NN_DIGIT *a, *b;
    unsigned int +digits;

    +

    +Compares a and b, returns -1 if a<b, 0 if a=b +or 1 if a>b. . a, b and c are natural +numbers, all digits digits long. + +

    +

    +NN_Zero

    +

    int NN_Zero (a, digits)
    NN_DIGIT *a;
    unsigned int digits;

    +

    +Returns 1 iff a = 0, otherwise returns 1. a is a natural number, +digits digits long. + +

    +

    +NN_Digits

    +

    unsigned int NN_Digits (a, digits)
    NN_DIGIT *a;
    unsigned int +digits;

    +

    +Returns the significant length in digits of the natural number a (e.g. +the position of the first non-zero digit). digits is the length of a +in digits. + +

    +

    +NN_Bits

    +

    unsigned int NN_Bits (a, digits)
    NN_DIGIT *a;
    unsigned int +digits;

    +

    +Returns the significant length in bits of the natural number a (e.g. +the position of the first non-zero bit). digits is the total length of +a in digits. + +

    +

    +GeneratePrime

    +

    int GeneratePrime(a, b, c, d, digits, randomStruct)
    NN_DIGIT *a, +*b, *c, *d;
    unsigned int digits;
    R_RANDOM_STRUCT *randomStruct; /* +random structure */

    +

    +Generates a random probable prime a, where b < a < +c and a-1 is divisible by d. a, b, c +and d are natural numbers, all digits digits long. +randomStruct is an initialised R_RANDOM_STRUCT.

    +

    +On exit, the generated prime is returned in a. Returns RE_NEED_RANDOM if +randomStruct has not been fully initialised, RE_DATA if a suitable prime +could not be found, IDOK otherwise. + +

    +
    +

    +MEMORY MANIPULATION +

    +
      +
    1. Introduction +
    2. +
    3. Functions
        +
      1. R_memset +
      2. +
      3. R_memcpy +
      4. +
      5. R_memcmp
    4. +
    +

    +Introduction

    +

    There are three memory manipulation functions used within RSAEURO: +

    +
    • R_memset Sets a range of memory to a specified value. +
    • +
    • R_memcpy Copies a block of memory to another address. +
    • +
    • R_memcmp Compares two blocks of memory. +
    +

    All of these routines are "secure", in that no intermediate +storage is used during their operation. + +

    +

    +Functions

    +

    +R_memset

    +

    void R_memset(output, value, len)
    POINTER output; /* output block +*/
    int value; /* value */
    unsigned int len; /* length of block */

    +

    +Sets len bytes starting at output to value. + +

    +

    +R_memcpy

    +

    void R_memcpy(output, input, len)
    POINTER output; /* output block +*/
    POINTER input; /* input block */
    unsigned int len; /* length of +blocks */

    +

    +Copies len bytes from input to output. + +

    +

    +R_memcmp

    +

    int R_memcmp(Block1, Block2, len)
    POINTER Block1; /* first block +*/
    POINTER Block2; /* second block */
    unsigned int len; /* length of +blocks */

    +

    +Compares len bytes starting at Block1 with Block2.

    +

    +Returns zero if the blocks are identical. If the blocks are different, returns +the difference between the first two non-identical bytes (returns +Block1[difference] - Block2[difference], where difference is the offset +of the first non-identical byte. + +

    +
    +

    +TECHNICAL INFORMATION +

    +
      +
    1. Introduction +
    2. +
    3. Error Types +
    4. +
    5. RSAEURO Data Types
        +
      1. R_RANDOM_STRUCT +
      2. +
      3. R_RSA_PUBLIC_KEY +
      4. +
      5. R_RSA_PRIVATE_KEY +
      6. +
      7. R_RSA_PROTO_KEY +
      8. +
      9. R_DH_PARAMS +
      10. +
      11. R_DIGEST_CTX +
      12. +
      13. R_SIGNATURE_CTX +
      14. +
      15. R_ENVELOPE_CTX +
      16. +
      17. MD2_CTX +
      18. +
      19. MD4_CTX +
      20. +
      21. MD5_CTX +
      22. +
      23. SHS_CTX +
      24. +
      25. DES_CBC_CTX +
      26. +
      27. DESX_CBC_CTX +
      28. +
      29. DES3_CBC_CTX
      30. +
    6. +
    7. Configuration parameters +
    8. +
    9. Platform-specific Configuration
        +
      1. Types +
      2. +
      3. Defined macros
      4. +
    10. +
    11. References
        +
      1. General +
      2. +
      3. RSA +
      4. +
      5. Diffie-Hellman +
      6. +
      7. Digest Algorithms +
      8. +
      9. DES +
      10. +
      11. Privacy-enhanced mail
    12. +
    +

    +Introduction

    +

    This section contains miscellaneous technical information regarding RSEURO. +The following subjects are covered: +

    +
      +
    1. Error Type. A complete list of RSAEURO error types and possible +explanations. +
    2. +
    3. RSAEURO Data Types A list and brief description of the major +RSAEURO data types. +
    4. +
    5. Platform-specific configuration Platform-specific configuration +information, including compiler settings and data structures. +
    6. +
    7. References Sources of further reading for related subjects and +standards +
    +

    +Error Types +

    +
    +RE_CONTENT_ENCODING +
    +
    An ASCII encoding error occurred during the decoding of a content block.
    +
    RE_DATA +
    +
    An error occurred during one of the mathematical routines. Usually caused +by incorrect or invalid data, such as an unmatched set of Diffie-Hellman values.
    +
    RE_DIGEST_ALGORITHM +
    +
    An invalid digest algorithm was selected; either an unsupported digest was +selected (i.e. not one of the DA_xx values from RSAEURO.H), or SHS was selected +for signature generation. +
    +
    RE_ENCODING +
    +
    An ASCII encoding error occurred during the decoding of a data block.
    +
    RE_KEY +
    +
    The recovered session key cannot decrypt the associated content or +signature.
    +
    RE_KEY_ENCODING +
    +
    An ASCII encoding error occurred during the decoding of a session key.
    +
    RE_LEN +
    +
    An out-of-range signature or session key was encountered, or the data +supplied to an RSA function was too large for the key provided.
    +
    RE_MODULUS_LEN +
    +
    An invalid RSA modulus length was specified (either too long or too short.
    +
    RE_NEED_RANDOM +
    +
    An attempt was made to generate random data using an uninitialised random +structure.
    +
    RE_PRIVATE_KEY +
    +
    The supplied private key was invalid/incorrect.
    +
    RE_PUBLIC_KEY +
    +
    The supplied public key was invalid/incorrect.
    +
    RE_SIGNATURE +
    +
    The signature does not match the associated data block.
    +
    RE_SIGNATURE_ENCODING +
    +
    An ASCII encoding error occurred during the decoding of a signature.
    +
    RE_ENCRYPTION_ALGORITHM +
    +
    An invalid encryption algorithm was specified. + +
    +

    +RSAEURO Data Types +

    +

    +R_RANDOM_STRUCT

    +

    typedef struct {
    unsigned int bytesNeeded; /* seed bytes +required */
    unsigned char state[16]; /* state of object */
    unsigned +int outputAvailable; /* number byte available */
    unsigned char +output[16]; /* output bytes */
    } R_RANDOM_STRUCT;

    +

    +The R_RANDOM_STRUCT type stores the state and characteristics of a random number +generator. bytesNeeded Number of remaining "mix in" bytes required to +initialise the structure (initially defined by RANDOM_BYTES_RQ). Must be zero +before the structure may be used.

    +

    +state Internal state of the random number generator.

    +

    +outputAvailable Indicates the number of unused bytes in the output +array. When this value reaches zero, the output array is regenerated.

    +

    +output Output of the random number generator. + +

    +

    +R_RSA_PUBLIC_KEY

    +

    typedef struct {
    unsigned int bits; /* length in bits of +modulus */
    unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */
    +unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* public exponent */
    } +R_RSA_PUBLIC_KEY;

    +

    +The R_RSA_PUBLIC_KEY type stores an RSA public key. bits The length of the +modulus in bits (MIN_RSA_MODULUS_BITS < bits £ MAX_RSA_MODULUS_BITS).

    +

    +modulus The modulus, stored as a MAX_RSA_MODULUS_LEN byte number, most +significant byte first, padded with zero bytes.

    +

    +exponent The public exponent, stored in the same manner as the modulus. + +

    +

    +R_RSA_PRIVATE_KEY

    +

    typedef struct {
    unsigned int bits; /* length in bits of +modulus */
    unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */
    +unsigned char publicExponent[MAX_RSA_MODULUS_LEN]; /* public exponent */
    +unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* private exponent */
    +unsigned char prime[2][MAX_RSA_PRIME_LEN]; /* prime factors */
    unsigned +char primeExponent[2][MAX_RSA_PRIME_LEN]; /* exponents for CRT */
    unsigned +char coefficient[MAX_RSA_PRIME_LEN]; /* CRT coefficient */
    } +R_RSA_PRIVATE_KEY;

    +

    +The R_RSA_PRIVATE_KEY type stores an RSA private key. bits The length of the +modulus in bits (MIN_RSA_MODULUS_BITS < bits £ MAX_RSA_MODULUS_BITS).

    +

    +modulus The modulus, stored as a MAX_RSA_MODULUS_LEN byte number, most +significant byte first, zero padded.

    +

    +publicExponent The public exponent, stored in the same manner as the +modulus.

    +

    +exponent The private exponent, stored in the same manner as the modulus.

    +

    +prime The prime factors (p and q) of the modulus, stored as two +MAX_RSA_PRIME_LEN long numbers in the same manner as the modulus (p&nbsp;>&nbsp;q).

    +

    +primeExponent The exponents for Chinese Remainder Theorem operations (d +mod p-1 and d&nbsp;mod&nbsp;q-1), stored in the same manner as prime.

    +

    +coefficient The coefficient (1/q mod p) for Chinese Remainder Theorem +operations, stored in the same manner as prime. + +

    +

    +R_RSA_PROTO_KEY

    +

    typedef struct {
    unsigned int bits; /* length in bits of +modulus */
    int useFermat4; /* public exponent (1 = F4, 0 = 3) */
    } +R_RSA_PROTO_KEY;

    +

    +The R_RSA_PROTO_KEY type provides a template for RSA keypair generation. +bits Length of the modulus in bits (MIN_RSA_MODULUS_BITS < bits < +MAX_RSA_MODULUS_BITS).

    +

    +useFermat4 Public exponent, either Fermat4 or 3. + +

    +

    +R_DH_PARAMS

    +

    typedef struct {
    unsigned char *prime; /* prime */
    +unsigned int primeLen; /* length of prime */
    unsigned char *generator; /* +generator */
    unsigned int generatorLen; /* length of generator */
    } +R_DH_PARAMS;

    +

    +The R_DH_PARAMS type stores a set of parameters for a Diffie-Hellman key +exchange. prime The prime p, stored as a primeLen-byte long number, most +significant byte first, zero padded.

    +

    +primeLen The length in bytes of prime.

    +

    +generator The generator g, stored in the same manner as prime.

    +

    +generatorLen The length in bytes of generator. + +

    +

    +R_DIGEST_CTX

    +

    typedef struct {
    int digestAlgorithm; /* digest type */
    +union { /* digest sub-context */
    MD2_CTX md2;
    MD4_CTX md4;
    +MD5_CTX md5;
    SHS_CTX shs;
    } context;
    } R_DIGEST_CTX;

    +

    +The R_DIGEST_CTX type stores the context for a message digest generation. +digestAlgorithm The message digest algorithm for the context (DA_MD2, DA_MD4, +DA_MD5 or DA_SHS).

    +

    +context The algorithm-specific context + +

    +

    +R_SIGNATURE_CTX

    +

    typedef struct {
    R_DIGEST_CTX digestContext;
    } +R_SIGNATURE_CTX;

    +

    +The R_SIGNATURE_CTX type stores the context for a signature generation. +Currently, R_SIGNATUR_CTX is the same as R_DIGEST_CTX, although it has been +separately typed for future revisions. + +

    +

    +R_ENVELOPE_CTX

    +

    typedef struct {
    int encryptionAlgorithm; /* encryption type */
    +union { /* encryption sub-context */
    DES_CBC_CTX des;
    +DES3_CBC_CTX des3;
    DESX_CBC_CTX desx;
    } cipherContext;
    +unsigned char buffer[8]; /* data buffer */
    unsigned int bufferLen; /* +buffer length */
    } R_ENVELOPE_CTX;

    +

    +The R_ENVELOPE_CTX type stores the context for a "sealing" +(encryption) operation. encryptionAlgorithm The encryption algorithm for the +context (EA_DES_CBC, EA_DES_EDE2_CBC, EA_DES_EDE3_CBC or EA_DESX_CBC).

    +

    +cipherContext The cipher-specific context.

    +

    +buffer The input buffer for the sealing operation (DES encrypts in +64-bit blocks, so incoming data is buffered until 8 bytes are available).

    +

    +bufferLen The number of bytes in the buffer. + +

    +

    +MD2_CTX

    +

    typedef struct {
    unsigned char state[16]; /* state */
    +unsigned char checksum[16]; /* checksum */
    unsigned int count; /* number +of bytes, modulo 16 */
    unsigned char buffer[16]; /* input buffer */
    } +MD2_CTX;

    +

    +The MD2_CTX type stores the context for an MD2 operation. state Internal state +machine.

    +

    +checksum Checksum (see MD2 source for details).

    +

    +count Number of bytes processed, modulo 16.

    +

    +buffer Input buffer for data to be processed. + +

    +

    +MD4_CTX

    +

    typedef struct {
    UINT4 state[4]; /* state (ABCD) */
    UINT4 +count[2]; /* number of bits, modulo 2^64 (lsb first) */
    unsigned char +buffer[64]; /* input buffer */
    } MD4_CTX

    +

    +The MD4_CTX type stores the context for an MD4 operation. state Internal state +machine.

    +

    +count Number of bits processed, modulo 264

    +

    +buffer Input buffer for data to be processed. + +

    +

    +MD5_CTX

    +

    typedef struct {
    UINT4 state[4]; /* state (ABCD) */
    +UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
    unsigned +char buffer[64]; /* input buffer */
    } MD5_CTX;

    +

    +The MD5_CTX type stores the context for an MD5 operation. state Internal state +machine.

    +

    +count Number of bits processed, modulo 264

    +

    +buffer Input buffer for data to be processed. + +

    +

    +SHS_CTX

    +

    typedef struct {
    UINT4 digest [5]; /* Message digest */
    +UINT4 countLo, countHi; /* 64-bit bit count */
    UINT4 data [16]; /* SHS +data buffer */
    } SHS_CTX;

    +

    +The SHS_CTX type stores the context for an MD5 operation. state Internal state +machine.

    +

    +countLo Number of bits processed, least significant part.

    +

    +countHi Number of bits processed, most significant part.

    +

    +data Input buffer for data to be processed. + +

    +

    +DES_CBC_CTX

    +

    typedef struct {
    UINT4 subkeys[32]; /* subkeys */
    UINT4 +iv[2]; /* initializing vector */
    UINT4 originalIV[2]; /* for restarting +the context */
    int encrypt; /* encrypt flag */
    } DES_CBC_CTX;

    +

    +The DES_CBC_CTX type stores the context for an single-key DES CBC operation. +subkeys Array of DES subkeys, ordered according to initialisation (in "normal" +order for encryption, "reverse" order for decryption).

    +

    +iv 64-bit initialising vector (current state).

    +

    +originalIV 64-bit initialising vector (initial state).

    +

    +encrypt "Direction" indicator; one for encrypt, zero for +decrypt. + +

    +

    +DESX_CBC_CTX

    +

    typedef struct {
    UINT4 subkeys[32]; /* subkeys */
    UINT4 +iv[2]; /* initializing vector */
    UINT4 inputWhitener[2]; /* input whitener +*/
    UINT4 outputWhitener[2]; /* output whitener */
    UINT4 +originalIV[2]; /* for restarting the context */
    int encrypt; /* encrypt +flag */
    } DESX_CBC_CTX;

    +

    +The DESX_CBC_CTX type stores the context for an single-key DESX CBC operation. +subkeys Array of DES subkeys, ordered according to initialisation (in "normal" +order for encryption, "reverse" order for decryption).

    +

    +iv 64-bit initialising vector (current state).

    +

    +inputWhitener 64-bit input "whitener", XORed with data during +encryption.

    +

    +outputWhitener 64-bit input "whitener", XORed with data during +encryption.

    +

    +originalIV 64-bit initialising vector (initial state).

    +

    +encrypt "Direction" indicator; one for encrypt, zero for +decrypt. + +

    +

    +DES3_CBC_CTX

    +

    typedef struct {
    UINT4 subkeys[3][32]; /* subkeys for three +operations */
    UINT4 iv[2]; /* initializing vector */
    UINT4 +originalIV[2]; /* for restarting the context */
    int encrypt; /* encrypt +flag */
    } DES3_CBC_CTX;

    +

    +The DES3_CBC_CTX type stores the context for an triple-key DES CBC operation. +subkeys Two-dimensional array of DES subkeys, ordered according to +initialisation (in "normal" order for encryption, "reverse" +order for decryption).

    +

    +iv 64-bit initialising vector (current state).

    +

    +originalIV 64-bit initialising vector (initial state).

    +

    +encrypt "Direction" indicator; one for encrypt, zero for +decrypt. + +

    +

    +Configuration parameters +

    +

    The following table describes some of the values defined in the RSAEURO +toolkit header files which may be modified to customise the behaviour of certain +routines. Although the toolkit has been designed with portability in mind, no +guarantee is made that the code will work with different settings - please +report any difficulties. +

    +
    +Parameter                    Defined in     Description                       Default       
    +                                                                              value         
    +MIN_RSA_MODULUS_BITS         RSAEURO.H      Minimum size permitted for RSA    508 bits      
    +                                            modulus.                                        
    +MAX_RSA_MODULUS_BITS         RSAEURO.H      Maximum size permitted for RSA    1024 bits     
    +                                            modulus.  (Note: change this                    
    +                                            value to allow the use of                       
    +                                            larger keys etc)                                
    +MAX_DIGEST_LEN               RSAEURO.H      Maximum digest size, in bytes,    20 bytes      
    +                                            for any of the supported          (SHS)         
    +                                            algorithms.                                     
    +RSAEURO_VER_MAJ              RSAEURO.H      Major version number of the       1             
    +                                            toolkit.                                        
    +RSAEURO_VER_MIN              RSAEURO.H      Minor version number of the       03            
    +                                            toolkit.                                        
    +RSAEURO_IDENT                RSAEURO.H      Identifier string for the         RSAEURO       
    +                                            toolkit (to support variants)                   
    +RSAEURO_DATE                 RSAEURO.H      Release date of the major         21/08/94      
    +                                            version of the toolkit.                         
    +NN_DIGIT                     NN.H           Type for natural number "digit"   UINT4         
    +                                                                              (32-bit       
    +                                                                              word)         
    +NN_DIGIT_BITS                NN.H           Number of bits in an NN_DIGIT     32            
    +MAX_NN_DIGIT                 RSAEURO.H      Maximum permitted value for an    0xFFFFFFFF    
    +                                            NN_DIGIT                                        
    +RANDOM_BYTES_RQ              R_RANDOM.C     Number of random bytes required   256           
    +                                            to "seed" a random structure                    
    +                                            prior to use.                                   
    +RANDOM_BYTES_RQINT           R_RANDOM.C     Number of random bytes from       512           
    +                                            ANSI time functions required to                 
    +                                            "seed" a random structure prior                 
    +                                            to use.                                         
    +SHS_BLOCKSIZE                SHS.H          SHS block size, in bytes.         60            
    +SHS_DIGESTSIZE               SHS.H          SHS digest size, in bytes.        20            
    +
    +
    +

    +Platform-specific Configuration +

    +

    +Types

    +

    There are three platform-specific types used in RSAEURO, defined in GLOBAL.H +and described in the following paragraphs. POINTER A generic pointer to memory. +It should be possible to cast any other pointer to POINTER.

    +

    +BYTE An 8-bit byte.

    +

    +UINT2 A 16-bit unsigned integer.

    +

    +UINT4 A 32-bit unsigned integer. + +

    +

    +Defined macros +

    +

    RSAEURO uses three #defined macros: +

    +
    • PROTOTYPES The PROTOTYPES macro indicates the form of C function +declarations. If it is non-zero, functions are declared as:

      type +function (type, ...., type);

      + Otherwise, they take the form:

      type function ();

    • +
    • +USEASM If USEASM is defined then assembler routines are used where available. +Assembler versions of the key performance bottlenecks are under development. +Please check the source list to see which functions have been implemented in +assembler.

    • +
    • +USE_ANSI If USE_ANSI is defined, the ANSI-standard memcpy, memcmp and memset +routines are used in place of the RSAEURO stdlib routines. + +

    +

    +References

    +

    +General

    +

    For general information about cryptography and its applications, consult the +following: +

    +
      +
    • Bruce Schneier's "Applied Cryptography&nbsp;-&nbsp;Protocols, +Algorithms, and Source Code in C" (John Wiley & Sons, ISBN TBA) is an +excellent introduction to cryptography both from the theoretical and "real +world" perspective. It contains full coverage of all the commonly-used +algorithms, and a detailed examination of the accompanying protocols. +
    • +
    • The frequently-asked questions (FAQ) file for the Usenet newsgroup +sci.crypt provides a good basic coverage of the issues involved in cryptography, +and is available free of charge over the Internet (available on the Internet +here). +
    • +
    • RSADSI provide a good introduction to cryptography in the form of "Frequently +Asked Questions About Today's Cryptography", a document available free of +charge by anonymous FTP from here. +
    • +
    • The author of RSAEURO maintains a good +cryptography-based World Wide Web page. The page contains links to many +other cryptography and security-related sites. +
    • +
    • RSADSI provide a number of standards relating to "real-life" +usage of cryptographic algorithms and protocols known as the Public Key +Cryptography Standards (PKCS), as follows:
        +
      • PKCS #1: RSA Encryption Standard. PKCS #1 describes a method, +called rsaEncryption, for encrypting data using the RSA public-key cryptosystem. +
      • +
      • PKCS #3: Diffie-Hellman Key Agreement Standard. PKCS #3 describes +a method for implementing Diffie-Hellman key agreement, whereby two parties, +without any prior arrangements, can agree upon a secret key that is known only +to them (and, in particular, is not known to an eavesdropper listening to the +dialogue by which the parties agree on the key). +
      • +
      • PKCS #5: Password-Based Encryption Standard. PKCS #5 describes a +method for encrypting an octet string with a secret key derived from a password. +The result of the method is an octet string. +
      • +
      • PKCS #6: Extended-Certificate Syntax Standard. PKCS #6 describes +a syntax for extended certificates. An extended certificate consists of an X.509 +public-key certificate and a set of attributes, collectively signed by the +issuer of the X.509 public-key certificate. +
      • +
      • PKCS #7: Cryptographic Message Syntax Standard. PKCS #7 describes +a general syntax for data that may have cryptography applied to it, such as +digital signatures and digital envelopes. +
      • +
      • PKCS #8: Private-Key Information Syntax Standard. PKCS #8 +describes a syntax for private-key information. Private-key information includes +a private key for some public-key algorithm and a set of attributes. +
      • +
      • PKCS #9: Selected Attribute Types. PKCS #9 defines selected +attribute types for use in PKCS #6 extended certificates, PKCS #7 digitally +signed messages, and PKCS #8 private-key information. +
      • +
      • PKCS #10: Certification Request Syntax Standard. PKCS #10 +describes a syntax for certification requests.
      • +
    • +
    • Details of the PKCS standards can be obtained by +mailing +pkcs@rsa.com or via +anonymous ftp. +
    • +
    • National Bureau of Standards. FIPS PUB 113: Computer data authentication, +30 May 1985. +
    • +
    • Privacy and Authentication: An Introduction to Cryptography, W. Diffie, +M.E. Hellman, Proc. of the IEEE, Vol 67, No. 3, March 1979. +
    +

    +RSA

    +

    For further details of the RSA algorithm, consult the following: +

    +
      +
    • R. Rivest, A. Shamir, and L. Adleman, "A Method for Obtaining Digital +Signatures and Public-Key Cryptosystems", Communications of the ACM, v. 21, +n. 2, 2 Feb 1978, pp. 120-126. +
    • +
    • R. Rivest, A. Shamir, and L. Adleman, "On Digital Signatures and +Public-Key Cryptosystems", MIT Laboratory for Computer Science, Technical +Report, MIT/LCS/TR-212, Jan 1979 +
    • +
    • R. Rivest, A. Shamir, and L. Adleman, "Cryptographic Communications +System and Method", US Patent 4,405,829, 20/9/83. +
    +

    +Diffie-Hellman

    +

    For further details of the Diffie-Hellman key exchange algorithm, consult +the following: +

    +
      +
    • W. Diffie and M.E. Hellman. New directions in cryptography. IEEE +Transactions on Information Theory, IT-22:644-654, 1976. +
    • +
    • RSA Laboratories. PKCS #3: Diffie-Hellman Key-Agreement Standard. +
    +

    +Digest Algorithms +

    +

    For further details of the digest algorithms used in RSAEURO, consult the +following: +

    +
      +
    • B. Kaliski. RFC 1319: The MD2 Message-Digest Algorithm. April 1992. +
    • +
    • R. Rivest. RFC 1320: The MD4 Message-Digest Algorithm. April 1992. +
    • +
    • R. Rivest. RFC 1321: The MD5 Message-Digest Algorithm. April 1992. +
    • +
    • NIST FIPS PUB 180, "Secure Hash Standard", National Institute of +Standards and Technology, US Department of commerce, April 1993 [draft]. +
    +

    +DES

    +

    For further details of the Data Encryption Standard, consult the following: +

    +
      +
    • National Bureau of Standards. FIPS Publication 46-1: Data Encryption +Standard. January 1988. +
    • +
    • National Bureau of Standards. FIPS Publication 81: DES Modes of Operation. +December 1980. +
    • +
    • National Bureau of Standards. FIPS PUB 74: Guidelines for implementing and +Using the NBS Data Encryption Standard. 1 April 1981. +
    • +
    • Exhaustive Cryptanalysis of the NBS Data Encryption Standard, W.Diffie & +M.E.Hellman, IEEE Computer, June 1977. +
    • +
    • An Application of a Fast Data Encryption Standard Implementation, Matt +Bishop, Computing Systems, Vol. 1, No. 3, Summer 1988. +
    • +
    • Differential Cryptanalysis of DES-like Cryptosystems, E.Biham and +A.Shamir, Journal of Cryptology. +
    • +
    • A High-Speed Software DES Implementation, D.C.Feldmeier, Computer +Communications Research Group, Bellcore, June 1989. +
    +

    +Privacy-enhanced mail +

    +

    For further details of Internet privacy-enhanced mail and its applications, +consult the following: +

    +
      +
    • J. Linn. RFC 1421: Privacy Enhancement for Internet Electronic Mail: Part +I: Message Encryption and Authentication Procedures. February 1993. +
    • +
    • S. Kent. RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part +II: Certificate-Based Key Management. February 1993. +
    • +
    • D. Balenson. RFC 1423: Privacy Enhancement for Internet Electronic Mail: +Part III: Algorithms, Modes, and Identifiers. February 1993. +
    • +
    • B. Kaliski. RFC 1424: Privacy Enhancement for Internet Electronic Mail: +Part IV: Key Certification and Related Services. February 1993. +
    • +
    • Privacy-Enhanced Electronic Mail, Matt Bishop, Dept. of Maths and Computer +Science, Dartmouth College. +
    • +
    • Recent Changes to Privacy Enhanced Electronic Mail, Matt Bishop. +
    +
    +

    +APPENDIX A: FUNCTION CROSS-REFERENCE +

    +

    This section provides a cross-reference for each function, indicating where +it is described in the documentation. The functions are listed in alphabetical +order. +

    +

    DES3_CBCInit +

    +

    DES3_CBCRestart +

    +

    DES3_CBCUpdate +

    +

    DES3_CBCInit +

    +

    DES3_CBCRestart +

    +

    DES3_CBCUpdate +

    +

    DESX_CBCInit +

    +

    DESX_CBCRestart +

    +

    DESX_CBCUpdate +

    +

    GeneratePrime +

    +

    MD2Final +

    +

    MD2Init +

    +

    MD2Update +

    +

    MD4Final +

    +

    MD4Init +

    +

    MD4Update +

    +

    MD5Final +

    +

    MD5Init +

    +

    MD5Update +

    +

    NN_Add +

    +

    NN_Assign +

    +

    NN_Assign2Exp +

    +

    NN_AssignZero +

    +

    NN_Cmp +

    +

    NN_Decode +

    +

    NN_Digits +

    +

    NN_Div +

    +

    NN_Encode +

    +

    NN_Gcd +

    +

    NN_LShift +

    +

    NN_Mod +

    +

    NN_ModExp +

    +

    NN_ModInv +

    +

    NN_ModMult +

    +

    NN_Mult +

    +

    NN_RShift +

    +

    NN_Sub +

    +

    NN_Zero +

    +

    R_ComputeDHAgreedKey +

    +

    R_DecodePEMBlock +

    +

    R_DecryptOpenPEMBlock +

    +

    R_DigestBlock +

    +

    R_DigestBlock +

    +

    R_DigestInit +

    +

    R_DigestUpdate +

    +

    R_EncodePEMBlock +

    +

    R_EncryptOpenPEMBlock +

    +

    R_GenerateBytes +

    +

    R_GenerateDHParams +

    +

    R_GeneratePEMKeys +

    +

    R_GetRandomBytesNeeded +

    +

    R_memcmp +

    +

    R_memcpy +

    +

    R_memset +

    +

    R_OpenFinal +

    +

    R_OpenInit +

    +

    R_OpenPEMBlock +

    +

    R_OpenUpdate +

    +

    R_RandomCreate +

    +

    R_RandomFinal +

    +

    R_RandomInit +

    +

    R_RandomMix +

    +

    R_RandomUpdate +

    +

    R_SealFinal +

    +

    R_SealInit +

    +

    R_SealPEMBlock +

    +

    R_SealUpdate +

    +

    R_SetupDHAgreement +

    +

    R_SignBlock +

    +

    R_SignFinal +

    +

    R_SignInit +

    +

    R_SignPEMBlock +

    +

    R_SignUpdate +

    +

    R_VerifyBlockSignature +

    +

    R_VerifyFinal +

    +

    R_VerifyInit +

    +

    R_VerifyPEMSignature +

    +

    R_VerifyUpdate +

    +

    RSAPrivateDecrypt +

    +

    RSAPrivateEncrypt +

    +

    RSAPublicDecrypt +

    +

    RSAPublicEncrypt +

    +

    SHSFinal +

    +

    SHSInit +

    +

    SHSUpdate

    +

    +

    diff --git a/docs/rsaedoc.ps b/docs/rsaedoc.ps new file mode 100644 index 0000000000000000000000000000000000000000..4a9d31a24c1fef86762aabc1744d008b92ac0801 GIT binary patch literal 718764 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

    2R?95SbQIiM)TlQ+#G@+W(nMJ`sxW6U6`_=>Wqg zilL)F^i588%XcS2cx^ImI%{UWV~-*X?dVB9Ge9E=U&{MtsdSmn73C>#x^H0AT#1J> z5(u;!PjJ0gSKtM3Gn2$c`|z(?#P?c=ti^sOm;*KDT?H8S^4^UC-oi*=2)1A@ySJt} zfh6$Oq`L^eoxzZ1vu}J(SP^y{SB02vW*mt`Z!m+`L*5<8k8D6rh1BI=f|)Y8JE6Nt zrD*+oI^)@ zWjbu!y;(7=`UKlgpxud63yy{!DfroDvX7tH?vND4Ue)5>#0o=p=JNS$ zlJ8mMI8eg_^?N2cJS40$_)n_8x5z&k zcKa7AVzA{@L7p+<2Jj)kLuNY4Xbb-}7W}kSVMlaH#^}MT{|7i>;=^t;NkjivnEi{j z@&!VJG#2{5+(n#Y`8Rv`AAB$5UX8q*4s_E=exeWS!#^pkwWW(8$umoAnqpLRn6d-$ ziTA@$9Mv|WE+k>Bm>5OQe;KADsK5Z&i_R%W_&NltvKg0S-$Go$TEX2U_^N}=jr!2|O%LQ<1dPnD z93(gw3IiUM-0Q^(V(oQf<(Ysnwv=R~_TxVszz5od_R*%I^)@3C{btm-qPSs=#Q z%i6k6fj}qRe{9VRXbkL%4La10x_rF;ANmTf ze5Ai{M-OZJ*Mag)dc|K>rM=Lvd1nccKnN7Dg%-h3;PBf43U5P`XK@G<5cVQ&;qV1;?~VjkaiN%Z}BE!5{eY zMbJ!d4uUzj_Ke*I!c>ya8>%dqn3J^;tJQu=pCVXI4sssrfoG|NCBT`)9$Tb7Dd%+6 z3cIKS$2azZLL$0_-aIgdfzm~|OWlxY#RK07L5JK@4yBm7_FX{#ArXI&Mfw}p46PCW z`sWc$mH}KTmH^=db;W!`|J;@UL$mwkBz8v0Un1%mdjmHkYVRieonKXA&KQ!^0w{|& znec?#@;iV6PJai`UGQ)RQ|1pPDECfF)n*U3(FvOfodHk#XAF*iWjU}g(5?6$SKC5H`;oEu|scP>0MyLVe98NXiO(-*wv*Sn}3rEg({P$anbi7#CtfaW3N76H75 zt#A5`vWRt?07|3ARRVa8AzZ|67r+Gu3<3XpG;CC<4OZmNtt&Y z(3jzd_Z=W71hm-Qc_4&RVTIp&fU=0f?>@k56!+j+SA8HIQ}`VSc#T8pG``|TD#5Qp zz#E`b(C|zt=A8(1SD3=@MZjxF;ddk8HLUF2kAQSUvF=DfDhgW%J}VqQ4+mokzbpZ- z@%{S}kWMJpoe4-K+4s@mV9K~V0iVNzY*;r!7(9XBp@7`5vUiUH(h-Hwx!^!tZu~ z-4|5&{SJ5yDSLN3ARXRa^MF)D;a5H26==rpd%!EWkU88FWS6NQk;u0G1psCLT6=Qs zJ<@fU%neB56erjW32g{M?gQVygU`^qm?FTg(&V>gvcHyG$E2*Q@sxb!f*&+sVR;$= zT$^2-OM1aiBKN1O@&r?x0I#F_^7dx4yXDimXw$6B1|duN^QGhhJOaD#d!dbyef;T+ z3r$cV8@&lD4uFBNim~}|EzJ2-ZS#IGdN&6qFnpzZTPy0(C)0iEoeWa_W zgWNRQy*(K>n;$4-#`VC~6zP@(Yl6QWKzM}V1zGZoncKIn8;iTH)a%_?nvlXt%vW};a(u)fN;jd)P%q5#62tUX!{(L_m zrb{<~{O>2+?oQU`jQ{O~|3n*ey3FljF7hAe9QuD@#`Vptv{+7tD=|vn7?@)dfJq1D zhjMl|kt;SR6jb|HGZlUdU7&H1{vnnMf?Bv^_*nF^lUOUbAjA{;+TjYE7=-+Puf!7n z=VC;lH6nrx&2hPk(eU>J2;%;Ks)|oZ=bP@df`2WCqjffWxTfEC_0wFdbD&&viYo;R zoAsi}?lu!!m^RViznR=mJvKn%kW?hIRR}Xh!VHUwCnhmX9&qA(o7WpG4+v#-6ZK^Az>{38w!79B^3d?%%Z% zboDN<8HO(7W{(JKg~FUc;e#!D4dLHk0?Wcbqr{$1@Ir9t15q|h+6kI5{>3G@$qg{D zC9u-Rt(mvOz}p(X2V0EPivM{d%bO+ccB6lD>Yow8GqgxGmqge%+mEa5R!6LW))L*V<`@qI+Az z^7+=plDI@GoG`W~h-tbb66n5y<0TPMxD!aNmi{!m6mhmmM`J#!qb)^(!zag=Re{~N3Q^y#@YI9hd+T+)3DU?EDDJ+&EVkydg zV`2%vaj}#TOG&YmVx@a^1fv)=@XKoy#8Oc#;R8)gELFsEkbWtN-?AuBu2lekc33P& z#Bxk5$Hj6&EGNZsl>H)yC53WIEEmLbSuAT}8T}Q>X-mH>sRczXBx*5Hi?d&BoE8za zsHi1GEh%a#Q7em@CTc}dD~Vc#ek(z-5)~^ku@V+5K&T2(3%>=iQejBNQS0}AP2~H1 z4FfyP3jZH8$cmgQASr27{0AJze=tPYgQtMwlmed91Gvr}KomTQ?AU`y1|2Y!~Q`;N@4;b^nw=f0#O|}9qq#w{C z{eT|n2Q*1PM3?jf+N2-QC;fm%=?8R5KcH3m0lm@>XqJ9NAz7jy5HJ0Jfayo1=0Fwp zsIUi6fl|N)Jjy^zfu20KOu6Mk47v26hVR0Szsr3`uykSqh)>A_o+fwYw34a>YC z>l>M@VUhYqLp-T!k&l4~jZuuTG4KFa;d8`;hM)&EWKW*N7?eUodY~bDP>O!|1Ei04 znksuzLpA~S;3?J(8=o>+H^%rywnpUg2^47pl)}X6!5i}Ni+p@MFg~rH*d;9)v*If+ zVsVTavFT8XR)q(3N)Mhwr)bEhg9mHRr&C5YF*7zR_Fyg8q>zdB)R4`J9yAX=D|%3> z6lWur;%r1bsC_BUN5qrYVI!8}XilYM z`zgn145Uz4229X`9>`=5O0gE~fqkSWD>Pb^c?+zYTHt{eyl;9?ChuFolV-&ptPX2| zOx8k6(7>p`THpcJonU0gS z10sSNl2~A6kPxhpJy2-W!4p-9D{|KP^Mm;6&$<61^Z#%7H-P)^z=4$9JM1T%okpsC zNz&^s>8?46>bhz_`q<m^;&DJx4l}xc73;qNYdomYn#3&^TLznSg|G% zJ^e64Z6*9HsoGOWlDuAz0UmB96sZN*I`Fw)plY&3a1^(2J&~+z{$;IuL$;IPa zb#W1JrlRS_(b?(MrXgUwh%0@1^pKL;Z9Rb|DxfAgN0QV&b-T2)P(InO*8{0WDRe<# zi9A0=Pt)kN=%s0U9q7U9r$1f{P<@jmzaCO6SChPSqB%f{WqBVD2mOFcx2c4MM=t@oW%tD6?lN8 zK3wHe;rr3l9$qax(oO4a$Tn8$-Iv0&vA~bf*`4%0ze`B%Fg9THJa`u*wLXozTAj>7 zQYZaz`ebmj)b+X-Fdlf_#wb@;amgmtZ>4)oj20ffTb!LF1?V)r$u+*u@c>(FTo$$lwa@HTl3=LdmPttE|+Q(JTVfk2qz`x32NM zS0gTG_58g3B(*h{1JiDHD$=$5b_@g$`Tz~pOLXFpdSxw+ZBNXRm-9(dc06O#q-}_} zJmdEipnYAoQ*9c`iv`qN_mbSy0|3rw!MY*vdS5o@{W87D?9Za(m*!~9h(LPmNJqT@ zs9354w>8yW9u`BFc+*eNgAOv%a_(|2wt6;K8*l9>zkx>syOpcp4+#m<2+Xm zOPTsc1>*0G4Z)B)4ped>jiDG%0?R6Qp%^eJZuQ@8BQmC;^~mV;{EC zoeevFQ6$>k5Uk2XUok!12XcWVKL8-FEPyc2do*KAr!$Jk<>Q;AbpL)&-6S!GpaM$M z`q9E^ZH;ccUV^F1UVaGPVxLtt;4DU8Vy7?Jx9b82$?az4kpOiExJ|t#omT@dw(H?@ zMo#Jx8Qb>&uGCdBg6vryyZKP^nU3K<>K(xS2s;;X*#PqC2Nvm6B>(M0lJhXy$lf$R zZwQiH(3P_7?hLh6MW^v>lE2(WMelWpA^o$n87QK|pk2x&A3UHKyWJ6tpJc#ERJ#X% z;-F`L8N?GSN2QGN+=HtQM1t0YmeP~=yNb+%X!S zh?bVecHP~i4D3mEG60M11E6aK1z`9*PU0s-xb4M)mRR$XEd$ZwE=uk6X5$z=)WU=_ zB}^$00tZ-lfpD7$F@tFqGj`dW{>>L+*~EGy4-pzF=w^n_SmLtn;(!2Tok>@B=*o??K;-1W4={n=6DUBQ;*$3;82&FVNMM!akJ&ea0F*1@wsib0Ky^4^Z`;!ZKH=s&`C_hCH3phFNE78+NCFO^zdRu_~At!_C{^1;7_#es;ars!^I;A z=*WjbJw#~_pl3rOo&##(%^E9(K47z@2}1aDe|1K{2!gS&4N+Y{mv}ZLsr|GjNIK1i zO`D)EdqQ~y@O;VIrkR$*Hocp;Ntqz|3^YzZrh@9p$+c6(MZ8NPoohVC&59$p<80}N z9&tBv+oqKV7Z7Ohd+}3OyL9k)dAhldJ0a)1gu_*!zZJ2h%wsCnEk-DTd zUh6=;Mcg^;#ZRzl;CX$^%s~R!?t4=%pljZTW#=kx{~>Ip$%o zSzk=jH>()cu>r8WS z8%*8O-It9bfc$DP zZ!lb(^su-mUU7ZgHK90YkP~W$=u4-q0%_T7v5>s0kknZSPG1<0 zLrk%exOhsOJeSXv+dE*2eypWe_xJf&CzLx2#15NdPl!`VphhVYS)O~oytPwTjf4ZYtKqOcix;C$2=8VgeIs zUZ?xlgC&x$56M2FZbTUU1lV5TLxAA@88NP z5JtKRh{P2T#=zagwnS{${EH$eVYZQPPCP-?z36@^xstI)+Ht zENG17)-M@bg6uC7P@S-fI-`(nmI0?^?D4KSRaWkD1?$mVpb2-gr*LkOI-Z{~u^hxTcrCc@HESo^rmKz5dD>T_YFVGUux2&yO2y;G7j{FmW~n?>r(@y8^#s;L(2o(jt00pkENJ&0GEFY(^4S1 zuKXdX>&(KIYb*hBi(16-~{++fDgIK2VL_2iRR zUOI1J$($`9zle|b&upqK;r=MvBbP@mxm74)pQU`6765t%AGfDR50?#e3)PLZS9z&a zuOTdQNm>ut^#O-^q6JQXGo!5Z^zH)j+j>|tAeMFZC;oW(;n@M3{{1$u`lk5=!6jU* zr|eDGFb^fEJyFSo@_IS^s6!#Q9`#F7rs#=M?MN{;^xa~Y)-jjX3;{xro+Nmp5KG=t z7ION?<-3x~#qnkE1tWJNF4;MWREVCvP-q^&KXQY(A-Gl5C%ZRy*HXJ{%V6Z=qMRx! zFt+P~s6cxIeie7D!I@W27%Gv4y;}YBww#IH5WaTUJ?qV zqS-V+#s^$WT6lstx3lSsj$D&>Xhd6A3?_yXt;BqDzc zx{}lTm5ml2K%OgZkGO55zqw>4FG-7sw*vcIEI%wAd9X_$AI$3%?*S%`ETWRZi6^#KGZu06rcSFZ3uhtKwCjRGTsoLoOV^B&oFFA>dPsA5pIkxq)JV$<75|racU)Z>Z)>&Em0qi4G&Fkm`3S` zDud#g6@*DlT1P8qstJj)3M#7X8TT9Lw&<0HZ)Xig=@{ABNcKl*NnZt%S^1?gMgMyD zl!4qij4sPUIhT3|)_b3rIu2b%3VO6+B|+S!PXgo#L?+dtguqcD!G5*bBd(3tS?_l-yvN>0j-;jv_r)P&&V>SzQD*s8eQdE_kAnZ5{K)XadB z6zWB<;)#KIm+=qGLZ4?i`dS!Any@xnacq_3j$_(K1uWpMLc9UKjdmQ1Y###{DrENE z*(e8MIgLqAYapuR4SJK)Y-b8{@G;;~Ps)v??Yig9Ywh?^DbxDWrRkAXsdxRw?&Y|N zy|^v{1pQ?3?f5ARrg(WRK-Vo4fmd(v`L#Q6vb4|rg++DD_6rbdyj6fWMOcu5UKMW- z@E3K+(&Vm7rXs;5bNsY?hqBZ@^%ZOB(;OH)u<6e00@nynAah`2kcH&~QWQ_YiBm9* zzSnasx@?zgZA$QFYR?2DMAvMvI80W3@Y~8Bc=4@ED*mR8QU3u zj^phbjx5P*D?e_af2&i^5p>pb@S(|#r{wY#5&~QbaNm;AX={|qk>p3-e&O;a9q>d) zyfF;w_2UgLrBvajDXo$)$W?6`L;CDQVAGL3LugEfrArb6KvdJyxl{;*+rV? zL{NdkycUD#msAHDlUom1ZwKWKu?5{|7 zLX5Ym`jpVpfsie zse@7oRCVSjQwi}2a#@qM3{LXy^p~8&G%+`Fowx6*#Yy9Y98lMOsdueiqSvP*8u_x4 z&OOR9w3_3L)E(UviLafKBAx(V^@A(tDDP$*6)SrT!FqDW$wy#kDl_cx_HigTd5ysJ zfK8Ov@68ffVJ_lkw7wAR2bV2L!q!Iq^B_|P1gT$cU4iIku`QfWhON2w%33}LDT$qg|K3&r^hqIA>ne7<>xVz_;R8%W$-#qB zcS3z6J$9vDH09P=9gP$50!fXUa6_0__u*xMI_0?o;nd0M|SHv@c8S4E7MJcqAs9=o;8p0CdV{0MYG zHRu$I^;iJvh}zD<19g>^O2z&Nc$|8YTg}lCIeNTOwFiImU7-_zm*xe&48TTiz0}|+ zmYIL7U2%brhU4JTjA_9U(}u21_!pH{9ym1Gb&{U#N&$-skU9+OX6d~0lJ7j?NuSx} z2$M7v99jclQG}t$tpU$OoDs(H)3XmJM71N8`DP$)&<{{}(v)rkkvSGQDZx6-!5V;h zQPeySP&?b_KJxP?lk+c0FoSw=srJv}C1M5<@WShLl3d8}v^1g_Y{scaDi3`X<`^Mg zXhQnP#owg%^(z(t!G>loXa<-tG)eLr5iiOtOG_LGF9rSE58l)Vi3sk7vkgcYlMoRCoJQ5Ms#!y-Z8tT;~Q;Ukax zPNkE}@*8QPF6YqqT9Ca7t!TTxw}ZR1Q%=FvX+{(H6H26W*D#%zzM1D-D<{W*=R-{H z4C+PDMB8V-uS<{yla|+2d6!5<4#~jNPBAL_r@~lCXT0;~=B!H7ZZlEOMDfGjw6nN2<#@Q?sF9^Cw)lD7+=rSrSSoJNE zj%x0l6AtC)rI1pthgXD@L3>tp)X2+`Am$Aj*S>70Vu_2Ct&j+kP69rls?lOmOOlxi zHBcyC`y4H4RZ9kGgIu=jwLej;%PY*LURBe$4_CI>u}>~UwBx)Q50Hl|6A+3XJqdeB zeL9g&)7__1DD-v<4Johz7FJxPpv`-swok@$_0F4irmpLGh=jJ6e0ly500ursj`tWg z@g$;oPW$k7dL}DU0DvElnM4ZHzlBP)c!rkty0TA}r*QJ!>NO!%58IaM;X^1QFB9Db z;Mu~z_Mo~HQlnF(JwPw&v`I%G-;h*&AhZJKs)O~azJ4aL@H7YSfY7Q6!Wck^+U}uS zHxf@UcD|Ir>{7II@S(Oh`BBOFC0qbc=_M#?bP|_+rDJkKkyR&n~fB@emtr@nYLeocTz81bdxfK82d*dPV&9X9PF zi8d|hDxWMLvcwEr3Xw7_wWD>?@fyh90v~f&A84G^7%(#33C$ZJJIo!f4HVd=_4*zR z5DI|PcHO95NFUeQ6fTl@MfLkn&r?^`fjjziU31&sk6vBU$@TROP;YUR?p?gXy97_L z;8e0fcyl5BSP7($x8SO*1JIG%>Oz%UAYc}?%trFZL|+~RJs!%KaKtUh#iKi$F{m=| z7du}l%z?->5O4zN^N`F!N0|B%ntjydr>Ce!EYk*W%UP0H?y{88w4!>d*t60A6boMs z!tGKl?!-_Hv>SO!Ox=Ni)B_N}#~E;SL`0bo0H!i`K1Ba2e3G!&kJC_D{BtR}xTC-- z0uazsR(YU5{8Khp>o`K`u&J4GK++DbZ8e^f zdJiF}N#p*T02?s^7ps06L`f%(pkD#|3~48yxUMhB|KL;I%M3)brUjEN-xuhR-e5fa zkn6!`fY_10Sc{ZFqVf3!5CW0L3(q~dR@{&(ogh>jrF*7!6kP^7o~6=fDSLnvts_Be zCpWB)(>C+DHc%W?V0|PQcZ{x2;5)g5W4~YUWTAt=d!Y@-+F1^&ti{bH~ea=dxCo{jM5W*DUTCfHOub2C90t z{6_oivN0SQD0i7laI;L3bOfF0c(U(4Gb6pvBb}T^pAiO_U;*C16fxD z;1oA$11`m=|MbRHy5IPumnz&e>L7qMtGOXL<=|g|97M<@6?g1GhOdKE+xJck;g}mI9Z34mq@N;&~{LA#i!1abbJ+=e?ZBXadFK|-%?7 z*{tkxdEikS4sy{}_VgK6tj(V!qba7kUjs7`U7f;NUKxK*kKjzYx{x}`+Zs{?CkNQE zDCqNWMxHGKgxfdH^24i4%$&lOP}_?&XB6J>_LO2#YD{)HHZvOUF85|94KxyQ5;#wV zbgveOyGNM_6qDgG*w9-zjbK;ASML4C!!j zibV!+63KbflAkW1amVBn%)K6fzy5NWOC?_Cm+8kkR1~tFq~UvG3Ul!6^}hIi`!dDw zr=iRI$N7EuEa!5c&6=$~ETFElY+Jo#>6O-r~5OOv2<;ikQvWk#uVhEXedq2nZ!@K)dy#uNZ2Fd~<*O#fE^& zP>H%fu0ehXm68XqfZasgq#db;sjnLRW-t@5pp~ywbf_hGC~vDkq%qV^XSD^ysR!Wy zJ?Wplw-z&a>}+#OOszJn}Deh`>cTVvTH^W6&rW&94@hS-Mnt0zcH3jknOHE01mjuA{S z-VOveoIxaRJcKEB6jVTs{LEeVlyEyLkn0(4(akF9JWanG!#O^NSwhAsS)KqYjRfTx zZsfNL4dO)-t{ZYp&=IfqDzQB>Ov%-Uz%krAQF6Dmg0lOC&LHtXXmZt?L@IiOKrR;KA{9Ns4yRy)W@L8h zpwOdvoUo9)ThPN>6|S2nXidE9r40x24Gw66(NR1UXp$O8wm0~E~+~L@QGVvO6v;ftN4L= zz1d`E7c!buAm}8%#RkWw5-otT4rrajuaGH!aUgKq$g+^6Z6Q_Q*i?>=V}<1d0zb7E z_|FjuAx=_+|L7qJ2NCF$xrHPt@pK97$s>>j&!ThCY+e^Tk1ZU^w8c`6QUCTBBL$)L z%EdC72^26Y==2tV2dc1995rVH_~>+$kX)#6C%r^5yaRri^$8sG4L5}%fT{5G!Z*+S z5x@@wE)bNE)5pD3Id?wK+M{-O%V0m?L{Feho>PR52q#HpR(<5OVxI3bKmI}P0_nt4 zgl?fX+~tR-j|_B3oVS1og2MshL1j>(GUMdJ(y*}~k2ACdc6M5b4kme|(~BYLx*CO1 zD98e^II3?N&QB%#M*`Lp@{(;1#DQFbrPlc1{xCH!kvA*HP5@vIZTK9S6P@|n@CWBf zKyN{bf@|>X;Cuo!N7x0-jg2EV1QBxW@pBVt>1OGAm-^#)fy-wZcD|Zf%pak9B0k|f z)s73&ou>>p*Q5j|V;jd!+2J8Mn9j;tyg`oQ6oSrkoJ@n-6ot=!61M}_CZOH+1ZE_K zfY$3TNs4mg_-y|cd)RiaNwAf0LP-I1L9p0onBeyJ&Sfe4;Qn%yKKDFlnOhCKFCBq& z@Q2C+Z?+8EPRgY1fiCPEB6MAgN&@;xgMFzFFbM!k9vph`K42?|Rgok`Mb%rJWOEwp zkQ#gC66!O-Sz-9P*cmZ)04@SEq5!i zurhNjg%}HkQuT5T?{p1>aeW2*`Fbeh5S+dN^qEs<(kKC_?>@pF@RWxpyfMSgJiU2X zyAdgPZx9^f?x(v~gpk#C)p_2zO}5ziQusU8-nje<1eecFHUz(*d~=@*l8ziE)bnY+ zRVxP^74FEZ@-C5!^$2hXq>}St7V09L+Sq4rU=4N4;Q6=1H(|%blIyiaIXpM=3|JbefTu=jVu7z>$SBj1EAp(+}ZLX*UkL!{&t`{eUOE zaZK^5FR_LE@!`m6-bk{Hqg!pn5^H&w*Kj8ht-{Fk2HfefZ_@(7HXxBYI#X0hR!Ko` z+IKV6VLLpN?2jhlR=X*eTp66#LbL>VI|X#?uag@dr&h-!6(`3Va6rH^1U2Fi3;)we z`5gW5N zDkD>YGfsBSYZ+9@WtVa+pWMe}S51>rWfOskGr9I(oP~QMX;tpR%ORz5=ukoUWi^}z zD3At;_?Q5?fUWZ=W_xmx0`emGn$3P7ph8ycY0_Vq_k&=}Hru!ePuy8N0ZY(9E+BgZ zX2RuEdkN$)9^4_$z|C_2S$$Iy?bY0YW|;EAqoMQb$Rm!2)D`32u}2 zH0}s1-CH0W6f}}#6h$l$zz_#QI2w&3i2`|ZLHRhhOsJTvJ4d zbEeSZvIg`FBuVxkU6L~t!}D)ma*&co*Az~AL)>n91yrCj$)5W2x!mX;AX`{mQrx|vDLUvg4^m-WF}R(sVicu9OzF%YwO`dQ@)S+Tr^3C( z|HIaMZmX(n;iCV23&5On#GDg~A}HpZv%dfNdf}LBpL_0VZP6T4fvTQ!-AtDH5S|RU zKS*gEs#IVF?@=FDil&g522Tjl3N=P~EeL$m?yH$}2tL!DibcuLQ4 z=r;?|h=4lw!v`w$GJP`d2G54CN1ECNv==EoBD~2IMcB}f%1@-_iPOH&rl?>2akdyh zxRyg^$sBP)@o8Gxj}TL-^{`gG5WS@6m?NLCCXg(|2FQ%I3s>ixMH>YK(|jmGM()kb zy}kE~fQA{8+sOn>^c!kS%1%GbXf%J7a&A)YHgF6lQK16CF2Mn^Hd9S=tBcq&2bXJ@Hb{pc3!L}CIgUZY{}t=m@Ed(#K$5_T*C!m! zLne;AM)z(uV6#0{J0`Hl82ig@*7Q=Og3+*GmReCyqn0^#5qK#egiFO)cP3d{V=PuMMl~Dc2OK54(qjb;a$UW z#Z*o`_#8KiKuGe9(g*fw3-)R7K|*m9M_8UmCy0b>Oy3)kh@ZU_JxJA`TIXQOqQcb% zXi!Us6V;(8VD*(3vIpj>)9WZ4@|8c=nZo|7ehIa6<&Yz;G`219Gjn&*(S-ZZfatgd z5hu*FsZ44%Ovn|F8w?Y%Kc=WT;~M;3g)(Z|^7q-X%WRSWK>PT69imk=%1yhU4BO{2=~R3b$LOH22W$B#5D*(vZe zpF>jNZseJEHL)z78YZe}!~R&mPG^A%_kKMMzhG8HZq%hBfS9ks&TLa=-43M!L(5=6 zp;&uEZbwjfU3DjeMTf1RmKTn173$z&LzBxZQ4C(sduY1_yduOl*1-wi1Sy<$)|z8P z%^YGBrNDeb;b&j34rss?<57Ok=wEc39l2u2)|ntKg9a4wcfGf5LAz$PmubUQCYP?dulnvBV?24iXpzZ?vY zSX;n+G!zeMPPCY@9%TeLP)Ud-Q57jC+5l~GnqG@26@O9s78V-5-o-4R&OF3L`olDZ zT`8G{zBXn{6D}-G?F1Ez(iNm1wOk<+t$dq=V$x#F1z8&vJ!Bsuxkeop>%$=ck==oj zBV;P1Zdk>+*#Rnypv*_~!=eBcLa}Zst5SB6F$;&QjJ}GIdj%6#ng*D*qeAFT`T6ZU zVSlq=h7mFbidhq5CNhCf2q0123)-!i+U>gGG`}P}>UwuRkO4QPyb!w5m|3Q-bqcV- zaFj>g62TZ4AnObA7fgmk2=H|enjj0`paoQyv#`)Ce~VHG4bBclQ}JlDN{Zzh(oiQM zhP=Wh8}}4=5I8g-lO&`JS*P3@k#8fvEfio{X8h?-pC0wele7UA7AM@VWi!}#&&Pz?qNeLx%TOyP}C@B`>X zyA_wZpir2Tc2scIMar|BNI|YOij-n~qHtygX~~J?CNSL}zof9R4K&6gOAVi(q5m7> z_%~|e$_I$RQT5BpU^v15S)xb3wSh5x2~p)35bHsRgX8Ad%1h5eBi>u2AgxRSEnYP@ z%tr`D0vPoUh)q}>WYshG!Z6!ezwmrZ^@%q~Vr~Le^1~)x53xX^*GGBEYz$gU#@7L= z*dsXrkYoYWG--nctGu`4Cn$&^%N`UJ2S0x@@t|e<5bU<1&_!5?9PQE^*>Mm!1UliF zB`O&GG25LLa*-2ZB6g1fRb3)8)}Z5=VsTS&LI}}R1j=Hd3U~=w=m;GWs;2bPCKW<4(x4#b zP(a%t855`njxgf=ccK2)#cR{Fc`FE-_7^Z!g&^Sa3K|8g)Fqi__6=D9tPO$#hxWl3 zp#?lRs;36m`jA0Ett{h9W5sq^uoDAAtpBYJpA2AZKy?K_TtwF7YD0U$Pdq#5v8-T~ zs`y|xLz>kGux)B+79_!fe?uejR6vIo>hxhNy_m+JiY3FFVkI_I?M>qi$_>=#!W@Z` zDH>w-q5)GXTA`+l0rpIE^*Nt2V*a9q=uQpCk-fGsfA9zAQ!MrSlay@Sk#Spgvi=T zAq&WccM3caT1RaqRfUU>Y$OUnZVNC_Y|5*xZ3X*TGd!oDgFxn>@(dyc9O`AUQ^-*i zr{V<~6Y#_s@Tq^(Bhb(fK7n8Lv%@GT%%BEW#ppeTS5A$+ZFKWEIXD_5qG8(_y$_5p zDdJl4+Dgv@S(hXrSW6qI71AZ~pkD_exvG>!r&xJEf^x<7>%}w~8SCf}XHYaQs2)bI zopv=~#Q;VI4P+}EhCkTExbAI9i68RUONSLqG&G7@n&zO3inc)D#zH8~hVT&>!vgI? zeWMUaAO(2b*fX`=vnndMT?HasYO}LL%A+xxkt{vSN9o(6Eg#Ar3HK57V^pX-g0n(? zfIF#lg}Sqc70XuHS(wJX)b4sL z^@{tA2SWQWNE*v*?`|C5SR;=C(m-i0Is1^z&@{jZEb(QK8`wGvynw1F>04ADp{E>y zXQ+uWY&wX4st-f^D;Gjh3Hd?{YGh)r7??>WLUDfngB@Vn}+BBSD+Q+0sXu3KWY7?o^N}idb%gZ4w};E$I{L<^>*T zV5t?R=yr>sbAkIx#1m5hf`wZ`3i|OqaR|=mGi-CY#(&dUn5-i<<$}>UMJs5g$iI-q zf16BC(V)vH1$^oKgsoI!}Ft042Sr$L-P!nak*#_OpHC9zzkZ;NAZ3Px?1fv9^4yxO$rgMz{^hb2Rio+Cztyr-}lJs)X}DHIPj#l$@T244u57s_dqZeWDA%f3cE z4(yb_KmY!X)tz7p1bso$lRX=Yg#biz7PX)JHf|KB;-yCLm|kz7ojQ~7Z-gomDh5@s z`74Yn*bl8RD~wR=|NI-=MkWk?H<>#n@cy?>gGQO8g0*0%;&tSwV!^xQim{t1o=9IakTWf5h$dH_G$$TNN|Pb!r*2?P zlQJa1Mi(+L*kW1xpDnicKH0P8*91}>-OM^OSr_sd(`4NYH(sZsGtDlK$DdSe4u-7P2A;+IB`p_^zRZ{6epJWcQh_)Yi(T22I^Qa zwYC~$aEhmAk7QSy$LiJ|py5a`VBmeB3PBxK^HjmC$N4?@jYZcjM&&)&f2=!DzpNdmqY?{uWdlL2G26XEqKW=hp zQfARJQMv zNA-g?npg@x0J@hv>8p;jgCD9@pn>es!ah4qTZV1O3&ixvUc>MBm43`=R4hvQZYBrB z!YZUo-gRc`6t06QpZie5mhVX6B-nk0PDx)ax#-lf8;>A#bL3-)KKE>7_6l=hC?V&` zN@cJpy;^ZE^}S$sVqK+)t=xNhZ@I=K^t^G-6!4ngnkJUi1XZ4yKGK$;@_DTGIZV@; z#%_{5PNx&IbcKgiM$JEr#tav}w`G0Vn@*>W`2)r}x$2h9yI=;gi+Qday*{{$BS%?M z6e6)e52=2Z1%`5erl$Povz*72MbE@V;)N0ynN0I<9G*jx+0382-z1Cz5}c9IN1KW} z_j+PJ-WA$elA&)N`NS6{+ydTBM@nlv8@1=;N=z5=f{dHxz?9E4mXq9kBYBpO&U=#c z-StUs8rQM2lx~`)-H|E#$FaS9RM|IlnNPAOt^+y1+sB2g+@m*R4R=As9ho71tPf1H zK~e`2nJQCOas1=DH%<4>8SboydstT@M;A28K^c)QB$mH4rq1d~#?67uLSK1eP41*_ z-G~B@uv6VD5yR-8V;};4{nLfR9fNq?SDB%u%si0(Fs0#4S=@D?3QUdca@<& zZ8_H={5jG7jGf^L?(yFqr#;go=NGVj?-m{cMT;qjG|%i0<#{aT+Jf8jdG;*J93hPH z+-9AQXN#9k7nPtbinA%7AT4Tx61=ziW8ZjD_q2gow~7XJUY*?i9Le?gsml~04@*6T&WTL5a5iI7HowmDd-d- z6#KLBENics`2Fh81cP<$TqNH@cY-Jzc07FgX@hqhD^p#T{0J~ES?`wAOK(RIP z+#drhn^2d1T|jZD2^Q*ezB9(4#))ly82J%;u;*b=qZvjl40A*uD&Vfm1X$&FGYH;z z_H61BQM8D0M^JR3=EP&mwWs29(6-pQx+NrE z#J9h6%}u^X%+7!u5G<`@oq~R>!_(%*E*AZ1T8NKLV3}4$Kb`75T9X1YSgZJ2?}B<_ zWLqN(_RWbfa+Fhg9$C3(_?=D!j)5*9{bPzQb+(}&U1382hLfnNBjeu|8eH!C)4X~+ z8J229E+e`bdPlrFK=8pz-Mo@EgFn((4>?tCkpL7x09fqr(Rk^2w$4>eW^|D#^lL(X zbxCgW6{M)33zXbQjK6@PT=l+ zB2wdW0J{Q~mN^?OOi<~i3hf8sZp0C$;`UmeIxpOCc(9}LYPOiFCa_;hB=g@6wK#@e zg8hrfrs4pJ)`KL8VB_1D%r3Mz1($W7E<@bxY~pV)zOb2fi_j&_>NFi&WsM-*s~k*? zHp712o=i?B4CH^8wajj&?J9jFPi%3RcXJ8I7?i;`LuIt}E&$n0p+B}M+cMWF9iYM~ zA91zYMU!=Mt|N{|>+e8b z6#0O=+8tfOs+H>Go?O}!t?4W2qOo5)Zeo0EY&YloZQO*v7d>3?H*hl~2xV#6D7Q9h ziOiIEbei?$^pm%Zii;-xzX7ql(Z+b%Hh?OkQ|D4rF}PBZq&5_W_{ z2-*?NL_h#eNis1y!$*0bOLjAyM=^>Hi~ikhKCPb!K1I|TfYFr4w)-c?h1-vq*%d3+ zr>SETc(%oOFe@g6GLH@myDVmd#~C)>q0<5!8VznReH>sJv``-=TuWFn_!;uIft!1t z7QMOucj=WU?&GKVI)y^zv0c=__)Zzm+AexyTXP4^!c;0IZJ8_qClU)0VbmnfZV?Dn z=;9p|GFiBG4yqZ}NtcYH0;MG5hLcIb64=`)w1t4b`vJwQ4Cc`*AhRe#dyi~uiP`C- z)AE2?AqutOk@Su$Cc!dry$0jL?ij^yz;ApZy5^$iW{DEAoXvR~ApJ5h*J)iT?Hn0q zrzJ&50f?=FNk7)*sBt+ruS9G9x?WCpYV`UXcH!5IXa)0J5V59Vu_#G^-TSVKNl774%;I-reIof?#Kla*{*D1J6!_q;C zAq#V{Y{Dhg8a=PkRzW)z>^T$Z7rgZEf?LK>thkPr;`Z@QrhH29xUFe$cDDWZ?KKB| znQhaXAymxTtPU$GL+#jX3QqzEDh!gKt9OM~6Txb>73|DY0eQ;O*cwQdOcU?zRm8$r z%}LNh6kRq~a;-XhHW=}nxU`?)%al_bEfB@GKSb&xZoHYTm@NmN_Hq3f6C&T07lPKg)p6@Ou}aFZPDKy zCg-?wzY@8ZcHCpiH3b>q4FN6e*MAoxfCz4$!@CIwC$Qou#UM5hpbvVBaoLP&!$Vk& zaGhNO|2A%v=9wi8FcQm@eI!RT?ZqhPP}JgN>oiyNPYv>LfhY&LgSuHE?Sm){Jc$C^ z55Lx5xvyz!_=@M@4ZuiYegY?O4TS zAcCKhjsKQO%eIREgaSa+89^-Q&qWe!w4yYu)Aci+*^tkyxj6ZD=kVMCDie2(bc+V8 zpn>5n22nE9Ioi>GL?I?sZo-UKRz#Ve#*dho{VPAxrs*dft6<)@Jp{B4p5XmMw8@%gPL&;EQ zCj4`oQ$KZvZP+B`LKOlkQ661Nw&2848X@N?mJv9k_!Js|{E$T#sKN5Ir!SKAoPIc% zqtG2m$n9k=UH#{bP^~s*21iC9K)c6P;7(0zp5#pYT3A0HCHkn09fW#B#j@|UjDFMdlhm{J(#?DN0I8#J&JT^KA>frg?pRI8f8mjLG|fJ zZ!~Ngc~%WK0Nu{8C+NYsKd2wxTRYb|Tp@bndk;!`!$oM$Rv3XE%t#xp)H18EF$oQC zvJW+EiH#zwQwVRVL|`W=FKFbfIMd@B9Z`ILL?j9kSRSMnQvqnjQdUM+p~Z>(rMvV!9R`wtjin2Q#KF8@q2E7$2?qT0*mwb2j#x^p&x!Wx%S1dJ5^9OppG zmJI6T(q~(_dw@a1L_jF(b^nRbO%PVbi6SP2E;uIIgE(QsYAuvxv0xf!xgo+D(s8r( zQB03*g^|d0d}AktWx(9Ftwgi?#pRj5Hljl?k6fmT^mh|`%+^cpKZXJiywQEX_Q z`aZ!Es0yH@1UY3Mi@B1$z+|cW9k^iP#c|Wmj?l{<#_9k`S{%4`mqQvGqJnaxc=HG< z7CN0W6@D`_M?h;nvJL48y$mAV!5PLef@F#Q@JV%sMq3*uVH(0c2fR6dOzyIv2r= z9gk^liFT2gOo=`{n3{D2r9`v!jGpV3PQa+Q28zSRvTAn`^?zIk_J z?Y3$H^qBMr9+aJHXJ0}zwu>w?qR~(ZC>00^4&uD{Fuv<}M&586G(`Ps$Z8`J&602+ z2&Q=S#WEBB5jY5d$g|}aJl%{47}S$QyU(E`LCtpT!cv1YdpK$F069YHne<@s9R@L{$*K>g zsKB_y@}K}Y3&Gm~ksmhU%I55l4RwzbzCqUyFZR|;=~B|0Co2>gUv!|MyJL{XCm+Zf zTeD2ppZsuN%_YV*^EgL@L%souQN}hINk=N2r%Vrukn=()_FroaWMu z*8Y9U4iSiOn$ zeKBTrBxEi)whny}i_NnFo?l{#To+N70=&ye9RCOo-J*@?M`S-C5Jv#*YAy>?5wjXa zv5K@J4f_SDySejdQofa&n5)7j>!JXG zMz28c!!nIQP!1A|q8UAmZP`tlbX6xY+{fNjSb%H^6_Vqnjm)%^zd)Q+30A8ZY`UBu zLVxa$;on>dW^iK94K=DS-i@TWyjQc@scC^3k3&5uF6bhSyuAauPH_SUVi^E?~JqeAw zr;1w?jwx+JN)X4mn7lAC$z^Qlh$($o@yP?P`A(CSs%SEVKxfQp*hR)5o#-6lt?y1k=ZvLaZw6DWD7Ci z8AixS`oQxvZ}0;1vOw$d4gCdJb&YErJq-}J1cHdcRZP%;zYVJ+ES&o=aUti>#X=3U zn$mC)=3s3>Mf}H&=EZ)LA+D+?0qsMY8x)pnPTW-xfX!~1e2kOzp9G-22)9f=aRYP5 ze&eJ_dwVl7x3=c&{!Q$BM&! z90@=41rj=Y6AY8&(!WAKrCkK~J!9G_e`aFH%N7Q)XU{=k%z9BHBl^whfLe~r>5F0= z7U!%-l;|a4Kor_i}TYsa%lH&PS;CZG5At4Y4A1}p2QGLB>V zEh06hVKjSofRv#EF-t%V+umJUPwhEJ+KwLgmr_jJ%o) zVFnQ@*I2O|i7iahrLuZfD@7+#`~wDzONYLJ2TrIlFAz4PrRuipxN?t$M_u9v8_2yPMG^gVn2E| zexqY}8FJ^W{FxO%`uHLY$y@-t?L=wM^%#^4I#5xK=Qhj{)OjJ8?DToiaUKh5N6F`A z!W4zVR4Ky-1JD>l7LamW*Y_?#o9MsJUTVA7=>7dU6jnzz}unLSeVRU5*XH3WF z3T+aSM6DUS&v=Z}Zomq7Me9A*kb0Ud!T7PQFW?>;uiwXQ(8W%PV&2ma+(?>Ag0d6~ z#AD_^gbe)$j7c(AYUeb&kKq|XVH`a}AaP)*L5bc>vep8P0dip%?YQXru(LR2`^(J) z0U9A7OfDy%-U3STCbU!I@Vmu_h6_jucvA>Sq4bAE=1}keb%SZA=t=33kKIWVtU~1E zMqj7Y%*lmQE2`4kEV)Rd*F*3J(Lm5lc(}_~-6nu{9vJ$4b1#D$=))Vj?!??43*l_o zPY;|h2t+}$UiaUn62={EFUjp#f*IkA-QlnJ-E;}j8W3emdQ;%t;t?K5JYcQon=S2R zJ=0UujJCaa4lEx81hN+tN7=JTefZ)d_oV9|`W9t7H}LnCWLs3Z4r2PWIN~Bp6k@1x z@Q&71Z;0MUG#ic@wZ8)Yg=G$EB0JWjo!UD$@4pLv`dxzU(L~!PmZ8@>{E)xE5{+Pt zU<6{(qMtNa0gzOF`W+%du(8l@2g`JkxY@`l^ZSN-*ONd3bA-qfpJG024JTzFCLKZ9 zUKgR@w+~L>OO0#Cqw1mCJOEhiM8<9NWmG=@^5h}ALG<`d=Kq5bY;+Etw!NTY36+d{ zSawsW;Wp-ZEZ3iufl2(vNiP6b*}#QJGAX2H2c&NcnhQptTvV5Fra9ki+$wThKQe8ot`m}go4~8ukNKz3AY^G+UwrL zl7bjt4PVlVOWHz?nwgU>^#g8ZMQVv6B0{s11G>Lsg;!L!{62MyF6ld^*Xza>GDNTQo!lHF0BvLS_S>>E_nz2fpRH z11<;5t|Mm^uS#3#eQxa?S$K$qjJ9Jkpib;y5X!xV@aE|U{mU*?E}phmFSX~Nxv*~r z6|v;A*lyp+C>ZavqCgUF)=uifPf|8yf(a4ZGeb{1l{7m>4ay!EjtfX@C^e&0mX%p{ zd`s7FNjn*yCIE|&76b39<7H$A7IDDeM2!S`S&^dI*#`7U4u(F& zx7$xLWYH{Ww1d1RUck7Q9_|_q#{CYEdd`hydtv_$Q0XAJ1!A|?8)B&J!nA#LY?uD4EaVO91fFyf4+5y6V5xD3rCOkjmC3}w>LY!GzzM@W#FwPLf6K;u;O(VN-e2+TpioT8IK)+oq@Q_($C2g+M{@P6OS z$3555?Ju6~%t6F-Jtp3WN-7 z81@h2h+M@QyobKE6UxcZP&j;$O=V}XD6-ute(vSkwf)D0#nU9t zwthm$$p?Aw>O5|`WByTveHZC(zYnZNjRug6@zFZH@}WZGV;)THal}ceAr6$PeOQq? z00zMAcQrsG#x7Rftuxyxt9?r^N*j*(}1v!M_O zAYcxxaY7~J1v)`6C=-wMyg?c+Vd$$OYZ|=o-^PUtCKkYw25|!JSNYlPsD8x}r}jKW zxQOr*k$-j^QJ!3YsCZ{;W>7CWE?IdWJJJ*8Y8}oT(wgfdj}9EA`O$-|nN1bEftN`c zy1jk`MtX?iKy}j5nK4e1F(BGk3tNHRET)9C3oDk2;Qdz7rhcUj0MvAuO?VZGs9y>i zDc{wCd5ozNB(LxUmiHH27b|cWbZf`<;j0R<*iD6%{h&{8lX{V145s5U>O_Lmi$SgI zB)5iWvy3f0j8l+mVK8UN=F;b3rbJ5ng;g)=G+Lq`cuUV-r6hvF{{07%gK;|cu^msg36>j`K6g)^M+82@?%To zjQL?WBMj@NqKKb__tLl9C|f*b|owg&JapU!R@IA3@_9DV z!>)9>YnoU@Ww#M=CEOQ$cRafA8T!PilgJEWfz=y1P6!MuF_NB++l>HmhVWUxc;Dd# znIdhi%4_&Ns+Yo+yGZ8e8l>T+6_)N0I}LC)Ku2OIb)l6!wd1$rgs9TLP=2Y9wH`;H z;<$)>2$Jmicif@@k?xCKJr@ff({1gWAz8@|@`OT$=q22&LxSLL_`u_X(t+$0MjB^G zAm50KY&R-NPl4oi`vMr}&jTgtIB17j^@LCH-JpN=!J1KyTMBvdoTRyl!pMA+wzfh4 zblI8cz7vz4$|7X}mQpx`*NBHzbT3IkVd!0N&%=8jCv%`H6-pZ8q$$nS1y|9DY-9{l zCWPmL{`3Wx+!ceP9020{e8&62IEC45Wk+v>=@`PaCIu%K!gKTpuDXDq;RvwE6%*M4 zvdplzb|U0x(-l?EGv5&)2m%8PHID5I6y~TNwfm_+ClZ7GMruBQtzOV(Bd<*xW_ee*=q#+I>!76htJM%o72&gjKq{Vc@eIMf6>dtd_(w6DO08_<@c z`4bS-ybY#f9qZi5)IwTV@sGfsr^OP2lEUEb|E}NOy#=4JaV+VzBWROK4bceF3Ob=t z&4TbcZz28y?ui~D2p=ou_0d-NA+f!2GTi}=D8wxB_w#B1=e!SMfA-)Jw1z?F#t=uC zKdZ>RU4(Ht!n9gQMPu2Zfc}M1A^U_SGEwCg&X<&hs4lf5zQh{B(VI2%%{Y|T$Z;XI z*+S82LF6Uj=|VsWPxuq{``GHd{`r3unYuUFNFuZ~yGG^$OT?hlYU?y9TKc=d`#Ltp zWrX7WkP^DIKPo4n3MuiDGXjAJ1n_BbpSM@3UtoLwqJtDWH>1lB2jeii849ET{|FY7 zqTU8;?bCL<*@}r{HnhhL00!H}=z&!)3$zq9_Vnxu6c)rYfqaWUTaG^jeYe_co|+Ns z!dRCRi<7WEX&h)Mj*=G)X&0{Mhn?QC#m&)^_8!ShbP(o1+h1wV>|eCPks*Yk{V9@H z**BDQ^8vkwD3Ku`jOGz9H63(EU$v!LI_7=fjr6 zP_tNF=fCZkpFmDC_J@{#%TJ0aY#B-7y5InL&EAUuHo+6jG`i~+1gfNrWiX9p zgn<%pY{9_Z%b>rtEqQlx0A0~4;_dNl|-?Vnn8xT1y z--?)XPdnYaDAA6I0h;W`f{zQ+pdUue*W0YjIH9{tk-S>{?qiQJfY{$* zQ&DIZ&blPB@-QV0q2KZyhCV%PVZxgoyz|s8a)N!$2;zS)BkM+a-U@Rt;{$OLgm>N` zPqZfeQ4=F6tY(LtmJ}SGVQ5{S2I)bSU{>>OkVVxc?>7A&YcN6NtR%n5HFsRcJ*MRMh;{b!q->uIXUBPnbA?SSzw*7m!dDL=v7Z z8EwIQEM=B9XL#*a)U7o7BQpje0nzjA37oc;?l7frh9Qeu9v2}56KXLIH8g`*o~6Ud zPKVLMvNO)CaY8ms(FOcHaP1&|jxS%WQ~2=q?q+vI%R4tF!4ochl&3Ge!aAwplYCe9 zf&)%HB~f+5)F&Mo6go!F@D4Er4JNDrjq#N#Q0~pgMp=b}u-GAqX=^K}i2Dp*+!wEd zzjq}B)d7Ozhvn@6{0p4#tVIqOAb;MJG2Lf?g#K*~D)7K3p*}jOa1L3V6jX-Odm~_c z3R+|Gs1dfMtHE=3B>wy1M(qZy_)Vp=P?nbR33A7Lra4F$AHq(# z8@(QC*Dp1H>8TRmKkU=e}k?v6>wvo*=md zd4`p-k~%z@lp;3>ZL*T=zmaEqq5#10?-Tp;e=jDkjUFe|#5El1xp36sH|8ML*+r_H z2$Ae^R?o}u8B~Dr5QylYb8@eJOc*fmMjrwtL#bFA-()@gkK~*xk3|AooA@^fca5*g zqQql+hw=diZizezD`l4bLo@j~MuMd==UU zh>qQbs8Auqj!1LfI7z*qm1m>A`Q5B~&}!n09o6$GyMZ0nUVtZ1KYIzP7Wf62lm}$n z@Rmbjt7w)FNiM20G_sFKK^m&@a6g+s_30zKKr&ZO?D7h9Vh6QrTW(>NQ6Lo|aRkgK zPOyAu_1_vyaE>iIh-VjeTDR;~+1A66*qG*k%Ntb*@zNetUOOv`--;igkM$B12GPqs znn=Y#RnqjOfXMrV-sbGRrtAX|yC<5S80o>hGOZ;JUM3Dkhdyg=B&eS2iqZ!w zuHCF}z+^dHSv)Hc5b&#@)3Pt7SDEU(1#AYjHF9A?m)6!NOw!fvG~-<~w| zG=a#)!A!DYGgB6`_jKsKCZ}xN2FCnge!_1O08Z)T+S#%}Tzs=%Bs)D1OMxaeJnY#w z&~EO&y@le&q%4w?W3S*CG}TkMvn5dOl|`{TRTlRCQYov2et#UVhR=~zdk#Vj?Uh%o zHGno49B?x_3BY+|kOm8DdI5=(7AfBAgh@C>^Vv~1q1E5Shz9Q{^HpYMQs$q=8no^Z zkfKTNk(9s~NC?hNzj_bC9%!LA$yhcMtHJdR#VEbkpnn}GCh|yDyw5R&Hljcbo8f-Y zqZ5N%Kte0}1XH_N-}iR$?;P5-JYz{Qj7j=XAum|8TMMWYWzi08iQraXp5jRv95(%7 zd=cJbS7h$PmqbYGi9*+A=w>1YTRzWWevVsOIQG<286wzJLf8bSuW>Py^RrQukcS-b zRa`BVWxcjxAO}mvt}SH|P*=)yog0$lcBYr^l&AO9CS0rm_wGtjQ^nCwY0?2zWZys- zP?bHK@5S0KXp$3{O!BLd0(zvBZ@44dS9}S3?%;t9m#*py^unnKJ((b3{SX~%ZXui} zezdz#H6vrX!@9P_Rw}xBPTP;zE=GV}mM{0vn+PF9aUX)8_e!sib+X4gyUOD*ZV*r> zy1v>g^}!GinD}PHu~i-yUg7JJaZf#0xEb$VJ4Ym%4oW#) zKpQp9T}b<;PO>$vKY#_)t%(S*g=c#;=Ou>tP_pKxqR(|bjniODs*nO9cPJ=k;v(caqbAo-2S zqD|5-REUSl7Ot(ki08ZGf0rSCy(eTNm_WgIpaH``we5Ru!g5-3MkL(9z3)J#ByYXk zBUhCj%NGqWa$@Ej=D{1q`rdDJ++VvRv;I1hUzmE^<8(+LA)~_*xWy2XZ2W*1#)Q4Q z1an%aKQ@hjSG|eeDk_6-5;IMyqKFio71G+H(GTZDIADS&PzLs{VsVuzE}e<;ELCyF z5{n5V&*fiRajF1J_q%#D#MTo{X zSe4YR(8CW?UBGGt6J=AI;?HCimq3X=<$&VYyw`YLR&vSqDbkzSq(v1GFZcBXk}@}x z+b)x5;I;bPwkmAv(gR|yv>=CE9eN9iCGWWhWRom$G63d|ta{`7E!S&WUvmf%WWp(V zht%6=3kriK6Z^NTf=YEL0Xde#Pg+&e-^X?bi&a(H5S;dfg!qbYrZF7alIJxj0OO*# zkV9L+td&&R&Z{`S1KIz z^ybL`EXgM4FlS$u;7aUl2Yk~8)CQd%Loq#p&F+T%=^a*kIc1yek34X+(Gm*@)L)KZFE(WaFM>FXHNLdA?|3xQI+Hs=^$w zPO>uiqz4Z24vYA7J@wPyRzZ2B(s*DhSDAMJ6DM^O z004=ha1q%jqN@>fZy&#A8lFw~BW?F{fidJe-HgB{As91S$E#G_{H}KRO?OjMoWc=3 z8b(Di^-!=+Qo*4NO06=Mv|Pb5@Ln7AzAU3-qMR-?O#{ZJ5kSO{R5pkc3O}SIOS#e? zp2r5BbIOC{RXs9*@q&{J7n+xcm*-njLpL9%{l$KyQ1Y^!Md;5IMu2%jXH=?B9mwYVN%k;*(Lq@hQ+u{DOdluiG@?^w&tDPp9a!aq%0ZPcFV*-SN0TJtXxbt!hdX|prXPBo;D(qV&G;OOBjYg zFU6X$M7Er_XX%>Z(@Iq4*3gpX;ybx?_q6~@liB`I(Z=v$aCXBZxjw*`Y|0g^7+PCy zrTY$jty&pR(6iW^i}-YApK`{{%DX=2($yx+N5Gt9VJ`nmxf-Gn?S`)#tppaf`RC@ffpHK@VkC*u#a-6~&U^3Va9NL>m=4BscC6xqSs-NSDATb%)I zKe2aJSwz^lFE|WQ)`3o(-9je3UyB6VCV;nh{v(M0p*@iaTpG5Q2cfQz4;z%OgKI1o z1(bfjBd+Su5?vxXE>T<0H>S{P|4OHrP<%(6J2|-V^7!#MH}oi>3cW62`djQjP=c88 zZ+(#U54dLa`ADbXV-0T!VbhX|EQ>LH6>skU z*2zdcl}`0``TG<$2^};+rFPJEc(j;bUHXl>zWTST|JYB2_`(2X=Jc`feY)|!nMe#) zltH`ECw$T5PgIdfPj8RkCf^gqxl#|DFxoqr03@OZE$Z^&#mNOM|^fe&w0UZ@{oOmY%>0LpJ25+vB{UF&Iz$;j5TpTBVX=~7X5OzOVl*1v=@Fak_Lv$cJhLJ$2p`P*x&uYNxvAYzX_VzRk`XXWwr!PKU$VL8d}^106N zTl>4!A0}#83kw%;>|{DRW?XtDFwGwALNJUlEkoR$p-@ux6hl6vJ-WoZa&oz1@fEZE zx)?D!>W_k|!fYj2fUMGl#GaA9UEVzkMmXewuiJ>A21NSxx*R&iB(_r!^p?*1puqr4 zS3wk;u?Bw+w~R(_Pujb{Z{~3W_>)Y-Ke(1G=-DJM1+A@d&|kBRS=4)d`$G$4AG-x@ z>Pk%xl|K?l$l7AjedYimFaEG`htaae;D?0$07f`Sks&t4G$PkZVDQ_Y1xST>WJVtc zM?Crv2cce5atNomm|lCX-zMnyWxHjOHuO5E2`92eJSw?xA>~nQc;v$7k(Ps3ZAAC^ zp<^(VYH+LHPKddG<3^aA>cytM1bo4PWAg5jX?5+$FH2>_gTl?||1wDA2Z#B`rjS^V96oMK<8j zO1OL2ZdS&2^)VAy?7|LFL1JsWS@zfIFVRpQ=bav-IRB2#9RItp-a$)!nRNpf;XD%q zCi=Ap22`oYIFAb~?FvBNCKDZ2FPkRWx(_P-HNWnWL4zPSn|p_0rzT=@vyxa_8w_;> z&+gwvHPFX5?0X#SeMFhaua37M06-y|iTC)ew4uWP&xJPG@n+@1Hp@=fz$jphNdA@E zA)HCj_U`)CzQQ2X2caH9fZBNs0?dRFWRb}&{vrZIsR7ODI`y(AG0Wg*GF}=IM+Mnh zs)OvD?ku-0W-%p_lC)$7UJ5wDmZa>d&rRn+dUU&|OFNsXQ(t@Vs?c1K5E5ts1%8;T zR4+r7)v%V?NktfNyl+POa%k}sL8xVG`z%)=J%iU~5wMD34m3%42N1et9GesMb6!?1=mAZw4%nMEN>U{MsAEd#G% za8U*qSChO}g&3oYkJ3%%0vwKOK2*CZqdg2po~*(6s{su0kfb~=%jmO~pcaoLLW%J?E8;6siSKiXi2o*bn$T5!x4$bFPc&b-GXywgG_V||MHO~> z5>PzU;>PO(5D>g~wJef%efX1%bUqdp#2~OVy1o4()J<^XZ})5N)Xb2h@H|-$8{a)Y z##Jd<4#t@8gJKP|%wfd>*YaIJ53gI*)b2D-Jowv>Mu0s>!?lqj1RnUlyP?Ul&%1Ep z`5q0D>td9TBVhCKQGSKaaykz7$~}`v%HjOH+=@-Q4OWTdWx zVBm`&Ac7zS(RO%)$7XTnGS^gDoh_em^>sNEa)kQsXR8j&YAMUsuIG(J#puBenwt%? z1RzQH%?M7Q`$6JM!Tx;oSe#XLsi5!=`s9m)p{qCpsvKCikDJO}D2G1*5Ysq8CbNRN zhJGG;a4ZG+Mr%-RchDEXyG0zkj7A;~o2*iT6a>!sGF>@%xt7>6QL`>p&`?F0M`I>j zcFA>5m5C_hfHsLuZlI%SVI%ld7@(JH9Nb{8;^vTKg7rKQx+RpzcbCCvl=IgkHO_CI zrj1XnIOroJ`GSqn#C(NtOM%SDwL}>rhDLhCdf0 zjavz6iOUk=>rSm6G?ySYLQnwb0J4I*jJZ%87h64-c2FK}4b!Gsoek^QmUN$R^K-U{`sZSqeWLwTK#49k$eNt=+riXb zdb=++UUgFsyh#>5!6QcAC7dUN6Tz)!u7$M{~LFc7>DO+Q}kaAEiC zSGSA4)+su+*LxWgp*ZP{f< z2@IO}p}fQrw=M0pNYN2MYf5F3NTZWz_Kk)UjOUm8s?_-4EQ&UIz7ZeGSpp$G%I$Y$ zS`*uv@s<)jwPqj)B-?6T%ljj|N=$X(g5naAgcR7ToZh#3&gE3{yDScX@>Sy9udatk zqt>aN*QdV6Iz2J@f$en|8YGkPSnRKcy@Z{-TZ%`xd-*ftTJgC<&hMXg;z8JSj*GYb zRqVyKAkDMg%beQ+V1`g(=5b5Hp8GkHcpdpT7Wa4+ox$*P$T2m&p@H5B10)f^7zQZ+ z;qP%N^6P%r2PU{8Od}Qdt((8O0Wc1XC_n9Q<5R|xkOiiX&GvB_UC8-T7$*V@ z8qs}BBM?ZRw1~$Eb0y&Z%0ZGW`au(9pW{J0X#coat2w(1R30#~&=#~+LGoKaU_37F z$LqH(xu8~X7B?orn{dW_#t&|6pX7XTx9YfuE{EV~^zEJ6=ezxfxpMb>&P_QOY1`IR z+S}glSfpiYT`Qh_r+QC}>9Hk{U1?9mTz$J{3rLsK2$O)ye$Vd&0C+AasE;4$O&3$A z+6*lr5u$Sv-fPBwmaN=~;myZ0dn!Jio&Qle{>`~B@5?wN7wmxIC8}?tgA=Vd35R+_ zceV~AuEx3~B&1iOTWub>5eU-YH4DRz~4EDb;=T8Znuqyq)mX%ftn^5u?dJ^9>(IpDbDkd z+k-wWnL*5pJ>R1n;4iVlCB++5C}?wb1U%0v@5-4>?GW(wUbL?1Ae!~qtSKll49dhI z&E}I156E0zU4CnV&@$&&yc_HKZe^<-nR4)Ri+bO`$TQ{pt!a6cGtuhWw3jX0I9^}g zx2}2K#k)&K7ocVrWqY1Gk%~Y@l+D~g>>BOlN9sX&I(9%dH*KE^HQ=jwT;ug6!cr5! zQ7cFdIN1S#dk&W3sz;PDWw>B(Hb5fhXU7Sxu0pmanbi;?Vq7#s1f1rrOKvzKqL>=+ zBOnsM5*zMSLN$Zf-?XvG(6rT6V_mGF3E9AKSUh4$$*l{`Cmyl+%#S+ELc*DvIJkq` zE$+Qe!Y*3g?syn*x1#sK7upPH7yEyo=0C9Dfo!8B0J-Jcwcll0y$KGRquL_U^$w%N z3k?c1r^Tztl4FyFPQ&~fbg1O;6I+fPkA4Ja^2+p{<3v-LY>4J!)%w;hZq2L3{+Ari1S4zq*UT z?qIyi_fAY0e-YKuukn~);eP}96-0}rePlWVFlzMXO1{kDWC<8`FURBcs@QEEw^9Jf z0xtjeMWvT6NVqLIb2|q`*N_hnxro35Fj?vUA+d(nGXxcnvsNseLlPgE7t}i70Be>@ zq2pss-Gv$?275Z&-^nK3UFg3K0$*0o_HRe9(^-Mp>F0a8V`$_^xoYCFyU051HSRyVSN z5r^Y_=-l+cx)t3##)OO!7PjMCvz_i@yKnE4XYfhNLWi1c05vwN1I<_%JrR|jv=_D< z+7Rv|G0~dE-#>1YpZ5&z!6{WZx%1MgMY1#euGcext6f<}3+-cXCt@h}cL4>0M#yU8 z{OlynJ8P$!-$;-}**>^q33Fs#N6B(qM9~o(B$&eMVX0Hyh4hZ6IYNCdKu(sHlU-nK zm3@$cs)OFwH)I3B#w0jDcG$SM@9iGPGm_@FAUP?<9@UlWe6kL4MziE|j(hYI6`y8( zJfZ(=O&3dt37zJj38Y&HQ&7$-<`l8{AygzF<6s&R#tCzbmQ5}B za3s3J|3YMy#p*^*_RWvfK^6E^>@h@k+!%h&JOYs3^=@*CSx>Ix!Ibacv+)9=1-#0N z`#=Sw)-^7mZ0=XFVeVFX6>n>v*?A4}WMoILVl+EJHrG}K^(K%Lk<1*X;g77maw-C* z&4{%%|CYiGKe+jK3%CRH!S;vyM%LCWAp%R-uJPyeWQOo@WiTC<4sash7=G1FLjgqp zNawrL;Jdz6?Ih;^hrRD;Qx)pgock{TBWA^bVit2wm~+me{{Q=~P1QN)ez$wjJ?cSE zc&rj(@3mKsj#$Zx>`lYLk(fC!ap=pZTWiiW|MR*LbdsDlVpvZ~T&4E#$C|Xi6{B5> z?LjrHR5*fhg8_s6m@NsxYak7F5J$TWh-jg`79X`%|57J}Fes>5+&w4UW9WhaQ9SF~ zby91v*O{7b!3W;NNR912wm>ciMhC$JnH=%HlchG(XE$s&nm0my7^*{a8)t8m?b)m* ze>emk5FsEy2kZNIOI~X;ZD;`#2J-M3-QQZYsvtbZNn%JAeLIfESnC zP*vP1aFSM}HuqkiSf{^&DA<|md~FEMWFF`oQg7@n2hEd#rXMX=YVEW%!0BomhI@3e zafeL$(N5h*7kXCgpUYf!e8AUSDl`MhmBpHV#KDj5uG(M@cAFq&kR;&HmO+x^82j}5 z=Q3`pr-EIKOwSC@wT|WXf|*tL00jLjY3!DUR*fXl@X`hzd4G3sDg|7CO!aT3DB;a# z_w()Q_@EC59ZPVau&r&qyv_WUAAak{Z416@szBJD6`<#|qY}%Eu?x7T-6H?}8=veD z7FBLpv%Zi;V%SyW8S7o@(6YDQ2(op$NnzRSJWb$flFH=A%_x7_X{iH#Ek^ zzs1Hc45e((In^v36<~QHdWarrPCl zU-9JxhHbI#A4Z-dOR)*;ANwVF90MS9V6cgQOZ-(2xkH4Ce%*6P1+le8ic3VkP=d*U0;#Aq zqlHBTg64_{3d}{gSPf?=)#e64BGd8G+3Yr_QX@VEeL*6nAuo}Tg{t&#>sp4?aL;c} zEIa6sKv0WvsoqF)>LFiV;vSUovCt7ST2N7ho^0M4j5);{Xm~xj1Lv(Z;FdQShWRRS z)sEbtH8^lFx+c+IVOwLj?Vo;e#v0 zJ`lPG3Io+sK4J##AK(XlepV*%lM0Dj7$Y;W=iu(p7k`g~)#V^g=k?Rz3dTs`4KsY4 zDY)ih7Y-E7&3pK@y_R{!>nx6e`R*w5rvax?i~zV)fa-`9;o<{5%O|2;PdybtZ@gdE z_MtX4E6_<`fMr3aUpT#4!~q%MMnX89A#sUN<=F^(Kp2B&ZC3BJXvI9cKuR8vn(%Uq zC_rv(54Dj0QY2_N=nHqLzN}fAPW@`OE$@j4%M^#Fuk7Rwo!#6749MCHtk~5ZDZJqE zB?T&8J9U*fuwpr_&3yuFRg}K>)FL|Mg+pk))-5~HSrmzQ08k*chSNh`Ha1l~qwe-- z-8fp;DTd`A6kNVZjVsHsH{cNRW9>)<+tpf66D<+-dK9nXD^Wa$$d+BSJKU5Nf0Z}z zqlt2OuCn3H1Vs9=7B|(h=}d?6fl5F-Hzd|OnQnmJ-T6ZDT4-Gl?+p!cWi3Ey4ka8= zyj8ft=iLMwI#(SUx9#;vyPUa+k%1DfzBcc?CQ&ZmAm`^QNj`7N+ni3uwRQ=%);ucD zNpZbGfofq6JWvBJe?x_>%Yb_~Mr7mpbCKwigsrp#Bmt3jj-Q~fL^coxNq*7*Z&Yfk z*F4G8jSUE(^lNj=GY!TZ(3u<}ME%lWpBz}P>hIQCLTk>ikQY}wO))|TAXzYY;?hI3 z2@cAifUm+K&9}=3N}00HYl4bt^OOQ=&R%OeH=f#M^ae9!nfHWifyuGM_(lEO?S@JX z?-tMoe=jwxbHP-q>qEW}J-pwgOaS7IY5HJ3=$KY1>jh_bVJ`)=CSPl))g~{>n`&i~ ztGa47ONH&3gm%zouLr{GWE&OVEr8OdVFM{QKp+pW=Ub6s9ecB?_n+^I&exy~&3Ecd z-H)p*uK_jDSf!NneuEx0!bYlUi82(({Ev9ed+qGE*H@r0vshE97=(NNPiUOcHheO zXT>-rwmlR5?NWCS^9Q8dM}F8zK)RUG00LvT&}9&j7cH{I;&$JHd!bpu^;{qPxz9tb zI0zX09zcdAu_57pOC&7^%eRhYPul1izY##iRwsl^`-FAfIBc}jyM#uSh2hiZ-CiHG zOLn7isY6-HZ_Ks1=RL*|uaVlpQjLLiTkp_QW|2l{y|H4v5Pex30EGUiU1Z%$9M3_! zvNPUCfx0uodVOkBF1m@_N~M%@yTh{OH&&;&CqSu&3wv3-4Hm#eGqq<0hU2ChGxH1VUH%ym=Mp;cI396`gVDlZ!aV zi-`Jbs=OY-AF~7_a&+he8ciS)F$m4eOMG!qS+d=~9o+<1=?Br5zZG{74g2gEBOqJTy~Pu@`ffQC)qP>t#GJ zaIc+~y_SjF&c<;-L#x4P%C)iVqmP%PGd4;UZH1c4fY5nalE^GsM;K-rE_cN5(LgbI zkPB>URWUDMrb#;IP8wYmnsc zo=Z<`9G6T<`_>v68I}^Vg@6wTAuOj63{qAz+Y;RC%e%T6A4fpk2Nj)QxLjf;Ug&=Z zrR*zbaHQwJy?8Eoh>zMBY`}UO!U^_Ek4};REupCl%j`pi@s5$m+v%^O1Us+aNlR;C znMl`#R%~T@Sb}%OyP9zUHo% zf7cI2+Edee1SJ%gW3vbr*}>95E@>+#yx9O)X4^vB%suqxhiKWS;x2@J>x>HqX#)@F z7W0zXG{h}~HmEeb-wWOdwzeYfZ@ETA*l&rJXe0T3yd+-Q^TiHx_qO;BZ z#{SL+T=p@zCx$=XeINvqW|fk+7I@t(xlrof2S#P-$I91KaNO)!@Y?me?0sK>g&6c| z4m352K)Jt_#~L0XtbKt!cSdaOsYYnORFzbOv|dFFaeSo>_CgU9EuaGHp`Dl;{nS(4 z=66u}kXXRfcCIXG8{SoKh3mqg;Ri`}+6Qo5_mU84T3H`6|V{(r{ ze7bPUQc?9oPr*E=b-A)`#cPrwQOpZLKGnKRw^T8Q4?XF46bP0 z2%cGRz85+SHL6-9&lvAL2O*@3cSx4*x8Rb`ac=K_AZ63h%?aiGeoToqsEy=w1#wBr z!~|Lg(etaPlhWa4iE&_iPw*#YDRHH4@M_{+;RA4}feL|S45N#l_3xwd7(IzZewZDh zA~YBx&Wmt{4oN-CXl5MoZ7*3F;GjWP0!iTOB5VWhMVTppH?2@@qrn~UN~5V-*`d| zvi}f+QMOtxl)ndT*L$YP#LWSi+9zBXE+8tM9l&890!y1oki{ji@#b@Yqbk|3=ko%{ zb>pCAL~p>bZv0b;J7G-`m9YyAmPcY772Lb>-W&roEqiS2F@_y{BXskxdLw2wy66$ApM>-+178LlRy>nBwmoUkHpB8vrwLo}j#w3p#4t6-L00Rg!*${b8lL(_z5Eu6mn3U~8 zmyJP!DQO1b{!Wc4sEMYtu2R%V`4C$$J5C4wZ)MK&30?o)MQ?v0UbH2bR+TWUfkMxR z{Ap$_*+)greVzz2=fmWLD08JI{{kt04`Ok z@2V2Yh@dZI?!R(_Fz<@(oAfO)DGXE8PGK-9@N(9;$Bj%K-wQHz1>1qRAmAP)6h8UY@kRfmiZ!&ia0m?rqUWp*49K067{v8U^s=-jOqt znYv3PK+jEHH>vv3LHu8w@Ef-C)ScN;ZZ^03=rid%^O;R6M(gSfJ4|z~3=dw2YEqmR@ zL|(QkR#F*=#h}-v!3wjj46hQWfMSPcMO@@?*NdoBPX`VZkRA|d|2apWjN`d3^NMauC=Fsm7 zR+;;Q86Te!pj~s$a4hm$eMb_I@Tay2qjR_AwwdW1*i?!e=Vi25XYML`G|O?Nb`BMF zhZd{cuGoZ|oV82yZgo-$%6PNy!ZxKB_3*mjtmMAjN3b&O6`DTFK4H^OHd=wN3-#g` z3yEfFNfY|>Q$fCG3I;REg$+MH`7J(zm^G=-yR}gnG!sPbHTtv;Z#GdXNoZIX|uzFXQ{xAI0hA$LSOIzlK z^hKYR^fskZG4Ga$+6m^6V8#6C_JM3o=Fp~Gx{uH`@8DkS3O!ZZPhe6F2Yq6cI4Y*R zC>_0kb?4zWD{~AGGEWN*JBn~z`C6A<_`Ei{<1`Tk;{xs}&Y9Nqw${4pYc=TQ zGMcpm3>!?bU1>sva!)8PR$@(sQ6G{5gbeZBJFR*qypdoq~^%rS> zvs^}xb_pvM>PkJhb5bdVKp5r1z((X0(9pekmCf# z;NXfM>f=CN3*qYcSxUNRL3knj(_Cih>Z+Sjhafrn<}s_cZ5SWWkSxM2w0RU9uQ;mB z4Pphw3gh+XLzJy?Z;!SG`C;^;(nwdU4qxNI)=m)V7292|!WtTzgauUvF@**@O%tCh z{yprMciho9G>kbwKBnijeKTiIv z6S|A};aPz{fMIr^FARJ`;5KR&4(7-#WuDdEP|GpNgKDx_42HSf`By$sVHHfE+OR!; zd=(?K!inis`3{>f8w(nIj+s7=9i^wXUPc$LPHN=PscmzU znaT0o5tGiWCML_ ze0gZ%&Eae*<-OQ&uI4d&AXHtN*`+PRXv7?v(v(LL57f$eQsPFb`u(iJ7_qg$8zT3D z)wLaQLzy5_x@Lp&lsKFh3WpdU#4Q2Yx|h34)$QkqsR|e+W*5tO`bCMja{0 z{BriXvmEHDD1$4N%&C-5U&CjB`Wcd(IOi_1Wq&gsK(@A{rsy3{HkFdkdn{J0;0ci@ zHa@pv4Snj$JNN1DXv1nkM5TujS)<$qFNmg9G$+5P>t5|i#b&6V=_nahe~gc*2LCMN zveslT6{t*#Ip5_2t@mkzkAKMfem1l@g??Q*#Gm*II^EN{SeXFt98R$~2F`tNZelbD zG*BA_hp>rd@8%$i^5x-%7y0m1nDpzdRLbwP6l}Ze9tSik3g)k6Q`<|a9ykeAco+f9 zrjRHJTXaSN$)sNU{C3E%hSviH8H)s16cwO=k4g#YPfwcO?5p6VmKiNaRo|iOrFO7A zuy)L-gHqbrJH{75P&P|`o(qcO7v`Pzt*NB4+nbclBEG<-OEYy5QvmMSYE>!y!i3{) z_2))ZZ4;uFmCY`e;g@^Zdx+UmyA84|Xikah*c^uZaywk(EoSIy?hr~pwTCeoMz~7I zd@^bUVJD)}4l064i8xJd314ZA}C32pAXm@L@i?=R4#f(4epzY0R162kBk{Br!05eIsUaD^LzB#()qS=Ej?Adr20O^TupwG*K%TQOe zv@??nymLLQ!MY-n_o(7T;<1L$%#^*!^C^qO;C(rPeFBrTp^fq-b-)webAY_JC(HyS zv21`KVWpS6Oe%+pO?vE}9&3h}kIZc0bmd71XUzqjc^!gBw&r~6+cdk(IKr4fkJ@+Y z`UebC6H#>+86?zIWwSHCEroi)x~WZ+V%Y^vuKYLyw}r2W>X;5!3Wf*9*%Qr~@NAcE z?9X)ys-y)(m}{z1l5B9*<9EQYD2Ih`7G=Ge4(Q|->|*-!5$#)iT?@Bq*zSM+x4=&X z+N5#!9sugV4XTKU0^q48dv2aB@datQ&z^cxk8XSe8o>!hRgiH2Rl_J88kE$#O^iCD z{IXkm0i*mWXn>?WXsYAG>V-*-p(EacZU|@0i~0&ErOuVjpbiy0x`CUKItxc10w^5DAI?WhU=)h-1 z(fW2|)M>%CxXn|->9d6g$Pb-as}&f)4unXJpXHz{4AwcZU|092u?9t*zL@)?5}tVd zgfmceokc*)KN(uH%ilGalJKrlP~XgfUmb3UK~5pVPeZW~eMGZ(OlGc(tAchI7`U&}v@)?QWcnvP)D^O#kD8LAel+4T2nC zvbvLpBEfj36i~23z@K9>qt_3QP0wX`_2AI6P&fqBneYoRK(Ud9j8k06)aR?Rg(;h^ z%*b@Wne#E|O5?Z%Fpf5`So0vI1YB4bc44CJmw*Ay5*$QJFJ~T{TVOuWx0P`ymGcR? z!N1$ZpT@?6PRof(;o1*y$|D@;s*ed}g&c~1X%BtGHQT-gloc%bT3@2{zG*Yu2 z>Nvs@TgcNA;f9WSKIguUX{XI}&K5Zjv6T-#b+$#5vdUlxx1#z5KJK4FIRuAb8mIYe z&sGYS!>~`{4fvO>rOo4++yV2RAqz}&Lsl6Ll^dHhy^n<*z+*(WO^v@p16pTBT`AcO z!M#tQJLIQYum!qzA=pJjeUK*g=?XX3c!<^2Qi|4YWB`ni2S0A5fB$qj@xOqaY!6ZM z%3C#u3GK(7X^ekS+7LXx6ux$)(H+I=q!UP`6#qVhi%m7Wus_}d8)rEz;|Ej0ejoRU zs?y-rk$&>pJWvvlMAji<#z^-lWBx&1CeLYHaXT_oJU{BiE|i{WzYMthP#?=Y{@INv z#bP^6$CAO<_8KFtR5E^XL%VaKqW|a~GFb?cK&})oZucs7rPC%|=|30RpEnA&U?B-O zG3JOfJ`jigct&7A!5HXi{2;OJz^ChyB9VcBkaauM;X&&s97f$;xl z6Qh~zHDPZPFM{ceHmJB~M)hOrB_jw%LDCG4*cdy{h#>nGS&!raA=Lmet@uo85LW%4-woJ2J7*v~Mf&%Kr ztU-Mhu_=pE5r0*^E)(HUgf6k{xq0m2p8*-{(!+{SEpY0ztl-4%uu;sZY;zeyZ(ckD zf(bW5CScGjETfJu0qf;XmY zGGZFJdp^Xh(J%~e+Q8kn@?xMK_`E5lcm$_`g}{0hQqtQ4$U`^Ql7syYg8L2Y5H2*n zcbcf+GieDZTXC8cZQS!PsHN)LwO!#H!^>X@j88tBqGq94t)`DK@tKIhV(Pb}-IQu@ zcTe_I^dX|BxLIDax!4Jt~D2!+TjAe8-vd(OE zJ|4V^w}H;xx2+)>d1TrcmRYb7RfTDtcH(tWyg8W&kH@i^DXVs)(Ua!=j%nN#ktuMaJb7P@^p*e z@j{-X`6%9}<6S|ipfU-y zkB+?!K434{e-Rv@@kMR_kju^4!q^3;D;PkU7+RA9|33Q$O~@M(}_ z<%^>t9z&=02QK(@RWYVBi?W2@G92jqx=zfehJMXUz7NYRhiHPB0 zNuV`VYoPrgniUb(C1+QjH_I&tsBwM=>y2iakL;M-Zsxq&X=YQ3Z^Pq#o)<1~tPcai z-4xc!rxf?~EuMzVp~km-PoEC~=#Uq{@S4GVoJdeXk|J?Ic-Bwkz;1+Hruf?bv4wPxE&CfjSy$p*yIn^BCbDA*5WeA#wLA1~f|7TmY^B5W;T?iG8Zt17}080 z6bF zD5dH$@ixK!#*EeOnNwx)h&GoSKa2{0Sekb|M_vq{?}bPs6~PpB^u-`*q+qB;=yuT3 z4;Ey&p$r|Nuavn)=9J%L=MuXU>=$E1UeK%F7G+1DM!@=#~5$wJbk%r}P( zpl0PcduoRIseCQW&F!jf?`XaIB;m7Cr{t|?MXvxy86`zRWd{0-HW=UW&DlmfwW}`J zS@JUSeM*aMX07OLhmhGU(U1)IfidG;I;mt=#d5*2f1=U- zWAI-xfq?QW)`E{>n{yBcw_B4gfG(}igE@DyHzV^sQHW@&gg2)gkS|vWmKkc=ZT4#@grIjTN%-iJ8-?T$TpiHX zQZ636K$b%{i*<()fFbB%pg|;*lFfm3N8oc#CB@ATa7ry@=zjL_c#SsI!Wc}1Bn>xN za^Vns$?(3gdW?oQdf7)df?!cMcvXw!tpBOZ-OUweo2yHHy3i-evPxa;DbGMHjY@z+ z`C6@g2-NOBvBM> zv^%6y4-MW4NXcc%8Q<-e;Hx8)?f^`;fNnLJUa;5W*Q|tGKGCVHM z;F*_wNO&KLAmBjt=PdxaO$-iK$XyDcRy-jj^Ce#6QIjV9zACK-rLY{h@qjy3J447uXt z@dqJLa6uFjJbX|H(Uo#uEp9@*OKl1tPpJna$<~2LJ@o&*aN=0WF85gMsJ_H0sYC=c z#*x?@(jyVxX{0^b!{`Af)oWEva`jqm5NRjEnk24qBMyVYBfv)%9dTRZrSRqxZkjun z5PyH?W!012W8-!Y-0~R_4lv069~UdAh57x7E}h`=%0aQk{4>i<9rxr~{?rY>4q6R| zW{a8>ebm~^%W`!}ml^ahJ6?(>AUxc+hs>5~lh5RXEB1+V1oKlqTb^|pZ#4?t38o;VgW1`+l~ zKMG(Avm{{CHY;=MqXmF*+3@o`lp)*+T^mX64mRtCOUoUF-)>#s(21)IsCcTYMUo|I zJpc5x)ES6Pbln+GsMRk^Za8ImUX;~Ox-O@nhlSObJJTjX7^uKeM;v#pDEnPwfLXu1U$naXY8gReN=KSE5T!_doY6m!w zay-SpFo94!9)Mg1%eFqEB)L=IVRD_mNC(_pTcc3l*|KjJF)Xq@YbjcCX~nl`)#R%u zdj1e^X?_$(V+SLK5D*;C!dpIw;R?^?Np7f{WXLKOp_`482V|%vJSsG>G&$46KEHU0 ziuB4^3RwFsL$FF?+5JdZeS<2=sMIx=8Nt*1HFel2+B`Gvjxq3M( zc;C3sK80VMCR7Q=8?>6;00H(mpf!9+Gq5Sft8k_gpmA&fLZvKYrsS14D2m{nD_SeN z##7bh?*%h8v0V%>24p41S;DW|KovgjcLV?HP}?FlJi!XfJ%}3qad!HKVLh9ZtXeUh zMEM~#08p{j)HSL5IXI1KAQ5FBjV~u?2M%gXfqt*Ei1$%w(6Wy|%O-Y4fA1h58*rg` z0~n~&MnEj(^q+BjkvRRBfH;i)kYq@%moGL|lqLrv2STKG)z?7rCY(AGOrTIj zxXu-`hp}2HuGBOB`k5xVL=93-!oAx$ zPCrp`K)m(ug;vwXpY0~~#_M3;u0WCgIsJPN`-C%mH6@H2t4q&jr3T<5Gwtm~?2MvP z@KywN9-sj)>9f94C&X>wQf)C9!`3=AxF7hnJHOD@dcbAN!DM8@4J#YhPb5|81%t~j zaQ!p8`od3TZILE}y!rR3S`XybPsYvREg7OBwD;SgE5+A&@d3^?=}C_r-;kc?Y3A=P z7~DzAZia+GbHy;l#Ii23)lFv1L}!SFjNlRC=xECoMkcQC(f2lnVnh%={amA!+qZGmaAG0Dc>sEsp(1gw#V|R_-1ReX^5ZVk4Ik3CP3K{i!zO*{KR_I!O!K8 zEy?qXRFUM6y1?BlA8%dA{ae`o$zttpI|?7Qqcn>b7Q!WReVd5&XJGP#MLy#|t6JXD zIY^JrpulhegmEHYFKphS9X-W_!%PElW?x}N7+S#qy|)sVaW9h6lg}rayG%H>R!ee1 z!;>`OKH*a@QI{U&mP!CC%1fkUDYLn{fxEVlJPYBZ>I)QVAuDc-HDq5KPN&Cq9XAf` zagP{1KM|5_e3V$=Sr4DG{too8btgpIpjsKlMW#wfGKXev>Dw-wL4z68a(U6a6FLb} zfz-4jeOm*EtcKyDmL7K@{B&D~9qC(y9|Kh%R_o^YLBLH7+NIPw{g$4=UK$8@w}WB? zDg3w;i!^`3Ws0`)SmyEA@soBk;LTNwOsFxDeXW{RnVZWcbFAF%158buf|#6}p)qp7 z>j;8C`9lQY@cb~@?^BDxxSoxL8MLQzbsRv%29X2Y=iB3fqF?G?3Vr1A7B^tMwQ?ws zza5~EHGF1DknzJmJ3nLDC}vtW>zZ73T*GW#+}yiJ-`cfNgSH2fgxNrC8cW`2usU?y zgPxcQx=9^Vkw+`4Oudn-&7t#9eObYxwMKA<=fo^GGh}?n+`9GCC@Tx4MAM-%2risL zBO>aU@9?#V{HRfJg`YtufUh(X0rld{?lz&r)C2|<(_SLxEWFgjJ072$CREwwMFa9YJboNdmigYth+n^chW7=H!96K|1 zuYH{Y2k$JyD3Hy~ila)#OMsABr%et+{O6nEY<*uAvac^HdeXHGh^gKS)lu~l&SLgK z=}Zp3f4zZN?AzZO2F9U%(r+Ega>Tn&ccfXf(J*3BNQ$%u#zh@=l@gmP)AsBI*3QM@ ze@G+#4EqHG;f|jom(202rCxHhaTux_Y}GRYj2C8a1LLDXC&}=iOH6v)7A5eoGzZTM zvc2LfZtn$_mjkcmD3t_{-n^Bm`|JgVg)M+F^^jCpYXRhkyuBL_Ms+t)XOrwz6Taih z9e_ngP2?MCt2D~GHqf~OD{s5quR|a&K*boH;yXmDL+(DQXsDMQKHQ2mwTa=Iq z3go1em?dwZ*$YiypOehSp8X{Wlhh9c&Qy`JCdwFnKv!I1Auc=5BS9A)Y;L)?Pk+Bi zN4QKIY~jfj-$ZWXNSJ|B5kBx4=)-{QwVAJQ!nu2Xb8I2{4xR=ggsgQ^T}N5RHZhPZ znc-Zno*W^1s?4KiD_{z~lkFuiI!b*Kt6tt59e#YLL-_=DIn5AwBe>MlxU7p{b9@Vy z`W6dpOG{H=ER2=FXx{+zC({}jnRE%LFOQv{O)KP0-B3su-ZM^YBgTX7FsSv6$6W{%XIiGJs~djrtu4knNv2Tmj+_2?H=V;_@d5*aa5yB(Ho9$Biu}#wBa+$UO4n5!k_O#k`|H%?KWzl zcKeF0hX0)5-bB%J6pi&n{m7erg@Uj8(z--JX?F2B(yL$q(~9GME7C8cn>~-z5qFf; zcv%3`7>2>qPKht1z=m$@Q-Qb(y|hum@GcLjqO8-4&lc43A*g{Ll;~L#1qgR*q89&O zUZz(}CTEY%#*l4+giDH3t4?YT2k#CTnTghvl_rk6183S@(EE~5??$}zZ0tn{8F+Qj zE#674-;g=jNS|?wmcTC}Ta#RA!&b8LkqCP|pRyLdfQv<7!~^Mr@B$!fMy5;)cK2!M zfXpu4rP1{AgrM8jQ4>Tb`Pjx~2(|9ld%aAGk{p?$9UL0F;xt7JRF~?=K~hC8WYyau zS0Nq=U=1w7zJmxXOeqmhby4xOmrGjR8$8C#L0gDhy=R9Hb^YE3Dd!A+`v^FR?JF7y z&5*z_%BX5#h=g$h2BgDjP0Twb(DCJ@(ahB*Af|DtCQQ<21Efd>E_(3o@*#oRJLH)5 z;B(x?DE%Z0z7sl0C=&4o^5s+&+dUm*G3mUU{tnhM`Vx@0Uv?aABQMIgI?`Bc}lR028pDOQ5mFl#l72BI3=AE={Ku5OHVy^USobL_E) z{u=__6S+Ob{L5r0=4dgJKYk02H7xgtPx=ZW;IUS4;0$9?OKW!4r7w>b$bT-zp0QKa z=pIj;KcZO8Z8T+yDD}S=+^A)+-E0Q{I($Ju0mL6P;f(~@-Tp3DtYwb@oPBPy#hO6< z1WER0K3U&=1NoNcA-r}u9atyK!B|Qo2)bnh?)*`);yrPhlQm%WFhm^()a7PK@2eOG z@~w2rz=Az1h(LQD#b-Au8Hi!1h3NAFwue`NPWZ1k&eIDzAh&Uuy~?*o9vcoa^hGFa z@5e8)q=$6|^?=xT%-LJsd=r`C5GZ44cQrVLPbn){jOZo?feuqYV>gfNEWk+=FJ&o) zH}WzaoOw@01ZzIk0r;WF1rQaRMtPgpf!E(p`+$1hqboxNlh5DQ61qG6j)Z`p27YV! z6)OHn`&`O_!Fyx!(qn`1KU9DJOb3Uss~imoR~yAKkUGexD$``3Sg?h7VR^()(m{x% zVa^k&Y6xT@6#)q&oE41~bUg$WNJ{wk1xQJzu5y^eWtYU~G2@x!w+eL_6?*gsM?9Z0VBhyZP@FwNIVmE7uCo zZ*Qg4D0;#Ps6*()&WK6U-5v5Uz&!ltB6Q->QjdQSP+4~Xg_~PPQF6S5|6bs5xLrJq zAwvDRwY;0oJ1UE2=~0d0sirbBlNon66+{w4D)f$ zM~Lg4rNLfDntn2huQ!z+fbFWN=ZdCyAzb+SgR?!k!Xj>*u3%@hla5qF&2IEsJfV!F zV@C%~R9QQv$uVS!r#ifV@TMii64iKQwG8-i^wr|!Uh2q6@tqr_`;u@Bqne3XYLrN6 z{(FI=b5E6_ZwLAyA+Z3$m}Cw$B4}FUlvfkkxq4-!or4v_7=as`#^V{GV7PhP$gg8< z41X({D6Gr~5h$dOfiAUYAFMYvh+C><5Bxb^dy>4XcD~o$dq6QkN*nc=k3v~RBTkaz zN~1>uM4(qdeRBfCbQFD1XJ z$43$ZsMh0O^R_u+2>bdY(9^wO6PTuqTM)!V^*W3JP4iOxc`VYPT$KnI-)a~k zLs50s37N&ae=Z1b3LQH-B2nNSyD(FGcnrhDNA%Pq+r%8Kg*>!Byh^l@9|$szWslJc z0j4rb&;sbx6eYaF^ZxUy;T~MRA=?<#@H?BAS}Z_+oWsv@D`_hZlTmraYQ@m8jzrQvY;)wh9 z6U{!Z7kn)(f#^1e?#LY}M>OxknYxn5Z<+ufPi?BnqhN;OGaF+)07Q7NsshTiRM`d; z+Jw-ngJmF~K{d;twb{oGo26 zTnb?T2cU%I-bxbhL&WA_b^JWW9i@@fNSYmux)qR;_92f#lBKofXaZu;;`_c(HVAlP zVP+0QR@JxOm8Zlit%Oc44_IO9IC?$wk*HGDNtv}&w=G_4c(FmNaarPfS34&#@8My*?TCmyXR$G37k<|g5hW02ABh5Zkgc>#}^p&Ja}bI6DUHtYXhRC|<wcU}w z$}DLWEu`Q`isAW{INK=OGuRNo`|rhl0jsCM!-*M!+y>*MYM#VC082vuCfIIG7S$RB z{;St0A-F`=2bf5^MF+jfqt3K&Y!S(g_JYi5CtHgvTL9h--wA(Q`xZKM|z^Fx-G#Pz`a!m{g=j zF&my!H6MiQ5o0|71M;ANL19eK!Dg9=D{yPnda%_%bwlgJ1V5sgJ3)h@%4nZMJRa2vVAz`Vv#Z`z2YsPfJZ z)A9(F8NDV*g`i4?pHxi92_yVHT@iNyy&-aMd`kiqvdI%C6(vE@gwh+lkca%lj}di4 z-w-fdj7Y%fsvmB~5?cttnLrfy&>5e|nI`aGkyt2z^yfkcOK0lD?nf9cjhP_8e02QB z;)w2lE(~DoZ!o}R)<#&5^s1k)X&m|(ngN!LP42+esVxV-#ibEOIWN;hezx|@ZH)hk z9JCYBhW-19MtpF#w+AQ~F(zZkY@hq0p+G&Fb}cA2oiXe>mH_W8>V)i6ej z9W-7NYBDD3ZcbmOlroSb!EHMsG(#0@F$o!Jlqyo}24Dgg-glnZAF|b0<8e+z0WC(W z!}dCV;WKDpm#qE>?I9M-(_%sUV+%TFkW!F2ZB9gGL`FMe^`zl8vT!2pUFc-as&rIB z%4}Xi4*m-?pmI?M;>S7y=8x$7;OM>UDX@TCCbj+q0mP1psN13l2)OHuJSCQdn6oQOk_8tVz>7&$I%2{HDT z0{>&h-n3+_(^%~5hF8v$(jJdJi0iY3HcWSR^1D_H*C;AuX zF)M<$@mO}3qLy~d9kcH7qJIOYExjn>q3d|$#y z)VHCDsNK*4m9xjK-1t<$OJ9jK>H^by{d>%9oH7?jN=!R#H92Kn_laiVlW<+zj5@pr& zez5-nvLL`D*=4$kZ<}H&@%ak95$6Fuq)R3-)e6BxsBHbtp4#0ymHO6&lkBct?dWmq z3R~}cXHVOQ@TxMF{i^Mq@6;U$+}484B*i|l*xmX^{@Yh$ytAx{!(*&TMSVj`Mo6~rozrFog6@rc1#IJom}eF+c+PM*3#Lx zeuLQF4dwaYMQn{1)QI^(A5dmV=j5>!|dr?(Tb^6Jn}HDvdX1`<`K|(<^#IC z(M)i>Nbd#tQ%yPF)9eVx62q}H%5g63eVknFs{KHhBQ|M2yZTZuf=yixbY4Nc`IXxl z7>%Qv0!h$5N0EetK@NXe405Ll>mGh^1p8PtJ736fFb6CXwsu?+Kp(NP!l6~xPGxZh z9v>5H`gVg)>9wAU`?p+5pY0e-P0r^mpKuPn?g0ReVug;7jN(r-Xrk_!A~W4Nb!4)b z6#;fN)W>MkN-x<0w-yHzoz3{od74M;zD7rdCt#BsW4qUx6KA-O#+<|OD}X(g57<4w z!v&?Sc#G)6nV#^?F*eu74$B0^(yj*UBlv@!RCoTviO~o~_`Gn~v6p7zId9o6YHodk zP2Swjp8g21Pe8rs+&I|Ba=iu|23tb2kRY#R8AqDcOs;kYlZ-$uXIilYKsx;|kA`aU5cMtdCzcG^zCrai$G=%cq)PU(h+z zVO!`Wa8+`VK8D#%GVd^sKq53NYy>%Rc8cGPKOx5VTQbk4coc~eTwu+EeTnh;X6PK6 zckqW1$0Neu0EMScqJ$OUF*d1fd;nr$3v9Ymg>eGopB8A-g$sz~mD`&5q01I^#hh9c zRCPJBlhafA2yPst8S`0k<7N1PDi*tw`5g5m3JTdf!G@Gs07smI?&isD@#ZElI{Kom z5dwf>a2Z~Wr;d-gJuQx14p{bSj3ckycg}}WgkaD{U?+#EgG;IM%<+BdWY@uurUd89 z-`#u2JGT$BiAs`aHrvxARc0WJ;W_WmEkjYK+$ z;UR7eOr7!)s5kWb21H*3pw-Rf>KA5Hh5_IM(iymBVcZNXz`EN3biluG^c%$8{R1OJ z=hNqiGUg3>9wbnKw0ld=_XJIj%yrL19|86MlNm%U(Sc*u+r`B3I9Jk9<+%Y>nRnz;hF8$78UjF*c=}1Cbqj z{%dxXfUOf}h_Qdr^UNj#V9ulSnGMBoEG3YPr-OwI(tuj#b)x_E80{DjOyyCeG34JN zldE@^NlXpaka04m2C+1lU-5RBc~Vb0uMy#gT^H7$1&~SFIESf^4}3c>ZCxRKfx~Z% z*3PGF4H8H9fYRz%BF0kVeL1KCC(dh}61Z8AsNrbB5}UgpSXm0YU-*^5AGPiZm->RR zX$FnuekCJp&BPK@=S*T8sQ<&c*t2ay#C7di4zAF0u_b74356gfy zq@1}w@O2fE6u|ihkHMaI#C0K%E8C#!I{kq9mZQB>TMP@JXNQvhM^TBETm2vTOp1a& ziO=Zn15<>UCO~`!LIp8fLrMbK>@%FcMf<$a* z2i6Kx6yj zkfE^`xV4&E8gG^xr?82ggR#kpbrk~fAe;mu11>OC3Sc6M6a}n0(0QPP;KGEo^JoHJ zxIe+sON3l%&lMA$UM3Fk#coT~v3AKf59C7LzXI=LS_aX{;^qRtCZWe)6%&J!ubSOfdR@yX#(M2Z@0mtq19LQv5e$@SW{C2ugG2@xC6T0Bi@WB zLXm|E{mYQ-2WP)($oe5u?C@yP508nRAYYUiiM%0>YWE;*NHqu%up;~D2#)uCrAhIE zXa+R`>wxOS-wm-#AYU`mGKsr{k~O5CoN!K|*CM*~BbsBttGb7ft9)SEIdPXYQwo0N zvv%?uOp6IR2%;@sio?K-Tlxa(9HbpYg1L!Zs3Bkh6cgecV1R?dp3Yfv$}1tt{z;%a zL+cItoKLR~%?e;bn-ggc9iiZQ&64OeU>IeF=}h+XxZ#8(7)Zc{SDCcS-3H2KJYujW zItKPXS9|87*As@dd#)&6Klx>GjFCZC!^WYQklqX|xIk6gM+eNoE3B zw$M>w`O%}9HVGt=G37gqkpkD-4`H^urh&DuEC0{fPPGjgnqya^&8aB6d`7j+)u<-v1i)AE40qy zPxpXuI|~*7ZI3oY$dy?0%EJ~WIDjpXHPvfCh5|M|!c5Y({0lvKd9^4~hTK@ec3=K* zgpjJje&*ZEav>$eV0OgXz1Z$x1p~S2W*`RNh9YackBd(5^>PHsZJs(IKqRp2V+^!J z9DF>8ZHXjdzGUPf=y?b32_>KOmKRg^kIqLhv&3VkZmf80@Mux#l-#5lSO{n4%s~W5 zjymKUa)2WRZ9|+x1`_dyXKukqVF58PJ$un8LjYorJ`y~PkM1F>U}BNp3}uNlAJ7C_ z$N@J>r1v$q|7;u_?w23topWNn#9@Ch4ssX9zEl38aTq&lW&WSKAd=m0OoRhT5>enw zE979DpC5*7grj66LAixIV>)Ecb0EWcubM`-2vCy8G?B|C?1@@-b=4C6! z>WD#r<2j$CUJ+n%xgQz#GaC`adC6v&9L}E9i#-*j%1(^RX?9b!n`B8&Wr)rOk*dE2-s23 zL5^FJk^_<$KUOWln1qEKAWFmjpmqX35*w()6EMICk6~J{Lhct>{2}y(UzH&N3-UBX zOd6l;mu^EwoOa<=7f)E$gKQ@OJ z#@MYQ(m9BNlK{cw--8dKR_)q~s1&UtQ68K4MlLp|%JSPuWOhkRwWduB#h!TSFTNU@&0 z3U@GE=?WKoAT_$XSU8n`7N2=^DuXFlA|-e!k$1D6yucY5PyO)K#T%F=gPNoThW)fx^6{yKBknE9Spa9a-YbgA7iz&|PK8C>@DtYZYx??MsMj zskcb46=in-LO7@{%Ek)zTySark=S!SGN-KsqQO~MmTBxAa+r5scqH)I#f1%$t8T1V z(!Ryuo`W1|zwW6L9roeLP8b3TFKa~S!zvd;j&)(i$uAEuirDf;ZB>M=sstOS-POx%9Kc7F+mFI?j`>OpMM4RzT+EfFEf3a$4~dd<#_Ta zap-SM20Obiv+5|mQIDL)K4Vv({KVjcAAVts9;3oB;a`c2j+C$=VnLlu-6epY(#%EK z{H=_l_eG)g^nwM$KDtX__cTBG;kZ!3x0nPJU?reC4#cV)*FAB%#zlztCz#&bf}&>! z)M+0GSHDY8WMqr@_1$+Jt{Vdo6{lO8FZiej9wxMc&$-lx9li!?nfoFL*IkD*!w98d zy8G@625X~vp?8VvC#PP7!-Es0{bVhz>>9`^$mSwdfs7(Pn*JY^5ZUrff<}Y(T{xpO zpFo7@haV=>`1UboEOs+Esl-Oj+ekcFsDHXIJGsRl*?~j%|4uW5d3+=DdCbLlI{S!S zTwU$Y+wsOk$L!rpTWz(8TXyIc7J;+`6H1Mgy3Ecvlq7Bh(~qytxtjx-u2a)!6v>T=yx+V75O0{niZA*1KED%k z8>zq4$f0M`gS*dHZvXRBY-@*Hd^)dXSewSgA~(A`OJ1PNENoj;bMq8ya@3dt)BHcU z=lW*ZI5Y*9=iqbdiuBDq|DlTMoAI}g|7P86C%F4EEM?<6x!QefG$Q=`}@l^hGAo7f3+0gd2UTeT&vZ2TW5 zW1(-WQY2P8Z&cZf+h?9LS(b-V1!|c|3@f=67Jo-TvD_&z5qPN*?c&P&2=isdlNm=n zA%MPCC$A##!lGuBM3a1zlqLCL-EY#}v^iD+*Q00drNQg*QS=>$&k?F0%!|P`_x`T( z&9SO|u>|$J_PMHvQ@Q2EZb!H3NdVYGs56Z$yJF#@r0_rK1P%)`MB2&|x4H8>y8_1v zmVhS+Suiy7!mR&;{kT0S?;m|`VO^35U$8i4wQpuL62E-?j_h$_qt9@IEeIZz56>PF z&MKW|y0h5L*J@cmGW7-HxP#^M!=XV%h7ED-4$fU_>p)DQ3Cb)8`Gm7#>W_KCVh=Fk zmHJ0CNZsx}?lB6sDqQyak2)2F9uAYn z@l+J`9xpqCf)u zccUIZ&22r##s}rj?&o!UC>PuFmrp2f?Y^%*-E+Xd*$2M(L*-gqr~EU%KB;}l3xD&3 z8wV`NbneeJTZi~6YHzI2i-++{FYoSc?*)J*^jvZO_ti$qvKuds9m2bkomrwb&?91U zId+rV4?x73sc|wpYpw<<=q+s@qa84ZCGY);4O^@+aL9Q^QDPquiKtXzOhOfutoa2# zDx@H^l-$Wffu_$!u)x za7{DirEsg6{9-exoCSREt7i01LzAzG^HATn`zda%6&Y)v(P`r?qk!hq?el!O-k7rw ziTgM$w9m26^;x9cDaO|0ruwjmMuUhB2`@yn;Zqi^5sS|Iirf5$HzCCW>>6SLUp z>e4-(?;&t;tQYt)@Yq7WzrbIZxAcb|#+y2cK-313{S(RUU5Bh3LNZsPQk-95a@c!> zYa>@_5Ek3V>dtP4{O0x1o99OE2{>d}v=87U%G?#FlTSn*UBq4(brd&mDXqI1E1gvh z_~}}E`fo^dGoCNumCxQtdHeuwR@SC?f?*+yzMu9WH}uLf`neSg-K_or9@cBgj6W$R z0cUlw{7f-IP@uDC{s}_JT{+Q2j#_-K+h))GEkFFmK6@z$#i14K4$bk(s z5C!_Tk9@dr^nS>s9Tgqd%a?Z!cq|-j(}4B1wQW|yE-;1g=04kg^v-f(N!rtA*4-^w zdeT3Q&7&t~^m#C1PnjI7(nF0?@bl;*)6+~JGZee6*e;PKR6mzwNZA6#tX!jS`)pa% zS#-8?v*Q_W6i_MY0;+#qoGb5`UdXUSh)GJ9k;r}bYL)A-*7kqKxW6!%095&p#&Gq4l{c0Pw@;{1)Dv7-93ad|&AOwMVz>R^HHAMq3Gef~+T?5o_A zHe%zo&tn!gsR)n_TYNFEwV|X;!4l5hizAqpr0sKVKC{xQmH1ap6URS4{gGWR;tHh%A*4z%%L&UGU6CquS?X!}T| z9Iua8;cYSdS&n?;Ak*gFY$jx{Fi6SJ6Zh-nY5r8X*@$0G z_DLwK0wh56J$$(&a z14yZ7x>6NbJ%F#k83=XCpK{n+`4n_tVVnbm!6?Wk!~QAcrySR;LE~f<6pEaiZB~~f2y{fS$PYr zBZt)@9yki^cjwE!n=jA<%2rBFDT@Xk!^^SFQmE7U5Q*h?FC2deBdz-sI}px9<_@)q ztS>&hT+~~d{pj^qrGS4qDQi)^qv5%P*uMFCe*NkGlKcdoE#o|fefN8s+M4t^DR+;o zwqg>99{$|b-GLViw!gV<&AM+Xc5}A#9!r;~#RjV%GtXRRUVgYn%|oJvMp=fF-xq9* z-7c{|6dWuL3p{U9?9Fyh;O^zA7o100lw3Djq8$*CQ4{fET^BLF>ule(=F2L0G5Ma`b&1!lEyFn zOHgQ*O1#}HiLts%)OHbfAxq)BJmM3M2yPcwlJDfwac`ugP5G1WIpNjemtlZ2S)@bf zbAtEh`zTF zM$|SsvJI+D6%-J5D%{x&R_-uv$K-9k<7*a74!8&&rr7WmQ88~$bZ7v0NMzkDiDwNV9z>Apd+io<#Xwt$Hl?PM;(?uQ(o_n}{JW+ycWGo19bvxWBGC>Hha3$kqOD%-!{7qkTa;edP3RHJn?K$c z8ASzg8D+@r+3w@}3+qCLtbI^`2&M^%RaE1r+JB|XS|_s~r`Mv-*ezn@me3Ie>$5>D z(R@9&^<%9*rn-`!F- z@}ZvMFpH(_3jqw#Btaa$--`^|KYbakio1it7fFGupV8@kX3GPvToJDM%sQmdC`N0z z>A!!tS;hAUeI8xXN?a-z8#iDPEvLkj6XIVb0A1*y>3?QCkjXq2WFAjo z6j%N0i@a_#aWfa6!);bm$P^kOZ3kOzq zAepKoGVn90D^i7$Fd7bHH@D+rpf-%2vkmo+So-$6%wzBEboFN;=09Z@qJZmSvgHDfjbAeA*}P-d@Ye z9@2&;UZXJ_p{K8@hyBKK5#z5C89aqXE{Smg4M`Ip+k>SA-S2;E6dtRdYA!uwk(DN^ zO}WkhU$c*d-)Y6e{gHe&fuR;WD~ul*2<`WkUbd{#6RtBKfK&H_ zkc)zQPQ0>Al9OrWxic3*^Y4tpWB-qx6LSzqYd;DV zqW3Kn>{3S&-|v`JfYnxtSfJ*9?EA<5iUoG!klz`rgJuK*BYk1!LnM$V_}hAj-W)v? z?dW;u?`H5WfFaJa|1>SAvdo<>^6(=Dw-Rw!uS_U5^WxzpmY94V@=^zN9hcBN-+!3; zetvI01P3=@X{7_?(;!=*;S%VxQ?4LYp_EJHK@?uhu6gEB@M7a)2EVj)FDjzJ1kTC^z2;}lxy z@|=pig~;J7m9o;F!0|Z~9K70;n6ymhAlIvAS^Sp?7r${RW9O&AayoH1lkBbK9pGWE zNYaNZ>va%|;?XQ+ygGz2GC z_7;BjG{(t%^|}30jG9@w9l0FFLYXD+^yb#b9x#ag@D{PRc|yPzqPaqVrN^ORTCQ-I zurD49uvNuC%S^caPc4aPFt3_#X83^P*2@_UUld^`^-un4bO$Fre9)U>%A&_T6B}BT z=vP)v)Ya0MGG#r|e7^9_G@ET1U3%#LI66@b0H!~p)9)`T+BjscDP0N+${HFl3Hmqp z62Eyx8Awj5Ph^|o1->fY{j}Z1_oq8#(jR3-|2fCqzn>>k-bJ^nrDc8(^SI^4&e54Y zCfVAI2*|qUWCF1YfnqxcUw~riv3EWo2C+c!AzP1W99{Ew?SVYRT0f#Kg-n|UA{Cg+ebs6f6GEXpyo!5bdr><3OQ5Cr4hZ~`~$gqbBa2`QN@_Q=3 z(6N$O7E#`PG+nbE3k(8SZmVsuod~jbY}H+!DEs21sqJ*;LyDMjBekp69tr3VZkd}=B?W92DL82zsh(XFs8 zBbY&0eu@Sl(HJD`fPFFChlou1ktlLj+;XL0Vhdst+&9c;zgRgv5~<8AYo*MWx7}jL zI`}N+()Mv$i!az|!;5&h1(k2>gwkR*(h0YI8xb=Q!ayK)k8XSJW*3oIr_%U6ksB=P z?qG)e`P#XMIwTX|nP8Pb_rVvX{dwZBW>80uDZ|&zPtISz?(iF`w*{T;8XybFw^H>k z=6^uYT?{lszh|9VxX}o>;)x=dYwu?7wN%xv8rHjLnNneOap0Wc#Ot4KrR9e%bUc;Z zyW}IOYs%mlXZwUkilZr?x+1@xUoA|}?%k1sKwad7ot>P znCh+V=L9Eb_+!uHa@XAv?NImUhsDruXRv4>R6AoSy!%8~gtZa&9=70XEq`zzs&suE z{tgA9g~d4Vz)yK^7WRd^O3tY`7D;@HSogxDRnCe>Eshm%z;!6WPZ#A%^#P(nNCOIy zsqI}v$QtVLE+Mnmr}CsK?e=Ux{|P4I3Z@s(6%LN%N*=H~E8-0=D(3nlkXB>+bKRpq zpAb60lh4fo6U&G-LcSMa@# zdIk{*7PX$nv0}o$G_2x4_^qR^h~E&wCXJltWE$aTFgp2J52>Z1H+u4}q>CZj)xp%) z`#56ewZIG_{lAKK@p~Sf=3x3;f`<`?YSE6;k=XgPCw5>0QB4{S&Ge#}g#8zWF%2CK z1NclHXY8HxBy1X8L<|JbK zx)jcS(X6Ug_@&ii+t>X&!rR=~uAxR)JfcfMeUwb93 z_cj_*-Jj^Z+)V5~{(f+G3p)+4h9B_QSgEM<0hKRQ4T#wvq`m90j*E4b5w0>!opoCc zQp6zjfzjKBB{r;VhA_~PDWO~&b47*eCA+M=nsvS!TLWt#G{L+GkZQh5i{-4&f~mQf z_2av&UMfOBe0bwWOhT~s4w3dPM9C+@eW z&2OEZm>aRW>*5n`;jcEc%d}+o3-f&Q71D8i6Zc}YhV#vbrSOSAQPM@Mdwx(ygTCT| znlk9$oiE?<*gYmO{k+0d4~MHPvGr10Bk{oo_vYpN*^+iwxg}|bLSa>p?K)v?`KQWS z4G%yOyJ_Q(z-9R4N`lbKrd?GQSy*$8Z3hTcE~!H=fCEmlM;FVvPCu)3TRNzK13Ecv zB^;zm?PLKqr5%@3SMo_E>usH=D~^zB#k5ic9hee(kZK2WN)YR^?k}ac4>E2vF{Zxr z?9H{;Nsye=WG!kqGD+(}z*ffwk(pJOsa?8UyhWF3aHf{FUjU8O;8-yNxKBL1j%n)7 zmty1OUOS%L_i>kyixl8+z^Xxy{HJ)5=})yHR^gQe_akTcdby0dQS%-x+8x$qku(9D zzzDd%b@8divGc%lu&=YGvM9YID)a!RxuzPp0p4jkqGRy1z01Uj$2|SxuW{|T`ChoU zbktjam3cQJgM@+?%k!fp!jXC$8`e8yq3;V_hj!*}<|WUkse2wltE+Hh?>&hP>sD0h zOpIly`#KtAqd+pTF-`256@pY1TU|}s;(58VFU17VRPDNJ4cw^+Tz&R*9zh?WIVh|2 zz?s1Fn!0qkC$-(Eix%L-x!YoWBk&n1fNXZa-Kz3LO?V4i z+o{Z^hY~Hzdb!rcQI88%mEc+w;9%!45^3Dff@FIrkF=zs%f{|&EXq4uF-no6Du`AA zSm3yTTjmf2CkZoX((YGepOxV)yh@W<9HPEk(}|u=FBv7@%XToULnB;z1XAS+6hY`x z$3xjHqSYLm7)H!3)Xnp-sKdDir}9rzv1gp;J}B$*OHb`Fg(ay3J4E7dui<%WtS;IP za>2e1Qg7B8p@;>em{M4=>d)m5K+7B#=3}-*X{WJe`K{jh(Z7e zXT0+!nY)1(G$0H1Z!d)#zPoj|e~Ws{rf5q^nKa8McqxN!gxcU;;nF9Lbjo`SIa~Zg z5&BX4_eBCtQ-NrW&LVjeuMk|7lPL_6KeX4$ZZ@$q?68Y^yDPV`V+|e42*W~}8GQ(6 z{&AXs0zT9Fc~2AKsYxCaY6ywTt5#EI*|CuZsJ&f&Sgj4JR`bEE;O^(;d4|rrX!pWFXz{nK`GlIlrB=2kgBgxk1&!#YUfbuOTjF5ZpNg+&>;|i z#lL6A8dL8>6U%9Or0_^+S=ftvX}=}t9#Mj;JbLjlL7IxMop=9FW`3r{z^)mfK@|)y zRes`ZUl)U6UojED;C}pKJ$a$s1R;dSCZqnQ9viQL#l@cH#CE`X#UHoemJ{GYQ_Gw< z9}2Z;m$;Toc$UnAi5Dg<<7uyVnQhLuZ5JfCP&jZkX=tC}ZERd^n4RmEKDX6@FwQ$V z(DK?qqG&Fxun42X7>=FdS|r!bQ99~AIS^B6Pse-v-slbbOykpI6X5@s{x*LK87oF4 zVv-JncWqjHpF@u$_xko|p|hrIj5lfO<8`0%i>-#&bp6-tCX=RqKQ*$+`5oeglTd|| zp`wfVCGnyBc|k)@tz>prW9!j$xOKhtru%%2y2 z6#^`hqF>4r3?a1~I6!Rt=VQbaZ-?rwLP&AGvD2o=hB32MnaQ2~y6Vjr=nZ~umaTBS| zl4}I{H*@QA@XG6n9NKsadX%X(?;i7E#0on7v>Y-@8!nd4(h~6WbmXwZwcgvSvpDnB z-u;rV_n8HwxcS^at$bvDIdFZB8`$2(=sDzU0_$C16a;xuCOfeywaNsE56d zbCU0iAyQCkwDl17-JHU<8jfqRQTw-R_ieX-u?^45SFJf83hYGs;s~*j#EPfcnem3+ zaSRv-c@RE}QP&Q#aLp;_V3YD462xH-i|QbywaF3cY&&&ump_h2Iq(h|UoagNoEkFg zcZdBIc3`qcp$?rQmr{k&%1cX0-KtV@)>(_c{`aPff3p_V-(KoXEs3UxpGI$%#m7JQ z#&=7x{B@zWu#aGlJNv^%Ab)&MLA&^6^;1_b{q~*2{ju%uca&vN3z8x8fmW#0DCE?f zyLEkF49aVY?-d*&N8wH@s0J5SojcAJHHRX+FJC#Up%_ou>Al|X+e^OJewYkeIOHmT z42Om#UqP<1CWnuP1DN!Vhe=y^&kWp{^7k_U^VZms9b*gok9HxA>!p05y_0>#dFv|J zTfMRNgC*HA642(X6RqFtj{hNl28bH`HwZ1Pi#4$PZ&&v(C0;gB&5!2mqd!@99-BX( zN+bQPd7c^&)-&ZT<}R!-6GJs?fjuqS zw$(Ss_FcXZ8Eg}R;85y%66A_i<(3|mp*`9W^y{3Jct3RkO#CSx<}W%NPxEKl&EuOe z!z>#rlyFB5mOIKP;Gt0L(-&GttWb{mbU~Iffoq@sv9m%b%b$D3#ToXVqzIi0SFCr-ELQZEf&sg z2_KMF3BLYFtoddBs~gGe?xelP_Jz(4*l|KIuzJamD7{#4+u(QLv%yQ1TB=u|o&$Jc zll0j0CR_eV>F+)0fMPx-)s*UlN^gsxgAGE-QJc2Bodh5PTwR)#-mYqdlK{;3+fYg7 zFDF#RV2ZIp00(4(J(YVBi!hpw2iUFNVVKGhyOxdx6PW?ZGSZM5b>QREFNm`vg9(w8EL<*g3E~y9O}meMvvL z_`~(9Te~;PY(|>-?|sl_+#bqjXWS3Z_5;njs_`@$q&{^oYnNo(nJ)+C8Y32Jeny)^D91hYQb_h<`YpktYVD zTYoYU22uSc2FhawP3nKuEi&6h4T057YHp)vAeOM>@wDy|J-*hzPUg2SSIaBVdIGrAKueV90=$ zb;7LWtVpqo_HyrGFDxnqHniX8QuR?%ffmQp@I=KM-d5$`{SQ2o>L12eJlN&-bD=Ew z6W{9TvDl-^(=9cM!F3xqkH94l*?MchreKH*|(7nBNZ9{QKv8hz)lOY_HH6u zDRUEw3^3LmXj>cxx3dP7pm%%fLpcu?+YVo#rO zOT!n%>-wfq?NDx@?N(*Cxn zgKETr5aZqcG-vyBlsDeIz339HPq`#Pe}2CEcum`YF}qcOkaw6F9SBqCJCnT-k-(M9 z(4G~_q;aeC@l{95PVf(BbTko0G<;Kz& zg@{O4j3o&;GwkB;0xJ$Hph5heHduVge}7BmrF9&JtsGe)|J&Mx!Mq$fkb25GRMs** z?MGL8Vgd6s98adTp;RcA)RJdw{U;&5la+FW7}ssUi>KfxsN38*cTXoE?Ub(wAJN)0 z527cAWb$Z5rRIpY8k~6KcIn>XwHh3HkW-EVU8Qu38iz*x(5BAWCVEJm<3Nn>S>2I# zjC%W3!(FfoIP@>4kD=Bq7NiyKiPq1+WLUTH2>J!&FSYu*k$bFa1by-F3+yCCeHP(L zeiI}Tc{`YCtNsaBTS6u{(ZDR8x^O{(Gh|ovURXbdaRYJvw8YXrq%VYzD)D+22+;&&GpuF zqV}LTU5g|hkVlmgJ1t-e9{k+v8?L116Q6a!ceSZSZ5}D16MSPO^I$`?l|t36676Z9 zV`E>WxwzieMDsykfGIr0Ux3Vz0OcK@xT++A*s#rE&HOxTkT=fLf1DH2!HZ7B05JLW z7|{ux@&*oyMgdI~K>@M)=*Tr%g%uh1&}d`7U`x!(pgs4c?L~SKGg%etrH;Qnc!xLi zei)=FUmR%cfEGVtP_Px49Y?c$m%toX`x8ZJR)1T;3{}>o@7e1qt_6IuFi>EjMSyOz zkIItUpx-042M?u?M3wE(foT7GV#eVtw3;|33Zv9v0OPEiw1MXslOfPyIS^N)@bRh8{C*vw}DIWWc9@AaJJo{S$g}04E=|Da5m7sguHv-hSTLz> z`_kJhI<2N&2@9bvxjuq6&gA8r@~TT|rs&U-P5?(6lSo}2^W}y%G#7{)MzPgauU1rL z!x9d^t@^X_H(S7i?Pi@)fON|GV#V#ySiX-ErzHCR!TC9!oeM!lId3^fEnjGL6$6f5bm?I@}o zh}&?4gr9rB&l(gB9UNP7uT{rk6jBFxuu#{b6*vEbC__*bEJScyhRj2goqQpZyv3K9 z8a!yNIx5cP_2JNLe~)(YU8gIipRNaab5SA3OpT&XUOTUZ0bo(zOrWqI?$AWOii}}n z`_+CGkOJ0J%<(8kQF4Lz`{wY4sI@i}G*a%7mbU;yfa0++5YJu}Ow+>eR76iDpp=1g znn))31BM+w^XJiMEbMLa9w`Cznav|~&rNh_@`FSiig*ec{tr)}#t%ojh!7O#Rl&`lt_ZP}uHc8)k@=h-C@uGs-LqXbpHAiS3b1sc?; zud6A;Y6ze<=j3*kBvPdn!B-X&S0X06L)@Ues<8Q!s0-OQzpI4ZYCU(VuMC- zp3eW>+$D2Q1wXV*qQPvbk5n`>s@g0p-QNY?XL)=2R>Y-lL$xO>I>69y;a%w-r|p8O z+R7J-cuKC2*aPUal3gVNj7;HCA@jAf+k|A0VXYrj{c-Zy19M$4vQt?HGkE>I$-h^lLaj_7Q_*RO9RQ9#PHg`q}v*U_w&!YPP==>NF~@STo8#jx<3bT<{74 zD;xXnNI|xtwL~b#;`E?p+{x#cqO;A^#QJMRy_8HsgI?z~3v+!%^(Ls%@rxJlkWJxk zx~vi!f%o%RQz)}^i`Iy8$OdS^4fyi*LV99a5CbTxDa^&2Qbx&6zglKATq5e7Xe;*8 z#6wnD;j;ys>?NZG{PTMPQ+U5^3A zBUKlXW}w{y%o#a4V|R`em~HtVlWopj)o=wbbaAWK9xSxg^9BEdg=`ztck`p}7r6Yw z(G&=|&MVH^%LmTsY)n696V$67!QEtoq#*~d1IzrllI`)AL~W?nNL05qq|=aWpw3;| z1TKInrl^n~Hqdo#k8ZrP357@kI>51jHLTBtXH3NdjhrcRTZ)CUlZ znf`We`C?<1|SgU@?aYpcRQthK`D)HOM14qhAqdem0pmPvU zo$kVIU+1=gUpToliI1h&`B!{`@$M5&0S^NoZY0c3qiI(Qn3Qeoc@zQmH*%`+E=nUS=*kb%(RK&zZe z#8f!m%-_#1Qu{_Jr?lPOU1ZX6+W*XMtLsUK&2nRBp31YklxhvPz#*&qaC)Wu+4XxU zRaPJKV5UPt2cM^Mp>|#rg`DwWJ89v#+e*-RLO?ACf`Pd2O1}eg88IV294C(W)2uQH zbSa>V2JR}pBv%H?LYoE@y9ra`PnxEZ6y8@Zna;<2Q!c?OT@jw%aY8Rn-9&1;NRXov zz4JL%v-J2Mei(NGlAjhw2au!T+Asm6m{wad^Nc?U=Kf1Q-bZQL#o(swQF9-LD4w*p zm&rrUGm0GboXNfc0K{sh_`p1<>-|l7Av0eo3d}WhEAApOZPgXM>1z1E41LHVAnqf1 zN7D!-8pjbxik;h-7dvP-92ofNHl!(tcYfR3pY~(ec9v4}4`x!7|9LZ{)*i{3FRG-9 zY8bvUk9{>2RN>t3&%uUl`j5PyB}qzj$UB@^%Nn2YyHhgfSvU%(N2WVoH#K7nojj{>+K8BPx5jeo)iozQiIN zfelUPH+xkoIzX?reY*&yKDHG_)lpq- zN5YJ{WfbUMeQ$?SH{m!#K%l%Rq?HLUDwFH-kX47xKYvKjL7yBB{SlhNFVvf~xC8eW1CLZCERJ#-o+1>{x zHw|z#Y_(UaOq11+IM9hJU_7VT{3^`s7%fjE5$DU<49@Q~g;3y84ef%b8sB+Dnur|rt9I~Ns8E$b_Q4js$MvQ z;Y7wwnq8fYl>Y*y_HxfSaVk`JA*Ju;<%1K(yau2T`bS;Zq}b_i{S+pFd}Mya%OkY} zO4*w2UkA}{nbG}X(p0)Z*ki-;oZbcak&+4k6fj#0u#FPx1vDp*_yBa7iN4mfyQ?+b z`JtHB-2UL1gdWevSjwA;r(`oh4D4f2qD&NXjFQM#vRv(_fo!JW)04+=K3}6o z%`xMT43RJ%r3aeE(LwNa7&yKv^+iTr99so!HCG%J)J3cQnO6#?ijkQlAqBTM<|`2= z9#zL`WAgSTTIH4%?BO?EAzzkWTgeGEGL#hQc?&yj{T@D_1spU(505J+`qY=%YW@dZ zDQS5bIKvtTHE4yF&c<>bzD&j6^eQjewJvF0f}vT2fqJt(i4&^1=Bqe`2W088TmTO0 z6GRee`p7(CHWGZ>3A4~wVHHr0-q-{NxfswOS?DoU%-cduPK^-re6#50o8_usMZ#n8 z>t_8!?{cPM_yC*PB?68P7gC#4zLicx+b`$zgY#AiyA|?T6zU9P*YG(WYEvGI*hUdB{ zGa;=oY-~a3tU3WF_%AWOeuhVO3T0+hd=;)GUd{dI%bLu+aUV4aCz-0qEyn&G zWs*8&_$!L!x>|jKI7Gb+rQ;;NaT4J-3j?HOO4N(MZgYdSpVICF)fq%!k*+xswOOKo zPTfga^Q9g;CpnY>%^cosG^uprB-c21dP9!^rF2_PU%QhaN<&1{E*?JtaD_k<*pNrM zy9S!F0z?rF7y>9d&@`EbCw3f~1(?v6?*5`5!|&U<44b8twRT$-yND*Ga8l$HHn}m< z6<(NZWRZL?LfdJFW}kxydeM0;=AsH78ak%S=@DD%aX91)EcD|okry)S#${2wZtWBf z<=(Oq4_dbJBX*~QtcA0>U7C1Rq!mb|W!jf_C6n%*y(`{sj9CLYEKIiJchF(MGfd}K z)|H7ND}_0PgU{&nvXhRcqxFJC3rmt5xsyhP+LdbuMjF#8B>wP5l&P>v)aGC=2m%~9 zinM`pnL;kCen-&!c<-Ni_<}X zHiFfq7-VW98dAiANUXcsewV7i;ESWbON=6|Fh_n_NCt5<8pyqr2F!UAXm1V#0T%`d z&?*iYCBD*H%~jt^GD|@!8he^Y7rJo8n#@L5z0`R+4gGs)QYh=fATeQ%FH*EhQt)7( zc^oI>>Dfax5W(h+s*=`orWxSi!dkQ+6z8ccLW0{&VVd)LqC9PKaJGTBnH3p{T zjN6@#zgW}s4eNjd;X9~&aH6Z6+4?3OcCKg0CWFdY&w!54#Br4f#F5n3~|@_f~I!t?9Z-2WR2YMfJoICQ*G4~k&yq8W%2fo1pt zYW?)x`qkbTkC+G4ON|{LOi8AmwY}83SaqOxR|?)KPE&HrJ6wbCNREN-7p7107e~m} z&-&ceH;sx1hv7a8cwDsG0!n~e{}~KKoMZ**F2S6Pf1l0ZDO&in)C<%5?}R1#Tg{0c zhl^rV>?wCG3QI-|+VX(=%j|z*r@Zs%lVf+cvkMIoX%aQ0@l3xEJePk#B%g1nk1Yzt z@^%{e^YDZ-da8-n%VZAI54o?d@B)SMxe_pvn4_zbviXYmtQ+zeyujLUVhRkL#4h*Q z=v)c~*q{e?Tq$ENc*hh(l|@^R(4=L2{&O3j&pQuWW@m78vNm9X>M(jh@r2%c<%B`i z3Dr98_x%+Vr%0dV2A;MWfvS9!G+Nxahv1MMQFCYHnLADg6Q{5?`Fj3tK5@7#1F_Ji zN?C})t@YiAq8G(QsCf??1G;a`+UgU;q@A+l0niFOt`q~P&7)N(soV;t_xe}Lb{k_S z-J~WL#01M6xO|$jUhn1D7+CY)(*DsR;kpv~y?v&UuME!hXvT4C#x-}4q->}(YkL-% z|5R!jR!#l)*9jVA+7~H6=kMQtie0*Ia$M^2+iW#8 zqes+BmD5Xs%;sHIK|uwV^hKKJ>o6BhcL`XTJjc`z5+DT*A62ZY1TAQGHAaC88I2F@_X*=Go>2fD6uNme!Dyz+{ zW&v-8B$$k@cN!I1gR>lNcj1%Pv$y%?ZY-8R+mT0 zx{(0nyy6!x@PNWFQM`%At2o}K*^p>@$%E#3vWPX<;D_*A;l|bgVL78(?Rb{~!^j1rN zTsM2&rh~wr!dHkl#Ka40z(*&sBD(35qcpNO6)xEoEj^NoR&?w_BEzm71JNkG*454X z^|d&!{`-@|0KrmAzhyze&i=mt;I+c^r!szzw+%8YLdm!DXT(#;Q*=kS0($xeQ!)!6 zjrtdZEcB*;0>(YS>e`DkA`&=>Emm8pId{+Mwv|&8GE1BEB9$3O)2Rn;n(6vUA?Ax& zKpc{o0wINyo=bX)afFwtXJR;4_undWJ(n9atY7~waEr1@=IflM+UHuuvEF?zgAa$@ znAFP6)l*3@#-(!VGd`cKCFDe)DdCAuO5o$jfl6IWTg-i7AVtqsCo?JZ(D@{Z|2=LzQ?A86R-wdMe7p49q#bdk4FT9oETkau49 zTeKqc4>iFv3!TtI@4~Sx$aZfOGEYWEpbO+retJdS&uPTPq z2`iv)1e-BHXJ{I6)ra?>E)azu6_x&32(kvEnw~-FenCtJ)S5#VL(2mwiXjm|Jrlfx z$ez?_?_pqcCqC?k%i~6b7#Rx`z#R=oYg0HfEI+cuWQU3?msa=hvQz$iVl#2jd4dDQ z7dI{8Poc{OEFlL(pN%JtqiUUPRbMBSo+$LUwP1_bq7kZ*s;r%1W_yfuBmVuj2n62(8ih9Jq zEMFVs<67vAPohpPUbI9m=|+v2+887!b}5Ghspe@@IHniJ%|NxJ0y9+H`2|#eTVbkt zj+jJ~af9K)&v|?~y*w%{7R+WSn{c4!Qd|Am&~_={ki1=66AiH^P?bV-7<8_9c)3cE zOuZf-Z@cu?rDMA2UxJt0K2cqko^8yAS_R15-dC~@P zS%(m<%<+UbPR&2-c+y`*$q65KgqGWSjD%7N3SS3${k!yk6hMrRC@3eObC@QoDwkh5 zrNGbD?Sik*zZ+n_$gAEoC`?|==5E6gRv*}e5Jeq0GR*KV*KU2w;h-A52&mOsVx(aH z#_P(oF=jMINnVT}LGK%}9l;+H9VQClD$q+O890Xl1hLQUy2Qzk*k?PQ>Ly+k&T^~y z+!5Y;clnkU&SR+kvzr$#f39Hb@F(aJKk@l@890LjxdSt6A;ws5tl5=(h@uta9#+gI zJ8+gcd-JPMI%3vnNLJUw3t6H!VE1J_nt(HNdkEX=%kj95tN!)_*m+u7<7rFEWe!m;x z#=-BdYIN7_XwAQ$AfIT3y%XkcF~Oh0eODZ(PL7J)X;O8`61g~TUhj;ilSWnW`;?Me zMRY}Eo;mj2)utkqPZbMQOe>k+V+J)RiYw_SFv0~UF_%*0C4!L)dYCsS!+S4`j{V++ zeZjEqvoZbEFJr~jTlM(*T`?<)nvMo=bMzFw$%F9zxj~k5 zw8d(h=$0u*Q5yv%Vg!o12z}X)QATlWUD>=^b*#iiwkC-dT@0=yIz>I%@sgKp4bP;f z`=Zfi4b?;nWmgKe3WF%99A0S`+G;1Seh~UyO|Nh{&#|?%)EiR8FCE4mO62n`OHC@( zmvS^sahwP3s}nKacyr$uo=N{gH;=t+qz7gT-rRalVGkvZF?JH{pAf&CC<-{62S zf{M3CcaMH`q{Y4JJJ-z{1vBz$0mZWU+U%mpGzKwq!QX^t_a%zvwaI^jOr<@YS8Tflf5-?uV1VX^!Jco9;CLFW{Zq4;c~WUJ0_s&7(uAc|ocJiNUGq zh9XgE?2yh3Kzk9FUSP+;)zH+Z)ykm}2<^NY}pR~S)o#>puWGPFjAYutg{ zBXU?P-|zpPtCs_&jM1!W&9STd>%Z@8Hj?;s*smzo6k!i_%=fzp9RlLsC|oFdY%Amr zOjpgDMfCE4FIK!LY~kTKJGhDX=KDKDWZkK9$vM-f=tB0j&Lh_rwx8|C^KV$))pEG- zJE-AZ+uT)#YjJQUub6g}4TRw@=_1||w{NLVvrmQDmEz98Y=f67>3*s*tQee(PLps! zQId}tEPsUpAFTBJYU$#7Ak)hx#%a8@F$Z3NW&sAi*Yz4}+62c;-B(cU&Cv-0(pZWR zgXBD24v{jGm>g2``OjepXcQ2bGRpfdtjqMP2ryC#UNqIRV3#R30l*YV*MH7bGO0Qf zN-pv$(7y4F{~uQ^VPL_kUKq++9Uy$*ZueTu3TNM5GUn}; zd>hN(2z-M_uuBt2X|qFaP!BgRL+uqMXv^g=B}fdnlk^xsB4L4oh(_8BR@r0Dhc^}6 zm0=V46Nb13GBft(MY)3H(F8@?%i;FcOH8rMm`6IK?GkMt)00vDe64W> zXpXvZ1xT?`;}?iOC-*nbb;JL?6KlR7*8!Y;hErQ* zjPiQ$PW>!14q%`7m;21Q67>v_z9c%A3>vWd zubBvR+8diL3x4=Y*&L>hk}EO&O~83`pcQ(NuNMJb6JQ6DzLgwmyx+2Bkt%C$!Tu-WO;wXl+Xsd zIz8~^m&+&n#~p{rAOyFsvn`%M<$9OT4ixb4+uMt<;!q7vR8VZ#1-o?3`#2;sY!3oj zQThROgWa`At{@#1vX3ABY!-J-a<%55(gjx)(yaf2Y1@p(Qey+>5kvj8D55@;DY}fG z7I$!qJLjTo`W2{4)>&wz>^Wxlq=QZumo^}7|3Aq$|HjZBrMJfK7hh|Buv#z+&JJ%; z1ui6i=ogNJUfr*fd?X)}R@LZ|R&}%??Thq{HaJ|HjFg4Aqk>A6Hj?o>Ap~u#oyt56 zo>M4a3zX1My2CND>*p){D&)5ne)! zS2%|Hox&iEh{||O7W@FQCblRnHwcA?cpC`>&)vLiwVfb4w~7Qs^gi`*@TN>1w>L}O zYkoVEl4twx$%%^q2?Jj~{J!<-N@%`T`I1F|D|p)uhuh_cO;Gez8wRMxmlh1i`)5*K z#v_s%F4HN&6*EFB?218%!5+FBKecv1SOsSaMX7;=?Jf`8t)s|kG>X1L30}!`6ncO$-e$~ z{&}!Ee%7c)krfU}$p4@p!GYLRA~%5zshZqMtfmF?oCmSR7^s<;GPZRBZ$mXsqu9#w zOLIBd@qZ`L=s}HW_w6yej3BDjV&SSZtx%^>fbpj{NrFZs$4)D6*UzR+y4w$=kP$*` zfoDzAI9&8Y{#JR;vYn^vV7)G%iW(@eJZ%uMb=vU|zD>p|%mWQEOcYcKkwYJBXbH+L zDO;2|TT#t|o>YNkLh$ffy|Qa&4$q$xh1LAwRh2u39toFNVFaz}3TYW#LH81>^IfQ0 zZXj26;uu7wz2g_~^Fma0Yt(}rAyz8N_sv)3l0xLQOrvO=0I^B`48$=M88e0lGcHhXpjKKhUZlpqZ;eJ=hYPP=*5I-M$_ydwtZN* z4DW3}4S3PeK3plt`_g~aNRmy(PETRs_Xx}jD84@q=N-bZUhCF)f&Dm;XPI{*DeCEcX7dHJ@)}>(fo^@$(Pux+^z-16MyZjVEUVaFfW9Rs#bQLThlAYM0^kQo_ zU}=>~PcH+Vww`$w6uYBUqC?OUlr5z6V_SD?6t+~;y56A;LWLP~Q!2==y0{_#axvr- zgy|f+O5uV!=M?N!6Zd4#yvYIUGVoicTfUdFwUgnDs3k&ZehTMHJ7=u+W1A;j=Y%y| zHCQVQMyJS5lRRgSOArRzP?Peajfp5;9pXF^QMKq0%BVh^?3tWB&0735HLdG2nF%%a zs7FrZ5Nin51QD;mXV^bvY;0Kig^AKI9z08u+eOE9vp+Le<{b#IWqv7|ES5hPSDu-< zLz6XEvXsDUrWxA8$B6B!PE8sOyij}X)^Aapu&x^~D>8_aHe<{Xtn@)?n0TdVFy#W@ zUn4AiglePaRWORVek^IIbVo7BmHW5Vvsuxj1rhwnN~!0oy`Hj<}M%iR584Xd6@ zNZlQ=OmU_cTpw1Atf3Q@>v{h3tZ}y*-rt_fV^F+a&_quDC{r$)-Ga|$b0Z1EmAWHyK+zyEyyvwiQ5g4)_DQtfYVb&ok$7nknZ zx=cyrsQZumq<43r4D$?|{`#Ha;&x*oYhrqflRjO@r#MZ9G@B}qslH>^ z+Ne@WbzYYe^{aVEz}&0#n*xzmzA`)2gkkg&dd=r&YA-WM5|ys5zZ;x zpFT>x1iK?DpBFS*!>3A9)aS@~|CY{Ixmqr} zNFdRC*vFC-r&JzEudRZJpKYq!CICnP@Ho+{GfLOs$oBk0$=)JUjdEd>wIhluGVO?G}=c&5A`wXYc+7FPgl%vId< zM#btr6I3w=Sb}c8;@io$vtf7wdII%jh+}}_q`HvGS#zY>sUIEBHeEfF7*g~mIwimW zp@an9E^!Cy6ru`;JaIhwM96Y^vZ%obQNE}visI+I!IL4dU1r%xu5yRIPB(=hzB%tD zjyH^`#u~pQU1uSo{9LdJ>1HKTSS_3-Z!Lo(-j1%wZT&4OX}_SiJ{bG4WVKJwjU7C# zk(a*o6~ILJb#$JRlBTH|RR~w9kG&h>Wxmn))&09r1(`bfP&7vglGst^%N;_OQ{YsV zXh;3sc4Gk$y>RLPgHHTl#B_#fBh;>5xIxr9);4-0;l|Mb=phfUtVnR2MsQD|hE)^G zfFSfOA?Xklr#7O?!t|~{(u(R0tn90Z@dqfQVDvRUAp5XddeEs)pu6c52Q99Vk#|tDhqqn74)V8`uQOf z^Zu*9}8!8@z2Bz zn8p`^KUnGdeGp`r{2RY)Jsco#9N8&f!MKp8DRTP~6A+oNH0w9M5c>ELQ@1%5w$W)u z_RgsZa!slIe!kWmuOZv|hTF58M#tp<1$ilnS#D=sDKU5B1VVQ!u8-p_be;6WHq2b0 z@|v5Nd7St5Dn+zVkK?}HWEBDv%79DMp%9t7*_~&?_wV~PoJ`?LNzxWx^6WcyGkgxq zKXd%+@wVYIYD9T38?xj%850_FG+f^u-stRt$hZtWLjJ3f+F+U|^k9NnxL<_}Q?l7& zbfC4dem|T7GtdY4pB3DF>;!;*b%8x$0Gmqq!cm`I5{H4wfl4u?!{ZAmP|@H}PKuj5 z&n4JiL>Gw=rJ(as(rH%KvN5 z!ta$Lm)-1`xkkHS6w=ASX6Bw2l`OqD(cN_AXf0w{`YdpENX}$BQZvdl(9DoABo}() z=gKHdSo>>uj%BWI(nY}7ROH}Foj@RVIyIeSIKpclrv>(80Xp(&>dPa2z~jOAFby2N zT}|yNq!$uuCl%uI^4R!Bb0->ku+HEZY??WH^65wj^gw|tV`t}Z@Kdh}6yVF6D7MKA z*W;AcwmP%L+ysf<9b5@C_IBR#PolTDoMMX)-Yfx2X7WG11vekE>I~H|C7dQdZsv|T#J}QhzS?* zbY0$cA983zlWN02s>G;3m-$_Z?jAGY08|!>Fwf~ZpRgo#E}})M%=00#GLaJShrRUL zrkQ^Z$z@=d@Z{#w!ZePQz-oWtmQ&u8#Ty*k`VAo8ZxFJoimGDbgWeF3Q2=jaSYW+c=YPV3 zxy)YBUMO5uLR`Z%S&=I$?Jhr$aaPhTC$*K zfe1}`;cJ9h=mLf4vWlkDLwd#1VkY}_Zsmfwc$x^m908>fhk(cSpiF2!iQk+NK|qZT z)mWJ#=3jq>0bn~0*T&rE(|h%am}JNZDn~Y#U65Hgbb(|iKYq-tT%VO>2aK3(k)xq= zv<|HLK2-Q=Ey)SccpDEq$QMg!I;Ckp4^JGp041l#SeNMawF0!=(rmyXa^rUu^~yHh zL12al0>0Ql*P6s;kIz^=Z+hwF%g| z6N25*+fPKRXzOZ;!0T?z!)m6Msvc^fwf1Y^#^dj|%H;b+CLkaJ^(My{Jyw^L(TGJ+ zbJa&}W%)H_*apMd%Q3r9?gCThodUkM84*3lp_!j89*-YZE7{7X@Gz~Xreq1%C1z+q z6lx_km_aSz4EIv0ulQdz(n^;X^Sk(`HKa))44(w$#RzCp@=qhuhl0KNfcfvfwHYH8 zm&v`ovKY4q3QQO@K~(h}PhR&9;~R}r)4o=_3v6!~fjhc9aFF`zSwrsm_3siC7;Fs# z)q{cQ4KWEs`4je|n z#YhyM*|j4YKv8YvfCF~P*1Cutk;BVr>1i{%Sf;yo-}1p>%Ip*R+e-NO1?oyhrJ9?k~WT@~|%V{MAbqF+lvAO>w zjAZ>&ov6Z;=4KMq7^6AI*|v))17VyX`KAs*PBJP>a&i5(TB+CL-dwr(Pr`8)SV@jG zL9nT-m&;q#oZU+f$vJ2v~ zrSfT+u7w_QkVF&!D*nc2{K0OJl{^jR@(?>Ws;cpe(FbeL#ZUofM>fSq!O%7(eA}Dd z=PElkV9CDZNgMZvXxGYI@_y-on*?pbrn;sAMDx;&K&0K|BAk@Q1lHx=e%O8q*7H36 zM)VBo@a{WZ<&qE3v0Cli$iH~QYY^T?h*Pb0c**~c3%bm%)8(Q{pRt0FTziFa8L0M4 zLy`i7e-~@*4TpGC43g50<7bI}Asm3qbh%a-WK}j?C>*TS`v|wGPt{YZW?UHmI(EUJ;#bXe8Qv-{u z@^(wQ_{JDv;^Cq*f43j{{xXv$3A!1FcVI1}Cfl;*aQ^+>l@I;!WS#qsI{lv}fJN*k zu*o%Tz~|F=y3)m+6l#Y5tosw{3DGrL&Miu(OkOQ)CjoV68MVQoS`i{sWlHd%fI7$lOdt}$ z1i`QhS@@XNrH%`e$C#pKX_l-K#6m18pJ4M4dwv}fLCu ztiq3D#`9;2q0rp-B6a}fB7k`xf9RE!p7_T3O4>$OahT2~xQ$JXOC%LT0Puu#&Gr8) zm&~FZl51!7{6D!|*P>;@z~!mkUq0|j61y99U_43;MCawcmPss6OOqeOR8T46GK-Sw zarKI28ce-G%1-Hfql_794?Yd=aDB{*5r+AX>nS3Hn;og-p!##2@bYfeq;=F0>1}R7 zYirdvZ@d)>WW|eO7(CUP*kW6zb7S#+9rurD8I9K%xLA$4$quYGj#lB;#DW(N^J|x% z8_aZ9`;^AcuU&?U+JR5OWz&)}3t*PcTYHmF-l}*qF9M(PDYHke$YWLg+$9!g2o!Kn zl7y^8!#EgvF8^!vu8NYvoM~6UFK2+sOip5RmWa!46;-yS50I_5X0r0)zZTxZR(VS;__*%z zHb+}sI%E?S^`Op6&}DWgc{uaA>~_}$qmSLvXf zgi%bgKbq~o_9#zpB%@U2i5Z@5m2M?cjZdYU{fKRc+bY+bJM8bkGx%p1p&e!)0P_w3 zVlj8D+o-}jShB63F4XAa)y0$i<+Rd4#hLYMUAm21Uh2<&Mf#^(*nv3$iu0>FbX1dq zP{XWd+p$0OTY3|A=OmHXkwurqV`@EL<$wZ}CHpEaK$k?&urP3|{xW^GIgk@$d<$*P z^bTH-Pl&-}!82x^ZnmERbRFGL{xyD|o~=Hhv$sE;K?L?$84p89EiGq|Kn1k86MN6J znmcq6%;zta-lA?w#AMlqojM@t$$RVT(N_`GKD6nQOX4~s#)xFd(7d%mC(i(n=VySL zHB(t=n5FsL@|+NdN#NyU{p;w;9G$K=B%O_{=^2DmV3Ji7{UnJP7};Em){IUQtVq)< zYqhsn%5X#1Mbs3J;!TK<3H&4^jkAXX5mg|tm9@p_MUunggRm8lxFAXHvP{qSoH|+@ zX3Nt(Et3k<_X%+yGeh~}#pi4~mLHAlV&E)jR-r#aXYJt-hIB~9+(mF}r$sin{xA>0 zf`#!#Ofw=h<-l*0sHSbOOPQr3SJ_neP`bAF4f>s#dCKv{rYlu?)s8!1 zN{1w65Sk;W3zysDgN4UEL{2)rDf1Baoz;Ohr4ll(Wp1}Mmb$oo6#-`vkZ$jbC~a|$ zQ+{RR{UWhxYy+Hi(u5j?Ew{Rmjz$C}!tf2(v{*+(sq!Ef3tqsI=kyy0->!d8^PM5B z=$5%^o}nYUCz?408`YbAY;Y(gE%L7_af(j_oE!G09m@ONHTymD%8A7I3(#9`0XoLh zHjKxJ(H_2TIuFtZJ4iW3;x;}Q^ckw%?X&sB&CvS}kz0lgz#rSZsAu_fA;%1ohrS}Z# zYMJR)Qj<=U2OC_qyl^{g_=<89sS!Ah9x4;Ifd%7a@|TxL9ZnrfC8Pk9nAsVyRoR@G zFGX_Kd;zgKO#_31o@E!Ub+zOP?L} zrQJG}7mzBxkIcd@BI8z_K3G{}`a0DE^T+m`p*De?E1oivQ&;I(U)vBuH$_|a#U-X~ zrK(M?>7qtls87Z8UY6IM6UrJ2lA7fpMeU*3L#mI)_|nel@KWG|whz9&Rw-pZyL*Bo zJA&7}dJL;W^SJbavUn+)N03`v;zP$Tt%od938|;7z4tG(R^by1ej0nNTF6XR-n+{6 zGBf9v5wjS*4-s&nx9EkaqaY`((IVm$;PQ_2G<0kQ23<|qGX7+Gv0^eO;`OqgPM6%> zAOe&c(&5J{NK3afZp5eH+~E%jLRip$rXGxvGoL&&0DE{^zD!S_w9)xHeqVqE%s4U!V%C?c3^}-hNehv z!v%b9$JjSuT2#eP#S*otP5fu`m`L?dGjdzsHlc*Y7jAd9+B4>i!SdYS`W0Z>4n&^w z*L7h#}OH zf|S2Y@MUKfCpw`DK)Nore1m_6m(BN^WkyY;UK}iOeWb>DG<}x>Q_Rp%=Na$;B8O7E zK2{^*(P!3K-swR12`~+!@@e9DuSdRlUT*MR znAi?+7^YOBUkS{`@;1{a+s8A6PW6;!H%j>5hpezGSBYQWe5Y}v2$_Om-;lj_cP#9r zQuctW=)fKbBR%mVp`$p8_`#FoegT@SyrFt zbH$rZeMoDi;1){ROzAaeafGv0r@K2%Du^`-z-h+7V<1|Pzh|I*F&G3NK&4Fe%sh5M zqee9ODM9w6i5_B?GvVlT<}72;7N^z4M@0>AGn5^op)i@V?1m*FeycrIp>y5!vARc@ zB#(G}!b)oWGzSo)c*%*{KpwcBjs;bL+x>^0th}OESBwF~XP!0zo6iYZ1!&I@BeXQu z!&uZzO%=m|T#wr!tGnZNXLM=g^M%JAKjOe;@mjP`_|;N#n~WkNv)Ct4sZ=SYtdH5A zgO4J*+GH~QiSddW{3_nlPQSIvn|;z|{5T)iZrF($65FMly69)(WZ+%gDZ1JsoYCl2 zPeo&wO;Ct&o!p%)F+WbsQf%+w(;0n?TGdAn`GEF407vdiM+1+s@_DTHPhi7lr8v3T zCypIg^1XJbYJxPSRd#?7L(j5U$Lc@jjAP<97SB_N}oVT3!dHLpzi- z53WDF&4_Oy+sfO7INfIMT#W-YjCaI+ydj!}vC8={n+eQdjQXRQj}Eq#=Fw0V!paib zv<(4OEHS6-h6$1qz~9rH<~1!w2mZ$hPP z`h?;ZEws9`VSsI=((SQLW{{vD5?2P+TF40`_TK^=TRR1TkSI12P9#3E;Pr>I?^RlIoB!Do@}v8yJS;E z?kKcxj1bV!reHpgL7V3|09GQoHiQ4Z-y zoWyjLHuWp~Uixa^#1~kwP64Q+DFFzYlJHuWukq?at*WKWNo9*kJD;m#Z2Ja2$H#6K zy1&}t+Y0euAhtdy7?bH8mlVm??iL=xG(OtncQiQ zq8hRo_4#0*t||27A0dB}j2~FONu1tb;){q~;qs^~#iTfjg-9F1;DnTe_#J1Gel9gH z4N+c=)3nA^aAAkE$?$o0=@b`1aj_Q8-*Y5AU_K5;l=>W@chystPj>r6;9J<;=|v1^&rssJi}y1%;|SPyWEof*5y#HK733imbiW$uWXVZ)v7O8c{Ifw{Q26w%@V~J%r*AP*_L{QbB#^v8&J$D z4Dqi_FPlC)+PMdZzY`ERIi8rS-lcs8uj&zshL91knM^@&*k|deABi?}L@_ChJRB;@ zrt)VORvDwBpEUm2hRE6oF0w zz(<<<@zy<40&44oZsp2-R$r3YpCezQi%pS#y{vg;Pq6-mG@!d?w7XE?d!bwZ;bn4Q z7}n1^?bfz-3-J7ZwA^LHmrPyLbcN`lwwIv+J zCTS9)eAq-lCO`AbpU#nu5DewuC zY9+1{Kh5-W8bP&cGQ;Lc4WS%IV+kD^I^G&`Q@irTh&zxt2}~K)5~97W!zQ-{#wLST&((xA|6^D^sB>ZE+yxeeT2*N%8un36_a@w1KcE8WyZGupz}7b8jeBMxDyk z9+-6yEl&N$L_$P-4XlfDqL4jCiSPYPbF!G6JRluPHmO$#Ua1#~_^W!+eN zs-PILDz>pSrcf%U{?ouN5bCxU0^ZzFEw@J#FJ! zzo2JGPaSsLNicuy`7V ziG`#8W8rl;C~~OOY?1!B&-eiYAD2(CAQhsptG8DHLVlWC7^IHo)8A|05ibW1(=+;H zsmyMiQaY7g1;%4Y%-SXs$L4>&1NWYivsjPx)%QR^IO0m}vit@M z(QkdF_6(F!td!%tiJ#ha8UH+khOU(`L=VE9ej<#;X~J}j33Qe;^=3R`!b4V0&TcI1 zDSd(O$?)Fi{&j8a5tqI~?8)$}Uv=bNK^9>&{Rb3Rg2dr7hd&6=wz>29))$NyIZTz1rCfp=MuZ*}9z})JaKn%XN_PBj zPH+aXy_M05ms4?ur$j5s@-t{mY}!ynC?W52Az-Ur7G#*`t!{@U*?{R!&}Ni!Z!opW z9K_eh{>R4X85yg|Ul32}Y|}9Cd~7%qIydXz)TvcuRAbVwbYpAFHj(SDp6uEkdKakl z+J1#H?A;eZT>elPe*Mpprj#_ycG=zF_#Ax3)0%0`D#r1ja(N^EwKiy@YC4lm9$&# zw0_nKF{=BF;5HS}n4o*Qs)%DP2+<4iqNa(<;zb7V2HWS^Az7^8_7C`qXkQx^z%xwf zAaUt7$jaNBZ)BrOr7OQ_s`aWd35=F6U`AiaRY$ThHs{-#3OtNKO39>M&`fhW28n3j zTqBVilP$drz&mb*v!DhYDix^A8{Y_}o^UimZ|O%+yr~z@MUXv(abrWRZko@+*3j}s z)|hWfN{RvGsITl>#0gZY$(BNg|F7@a1Q;PMO5ti6*7bFdGyFC-sQRU4iwkF7PT~N)xP*(hHyeJO*>6k!f3Ot1Na~LAZApLlcC; zF4KX3W{eFxmxu{eXW%C~(7$@~rgR|}D@7soP07DZ8}ux^Ssy=3o@ia%=!s+8)<#&# zPyn`QfsD>Zh+4pA<5es#9iau+p;+D_K_50#0Th0ei})`u)Q!J96O)W5m0rvOhT5Ex z_ovS&@?qcxFccVZE`|(FYIRAmQaAn;zs@Q$J)%-J3x}7o=$pbcM}{R#)O5L?s3IRI zfNW_$xA(NX#SL9K{>R1g@$^3tx=pwZlO%yElu@w0e(-KkWx)4fehz5_5MA+qeJXAw zHF71-JPFU}h}Z`gw{eWVWOv-10Y?lanuV>Z*$NB7U1ZTZp{(JK7i04_b!02QS1@iv zL3!-Q8&9#g7+76R?$psI7iv8a*cm5-VuoC-YD$caJe)pZXff*?1+L!Pl(!a#^mXZV z8vfhx#Sw-x1sjCDj#GfC$Y2aZoP<1X>DNmwF5dOy)+E zUcgR9fSq{TdSDyziugI39AWWNANup@>h4FL?L1W(s=S){x<8(CJbPlQct&z+qYsWo za-YfW-n$XD*$1h|-_SNVTORSJGjGR2uTmYf3A#!s%|G+`eCY4wBJ;bS^S8Zu%<rl*f}gdQPUk9J$A%^X{|!Tiu*Y2gLZ7{^*){06vXaz@#WvMIBuSWl(&W)#EX zcejx@+CjJnX`Z7oQLu!t&5eolNYQ%~mpRjt;(^nR&?ObO1 zHpW2jjmPkkn$1uyL|Utmm-)}8Cyw&*D=6YnX7~F1!Eh~)7wx_|sal!`x<;DgtiazB zq5|nl8IRF|jKViX8cNZtZ>;9bNe|Fxgax~8y^t0fI(x_L^fWSt49!4J#~FwZkYP=z zc=cf(xOQPd97a0OpurkIBoJar%698EsbxsrUz#TfJzlV@kptx{klQD1wa4ZStAMRG zcwHHmqz0|5F(il(p@Z7fRwEC$uWiT)`=zr&nrKoNYnKrdfq#*0*qfNCWm_z$&Y)`-Sh_ znf(P>*wXV8m5_y^PN4!JHO#U#LXi1npkOLl$Ze=n zEE|@yyxU(?fWRzV@cvjhd(n;yLb=%3{ zid)Q!H9x^S>?wq9q9Vh%9n$296-hM_`H(RC#?qR(7{58*F{IXY)c9mirHNMXeyX8e zvy{T-LypF{E*4s)4#dFBr#;c%rX5B;2h4y{(qQ?;Y3EkCGJ5yKNoLEkO5JP%j76!L z5$SWFm16)9{e>0!GslOc{_OXeZ72v-N0JWBG`moIh*U2bIn2X#r~*4QCd}3{ash4% zQm;c0Z0B+1#K+b8yRwogJ7$36^H#g*AJXJny%z?EkVBEKfpX@c4W}SWMpD0)V&_RW z5Q>b32>;z$;WQsnd;t}zQHzC`LAWYgtC2s8Hi+HiFL;`-5yMsYg`xmBpn)V%Sfyb} zVcTe0Dkyq~cZSw$?lBy-6NY{;GIyU4OuZI_C?pzCHt*K<&GGq*#-A-O$6CniTfNFi zd3&~7f3N<6IURjK(sQIwLga)090iKo(=%}=b9HCcz! zeY-TAq`!(T{J-tw3n-@{>1 z7zgS?rX@@9qJkyyhMc!CuCQr=zhf#9MQBc@BS%c&X2R9Bs)NJgZ#r^=@}A@`9v+g$D4Ea97p>Q5$eXJYY77p@27ks$||j~x0ZrGB~58P zNH+wk4-M8Gz)Rty)ycg>Mng!^BvR4Q2jj?7>zhaZn>sX{cTJWnFBw9v$+B3`mjZa(G4X zvqVy7Cv{{giizt>h(f%rUSzhoN}szom7_p%e!{GXxlRSKdUufj8t-5DibC__T`nVUD4dK0Cl0vw&Ox|#-lww2AC4y<{J<9SS7xi{E8_;<%? z<r1R_roYrnBe5tsL;BEJpYW zG$(SZl?Dz$1}h@lJpu+T*GFDCsv-V?E2|(J=JO7 zjyN{-p50{_8)x?RSHR$!ca^SnK0O}6PQ5|=yZpS$AzW`M*}25sXt0~jx3-kWT;*Jg zG5}+w5$Bj2kv7vDe&YFO+HNt=#pPEJtkuR<`-8R6`Lj@)^<=Z7hoy#q2~{qxpQNVq z?(vg8xlG3OlLr;xCSWUw*u8H$zkC;ILBdL4)5c6^Ogt3&%pN}(-=g{{m*5Se{Gh)R ziGIUW_zO%zSHu}tz~e&&goL^fC(+MydrW+Vvluj~?I~b`LU|`|AcChcD4H+wv!UjA z@X)A9mh`bkf5tNRX5($(UGcWDW8GWzcdN_#0R(S876tL|GjyYHq*+qhT>`I&|vZ;Rd=GXw&Dgj}F*zliz2HO^-Z zB)&fTuJG_wPzVA6S@&Yo)eE}SHuFQkHaP>Q-}aT8{*cZal zL0z#R#41+|{eUH_8!8_v0Go;zfsaQ+=Jt7^WD>GbZT4?1z(pHupA8n~Y?Doe|k3CnQvvU9B3af0*~*1HY`f$`DXjLC#+wC~askFyp;XVuHfrcFYWD2hS! zMBF?$SRO=PeLg=G5kUi#&^rbY*AqyST^oEAt&y@no8 z1bJR4a}l>kuGsh8@$AcIm(dYt9qWX~o!%UN<j<#ZNG$ieuxiu!v>dG--9*{o-M&a!mWSa&sbubxvg(+FTP ze7fGWx^4jF-gGY=F8jNeuRDWDI&hl9tD&YJH3H^(jm(yLX2}@JRf|Yg+~2PTrh;G- z4@DJ@kc_~%!4zr_3%a!|2D;|}ONuaXl@?a~g+vy0kO@|HxNcIy3WoVt{oYce5bD6N z6!ef_&i%A_HH_$kIwjR%rrD!6D9l#E<_@`MY{Z1}=X=dHm>^^!gN%CSZ#crVa+^VV zza3YHk(8a$&gud>?@8rVz>-<{zj(lxGV<&CKRUcVj+eB@gqDQ!E0LGS;4CQUSK>i1 z?Hzmr>7L?ZcRtW)H5C%S%2KoD>dr{MhSt^)T4{hEBPa6X3$z!EzqA=?Tlhv;8vPEO zbXB?C(lJz(8{^gZ(~!A0rW|s@ve1nZNVNGGRe>St)Zf1ICr{TODD$+JYzChTkkq#p zzlN+Ko=|&-a6HfX2St<2FCD62$a{o+( z`v!>r*pX|Vhb<6a<1?4W`8gsePqx<;q$A!mj@t9w@iksSH(gjx65N!4P& z;)PZCA?N*#f)xsf^I`ruaXZE=IDxHJrmRlzvL-oBqm$GBV zA%Qf;dNOlWRk7bhTWNBkpiM(fRV`Q?u5=Wcsz=$#WoCxXmHK(L|D<|v2$YG%h-E}% zU^L(3Nj!@L=9wfxbrAXyxn#E97UuYF8>>tH%BKh{L_5wg_7Hng_s6CX=_t>ZM7_et z^^riqp1Oty`+0Fg!RUDkWa47l(qdiUmWig5KVO4J=NfgTV>4v#%SYLG<^79`!FD?L z*J7vtSu^R)cPY0k%GHO;RrX}JWlgQ(B>-K85|60adr%G>`QLNuP;f@0&E>Io9~kw! z4$HGXa;3z>B5@*N7%(Ch{E<=c3o^C(cq0UW4QUvV+yR?CnJ2|Bbf%1sgnrH90raCP z0W}Y67RZX4;n~$+#gkB%d-BgGHYizTTRdW|{8R>6u_1q%9*|_yIpr3T(cM zf+^7A4gG4<4dwz$?Ob&QnW0h!<)5}u%JicDvbjW@eENdv-C0)Hq{ODU)~0Mp@E49S zkK|$J00^yha)_2tXwbEc=N8aZL#7NgZA&t9tlLLmsCkv8Vt&%jZ&k<1XKjuLG993c zylCix&K6?;IC~G4PecKf-5ck0t5$D+3E%hl{Y^bDPW~DKlfMY?79_Sp47?Y$0O_=u{-gNc6wihA=0c zC2;(lUcqK1qxL_5M@}X)r;MLV@P}(=lDzT`z_iTOJdE~?bVsiyw8n&Gv^-+pndct= zExzJn7iCk-Mnkf;8-#Ck;tA_VJ559gccD8)`lsYQ^`|S7Ny_!IDXAPzte6y)_!m|g zR#VHJ^o-0EYf_=XJ8E5*>DBdP{&|Q(|r{P>AA19hB`T9g%1-ii;2NE!BO#%^5)kdu12cS~H=gIN+uh7}@d&zDHGA{g{CL zljk6=4{sF-alu28&I84~3mU99upb68n$|EP4I!NlCrobQg^*dH8<+ZBLb$tAGBi<| zP+W)#MvhLK3Iyd%Yt}Q8zlMToIL|5GHEN?Go$isdMU;6tZo0O_e+OWD&-UID5b8e` zN))fVG*sDr7SEPHGVLnh1L6(A$8phUlPIFx<8>}MBZjE7Hr9YcC=f_n^OgII7Lj6{~8DVOrH&{|=ijw2P({!-Q}x7t|kuFc=Iy2(GLm(jOpb6%+MU`!!0xTh6> z;X;Pc&Ehw+zfOIS-Dbh$rhvZiimc7{y_B}5@EED>P5m=I)ncc#=;NP16MXweaHjp~ zQG5UBX4@$cq4|ow8<}jOQWiPh!xN#~43k|#m5(l+_(}5xvS>e_45mK2;FqQIO|1izwj ze~Ko(kH{1QN&^&IIx|OdP!k|=76F7lo|zfUA^>-C&y|V z05E%PvFG2VGjplxmNneNaF69~4}U3#wDG5ZYCbLWr8)iNENVl_!V5(tljr87d`U+h zkv_Eni^4;UO2@lQVHA^?-L@dyZeH#Af{PK@Evj`$pHfJsN6RMKZ;%#@16pU+fR)Xq z8$AeN7F8Z`Q(-05_352>V{)O1Uf2dahM5Vkb+q;IeDYl7oWi(O`**5>(g~P&xDe2U)D_m{ zZx)s%Dzzz66H}(QiKugOOa%zC`Hl%vZ!YA-4BpC*Om3Nsn;~&l@W6%*Un5`Q96X`+ zAsbcD*xOOmX2H6{CT6MRpFI@#3$k?aSLN_EWr>q-39=jkJ{xF5|6rnFFioTA$lmr+ z3FUP-wQ)7hq@ww&IE~ z=?V9?HTFNq$M^N{iBER(<-;i{wRrHyh&QE6#QX)s5g8cF6H@35R}f<$<`Eu)pqPI_ zQ|BL8h}FR7yiKrvG_o0vR%&;fsh_722?d_5K>XOc8p?Inrx1Qd`NFVQS3*uzHWzun zUSB}?YHsp@X;;(FVuM=6%W5~AcdfQ?>(-ImJ~=1ssv$HH?y2}NIvUzyXNd4$xX*99 z+(B3a!b>d_hz6W`yCE@n2J-? zV`sk9+0C>Qrc~?``bro8-YfKo^c56?`C(|&HrK%Fiy#>K6a!0e{aaw=vIDl{(Mu$T zV3*qOGkBs3revO0I#Rz$i1|G{uqbz1tW`7m-BqG`E1wM?f)dr^sGY)1A&Q^X6=8SJ zpH#o6=^9OdJUwzY8BywsQB6F`ilV+Y_yVL^QGDpdHM-K<>tr{~wvD=+rYNA}5!I93 z?i1skt>&KJAwtBChVR6^z0u&E@%%#*tY+_KPU_qeO+U&HOO9sRB;p6{v}&Pc`4!N}{M(H=F4B!1Skw0~UUp7b30!}g z8$>lFf}XccaTwIcY_|4E&+v~o2Tx%KI0eyh4447lXxyj++I%%A{8ZFh(n?p_%wetU zv{T_-BM>+{bIc?>15Z?zdXe;xSkx}1D4`EYevCu!^I1oB-kpgSiq%|moPkcW! zqKUdP7*=7J>r5Q*cQ15bDF{Yc1A9oaDDzJu8s;%Fl#zrbeALXtd|=ga%3Tp5oOip8 zD;LlSH%eDrjQ#19A3%Tu4tQg#{s+@Mnds*Hd2d0HB28o4C45f%>B4e5IyLJr-N*zq zYF?hUFh9VW^7X^)Oh5{LohL7nhk~zaP1>VJ5?{B}6f!8w$ z;DPq|&cgPBp_UMg(tdXGk<6vMBu|s!0O)+|D*BhtDNh8Rp|YED17m>51}=RCvIy+g z(6CEK0$q!q*7?I}S^@fyooQ~vf-pcYep!}+Pap^eLZG`Ht2>O|g&OWqczRlYEZsw&vzI#Hs;L{IaHz$VQ7zW}sr!Wv6Cse%a;@ztY0Ygb4mT+k~_Tb`z>P zVfHeaEd^lSn&CWt;2^Q;_R&wp*+RHS#VC&lxD(OWwIEe5(CAo5Y~p6`o9` zc{HXHq~tZ=`{+E##R`@;*_fPO53$|LR*HXh7LYdde_Usd8F zhvk9XGsiKy`p8WTi*K>d^nhbM=Oz*DEzK$NL7l}a!}k^V)HZo~*r=;}n!~yp>1$PX zaPA}vc_ZC%%2&sNrCd3B;*WL00xdy4iUep?)JuCP>Ycrw*I1T_hFILZjxZNvWUGNiZda&R z|LTMCrZ$)A;L{#VKQcjXwxTb-uH84jxExlDp|OEZg@Wek%uAli$1G8eKvP}TVCBVM z3D>stqe1MVBOd`*u_6M2ae0P5GW*c187MPr2Xqu&R-whL%h_zl2Qx*<{wVDkFl?Gr z7uO{B(wQ!fE;7P-HU|&fRIn4v7jswVr^51%(Ql%!LS{Tq(Uz$XoM_cojDP_6c~1LI zMA@`xg)2(speT7Unn%#7G2 z7e1hNt9J$18A9zai<^EzCd2fv6HiwRMViH+QzsdUf8DIm6_2cn`5ajwLX;4HXoJuo z5)S13_o}Grob{M|ws5h5 z3`sdfFqW1Wm@@F{I3SMZx4yU5QPu3snu2U~NDOU=F7(~-a)}Ie?x;Z{fB`tfBu2+@ z?t#3rfu_-kQXS*@!?dU&{=FSWym+h3n3JcP6jBz1@V*t^z58$7I7DS%AD;=D?`b!s|jBPO`*#|QlMkjdlk_} zkQ&!)S5exC5^HguiuA$2!-0CkGk-n8D`hvx$s|9)UY?TQm<1dQH zUM#Lug!IKHLsO9%vN%&jvhj4LxQ)SGNa~Lr@7;A&&GhB>?(W1U2|J!0~>sE5@lU0N{Z}+ys z+15MIYs_sgG=_bAi`oX0qsu?jW7db`W*uwIj_gu01PZ%15+<95ov9`!%8|!K_tE9l zo2MUehJ$ns6hL&j%oMu0L|5v`(~zhVM~r0!d;4?ZC!@5)JgHdeLWU{oXexNrC*m3o zeuBLp85!_jHjMY&@lZN(Gz`AgLPqeZcdT{Tn&Pb1mYnBpXz*aCs_czS}|b#fL1zb+2a zjm8Ad=$eWOX)%uklUV1p&NiiJLFoY`+nocL{`{~a2u-;nyp#Ln)e=h>XgSl4W|GD< zZClim&%{E9-lOI3c|u{E*nk)fYL*A45tL3&XA{U8tLvW3-30icUY2df4+AW%{0QDn z1__R#Xz1DI^b*mEOFxTndvdaB`bOLnZ-aaXWd`{Z{L&Rig1UlwFLe=-Pg9-iqq25w zf8hceG}b6WAW@O`FyUBT@no2GD1VT?jNI)jwOmfk?UWP8Y;HA@wD zimN*ADVGB3#2dPXF=cD!$&tK^n6E!7|1;4F$gxTWEd&(n)*gm zla75NaklrN|HAZjso~qcDwSocm@&wu`$%XIRNWQvCZ0;=pxPKs9;0r3$h6RpVwErO zO&UkgMzHREdz$Yq>Ip#|GyX?WN~O%XEKBXOC|1DUAb>!0}Ak+SM?)P{E8mk({j4 z;;{EDN+RTN%aZ zIcu~f%HYQGIV`FaiyDp1Y-rDSwO!MjrI~{wV|$uJ}!sFvqUA(rW;=@(894e*W{!ezKMwmt<78nyQU^Q0AJwL zs4hvn25*DEjPzupYK%-Kt&2*^e&O3FxpJqrxn68OniM7X@}Bv(Fe<4HO}E0xpGvwx zK_KF_hemMpL+qycoWoE!K4CNqEN$}!DudD^gcLg`Y_R@^og>jkBZ`mq(h_H%?w%bor zGbgL4^0jStFtxq?lO?_x>SLn^!-%fTr9?2EWR;$_fp@r7FNptMNP1J42t%_X8!fVd zymBmsD3x%2qWD@GR~*15M`)D7Q8&E$pgwlKfdq($TN=qOeROHUYLHw-tf@r-6{a~3 zP|S~Fs4zI37c|wU63e_pwL#9rL{_ny!lqr&^r5zGRd;@Pr9KR1|r zk)67?mIDJ;Pv2N6HtOLslCY}zqxS;OvtnA%8QIWGQ}rbL0HMwzYq!BVxmh0 z>!j1FmhhaGViR;r)(Ti*Ui8Hs1U-o;R-}ziF!AvAt#wc8g&7R!l>h!@e?&e~y#h)d zbhas!Kvtr0W4hb}>d45D?J>w+FTO3`Ps?h+Ul;P ziQ(WlWq_zK7ZGwP&2m}xl+k&4Q#Cqd@+`(uWW|O2tby#$v&Gz5s5bUMCh5sa5u6iT6|afAw8EWj)2t=sC{=7oD7UC? z8Jrnk0+xJWDj|P7#n(fAWkdpZXXFD#=z|fm=D(a5w~rQ|ojMQ(?GlE}qcj!q#rgpS z$Yf$!Mjx2lzgQXmI?y+Lq?ULJZU6pf%IuZ9^blo_Sp^EM%fTt8mN-?Bfh%D(yavg4 z;R|K+d=&$-9(4QF-$y}3Gb})8l>K6#q~fK(*^8mFrU1nU`QIJzRD#pq$%Q*7pRF={P#8l z=AD~vg`l^K^g`ul%-22DN;dHmW%?tqF7fKYPdh(#R$Ei1@>mzUf?F+jz1t#+B|xa?+s(0zaus3}F{CJ%?n6vtVdHpafcEz$Ri^Ti}Hd zC&VE0X$=v%gijH7Nh%$AEJeW!u|(#1*lIHTwD8JL(O^=OAUE9)FbQh)OCoCw@Kwg0 z5+M?MfAfSs+Vc3LWQLytd;R-TK$%+TI{*? zBI0CKV1;0>i%%-uyYz(e6O?F+A8ErhHs5FO?MTsB8a8We5jlkV0E`TWq_1`Vup>o*=-Es6=BqGiCv<9- zGskUgrmMWs!aorw!Ond5Qu#VF)bQY}WXq zB4(P*uv+8Y*?U<}Ci{;z9ZG$Umr`?l+scJF_K6yu8S~6sO!C3ABbt<$;FS9uJB>2Q zWFI^s0&_u^`KL^mSxdT>Y3lrI9XB$hNJog)>Zyg#bzP$ijtlP z4WRE((InOtsLdZU24l+tQQKfIRM(>6Sp3f44hx*S#oyWoLLCR(GGD_~U@5qb@Wg0e z|Hh*ijX{5vP&+xrOK}dMZA_V|g3X@20VZcY)B zO39RU3y!*clWK5vT_II z;-+6SOqtomEa6OA+z02Gs*01EaCDfV;ll3O-IZkbCw|l@SUwz&*f2jjpP*s*N!ICs&0HY)`21m@+j*sdF={V z7Yah0sQ1@MOmOmvXh;z|4Xq7j2;Wj8>A2X0hd3&amBM~T@q5bcS zp-6Nsn696+fN>=keKBLpfWEnikrcIFAQ zU6jAu!S&u#EX@uWa6p|furny}^Hb?v*^My^MG9(8BwXN)kBZnyb7{2kFioPkgvkUv zP2P{OV$U3NHu58gBW;Y+j-6gJ`izR+%eDi+P)Ma?Yi)q<`F`rWd0@T2aA<;ZAF|Cq zrg>yCTC9UGEJS>1`6Wt&Knj?9o!cpqym_p2#^h<2gBxz`)c@Is)7bGi+dzE6K* zq-3r*h`=jx9M*KEkVp&DY{!1qK5HzSVn)N=ZB z{RbvOJ;7v?68{EqsBayx6jM z#Lo1;Oy!ft)R`^ul(x^P?w&nWT#qE4> zh9pT^rpFCP(ovNL9l{d!2vAg}QtPIf6JQX>STYGh++P)Owjm zaq^z&Q>OD<_9?=2Off*!WILUa!d*4pk6iks|IosQ*?co@qkL6c#uSfxQLN)d4h668 z$-f*z)+fjzs<|5oF#HsfgP;pMdX3-HO*dkagjD&u!g{?XEoP4Bgd!4%4a&}K_e2&d zaI35U!7M#2%K&J~EA;hyAi?3E*yrcZ>~D!{*D(Uxx#mpPQuuZWzRd9i&k4JW2V=^v z2VP+hKiIE2)kp;$}i6%iC4)?G?Iw%$pkE0Coa%aRN z3eqf^V@2Q(2g1Q1T%l#H5a)Ozc+utIy~&Tbwpx)$ zY|mI0#(>>DPn%;?u&#_QQ+^`60dw@mHKlCdII6tL41W8+(srrvXTH<=xW*>*E^_c znP1W=pCNPKnkGix$BqxiPYKhQCeA_a8K-5%=d~55ON7HaBv-0?T1DOv5)9x&y6lF{ zCYHS(lS|4G5ej4xK`sq6vle!c1?%%m+cUrSWJS|FN2>B?SNzJ9;&f6D&pQ?Xli3TZ z0!AKMA_<&fvOAyTQl6y1NDuY+|)CDb%33Vti&Y$}d-$pN)Q!qUF9>Gm(Nr?zDLI!N4_h>7an`y=u5JluC-m<=kaS zL{e9~7gN-xy)_NvqftH{)_R+YNTnTxorqG#@+03E{TWoZTgi`8{za*ZIj5av!$Kt} zU{RDYk*!j&BkCClsLG-oPjvuOAh?bOcLYsovu5mEgv}F?-Fbnd^0*1rf*fWja57G~ z^EjEB;nw$t&Qqsc+y84RgXJx=1}Mvbw_ zs=!B)oY+Q6%8^4dT2_hSMLGrNlT!jzvS>zJWJqtv5_kNhL_Fj;N!x>nR%&Z9!)7DO6yZ`0XZYT~;V|~& ze0%M8(vHJifxZ~gioJZM%|J8aXht{G+6%a*3SkAQQYBTxxLk<`>(K6|OZGSxE?9VH ztT$2C;K!5)yuhK=<$qFG#%Scl$0Zm`FAtlRE1=)MT=}aeXoCij#xdi6K(sJ9&$`I{ zr8%x{01XZUX$O5IR{LZrw^|`uNYzz{X$My_{@Bwf@Wn3Iv<}K#JnJmmj(mw@_j~F5 z=6Tv0Y*^fM;?%vyF%~2uNk6do|7(lzC*A9` zya;tkROjhX)btbBJWQZHoIVdBiUSTZUoFBiE)XurBj^m0#WYipORDci-&CJR4(|$N zVd_D6n(pZaRzi{{#WmbD(YQSI1)xR@h$!D1S~C= z3)aA;w_&fLMSn*T#KhE8juv>q_$5^AN&imZdx|Y*hb^$z8necIq_fNOs(*FCw@12@ z_t3DuY)bJNhh%?pRF6pRP`~bR)_`OL5_nP}&WH6cn&UAF2;P8hIWL=A%&NnsC9$HM zHE;!t!Y}Lz%~>D2I+>UNAFZGoY6x5dszSO3h4OzI=c-GZBuvyt6tM(PstR(EIP$g_-7kYw!As&n4=*rYz7Sj*1x+U1L4KA zT*HWk?zmOs8H#OIvunBDPGK|K|9WmmCUjQ%F1of-gFz>ts0*vA!-5ZpH^d|Y5T{#P znw;Dg*088eI}V}m;=rk;W_P#)Pz8+VLOKCLLyY{OBh0YMPnxcO8NRYEraYu^Q_%r; zSKPX#n9;o(6^w^ay%q+R>)OAWmq1xQCTUgr8s92GO_Ao!6jHbBb6OH z>bc(h@aE9g^i<)?eFBgLB4WSdss6mU0Cm56Qtt zd`JRUo7!5T4Z;vtA7S8g-iT#rdvo!HkdF=aB7GsF@>yOG+Dc4232)B*l5onaY5$4@ zZ{s9f?OfGB3((3cn}4RE&W5&J34PRMw|ViV0#81sF5{KOy)i=caR7Q7u?-amqrboX zTl0Aw#8b;nO@Da&{H6C1yWjOcBKoWt*?L30P(d*ej(Vm_r<$N(I%lSAK3w_yUK(75 ziUza#K!8dxZqd8IS1sZt1OwM1P;m=)UOfOuZ(fw>WXf};S>3cl(OXTg6mV-afzpwuz>%np|DNZ68f0(n6XI5C zndFKi6y>X(fprPJ3R~D$|BOopxg)noSm?CimcPbcWA;_ZHncYK7@DE6Q-$VZV@npV zVPvD!2ZrjBnXL9^CMjq;r>g9S{e$Ywr$g4)sfxp=@rW=!D3{qjE2{UZfaGj`*+L1H zd>TCsfLk|1TPtHfx6v3$CO@6;Y#1l5mH9eA|LPCecTLqTkf-?@3`;#Dp@PT!<6Sk+mkhOo}=31c$-<9xaIshvpY(~I3$Wf zWmYXsAX%N9ve1`)2`hxdK;&pZX#PbSjSX?^dP9keSgsodsl{b)&rrH%VVcLt$TUhS!L+SR z3A59+=--mEBo-*Yttb@D*1a7Y*$CT(WRA|YCneUG5CV3WVf{*c)K*)$0;_!mOvHIn zOxYe&BW;OmR6KkO_#Skt`jFa=&Dw{a&bS~K@ zf-yUuy0)-Gcj_oUyso0^U8&B6P!xM_tW})5mG!KY32eT+v@z%G;eRxqy&XhsA(BCln?B2XEwfLMVI zpyiLWw7FT8>aebZS#{lUK^=)9p}9vEdaFh~W(Sw1wVP{ET%b5I@$(PPmn9)`G(IVU z-ewF!K4vVmKo6pWmAvDS9<1i7d;q4y65rOV`m56PSJT6w;?OPrXPcI+w*eL4!H4iW;G}L&A=J({@#t zG`6yzA@48j+@vl}8$P)Z<@EK{$kY={S7+lz(^Rs?p&>^hL=eE*oKopI4oy$8wZhoN z-xmE|NRl}jUQ9lnX(az{P&6D+gAH-gENXUoW#?LoiGYL1-~ym;*(Zs3zNlj55+Nvnyz8& zaTKRDgCW8iY(|X6NVABY`|Lgv(+=;z=gtu6+weSZg?rrmwTxjd$v>9Zv19~}IWOZN zjk#nMG$Ey8mvf*W)E|V~*sYh?SVpsay|k81OP0r`7s2c{Rs(%c0vb6!Ob+MR5(vfa zpa<4yfT=G!m(Ge^L0hdLoJ5^2BB$c$)F0u!ITE0fSSRWVkK`*Uikj4jZA7HP?-C&J z>ZdDzbE%t5K4W?Z==9r<&HTf}43=mYy1350T~1f+8bv#&fCf|OPzPka`|@A8(@wPX zsNm%OoMxQ;WcpD1fHS(|@0rtle-n4Z36LEixgs>>nJh<(vcr&c)``Kpmn-V{Y5OQM z%p(;PkE-wvgVBW>;1HN&CinU89hZ_`u!5n1&}fH5fJ#j94u4I`xJrU5c`XFF2GU1G zu#Vf0K@xon66O>Jj}yhMlKMHeNt2Pv=$bHlj;~TCv4P%4SUcP`!k(3R)s=G@j;x3o z@$bUNmZFuc1WDo&5Z&cJHh(Pe3h|q*{`_$lUS*2t_QM7uc zTMGVXU%j3*_$`#7Y9-1BKIx7FPe^qzqS!KqLM%Fa5G7?9n7f1!x~BweWRQcU+X9_C zjb&)l-EH6&(*YCZ#M|S10OGr3RV-Htr78*iA2GsNx+byufh0OL{|jzgFw9S<MV!LGYt&&@k4FA2lls|WK9?L~h)L#eufDyy z)jHh7oCHqjlUBs^qSbA#4hxv-e^x>l!|)XeSDiEgpYTgYQYZ8!MN_^gtS zr*E?sld$9xfo)c%Ac$}5Az3lpdLSc~F&EqRWTvNR> z#nv{wiQHcVw^U_4uX(ZGHh5BFdJg?xc=l^r&Me&b0R@_M8(- zOub6zBMpqSJ`;6x;JAdLV;^^O9RU^Fgb)na6?7>81;6KFNYbw5In@Q~B}2-aHHOf~ zTSprs)*Rrzio1KGllX=f$Rt8U0}a=zA3kD92I!oqVa(XJ)$9I8mtdykVQth=0dH_8%cXJ$JZsY-% z{?QWnC&atG{TxywQ4$&DZvro_E!K_W!kLj7BA*iT0|=Z^prrH~K%nO70L5BT_O(x9 z^E7A8mm&WH1+(*rj20K;>0T_ArL4y0j2Yy4B5P?C(RuOhnjm=JPiyK?f2%!~Pt9-7jS z1c-W#QxlDpi`5@?zH@u=If1*(BC_UKqUwPf*{?-kyyV$kw!X+OI}cnUST+<)tL=yR zcZe0|c*&bbeoltF7`MF-iO5{(lNr=|dUo8%9Zr0d`90d#THshpRRlV#P}f~0+}8mQ zFtRAuC>ucuxh>X4S7?LqDrV&>SqL#QDx2K#JM|MVX+#}pdQ6Z3%rQSnO;z+e)^2<7 zzdnQ*Y`j!e2wqZx<+rC{5R@^4vrs!FCP8*X>j#ruhJlb9v-j3}FS}z$n0!pr@f0Y> zV!i3}Ozdj(+y<7wcVjTR?b`CvPklZbTyVqy++M4jJ6!r+8j=uB{pcd!(px#TQuintm-AsJaTW_^Qb%Dm^}bNfB*n zATBJnRSFiYhWij7z`$k-!$4q*~7Q|!!pk4@V>WzwYi4tZccM|Sp>dNrZl9A z1O;!TBSl3IS_=P6KeF>LXqwQexYDf3vK-=#B_x_}dcr!NB}C;rc_(ViXJn%VgpatE z21TR>DfeQ9+`n=`0m4+~5#|h77t?73ERAlb@2iz1x5p%bpJ;UqlX;4MUpvX)gve^+ z@q;grCw>E4v-<_ziCHWB=wtgr?~e*_G8mll%Y6{!R{GT^v@7uUt~5q!&Co`ISPUTx zl<(p~14RVaBs6Uc#{XKsPXF{)eL4*yG265iWVe zSzKPWOr88;lG+#klJ(mlU9yB6Neqkhr=_h)Lqxo$PSkfsaU7(pSjLI8+h4dFAN1z- zu5x>g!j82#*gA8c(UeSdzF#=owH+P10lkBo#>WX`a2E}CGRG`|B|9gX>fc!gSek|w zPLy~-l$emGc6Y6xM17yuWCEFE-9h(z;?j{DjH!);A`H%=tI9rYiXsyMU$sXax#BiL zPJKJ~0Yr+dxZ{U!Vn4UZV!0?V|IxILa=pM_(`|$@zq2hOUKaZSOC_R1Jk{e@iT#q3 zMg43?bHwl%H=Vi>6r=1~V5ACCL_e4>v7wcV$X8LRU<9Bqj@0)h1%J0XIM1CjeHAvD zaUXeDx}gp~#wHVk{PZrX+geaq(G-PPLo!a{n%=P`SjfjJwK!&Cn2~7fC(|D!TBej} zK&r!d=&uxJQkR4A#*njuoXG##48Sb}2W_$D^-SM}9nOMK62Bmu#rr0~?E z0ciP&BQ>9)Z)Am7=5=eh#}`O1GFfVgwr$8Yz<9>4LFw58HVcnA;F#?3cJlwQIveq2#PR{`B@gZpmtYXI-(i^z$b5i1@pJ47d6bhZv^wsVv zcs68RVc9{(iTGi)7hk6I$;)K?QxEgH-a5>ibq!(=Y;96*U3XBI|>a^_to4r!?lZq@EfZk*vq2;eW?wK+(*=+XzL`vV2n8l zipsJ^i!tcv=egJx)3nCemkem#3_S)Cl(R`7&?Q^zvd&!zP=0Cli^RyPlQMBM9LZGa zla)|b0U>CVbGL{CCQCWEe2MA<6^I!`xGBxOG7)tP@|Q4xd!N*0UONg6w}ZEH#bj#) zG<_V;pA9CuW{vCFGp(@^V$Luupv+ke!;Q5 zFAZtl5?iD|r7Mb!USg_E zR$sUwW18V9dE2R?B@se`KNOR6iv05>JlMn-6w!|Y$|x`0im$O@O5x!!q3VX!HmE_t zTbPx&&D^K@i#MxKzSmbZEK*d6z1_=S@P8$`Uyn5EFTBqPO`?%_{AT%`*rF(FZ4I>E zMN8!cZU6!N?hIrlCSZx_AC7fEHPEi*nV7S+uu898BFP0ld}M&-6CjnWlAe={C(Mu| z=up#obAnm7)ZDj82REj>roac!W@9w<{Z(al$@nl}n%pO}J!VWKXg=S4xoHqXjx6xU zDI4dCjG@b1mdIcBH30YdjIoursA7ZIP#@aR;*g_h?{YKldE2bg!Qt69BdP-7{S3R=qzQiVynVJF#RsGr@Y2UK=6NC@9Y_H>;MQ zM9Lv|*KEU41Alx|;CNi3y#ph$CC^565J1WX{{+`%z88@DZ;f3fvK1Shg~gv=9pXgK zVwrWMhKKih_9-mBMbwOQwSc;YIJu=NgOQKU8O00SnVo+;27PU& zPyhsE6I1O4>WXBc4~|P!JLOc;Gsz)~StGbn`u)>)U9PhD9qN%ISi#CCq*7ytvPDf_ zQp&1NQ4r9)b&MogpT%4@^rrQAMqObZxtT;Zk;Y!+$%X#km?!yHZk71{j>H|J1uX7} zY8!~53uleQX{~!1g6znBS4RHUa_XUfjl;|mH8d;HY)wDv=o7^4pKvGY*HRf8hS6?p zVO4<>H{TNPR(r2(1?e@-76LQUv1IbV)!eNOc>ea0NPnfq`Di`Qhy%w^P_tp=(>{il zB~j}xBMr2&vPG+AVQspFFbXln4hPF7!+;VS5nyC66b3HrFS5|5?_v~z3`?Qe3Q`-<2VZz2MR>Q7*ZA zqsY#cVJ{5jco8;~ zy|W%btHDqmv<5iRC$E+`6XWo)9~(Z3LAs#uV}4yQ`K_uI(!h{MFW*6rD6XAgUOo?1 zu>^Zivx@Ah(Z!JS-+Y%gSdN;$|LYV*zvX?R*T(Se&|d&73qEN9VVG&5+2+cH!m+O3 zG0i(&;K(vJN$2)~eU9YdSZE8kI=2vMc0+<^rH|Ok=TSOYTTNLne>gp3r)2J1W2d;E zg;|Ze^a7t0cZ^r&OUUk9c z_g!LX<#KQDeX(79B*cpj1ZlBksJTnOHOG4sn3odqbeT+|ze8#? zSth$bC@g5~=bi$ZF$)?|R_v@r+7oK_k97qq#pjs`kvBI=hlJGzh9=Q8Ux{0$=5nQDglz#Au+R$#j^YESkZQ zE{4Sf_^LaasePeafSN|iBz&A4ZJ6XzX}BbW@B?qRf5k;-hPPa}rOHJ5YO0YUB&b`y zXNFTR1^~#8(r4-Mn+HcSt1q1;@S^4`7sH1xT!SJq!jVVhJo5d<@mew3+~l8an5|MH zE>!sD27GAy6Yf*qD(W0+w_WU9KoW;Vc}u0Ol^!q=pgE^gr|72IHCdf@I~<#Gs-989-*7 zwkC~CFy8kZ0!^0>r>RbNs~n#%-?X#MtG()w=MH06Bd_6;x6dE>Pvn)aO>u)BZQSF}Si27Lz?rN}y2{G6o!a zb;(#g(R&l5PB3@3HY)u=^oFpyIuK{L%I}zv2$PhQ@lk({P227ye_%hIw+x~2OCAvt z-mpq!5kP1oka-xg6Oukx!`IXjT5e&}E~_I~q10zv%sa%*O^X3zS}I^xZ^c5Jr!8@0 zHBVZy{GOjE=Fco6NSr;4bq$I8$j={ro`x3Hu_k@mWYT;nn){(J_)i%C$^G%YQ4@)Z zikb(@*+c1f z(D9R)yQ$2R;;7lJp1P2^L_)hw(}dz?!lnTPgv@4Nq4nR8dJTKKj}KXp&-utT;*HDh zwVxC)9_LZAYJ0?CKB0tJ6drGwVhaNmAjp37=Knc+vGnM)WMe9pWLkZIXLsRS3LL-@ zmd#igD0l}5?H8H*y}L#xcC?OvMLgb-qt7bBrm`1EE)EY#H;#HzZ~_xJ!&FV*-sA!c zgeb)YyS4u(;+eSQKrF2tCRuzj$pT2%Mwm31alNUjX@Qm@z}l{ zLOJ)wJK7+PDd95nN{ucRy1gy09v4mf*CJfKTz{(u1H;VNRl3i=*{|wQh(EO#dqh#| zr@aWdsx2#S*td(w{oQ!eS}9*Cu982KnsL@0fBw)rh_VSegqQ?qmWdZ(IVC%f5!Nry<-%V zN<%ueaTuu%%i$7A)UTCyV2LU-Lm0>hyK-p?nK-8;`rzAhuB};x1gZhG)lKbz{ zvS@$@*Fn!HN`y{VE7Y-83j8ft|9Qc-H!lCG1QZD>OZtBIY$WiGqu&MxyY>8b4`{e2 zWmpk;opI)Idf?>+DJnT&D1aC86UDcO;(}2}GDEI5GJpO!$qBe2VlFmrFiPC?=HEZ<9tGB%`YWQP{*5jcG=i-R_fOIYzolUI7(>Ay2AmlQE|zWs^& zR24_dGNjT~Q{ImBiFaeiB@G3}V+clQd=;-8_$X2!qx+RO`AJ>KD{BS{D?0jz&b7ua zWotZkRPFpz`x2C5*K|l+rkbNM&KEFu3JCodFWOJPEYDP|Qn^Q3Id<_IhberVe|s*| zY^gEyQjdq^jKh-5@Gw1_b_YDXnpRLRMKCxtiJLa0kEwck{uooXyl@*IUEcplM#bIi z1^aBWG=fUOgq_n8l@<-g^VSyG`;=%m+rrbuArp5=>PLbCU~Ml=mND7whTS>OpWkmw zoeBDpC*Q?My2wuqs=IzhxfmkZUEWfier*##z2~sE#X`_aiRU(6_?D=S|Ja&YdPjTwsb1a05i4Ef+|NFjK z76_+4OQ^U4ITT7E(W%giFZqbBAG8WozO7@>BIAGdew9Z`wF#dP0|(+fk^F)9l= zfEdD6V}y$f^T7&{Mw-xvvFZrAnNe;fV+ydcN}_C1-Zuck&i2jg#tp?+Gx}iV)-bER zhskOkBMruG){03$bd)29>{qUjCl{``-fsiJuv;=dw0n~hxJ0lMG zpJV_pX(fzJLv}duFyqtzGYfO{u+l9`b!pM$?KI!CK!`$g!Y>COzM9+pzNtkqq;7vh zJY@?hMHTm;DhM5e>$9i-=%_GW-j$JYI#>yF>N)@d1? zKYyD_Ep0x>_+%8_T-DP})zd5mQ!{|~%I2+S2#aUzu8;~vbB6St>7c4TA2=EOH~(wc zG2>r5mq=P~P^gn`kYS-Jz)CQ2!_vWlLPb*4zcGQKRl)i1FpziXu)IV#H8Mg^( z(Xcd`^&kBUHbu6*o@|~fAS}wlWgKS;pZtX-@zvhAdjp|ICC4fBnnE7sT1s!FN@A%O ziSFNF`sYf1TxH`^Osbo_GL{ilxIQxM*5dR1JZ)7f1uKo@O#gvAxUt8W28+WyrLuOp zu8k;T@LKEg2+^|dcSP>fMKzD4vQd&Q5w`T!aeRKBK01{j>;G((?H3*x4<)iAkKMD} z-z>?0?7eAU6V0|h{63$e5m6k#bazG^kwH-g1sqW^h6baMU;^&jv;XIO_UF1*Rdpwj zwAG9KdtU8xe%o82s;(MVuUc~%b|Omp^(bVrCCXDkJN&|SxK;Yf>k5im8tK`t9D&HHd(+J$blUI@x#rp+Oz|Gr_a1DwiEUUO9 zrOEJq6;|*Rf?hO>=PXvw!S>+Mqiw?!mtg5e7@b+8)kf&C)~Xx`jsYsLyi5vvDT>$( zCA~r)d;GGC6F>}-^B?g>YP>fQ-#iPvI`jM*EU=454>4_*+-zz*ie?KVKE$$!9@qpQ z?0#!?|NLcpQ|`jj&*OzpgU`3jm-pm{SPUuZEW08lM?C}v!GN;8eh>B8jg0`R5DTRk ze--=%3yf_>B>)lfr0K#7!5H#aR1sPJkcGH}%8z@G5C$;6b~t_d z<};jkxMQ%}q!$~rhA$SW!BoYDs{mTD3_6CWUf|^{+d{T{$mDAT@ zpywxvx3WH+FqEy6_o zu4VTD7Bq-bs5j(N8J*eu@qL)k#53_u5(cEiUUjNzK1u!pmvRNh1RPQcCC+}bhM##A zs7*B(}%E*YbQaip147Wm=$UIjVH5~%Lr zn8w{riOI0mBt+`M@q-9bN$*8yU%mI@dF80mKYR3wHl;gja~m&yeuvt_I)z9mp;+<5 zeOkf{_(HMBwM?VNZJ|)zc&F)u;JslbcQ^Y)x3--@!t|H@jRi0>ht8?gfK4 z_;w$v6(a5U`Qa;j`B9)=c={u`dHcn}%c<*|FTcT$QC&uC1wF8^B>ke&x!Aw{cKs*L zJ}ra+a||BL#(PUfUIV9>yMnf%Au;WdppZP>m%VxfucZ-NK0Ragc5I8u*qdfT8tafE zte#23jHhNQVHyulN6CAfeJf&>75MrNUVUdJZU*;m|17z16CqDT?3w4z>MeLne!{5%$Hwb4rTSjpc3K#seVMBmZWJq)?Z=h!O$@=ttDYn3U!aH+$)(v^`bwtwMvRfDXf=bF z%)5y4#KS_zEZX02U&nk@x_+`f{S;^V{2dOX@_2;X$d)6(V(P||JJ{ZZ6N!-!bsZ~% zvkRMJ>TfTBxEP-Rp~|M=a7so+#LKF;&yVZZu+lpynGG{Ms->Kv-Vk1}UdCN@1h+W~ z_qadaqw*$v(zJ=-(zG$j_Jw5|@v?VPf>ZVBtJ^QG#f#=1Y(j3pJ=j~A-}*dzm*#w` z#ZZzgd!&N=Y3kQpt+R$=g09jGT*~KlC))2n`Fi`~Gt^9b9DSh!jGyw&_oPHduB^3s zr>)vd2Wy5Uj=>ZsuwaWTi2{cdDz*XJa$TeN4a^EAASR84DNW&dnF9z3vnc(u^8E)m zxD7YK)%EMEQFi***56SGxdy{N<3w3O1rFH*e$Pl|;)?_PS|mmFHmL5T24mAB`r2R& z5~mfSAmIo+U8Ya&^cNhmdoauI9l|DJBavBkMKU0$R6M+U{oe4g<2Jw(tOpedM{c%O z<|NChb_dM6{5HK`7Qp~nPFiMXo?T|HCzA;9J@c_+#7`v;AHEg$3w%Z5vuL;8(b+(W zVh_p2Ki?xbij|_`XAJzueZo~h@P{PFiwCbr$xUOOU3{;zw*K8-GL;|IYrpzaa0ATV z`p&TP12I*S?HCtYNj&HFh4rp4W(iId=MH~8{Wwdz9fRj*;0|H#PsR#MQ_c5O8NbebvC$dg?1B?y z4lk&~2*B!k^z@i~JN!-3Y3Os`EAy^mh8X{NBpL|>fa8r{_mJqdvKrt06*eBtZACLw ziz(f~ct&?S!W`kYW&jTB%}Mm6NgLe6#{)|~?|MXaWWq${Am*EKkF0?gDt1Y}Z$p$e zeS(G`i2#6w62b&4Fwx|Lghg=?Lfl!YR;HQ{?;ry4UH|q+h#uFU*pChoA|iX@#NYog z`~K$UUGt=XHF?^E(z?k)&NgtWS(!mKIuxE3n>VgFRBGlph~*pGX->z^D*6~&lG z%#?GOHP>TM=Bq0|3JCZnC7+I{LNpizXGC%9ox|By##*jt` zDX+NDZ2iRdJi97W!kYIaLh8#G%oyc-w?6K}LcaFp2aW-6yy8>FIWInlK>!SxGU3O` z0Swrf_UKl^%E3oYpn;#x?|j%=Hi9^;q^Hx1d)N2puYIesWc+)?|5ATu;hD6O8QH>p zm?C=bkW_2<&S2{suj_5B9#PuHg29kA3U+kAym?P{iNVB61rss}CqYU@9cC}t-e2(a zeC#~_m5JZqr`Mh%QK^6M488}c6-^H;ToIqi*QV&!VD=^}Onv=)+Xxe;FbnI+uxc}G z2H+JGk?z1)eQOW$6hm2UD1@^lnaJQT11q>1k39Ss7%@TCBF*1q>tJ?x{{XKuxSHb# zRfMK_Fa=5O#gF-|_BUvnxU=QsEPTAIW6O8~YS)X2`a9xxO-JFq-_! z?I)WL>c}=0w3;nKCw^k9m(Uv6B7!14Giz6sdT7}+PE zpYR4GIPE_sF|&Bk3JS>8e&K02dCr(0iq#PpljQbv^3w%b^N6R{R*oQa*YI4y`O$mx zorpxnd@(q$KR-iE=-ngQkC5jR-$m3E9;ZZohz->s>tF`}Wrn9&fvWoS~yP!Y)t+7dfOtaiG{{r#?X-nAFwj>vt6&RAjApbZC{tnx?$94` z3%B?2!zacSAs>0te#8owPtK;S+A3ZMzJzB}0-5iDP(iW^Csx3T^#$j?#Pn zR1Jks@Ybij_6><+v|Kt@+JwNNSjyu;(lu(W`0%ag~nGK*q}Osm%I^N%nxg4>)joMl<=rE53h zSEyEH&-FHZp%IEk+D94r^sXstz;roz8;EaCz5CT#?Vp3e+N&A!q6Gsvo2_doJz<<8 zt`Zz-g&sAU2m5t~XI@K2f*TPR3R~Vfj$wXJj=|i|@{m0Y`wze0dHCXE!sp{i!f=0_WPQ>kEOUOYop@x!QsJ8t$o6CB#n!B3cqHu${j^wKFje|Yok!?g;Y zsXl#ykojk4NIW$5#rhVkV7ySIlng4Pp!PaVvxw6AWxTTQ_BJE=+KoYok?B}7{ZP!? zLxy65k&-JcPIm{h>Cjj=tZ@J2&t)QP!kQsv@TJ3G(N%b zF#c|}wWsI%BFADFRxyIU^6T@XZ|_R*xE)0=p5OhvN#9frzh2#>R6{2qjD9p8GXx6u zb4gw@?>lu7KD*n%lQsDI=Y{P-s6w)e)O*7py{V}O$8`z{oEIYDE#1;rS)W6JV>-KJ zY-YDT!M>X+Inbdt@b1;#jdj%b{QmH>^-Q2}pIjC!aEa38hYyx1xWbMhv1dPK6Deo} zc?!j1MEr)$Y@aSCyaa75`KZW<=N?|&kQoXmLAmkD^aEqyqsoZS6d{10p3NbDTukoF z0zzJ~WR8hpNg|eyP#*qx{l)F+&o39J?!Vss1+lO<1>?+na5Ki|B056?wttbB+?!0S z-h-rMWFepK;$>1gsD|Ssu zrX;j77i|GAq`CLF@U-a`EUqxvNSY@_vKtA8k?_0qABMu9HINs<_-~9J%pf(Ix>P%V zac~y_veQQkHyh{OpQZ}n)J*NJq-%gQzChc6MhwY&S~9|0)2Cm)K4gW-?YpOU9)z}B zr35%n;blC>Fy#GKa7KpW7(Yp+hKPfwuV?DwYs1a*1=kJ4M~ot#GSq6kHnq5i_jaio z!ODS9V~FyI#GnHE5Kl(K6^2kjB&S~ zad%^SZ{s@{*;W(2#2YBb^0LnNI+0IH2aeeJ@iv>81NA+;B~8r*dX;(ply;KS^_0W% zp_&b;E@DD|e$Br)d()-Thy6oM3K&0c#LRyAc8AqDZ-GCec+mOV*$4J|o2_)r-|z_O z4JtB65~v1oU=x*4FeN;4){}&%r-=GVZ8fl5v3wt|T~nzV?*eDiQ1!+_MLr-{;$GfF zIT32$aKuC2rZj|)0Q&QjQ$)SLxdG!i-bKYQKVINQdU7QEP$Jq(Hya=KzvHd8#Sg+l zZI1N*x~cGvMIo@zg=0W-fA@6A3Lwm&H8pi@8a0;oR(NUOc+7n4mp9Hs}Um zj_Ayxd7za7F0~uT5$FBd-p$6`qXVn4f>WNZ9EGTDoHV!1XNqhTu>sPX%PP_9uWmwf zzkdg>nq|hPc;U-55@%rJY&`f3*YmUMbK9qz4-qK*7M0j|e_>vy5@>?2%Dl`7xB24- z*WXfp`(f?K5pL3l_a4k)GakY#b(>`oUL3GAB#e>#LljZmq^ybj?)A@GDc^oiLGl@R z=7TRTUzaRf-Ya$iiMXpiJmJe62hU|`qA&5v+Y^#yK><7#f>cwoc6eT@h*6U~2QnLM z80(ecxgXeUSylY_#Wz%sU&9UT?v6KP%qR_oT8(^^t|OY}5D!De@Kv~kR(Ida955hK z!lAu=G$Du0cMpG&DnM6&a-M5WD>jrhJa(b3h?F>pBay)5%am_ zJ{CSS^)b4Gsxkf6BIs`bg9Ahelvg5AG5`l=`8}z!g|e>IeZ1ww>UxZX6UpQCW_{+i zFiw1ua9-1d2IGl&gm=bP6=&8nwh7KBd>HUGZ`4t-wsxHXBbgvRw+$o9?XTP1UOdoZ zp4~#UtC6`Dj^Noem5CqzkT+@YuFH4q--AOK${^d)LIduKzq0%xJoLCRq%0(y!ZTY^ zUWo;$SgGe7vZIHpn_@Q5G47tPr^oUVy3jquQO>OWfV9lu)EX5HX1M*hR{lV~)~6i{ z^&reMx7-q_{iyYGbE$fBVdrc{O#HZUA3-|*x{e%u#OOe;YNEy{Xw=w3(?<(YP2$FT zC>6h2sAO}0eF@k1=GKrcH2%1FgF5ehlgje`Uh@+y$VaDiv+=Ri_WKoUW!@VgK#R2) zjhA=Qb%sg!^uVT<=Ax}871gZFLAU28V7thu2-4Z>= z-bm4hb%r}Viup)0i?1V4lVSyKqnHL95wJ-(cyWL$#ccRw0;1|?VeJ7j*x=81n9k1| z5+zG34qms9W)XIdO59)ub%|p$MR};cf1{9Nd=2Czcu4uzpc>{W(Weda?JbfJ zKFQ1l86tq6FC#g@b!H7QGi0kA@ZTHIt1qo32Ag&Iyb=}n{@ z?A@V#5!`GF&&P|7#wUn*HzAAFxQD|Yotn>g$tLLVVsr5fe?l(0jW?(GT+yx1AGYu+z36uC4-P{M4a<_j@PpS3 zD7TpKXL-9sUMga}S!l$OQ30?rqY(?Gz*-UAdN7S=aAxsv*G&enve1}Bp-JY1*u}-H zfEV*XX016X>yA^IMY@m#!}5yJTK9kr=d(9LEz(1d|k+R8pS`m z*}>(`SRb(tPN5k3>kCmoySG05Kp{U!9%N*Xpxz!dU}gS-__XjI~cFE%SOPJLF4PqzoRU!tz+$GJy0ZD7!R z-7uSQvwy_6Ydjoquz3$c+|O-##r9}tWyB3jH<{vN^IHd~uW@r8p%x2^w?2J^=^XEY zuE{Fi_g*|}K)Y%GV2srha8DS8K|b3sda!gkQaHe)S01C*rE^|O>Nx1gx{O6KULNpb7&Hq-gYPd+@CW(4f3J}!=0Y+e%|88 z%HnZ&;F00@c(LTk35pPI++jo(s-#O8>~2!VhbN^-Sjime)_aI3e%3{yb5z6|vH{*Z zJ$a9?qMxX6&AL*Lzpo!78sz0Fp7ehB9ZmuWTKEnTLj#M=bCY?3N8R^vk)ytbgod5I zY}`k%Qu#F{Rcizmvx2-DftUSQaE*blDS>AT-}nd~!!;xMY=43E>!2z_8iL7~5qk8J zO7)0X;;U(3o|YZ@@cPat)ObWlImLa%ZDO8K0a|5V{j4gBm#yEOzNH+7XpmuP8Ae*; z%3)}t+~M+U2u<4z1X&{;$x|>ZyH)~ZL!;+BdH&^TbZ@y!fu`A>@4%aW8y(=tj=;MT+u z+bWTGBlp1}qt`#1yWcQQlT>hj`OeM7+s$vhFKajFX3l;h)Si#}fG8;=A3PVISmfKNe(?A#HenSVd1f3jNK}$~!rD=a9cd5K z-NiNL!@a~Ud1vtieD&@eF1kg8*y7GXiqH86QDVq2bC@p-9g)HZKyV%|#F%1)`Jw2hVGQ2r=z4wFn1irLG zc)-8E*hl?slRQEWApsDk1PyG<2zvgxC;kC;!G&)gnHEnsVvEm@A6^5I$lE1z?f1eK zq|ie4b-+$2#eVNcSdWMw&_!07x8I1c2Rn(p=&>nT1fc)-&z?RsfjiWL<-J&3E!Uiu zht0r0#ioe>S-vEMX96i(>@`{t#_;Sojgu?*8;Ss3pS$z;*7?%zE-Fr*Jh-`ht8pt6 z(8xXKCBLPDT|fa_vJT2l;{AjGT3<&U1ZdmVgSU*dPD+j#8nP$f=A4Je@*Knd`c7HC zi;#BtHQh-fZ$qEOvj(?Ob&XGP-F`ebb&lu2?w<3g_J`hCmc8n{gQ0wC`ur4a@J1*_ z2Bb(mMoAkn-#@w0gO;**)|TC73RwSV=l<8@GsZAHG4Ooyn45zaWgg7o5#y;BU*%f@ zDV#r`2kH^?t3F}J`RalEflTWyeson(MgJ$fkxy=dhw2#i`l=?;|$nfriPK|7&NU_tqZS`8KS@=1+iNuq z6G<0pZ^_!L2aC8*Yr9j|;~EoK9!n)|luhO{B~nF$32Bh-;M0Hn`mxEF7VU<@->mVn z5aqsXC36LyT>QxD>%AASA-$cyxqScG9jy6jxhvO=&@4^Jud&>j4i_$xPv{vQX$u_Mbe4;jg_kReRN3yty1by3O6F7$=2GuCLIL z8r@ucuySy7dHKa%a~lkWI|*q#h_6qXU#Gv}$=MjIjD$x2mdPZR!bX3cp8eS0{@74NH0XB%1jzk^F~=r1ovKTl&98rH`fiL23PYP#Uy;C&vl?7Y6-gaMtT5 zLFu%0l7C#BNt%*sQ&T-N&*?%qsQ4rzpPm`lg zm%rah&dyIud;fMnTTNPL=Y0%x`|ZZoDN3GogLva9yRUQ)>@Q3I8(=D@r^!LkK2BQw zv))Oo|8wjh%jc)Z$v=Tt|9dBY2AoZ>7nJA2s2uSB=geQj%6z$84jNHY{`)!je?jSd zkn|5a?X%z;7Zcn|_eD16AUO<@?m^%NZTGtE)>+W*9S=^olSAz0_W;`^!wvsAX!iuT z(yTUudO55G{lfsKaS?6kWQOs~MrAu&!j8waD5xQ=Fo+sKh*k94f=~{KH8Zo;Z6BW> zB&)sd*#b`SxOLX)_U4}Ujt@$+tL0lk`**igo^PUaDVQDkz5Fh?xBKTb34_vZP#W{= z(#a}*zFOXI#Ac|~a;XsqrGM~a`Dy7zCn&i&R)UQHU~w(P6lXiP76VY?g4vLIR1Ip4 zzs!HPbCL|))UY>^bT>_-Ls^7Ht<-->}r&4QIu^Ff0_bS%Q1mw*EV;zx0c^5?XGQY-r6yH)T~tk z{ywf_^P2JKDa+t8Ojxd#rJZbagnwYd^MCn2H~+8}*9=Ix(aZy>N0AyNipve@993{^ zlUEYOO|xRnN}^`NY(rSDRC7S$a?Pw*0}|J&W*fqCJCK_8D-y={C3jEmHpCwUDb@@s~N@fr$VX~ zY<&%USazjcZgSp8Q8^1bgJ64SapleS)?>Gfu-q_><5~>LtXv@fbj&cU4-HzB{OjP! zoKe)Qfifq9G%BW@?|Jg`b1R7|aoK=GO;F}Ukf@4@q}x+)C2?5Boqz$tS_I0R2oi@l zT{TF(UXjktDmc<)j0QNDABNkbJi1ShTIfC$%iYLz@((;6X+a4w0SFFPBqhdpV ze>K5`F*TB5S)^)+>%F6X>-2l4O#$^ccorxzl~Kcp-#9wO6@2xR4={{*bC|&kA7I!d zw?gNr0sfT((&Qbe1c|ETy95cri6?_ZHQwe*kQjt4ox=(wi^(8yOu0l0(u}|o(YaC1 zBlk)n5bO04K*+zS}2~}*r<$)GY6&)>C2r! z;SUvL8=Kx?oXZaI;;e0`Sxu!3ejt;q=kfzwF8LJT4%?r@W?Q4D?+C(`EW3>F6I#lv zmZ<$f3kIOGe(NBifhyy$Ay`JpK5;ddXMh#khMGMM8(Dft1#;bD-etf3U2uvl(0%3 zqlJke6Pw;q4b(AtG0>E3!@nHa$PMDQEUGtf;GAUGgeH^&(}2{WUQJx7;*%E`aQGaU zxJo9X-LwiWL({v8l}uhtB_a0H;mI(Gzy1?3Ai1EEr(5OMi|#-JfnUb)FB~ zKorW;x$CglN;?fHgfWB^=^f*^a&`|Qp>3#v0l7v7CaTeVI8h^pcxxM~VCqrD!calT zfoX)cp#}!xZ_U6!amcgK#T8ic)MtaUw3}MV z6citd)WR5wWN$BuRKo~GvbPsSYGDjT3XBg$7KBkyWQw4t$R?aG6L@6oW+W8JhCURT z4yd9?LGhtTEsUW^_V%JkHH=UsdwWr&7RFGd!1z#PK^S-b1#ayW!BS+^XN-~1r3kJ% zLyu}yk?`8yz zaN^O#4QN4rDDK$vNHHZN3FyeiwWL_{8Dk`(BZ}ZX7Uo!n^%JDH);;U@4$j-d9{D;w zD{L4yb7LMFFl}Z77TnRW0zx+^Fka^9i*WnfhBEJhFgSJaMJ@(5_&nPSqDgE+6-)!x zH-UlCInVeKH9)26O@o1mz6Pu&#P^l6Y4EPthMLvDLS#?2nrnTlL|`Ce7gLNd>1xe} z(Gz!!j}+^r=^us}Q1|M2S13F6Kha1E&r;LJNGk0#+b2d+>Fr}ARl|spRC@auN%b%^ zk{TEfBdHojjHJ@r$4IJ%5hJPe_Aru8L{X5prOnhxT8wwo90hM<-H|smRmu_j+iV{990VBl57b;{Kswkpr42ve$U zsDfz<0{#f=xn^Z}aX1w;)W9IX4MGHaBN9E&u8i<2+t3rn9e$oHk;wtVZqr4m*saiG z6#)q{LB`$;k>i`w0|WuMIfbA!T)t=vu{O_UABtF;4qEV{N1!S8jJ+Y&=51~$VyzYi z*Dgf~!bAv4n(TovVyzYiVl6%!_6}=s_DzN{Vyzmc&V{gd6Pig5iiovdDDKz`kYYNn zCB=H7F@zLr5XnJ`^dEs^2rWKK&J1^a`sXYeY$nM8DoEQP0C)`{xUds6vOND{ScS_( z8hU<-;y`yWQ5jn*y`vgjIFt7`3gH0K!_?tIlipzyj3Wm|f>Z5Y6?Tio6~U zPKJrAV4~{PRKPGy?;3deWRyyT8({*9JAeX2nC^<62fMQ~ym z45D&uLoXP2_66uMJrF&6WK0I8$2;1()2;fl)JNuXCNDA{1RM(*j7LIyPGcy6%zEs;TWc#M0 zO17^Xwm3=FQ8+<*Bi|R4KN*JkzG@gy8VDNy2W=XX-DDWa_*KJz(m>FJL4GADf8uH+ z=T{F?uiL$7RzUcZQJD4XiQ+?z>6wd{C>z*PW5Z{R%sK>J5}~~=sUzP@Bn>^hMA?8v ztvd7)859pMks3z4MAF;GOQeUPmq>d1c!|_7;w3UL9$q3fjChHpw}+Q#EJ`uLq}ehX zMo-*Tgh?A#o987$PIkk`OC;_5ZWbefxz;u?h&fq_RP52l8+l7cV_l1$g3;#nAS5ykry0AWjHKR z!ijqaTi@jUg(1o|)a)GUvlShS^g6LM`1N`sjYzKc;%V>+~+8XMpiARJM(BnE1G-!RA# zyJ(a9%BEON-o8pvF=?nG#v1okV9L203&*r=sDVLUF?=zELBvkpr-g_I+fW75L{7KB z!0n&+X-R1@^`^x&>YQ8+T+4Z%R?JE^gvj1m|hW0V%g7^B$R%NV7FF~%tN_A*APVZ<0EFh0g8f0#nF zWYqt3a5X(v%5a?+dW30;wy5Q3Sa@U#y|nR2q0h!DN{39LHz*z{^lBJMp_kr1DfD_6 zrqD}opA>pE4Af(WHZs50BZXcKBPsOK+ara3JW6rG&c@LbHq$W7#fESUL)fD-DDy&K z*WfLd8wf@RgtRlG6)YvnY)*sXkr$$dk-QM;?UNUxhhbib^!CXMQNu`Hh=K9Q3n>bt zAjg!J^yG*bF?a8a3krO8L zU;vdTv_YG<4OK7=e2cQ0uz@`D$(jnH1Z_hN3=9d8g^6+l$Pn{r8){%GAr>I3spiIy zRU*WXjiCSqS*J9qCu>?+WVH-27A{-4BtD2G=I<4FD(P4%@j+00#0M>m5g*vwOMFnn zi1@(XUgCom#)uCB<0C$3VT|~|-ag{PSQG_er{m}eJ9Ud8mctVE81aFve8h)rG>!Nm zC_dtY7RHDV?Cm8!s9{8WU~ez+K?`HV2Z8Ys9}2=K$T3CGlOu~P8$OGaGs9;uiw|t% zBR-^q6=k$liVuR~BR*(hjQGIbUgCoqM#Km9_7WeoFyKXy3IxVSe9*%9Ii4b>!=(_G z9K*E0jn^PFW5HE#wX5{ruU@+M*~Z6gkd9T99K~!PC_eYT7RKEB?Co{$t6}8cXK$~2 zUkhXIeSz`0_q8zQ-e+&0dw&c{F*Yl7osMz^x@IDsk>1_4UmbJpvz5=apN*!u_65b~ z+SkIEYoEQnu6;F(T>I?pb?s|m%(X8tKG%LB7zH(^<6nUq8_2mHz4fb?Z+$lMx%Jb* zin3X`^##S}*4M(ATc5qXZhbY3-1_Y8b?a+k%&jjlKDWLW#_Pha2zN{&u0W5pqktai zPDQZ*h@m^rcSf##u(=8w#m!uUOoR3qJ6Pcm5J~7WC>{xYY8XlAliofFeR>!s^hs}@ zgg!NlB=i{=kAyxoj3o3)Z;yn&u_y{on-Y?qvhkvrD{Th5s3GhN_deX+(kgD`y1Sb= z&TO>8tQOjcLGgG@M-3yd=}2$PFV}F&=XCTid{0Mu`#h+lhCxi8Jdg%G&f`g)f-uF& zF$1^)IkJ+CVYEm$vGh1{^RsRb-a4d$_1C&R(#{CA1;tQCWE&KZh-@{CL}W{EpNMQd z3?s6ow@*a28b%_r4U9)bwi*UrFG~R)5!qu<6ohSwG7VVuvm2xt3(S3~f_pl`hFJuR z7CA3#yNm0=&f2rh#oagCE5Y{Go87g|l`IX0SBZ3tnJzv#*8*W58A4&P0!4}H1_qfb zdDX=b#1f|qDGtN5eOV1MymHHnl~MJ{?N?zKWDME800YS@Fo#pI%l70DK7^B=xrm(~0pue?&LI9r+FUy7MYLm#G?4p{V#7N*GFu@6(!!WgE=-d;>m4I@mEy}g*C z7RE3|f$?FAS{TC=+1rOHUPkeu?JRqWYE?#;SD;4Fp{Mry?wG&^f1g)F)$ukDry+XQjy+1St@E6$x@Nt9$6|AP!!Z{ zDKoqBi*atc3aY$dEOoo=>z&R~ci3*g;1_A0-KhVhdFgyC9px)Mn?AW<4&0=ZG(x7+)q$Weu# zv9(n;^hpYkhAN)RqyPiskrbeYk)#0W?UNLshhb8H^!7;#P{T-4fPwKy3Mc@h;E*XP zx%)q@gzrVu!XfD&u^bYWYEpU}QTQ3HT4h5Izmv36Q6r;O4T^`~Nev@@C+Y3uchbXf zyQH^|-$@N4ekTLt;dd$qqaa92Oc{SHPLMU`rWk@O<7Q3?awJEk3DzkMebP$Zh>A-a zX{83nBdt^oBWb15+b6A555u%l>FtwNs)muYQUl|WR$2(AI6-E^>p3J|JWMqtSjdGS z-zNRe;hzyH5-d_$day`0qJkj7A`OZMi&Vo1iplZL8`n_ za!-2ul-$$9u;iYB@hG|H3!|V%OG}sNv9$g?C=FV_@jfE{7Y2P)cIfq!pmf?okq7+T z{iIZyotfDSUg5_JK@@zRnYk4N4@)yM{K;;=)j3Z3CHv2X05T;0{xmu2bou+84zWAm zgN1+(_94J{=+8mBhYyqy2S}EKkDwOx4}<$b=_1q_)Tr)Fk-S+YML9*KGo-N>1j$3D)Zg1{s@A#lJyIQ^#w10O?<@qMk&Psemd+7J_ zyWrmLpVK4^O1nX6%&$u)tN8h9dA|{xp;pT!yz^4}2S1jdmR@v%lAEKAXG3xdxm2g) zL7x{Eu-iFF26Nju;x1q#H+_0{G5w+6UY`8LU)rhDKVYXGWm8YR22_edBp_Lx2s!yf z{B=Ytk~CbF#u%HppAIOA`*y_QH$GK#c8#D69n2}-w`W@8uP z4mi)GGfI5vbc+z*SiWm-jf!KtO_cXY*)D%MiR-4nvrM;=G2KeWboo=cFT_1>;!PRf zXVk2f&9^J-Td!7vSKC`ls8YGM`ONJF+#PVUG4`~A8C~+qr{fB-v)$O8wUv4={wD=t z2^w|=v5$GbECmr_*Mfl9;b|ub3+zl@Nkn4Tf`Hgzzyk=pY-6Ge(v=9YYe7Klu-^fM zb&n=5M2LMNhTHo*Vo#@Q9Q;6(({;pN@fjogVBp{9>)JBJU)=j_H{QFS4#%g;(&04D zeZd&(+fOm%p)xIqxc1q3yk|cJk!Q-(Aav}r^LW302Es?mv>@Wv7m%@D{S-u=DAR(7 zQ=gs3`t(x_d7$hvMlnjHhbbLHPtA3dDl*iJgmH)sJ4x%f(>)6CR!%E`Vsp?r>YTNX zq0KzyX)n`QD+9(#|EElC$E^p~O(ByyoYcJ`q^H3;dCoqgy}3nKIw4Rh$IV(exx3mSG(+G?-UYLedL zgPKy5u!191!$?q*^d2A7l)^+vU%3JdgPIJ?*r28irU9$8dNmT%B)!K6HKj0Mz%+oF zqb__l64WHU#|AZ}DB!>oDWEuUXVZ1mUF?}>u}<;*X3Jrr%Zp`zm;8u33cfyh=Xrck zQ@T1<^pSQNMkGN^24!qeQ;H%%O==hkYLedLgPKwpspzAJVNjFw9v{?{!7%4X4I@EK z24-wfQwk#$ebg{{3RDVVOjW=z0^=1(5(#T&4Ag_mD00*tCH7J_^fH*HBNn~q#bPQj zJ|W}s1c25d%Hb_?@YX%f~QT` zd%VX!g^A11J=HMcu{SVdJ@y$)4Vk{hU=#$I?$#9u5=A8qe=NHjn_AJxjZOCmn~l%$ zOxMgDPidzkN0?R(%Geyw6eXLlDOkv_0^w@%{QP5+$U5*~Tp7>5@DIz2iMeTi!a~A$cdK|s4r4Te^ zJh<$~7J^PkL`Vy^HyyGdu}C3k12eV|bOs~U=e00W2wGsq7lKY<98pC8jK($%{RvP9?e`@k+K+XG~1|tCfvl_08te?%LL7nj75Y z(}Qdo*CAw1_ITm(fZ-tvvqwz9z?4z2HV3ATLgv}b3&KP(9*~vZi1Ntu-$gKp=wToj z+P%O-6M3Fnyme@ot@(`cI8lUA7mD4>_ikWVGv)lpKHbdSN;JWGWQ* zDD%nu{^FpNh8`ZuY`}t4A}%6>;^CuI!-$hedi!{Z^e}W2NpBxNks3xEMFz&hQ>2Cw zSCRDg@D+_g@uBUEEa|Mw2GP@YRL+Vr;8TPsIyV1Unt7P&-Ef6fTQSv3Zy!^=8b(a@ z(%Z*WuZJOXH838gdNqug>ZP}jsa_2urh4h^VXB{iQk=T8fppX@F?=BuPjj%=!By_l(jHSZ}&j_Fz4XWrd!hG^#VRf?&a~69svTok3K5T&N z3k)6<$aVQQ@npF))WAelgvcA15N9)aH4)3Vs$pXEG`+(L2yHS9jIXw#W;JmW!TvJI z2ELjclqSBpzbwWbL;*5PNyw3**PEfK#31Z2#@igS^fLV2LWYcEzRV2yU9&BGV0qs) zxTbBW*-uzN@x2lT0ke4@Hn^s3sDXjZ2aYW;5r}#6xxu?>8){(Ukb%mCfr6dK+7UWy z8>(RH451-RGtT4e2sE|r{(_>QM54>6SD?fS%z z-(xWfLQD_h3WQjPbSN}a#x>})=Ki14v$6CDhY&AJs4Tdha~3T@meNo|kH&IC80=dv zp)kl&4=<0|z*Eez6OA?~twEjMQsv$5?i?U{lE)7cgx!PIv| zFC;1sr#cF5K+xdJl@GzQmCcpyMLHsb#m(hl<^9t0#m#3cZi*29a51wdBsj3C_(IZY ziXal4gD5QALxO`SDlioDC&NUP;M6dX;GlC629YFwbt9E0KrDUY@@ zvZSLh8{`VK4TCgk8x|W@V&{##vlzTg{shmGZqi4UlZ?beYRfS@_-M=0@Dk5=s_~fr zx(yI*S$g|u%W4?WmJN)DwycH`ZCQHzXv=ySYRl5wLtFMjamP`B9xW}UF+!1o*H&N@ zHuQ*)7}Dc%=kTzT%so$zk5R2A_zBW%9rcssBh}tBK zkD#cBp`a+eeFQ}{OiV%1z<3CXY8Vj|rMHKmI3C3va{*GcWOOA`tRhy*vc{Yk3WU|y zC)99H*)`K0rJaWAB!)tI`)J~77}3O~w~r>ShoL5JU_3N&HH>KD(%VN9SHp-VF1b8`rrEWS6;~G3kLXKtgYRmS%z3~}E0RbQ@U_j@!H1}~{XX6%?ZRxz0-agK2 zHHqy7KyqI(Wo4#d?=iiPy?Mr+S5nmNH_sIZ~hPms#V7qe5mkc23 z?UMndhLH>)1LKhaq=u0UAnEOs0i=gv29Wgj$N=&|ai>v$Fyp;Om`hqY`1rt>aEyCnXT3lY)aZ{l^tI7r*_AF_q;)JwkNpBx}mL7)oEa~lI z&r-vPJ|# zD5x=|Bpt66YQ(o;sFB`8BPx>`FV?O_20)cfeKG)~p^D)$UtW6qWB{mPBm=;}cw_*m zVI%`Udi!Jm=wX-vAiX^@0K8BXl$cV{6)3R=c4+ycQ`$(0+juD%uM)dSNis^6ZM{e_ z9keKK6jEewFH+RP7*Z4%A5zr97*b?!FH%&)2r06+4=MVfxKqzlt}Y0m>9AKI#X73D z8d5~AwPA|!#XDN+c~{xer=GVoRPn?bKW~BYsOPPQk$T?J8`X&NY8`-LaTTN+RPeKs zdfw98r=GVShV{G+j7L3hZx{tNrW@s`(W`uNO44#gH%wF(Yb(iXFc27p8ZUB2dOxdd z>|w~t{}4@1MM^!6~UdY~vMF{Pp_P$Emm z2+i1%HjWZ6NQ**7WI9iIlXdvbPr@YGDi^3XBgSYGDi^vbPr@s$ql>+1rN@ z|Bj*{#B@+SA)+LoOCEtTZ7%5dmoI2El9q8jw}c;F?6M72{ICWGo`EUn*6<7K@X}^8 zFG%eXim;pBc*G#jXAOIzZKzpITt+a0OfsxN=gV=8hmd^KtAU#)v@m77ZkPkpK!&d` zOmSk&M!o_uqB56LT$~Cm#CYj`MnFi7jeP<_q@m^nQCSx|Mi`%f5H*Yhgcul)fDko| z1cXR$pMVfO3w?{z8-%%8Vm=e(iLM*L64@!d;9+yt=zcA=S9q#p$pmf?gO89g4 zlTvARW@ayVg&!{jaqxL&=2j3qEX~aDC%gSt=Q!z?>^~9KA5`%7r^!*L%il}JQ)%zt z?q{n>>+HObfo{Lu*g9n~h#=m0%I+)O1N+O;{|1=K>1lEhw2u?0=)IFx|L532md{U* zlYauQ{^x_Ff6!^41>ZQi;9j~;S?ob_h^Mv>f|Eak4zWAm zk+cxbmm#DM|2b&)a8Dp?uLUw zl)=%;Kr=II-S+YML9*KGo-N>1j!{yh+namZJ3c7Qu9j~F?cd!}dAZvK2T4D%oQ?d92D{H2{cl^i?wD4Y9;>Vqc{th|ZGScb0o zi}EHIE1UZ8)pW>$_ph*3cJ|?_S`cBX0^-3_wIIS$+1ZDqszJz5+1Z1i{uRT6T31uL zG4I3xSuRhySC&u1dqKTmI}S%a&Dz9lrdv0yJZ6fDIfAC z_$E5TGL)A9B$gp92BnKd{3*{w%!IEiKtPzdk8U#%NDbq$dx%?SldGlR~JBvIM zWqQgcpUEABBhF%_-zEG5oLqL`Z_yuU=M((lhAT)KQkSes44=>sC5VaqKxePO4=sqq zeW0^f*oP9tM12s%C+I^7Vq!kf*(c=V5{3^okFr`G{|KusPR%t~oG}CgnZatn__mW% zNOCCjBz4Gw-eJ(CJlZ-Ay5}d~l73biq6%{-yQ5-Zo>Gi@ho+r|Z6MSNiW@*seKAiZ z#v>7?oeHFZ1YClI5`H-`BpvQ3(@p~t!yj!x`2I?c)?I_E*Pe=RnEWyI{XH z?YtScJCHoda`Y}v*Py4sCd6WyAs=y|4zjs#-dJ<9AqBFL2L+~M6%{K66n{HB|qrC z`qe--#cLVd+OPrPE(fLw(NMiI=<#FH@3~1KrwE@p+xoa0rJ?`IGjc)kLfmHpp!-%_4di%H=)iC02l-@q> zMm-GOjRwZU-RKMBPQCy+T2jj5$BT=I2(EBCPZ`O}!{ivP{B!Ci6_#mCV_TGe%=-}G z{I(5MRceIp0a8n&SZCPKwF0|S>v9xq0;hHa>UiOUGQm(_$dR=b+Wi{lV7 zwL6KzH%nYc;Jx(bb(w?GfKk*F#hrTrVzh*GC1Q+SHQ5lin5D&o12-8yj)1B#P*<9{ zcTR&>PC8UkX^{n$42p*pQVkG~N|b9aK@zxas5znt-3<(iEanm%BnJIz@M(gM z_y!>)yF7x!vre|5W;O7@0zqJ4w#Yde1l-z&8W=nbVNbT2`yLufCyb*21yyrNGSe$i zwRIz~fHOiQ4Oy@6eD54)gpFE3_#HH}2J$&_2piQRq@8B-Lb{?1iia;s4I|Dd>Fwi< z(!>~ASgbz2Q7@TJ+QZz?LiGA zwg>k1vOQ>FjO{^Sd~6R|7-M^2Zy(#kWfTQfr-SIJ8gI>6kvKFl&v3wQ^bUsgG*$7nZiXg)j_0xI^vX>agLlj}G{Y4PNvXkqV_?GEbTLE^+lCq#1n}`y zCafl^;5C`aiXtMRZ9^4I6Z)vYz^|OAk0PquHq^kxH7KM8rkoobiO_S~&=W>Mj42^G zVl4JVDD&VWM7|kf3{iq0CC0UGD#ETH8>wny3l)pTOY3_B=l!BJ^!T4NP2v`_I6H ze0qH1Y7nDu8~VbybMcoxWgas86{ryb43;&fO8&EUCVk=-hY#ILsgicSt0gJA6^oC+ zpm-=%Y8X+fq_>Y!rH7$XCB1!=Dm9EKRR+dGsZzs;QYF1Tl&Wzk?vM+RbxM*~AZzj( z&?1djaB>(fyL6I<70{zA{K!MAl6E?}hE`=zJhUn`jA&KT+efR?!%(Y|-acBD8b-7# z1LL7psbNH`lHML#)ff~7SzD4!;}l|r?2u-u@X9t+Jsi9xWG#tIe-BiEL&<7r1#fi8 zmXh8+=~8MKL)M(67g=jp6A4+fw-;G!VGLOdj1O6BVGLQbw+~rgMp2M;I>;5cbq)S* z!>!BE)(u@RcaAz|X@*pT;vJjCja>1rN$JiGr*Jh;x)T)ErJgL^L3XwcHTOb<5-J7; z53%M6_z>`HLlsN|+NrEY4AzrZgJ&*mLk$eXcHE`hG{jEj3HV6cw+%Hg1>}eH_^&{b zb@<(7nxT1K9OkR1L*z(jL&P>7&IW0xS+bFf1;s}$PN!UupBuTDy}jgOHH^r`?Cm8N zYhjFBEHFNDu@=V2#q8}P7mqm@a@c7e7;^x#u zI77siaUIdOlNm=yBd;`6k$0^M>yyBg>v?7>m^y7k4Gc<9!1_cO1nT6OsUlpS`qiLn zJU$@8gmq}rlQ%6cQ$J)w&1&Kr&3Xb;&P{7WkptV%3&tIN0XCa1p%6KyH3V2G0v<2x z`-)(R1UYW3Y;0|R2sRcs*IvC@U)){W+H^BRSS1QXumkc_^U5CJq4@If$i-~5hz~>s z7Q%piKn9ptT>(iwcvL!DKtUK1iS$NRHe`UwFb!CW)i5zh-oWrPm<$8?)GphLT*Q)? zS#T=+fCYx%^kfu#VRqG*QQSG_QD90uQh*}c6-R-^o@HbOikN9jGMT@Wppb?h)`D!n zg4eL9RR+bwTA+pzwMu&Xs8xCxs#Vh4N3BxBh+1V}Jk%;RjHp%8+e57ygW^Nmqbac2 zAXlL67%|GAZ5qLF8GyZxEh`YSnMYj#X?OX%wX9&wf846Uxxs{p;!{~b4I`xmq_H=yQDK8+sed-ISVWhx-^!BJQFagD#a~|iuK;4!yGh0|O&P_jB%nIIy zx+xiey0`aFk`vU^bMv9iKw5d&4BTisn}I>`uoEsfZL#W#LKE-Bwki} z`^3xYVHhtfy?x?k)i4q-YhXO$WsAbN^DjV;mX@wWkBoe>^k}pzVUX?23bczy(; z``_yiNIM-pqW*wE@u)wbhLQRM(i?JjUN}PpwZY6svl^*CATU1l2h^*P`U3{Wqy9ia z7zH_6QYuJ}sk$b*egjgVY`M)w++A6EzPYx9!jNm5t6SR}quPE2mT_cDy89VeqWq<6%~j>(#<f<3Y{lT@c2o`h@XP^|h-J52{SkOV!uH7*(IWeacR% zH_fQ}gz-`JFE7RsQh~cZ9Yjyt73M!11_(9=+Ft4Rd;Ng5w^J7?Nn6@^koM4c#q63w z+6KkLilv4T(w5#nq^*ac6-#>ikhU5|NZY`8Sh3VFLfX>XgS5w>6esO$kSmZjN~Ksa zmZgcPR_!dVyxHCgmRo17Q4&YNX;eIBhqww|YqAptdG)rTMrsHfF#QWm)Ig|p4onlm zwKUYgL{*sn4Ges=IWSm^ZK#2XLzw;r2C`IM)B_|j+fW75fbCyk8VClSyk~I}`odrL zOhJp5jxrgx_@lR#7{P?Hc+@2_8vgd;=JM9Y{?6|9o26YhE5sb4R4W_90h8wpM5R01 zP_w1b@0$h&?z7yq{W7w~v&k2gBWj2zlHO4nhKnN@`>0`@w+%IChBpuJu@XU|Tqf@(jPtgk1}3T@Ldn3CQFkK;rjC*z z(oh3~50=&Yv6>J%P7VydYTHl+(}cZRVCr;aPs||zZ?Nsgqqws!K!RMG40Z()qK{)+r{0L5gHW7l9(f5@XT2#Jn0~gbljrssSJaT^p5I~f+z21#OH1FFg4UK zGB9PtqvXKU;S5*9#L&%6?~qoL$uKcrc2L8BfbrRL%WJ3#KN$rQoNYIb1{D;Tp7Iqa zu!c|uLxJ!q4pHFN?$!wXfhPqOHbzib9;-(pmTfq0kz+iY@*}tSunAL@z(jSLswRHV zaCO**8W^ZkxWl;`&~ff%Uq=N)X{dpTQR2t+M&fSXWsi^BHdMhhVXBfz)@iAlxM!6z z0!s20<4&Of6HLj+kzn!1Y%6t$AXqnC>*b0l+}r!h&-Y&~ZZB@^xGBjS-_jBW+Psep zY70IxJ7jSWB;WX!-ac=9t6}7gZv*4;#N) zbh}h?(vDk zgqkO9W4?Pi`Orcni<^d;Lkk;F^8_YpBMY^;Jhu@ucSC>}vTY8VLulHNW+KzbMk0ZDJ4ARsl21OXWs zk079;FbZl+Dd`H-2v3<|t0^^BE>R=f_)udymWmn$#fKWTFoqi0+lw02FhY&&?M01R z7((qkjK_00Y8ZJAM|%4_hogp( z=WwLA&vQ6>7(Rz1y*-}8@kDW4q5vhPRCEPOtieTYDA8orfD+$dB1L3>2cTPcS8CAs zCaY=)v9%3#q=?W3fkByyJhum;SZqTL4C1b!VsJH41Z{lsYQR2iLk$cZ%&6l^n6L)h z!ep43(v~z-!PF7EAibOLhv%R);7#{IQP5#ZLsy`~dYT@NtI=@8_!1qK5x`JoOCRI5 zG}LTqNaMEj_Azd&VZ^v?U_6Z5Y8WwYOK%_JwjPGYZRzb{-1b6I5MoM1IznWYc-0!n z>F&cnL5WMf?qTN$Z@DvgJUDIjTPMlc@Qdz@Hj{2~B{!G}*`2nbiYl96B?5yAF?nA) zstnkM8knexv;+f#_kwa53Th_Uh8mbS!gEFfgBlKbydIHawxJ5932%$QG+-v4%pH*v zZQD&mQIO*$UrVvK6NMaEt{8J7IhwZWeK*8MVi9VCqP{Qp4c=(W>c1|}{;XOu}I zWh2*}h~O3dYEXu|Y+=f|Mb1(8-!}AFje;O8Fi--&$nyE=aq>^#)&G2u^bb1iv)~&i7u-wNDT_Tw4uhnNPwWp0d7PgH?OwOtI>UdC z2dCS~A$I3`un>gvWw?ol{~WY?5X%|+05uJ-C)9%eVQ@bvT|^t&>0vyx@NB0_3n<|Y zF{#D?0ep9i9PYOTp&SrvW@fG1K0ZH4R(svE1)K^5uuiu(_q2C>P?}vW-wN8lyQT7c z6JGODFgx;l`CV|27iAcfc7xKGUzbi+@$=R4ej_$Rt(HqLQkVY0kL9PO7oDKw<|uV1 zP~`_-5_FU7O{^SI;KBlSQT}f*w~Zt20yc8fZ-8TA`a{3HJo$^iv{Ps9t(|(5O?@OI z7uf@j!NPWfnd5|$e$s6ZB`xA^Vzao3>uNI3YalHTc{ss+WGK0C+9n!hiWW%*_j}GczZGkZ1kp` z1_WW}=0Iz?5&e~jYyfk)h~Xxi^8sX08%T;k#)lil2@Hzr+}I462;Zy+HJjR+$8Iil zkTPtTKBUZM7nkJDVcdTm1QIDwVwV^mq^t!IQf6l#QdWbIl-b#bl(is2$^zm+%32U1 zWp?%;<#8D9Z2d_&9Ys&dOuz#HLiDXbY$s>lS#%Sr;WZ!r9+{1KdPAK>BFr$wSu*n{ z+1V$3QVqiFNp|*0p45WCVt{A{f_S7(YC$A(lAV1LC$%7wH_6T(X_FH%91Zysb2^kG z=BUsZaBe^*l)^J0W`sbJn3p?;hn-~Zd2)OVdB=^%s>f{VQ}oylS)8z0A5}m+N*-%L zq~b9<`xHD@gRp7^JNuM7)`Cd2V*&9fcI*w}4&0vz)1mc5ScRe1a8#Iw3=u-VI|~+% zk9z&i+4qwndjcI=Xzu0DGQ$=pL~&=KvzIqZ31XaC1o81@DM5@Y3!S|@Sy~WrWTCT< zAIk%yI0;(%$?ONk`CtunW#m(Y(~=FYq^WAW)A?(UJ3Sqxu$2~fIy?K^>1q((>Fn%t zr)xpvP8Sf5J6#JRcRD-!-04~nxzpL%<4&K5QJj|3q4eyu4mH`ZQvqa zxupBO1p@+&w4GG-LevG!IOyWzjI~1-XQ}kXva^pXRtqAYSOM{H#A-pr56jLzZdf%4 zy|C=;;e^e_C{BOra7E~EtijBh`zp>})`UYjwU_ailgwr5@2s_qBJ-)t`NwS-`4duwNBZhK{QWqW0FX~k_0UMqm8 z#t~333zoFW6$tU@&=6EXCLc9uBO?q7X2F;?8K!~6xokxRVNfs?X%wIc^6Mo@_! z1_iV1UQ~0Rf~erl=W!@*^YaAF^oWfWDm`OInzqiN&P`DLo0|Y09On|qjNkut6WsH6 z6Xcxj1&%S|1Ni^XM?lsAH-4Zz5Haaak#FUKJ7w6VVcOaG+Rwnp7<*y6ja$Mp=+vRnggsfsprd`*np1xU z?asy*BR@BrfsKywb1Rl05DH?++UD-|*76(S&1Ne~j8>@Pf17BDun2INM$qrWt3^^W z-lZ+LuFSttdVrGoMfVe2H2Y!fZj7jezo+xT-_!Z<8Av1YBRUMzdG{U8w9X)~CG;M< z)A6U`A#V?8xauyxD>#a(+0|Fgu0H-WT}Fs1Rd!#Q;){j28h}_!D`@xsoSyZL`mNLN zh)4)xB8vl`5-tv?@F;({0+r1&%P%C+=D^yFgV~_gRSFW z&^hXgV{~vgIAC=__@X#AiMiEHUq#N@t<}+a<3(Jz|MFhv;QaKo*N3O@C}{PQ)*$#a z`)Xx_Fg?!nZqNrz?`|Ft%dbW}lIEC)erx5F zdUja#?6CM#IV@a+xR|q5!*z?jPsFtyG;-I@=A-Coe@z$4u| zIfcjdTj#iQ_9yrk3@AbJPiG)IJLnyr{R`WBw-Bg^Sa_hs(iuqZ0-d#6$H#LH_c$@2 zpu^>zwVOD|D2nk92wwPG#S!7W`_ck*?)_^JbbH;oH#_v{cMg*7*#Hfpsr+=5SbWA6 zBNTF%P@f8$eRAIZPMRipkA4_#U+`ssL*s)u{uA`N_~X;;adLzS{`qt(X#IxX)cS_? z!8y+{-t44teK~YbhLlRM2Seh*SO$tzJ{Pu{A+{%g5G6*_saaM z0(lg_+cN)RNi_UxoBzU^k$S*?O5sK9fcfR(CVz`j5x&X#;lWVD;MOuBY)fefAIA{H zP+N;JJk_-4(&z+4&Q7PZz+e7_gJ;x^3@}KKe0~L66V4k^7_*)Yf?Mx6*+x|kR`!GE zY*s1CEqwlF>yp;!Y{i-wA|ilYF<92n?f|`!_BZy9J?P1=fM92?Bw`e}4jBF9Oe(>33Ee(2lGP1_W2r0?Fv1_n2n_3@p_)7Mf zfHgyvv!97G&d6tCz7o4_;J#kvys~>5GT7vCqj3Ze;iAJ0iN>EJfAzPoKfN)bp|Zk| z`TDaR?i^qEzRdyKMIOlskDc4G9M#|8v(+~YUl!(*!P~DXC57~;FY<_SU&&-jxB!5E z+69gKO7L6vX>jof=Bgrx0eMrQh|cmvhC+1CC`zuRI@AqwB{^<3veP}`7ume!RI+*h zWaC;MjnuT?Q*GiGoBKW0Bs9*lHfvV7YZ!VsWxZg8QI9@)l{RfX455^ zgTcpSgv*l=N*g0jWHXa*8UGwU3h(PjSa1U|5ynVivOEWgXz2(LhRP(W`ayCAtz;ky z;M!sEr*}^E8Jho)Ds?wN3~~$lJau|1E=C)3ni$lX!CBHenCHseUD8AZ6U{JJze}h+ z$^(@4E&>aL;|4;1?hdru=(EKN>3^t0}#2Ihw?C!>4JBnK6atWCt zV3WbyjmM>X!@mgjs*QQ_Py7F$gS|QViTP9hDu3V?OmKtwSHFbj)Y{WHb2} zXJLcH`M25CFpYF>ARYvkwRczyO&J4cQ|O;3jC4lWG6I^1r)lgFjB~D5QI^`Q<5}Y= zreEju@xLnmHy86S5&o!D@WaYj5RnYU^hnbhZ&L4jr3>xoloKL-b z7hmi5AC%Gg-JSL6*IS+0L3mhZ=XZDC-DyTopA2gK20FjH+k0{M@b$|<<9?5w@1EO# zR_}b4-`d8f+f$~q9V}@r;MaH79n{S!{1eD_B45y%^K#QIv)t1Tts zKzN+P|KmBL!M{r!DaJVX$JlXrs>UixYTK_i4Bg=GC6KN$!phIZ09Aor2m6bNvmhK1 zBjRB86VmBFm0^vBLS2YC;aRy%m!ckkL+i~#98CQz;STKCQ90wScBh5pZTjMuNr17 zq$LbMbu`f;TxtOB4(1Y|rrurrQQ;p|nq~vk?!hwoXZyU59D+00wYoi#D2g38vo8%3 zr_mV`?400YIl+hsDu7Mwd*|qT(w~!bogs^|*zr2T=EoT)&HigPzYdE2Pi=l3P6>NK zfo`xiga8c@vuxxLJ)6Bo2^#EdcsGawSj}TnxI2awV;-MdHs8RU{Wr~sI1*M3DQ1JE zI1n{(ciICm1r+hc85=7E10*eRTufTRJa{aMO_ho;|DjDqqff^FkO4(x7=6k3I<}s?ea4{)2v#?Nu>;dVf_& zTx7nvf#7$K|c*;iuUKD5WM}1{`|-l!q9V-RtB4 z60VU?^ZBzl|5EQ5UN1=T>jB2@@PO9YhMj1oCpP!(&z$qPf#wJ8e#dyytaHK%$JSqWH-Kxh1xiC~cDsW~ z28PAbJtyKnBzd2`$xK_Eb`!26oEpi_9Gm!IL_e^;KdK7OWk}Kk&GqoJe&F0CbUL98 zcze?C!b$kAUjHWrT<2tQYsA{YoN(vZ#ePc;=7UvyFo);HnCJb)aKk~m&XsIuZj~Sh zJ8?d4UmbC#iV?Js!TIr-EdJB%zYzV-o66j5VA+G-dA|*xQSTt}BEpf4b`N%OqfIW~ znmC&AC4k}%fQi%PR>SLgfXxLl9=1;4y=(Q2BW;N!1Q+hf3Ga7aAKzL7cyotbSbsnw z$7kPr=SSZ`C}uk_^v`bZU&qM-WQ2|w>5FZ1_M(?b+T!{3lV9f@d^d`1s3N|?(VM7% zqn`=C!4ACAm^RL@Cp(hrfPqzf2a}b-Oc-9xEXbsm8VV>F4sLYlwV}67!FpsCc6d)7 zlOC_U3YP&eaT}k%O>W~d(nnP3%(T?!wRNLQV8Lfu0?I28VH-q{y26W{teLVMkR)m9 zJ8nC6&1=m0)}_7gl?BL+Q4zWj6O~oC5wlf{>?A+yHoj|L8D6m@mc}&XZQ@v#F9mEU zR%Hj}s!U2ou~l6T8c{4PHWE1`FY|oIN*7fCdN7xO8zK#w%8p`X>8Mu6%3s)pAQ(n6 zBz77D31;{-n`KFPsiuZ%SU5xut&E^6(BbgFGA_6wE_|48+AKzZn@7|q@_&ehRAj*> zB@BnxK@0b?$PX>?!FY3dGnXpVW6UL^;7h0H$reX=7JPS3aE6SFB~oxs9+rns#R@G<(%!x{>J^%nT*myTu?S+#)X+TE zE%OpXh0GwWOn}PIa$Umwm3&)6Zj2LpGDp-qKmdTj&!CsgQUSM@10qiF{%Hi#R z2GCE==6GlPZ98a>gw+6c(&9UU!r^Wbu;*bCCs4od+JIJABWQ=fMFQsm^oBE7P>vIs z6GTK)d(=zj9N9d+L}g@Y2|}CQWW+OWL>qIASZQPDVHU4;x^H zuOHYg$CrwC+LYAIZ$KNeBNQdvDtu)v@IJ zzW1kCci)&eY#(6vbGP=)nb<-ITVsqklJJc0u!Cr%26`;inr;cq+_>NU{xY*FYpqrT zRjXy}Il-9|+qML?va+(W^5LJExX7e>6$tgYOVzlpgvnzKfw}X}ge*dv7c^2TVqkHc zT`C*SFW*dG%8f_J&H>R&h|#?m(?u^yRmMQ9oy9brMrLGojg+u2A%$kYa80AtlIug6 zN=!lH|1o5(VxP0)jZbYT0~*5O@PCvmr zk3zZ~#5B$gEDOK6X_(Z15sF17sU%>Mibdq7W)euJQ>Ns_yJMKY^Bt4F>AGYCoQsKS<_ zFb*Yb;NHvY*Q@P!(d$Sp%nsp&aPnHzaL0fJ61ztaFA1HH^A5F5OKLgju!y#nOVqeO zNj7q}nK(&65#KgMm^+r0EfB86Fe%CCNm#PZu#5RGFaLHr|CKX-%R@cC_@%{ZcPF}Z zBr+Bhm+w>lW?(fL7`bE;r8=LY7OC1nXznUsr`Kd6mguMta?><)bt>^H;=1y(t}Xzq z-IE>!`m~1RM+)^%&(2saFVgSlpy_ckEylf$*}lhDv&%QLi|U8zr2;Xt?}x4?l~#Hd z9sC+LdxFS3U9i_fNyBA@W18g2lyY0p8izeu-mms3(&C|Bv{-J8qPElMT8#EF-5sW@ zH>78Zj@FO`#37Zoq2+oWJfO?ig9qgcNo~6>M5UT=?b(xqll_O)4+l>k9%>QO=MJIy zTre>+n&c*O0Oq`$5z%_bHOF|(%7OT4h;E{VX%rSSOitclhri~5kYrpfA$+%bdA>OP zMRS^a^-Q4VG-<^uZ*mTwTs6}BN7`+m5{*%&8&BRrDT_Pw)rP+KDQfwA6{L+aN|&yDb+S$?yCESJp`oQtS z{(DK&iu+kd?FU4c5bjZ6mK+dxUbrPA2!iCY?%uuC)d$>I{FgUi2+i0uFLtp+!@^DS z5W-)VP(yit?kd%cWvuW>hU1ZE_h08&jVU$&&I7ng+D#Z|U45$|W6|wb(koZg`rYa; zMUt#na%gxiF~C*hN+4QRjd|ghAN0k@S=hI}gKJ7W$~A9E)onV)4w9EviBS8jB*L0L z3t$oUXfU(KJS8;c$=Q>WBg_H>5%YeQLW<7f$>HJS9}Z5c#|L}+PmcGi-S3X}_kY}f za#D4NlmdfC1Ajy8M8=+!e^uIfsMZQM14+L8umtyaMPlU?sKmeAKfb?vUtZk1@`=Gc z`A(sj$@XY4Vjq%b{9Ktlbf&XNz^-YH;AsSw+^-Q?fvXThQE~H9f=q_uoKW67B27|| ze8sOT1uZgLUebG;JNx|3>iXq>U{{Jt6~%`xJ)7%OBramW6IA28L{pP&=>(xX z?${Fw0(N#mURQ8(pz(g6LYfg8%=h2OQJB)WnLytBXD1IY7KUE zNN1lc6low_3rwTjn@95l=ZK*VL;_1B(Pd-vSZ$o@q#9Uh> zPV3@N7ngvfyAS#{91WQQg3PX#=y*01maVU`KaR(M<@h=gSp^S33 zyJvPV1QX(0z(!)qRy-3Ktth1cP>Dhl;)K>kL&azDo*7t7zgh@Bj_vTb3@gWzjzZB! z9QwB72k{q*L`*5}TMSIDoyB&;nsp^-xKU*LlC}n~l-Vokg`j8Qi1KAca1Ldo3Zi;y zm^1O(7{G7}l!;I)XEZ-I>rxeGIl0mW!x(JTruPC@()BCdJ{BK9v;mU@9gJ0J8j#Zv zM1~lfX9VMx^OsyzG}+o#OzCXcOqrpp>_sAiR+EwATw(Nt$gU|jv2u}D-c=3E;Wq3> zICHtSpp#Zim&;@iQ5WyZR#A$>Dq>-%lYX+WgJ0uX{Q}CbHnB@~H9bZA&-D7K7|Gu| zpTC`7shAKZssJ-&iHE~-Cx zFSmZiom>l-)Ibj(#d?(CCB${MWYD8c-HI%*A2e-n&U#te+I@1-dp=a8Yccc32R|O1 z>`I@`oV3VJOTs`MVpq9CNF4MLM$qyt!ATO&e52vX1mJM`6)+B zjTKSPVtlEitbczwn_t|oex_Pm!sOa&N({oH?Fy}c&%^5x>~#6e-DqTg>d9XLETr4j zN?KjH87j8-O-sh;yw)&3fAs7cQ=FxXi5+_Rn)Ixf!?8h8Ftlzt-L09fv=4K}$qR=e zXx1H%&FT4+aMM!WXL_26A1|ELr%x^2n@3Yj@o1#xiHL%sSQ}1snP`dBI}W4FAM~3e zN1oO&3;Lu;8VM$fNi9v_)YBr!p_ML6q6FveFy5`+EZ#G9t%za$3ASrUnETG=E&Xr6R`WGZ->MTO^d976^!#*faQQt`poiui7ev zPm%id1KVij$@yT%kwDYfuk2{^QQfb;*P~i;>&52czEBKY%;hdE8iL~NYN(JM8v zvCJ+$MbQ=~;alcCE247s1}`UhRe02|ro1d{NTj_Un}9NlvflX9%IR`i zM?})h=?Y=^gsy5thu_m|%tFM{r4m+7C6FU6Acd=1buYBm4gf+mICnEBQ6~6mW=)tq zp)3t{R$euH6-o5j^#%2lcK2#m zz`SFaNGg+yE=O0QjU?^f5B1l+(F%JsOIy@y7zG;xS{+wuL!sy9rXT)<}zppbfU1= zwLFoxwb;kU51?GSdwpOFb?F|Its#<<*60E?5}p42eibudyH6fg2PelA&>tV}9qbAW z;o;%lGs%UiqfzZ1?MFxBVfClo+aFf z?vs5Tgba?dRF7pRy(6N8C_dS1P_rbyA1ODLQQT6EH5MzIoNylc=xDWB8M1HN>JBoJfA*0dU|-gPtXb`!Gr_0e{^vCLn5#`+CP5w zSXc(@YNS?&kMu7^&K?|>Q$wIDP-BorPKBd*SUvc;`uXsgevyA3RSyr2PmT^AJUiLn zKfX`zlEY_@A2vSz^yu)XeL7t{+NX8+Pq2}{R!+{?s*xq?rcbNv_{R6iEy&NG9G=8C zmBA8Z7L4{fANLNAPlQXmj~`c0_V+l#-J_q&shZG~Hpq~gipTp$KOO8HJo)Y}NAq+S z0YWbJ4v&sx?}tyyE{r@WJsB2TzjS%I*{0I)HR#VPmoEA4!h**KL7wlz2`7KK=>OI(VW-w0E?x_x)~# z=!AyzcZHD;_a7rbM_jz7cprZ+$M`^$!|sE}qEO0->cVV0N%LAn#`z?QK(2LT_wlYj z%>Jls4c$zwK*gXU5&eL@ zOBzY*bwXVFRkMbj#EldUi1Bv6Zb(S)8LKZ2!RfeS@Ly88yj&JSB?}&`bs)f)B4>nk zB@F`3#iqg-dn*`%Ykopb_kLAtV`yBI(>b=P7BOwF~6xfRoLprtmIE-uU?6fjem)B%+EFRIHxv9 zdZ@$zqGTiWXT&14S}J5N2|BTKS)^66M2HK8;)pna>WE+;ax0*&FV;(x%k_!M^+I7$#MZZ1OD55>mRv;({3mdIi`A&NiK|%%c%Qme zv}O4*U`hn1j?Oc3tO2OsVx>{^fTYr!yEan|3lHPf;Y{q6&uN zSZcCGmZP?aIT??*2em$5`({J!MH@=qo(RSYW>x)STkm6@n`SSeWDLd@$swCiv}u** zi8)rH|G41rQy(@n={}%8Bw+K7993oIF&HD^%-UfdCZEGR>{L5nF%Mrc4}W;fLymsg zhzCI47W@mzitr42?a%a~hJDN0!mu+Es*{S#di;zd7#y(`1V^p3$m-8k# zh+3FD+)+bTj0kIx;BP>D$W(SDO<2d~n-@gpcS;ef^g}cVCLY{*d^0}T163y=)+RCv zv@%X)UiZPpDVBw;k8u%s%3CX59*&JU<_=h# zUA!jeN;fLJsnu-x4%A0*1uGJ?`1Z|*Jc}z$St9D|*BOk5m_Hl?6iVpg%F<1k-WLHo z$uBHiv68$b?Lj3=EU_jZ38y$^A&Um@gflb`Ya32J+p`wUVMLC)lH3To$9(X;>BaO6 zcx8%8i6GCTBdyN91Ch1UYOT7y=JA-zD1SU0j$F*Re=b3=hN`F2>+@p4==NgOMbDh@ z?*J0R(yZdOH6`p)Nq%HjQW;VZwELv9dALtY5PAzu}@u33d?+ z0Jh0;kq4pQAmUHH-MF1)v^O+LcaWxG+3>SRaZCmgIEht=fw_D+M+IunNqSej7gRzJ zMbS4F{z81Oh;Xb7w17U+2$F>K1P>7Y_!}x7D~3tRsviF+VuFhA(A&U;b{5F0d?EyD zwQEn)E}x#iW&!}sc6eOY4F4puaTWi=4RNg=6Si4Rv%)Y<9*^SCm00JeBXvHP3{2e* z(fZwywJ4_6(s1pU3m2lolCT|J&PbA%1OY%>`5BeTkho{viFZvIs3#u|`xI3K=_CWCa?Z^dEU!V95ACNSRO67x^eSIqU0muD#=}$(7xZY6f70!-?1|Q8 zdluFZw=KM0v$OY$1=j=*tw_{$xqggkgdo`7ZnZXNv7&$)E zLPZP~@=5mjQ)rLMt~Jlra5ogbM{US^hIV_8c9WtAso+z13n4vMbc%J-*{*aEqoh-{ zWr`S>(i5*eb_}U0s1KT8D5t&a2q~M|OLRWuA}Z@zN~j(Ud^u$dGP#}5ttP&~4;C-c zh1aj8MowSR|Jg+nhzAuB!ek_pflkT5VvyCiUnZix3EYp%h+47`9wU=>`gf~pru{ws z3ZO{o{oARfTzEorWv4c&n~Y%$2xDrBN-^vU^G2kar0kZe5RI7SP`?B99^jHNp&$QC z4nQ852=EhFpS;|&DWx<4d=t?z(QeJ%TkT%-Cl)JH7V15Zn`1(Jr|4v5XM;{ejD;C< zkLF9DjBls^LG&z8-GWN`QMt8j(c~JHIRogM#`j=gi95u`YU+NhBN9LU==`zgeeIZK zNjs>oDIckbZcE%z7%6U1_p97{zqH)VlMms1=l> za=T7gSGxGrD5IKH-lss>kMm!1mUH`zOkLl}k{3Y-ir;Zyy5uB734BGlOBw-DYZ;Ei zl=IEBh5j0Ix7&g)Hm*Si)YyA7C5TmlP~a7Mbv}Ks@k55e%+D?)6i5vo@M)Uj! z(hnu*@{_g^pG-Cw=_ z=d8nT@^@h6;J3ox0o@>Om%jsW32K7U#ME@g@oakj?DDKwmko&x(6udCv_yzhm(^Lj zE4cVo^*s?)5dLRZ)j!Sqqe=g7XQ%hierdy68C?zWx5C+He%;CQkrj9Kp&l7^n>FVI=?!$**iU0lYsu-l$gIoOs z1p40ny-#m0T)%dy>YdM}s?i2?V++>(Q`+1f(`4!Ln}7d*_=aEaUz~+se)IoHZvnaspH-)nMl7!ul8@WC$ir)rJHJ+0f1m0*I)>8c=_QG< zi|Q|zkhhXzFZ~}HG1CM6ta|%_HW)PA!B;0I#y`$im(-dAIeJt5wGvm3E!O^bb-LhK zFdcRXI*kPgvwT&3O;-Qmlhrvvk~PcO3iNLztBGc|>awh1H80QqSZc2}&)|l?-p^2l z8~5;qQ`G&`7{x|!W*A$4>Xie6dstQ=z#pxg9Ae=zQoV#`Cw$59gf!`w#XlVq~$1t$)*s&n8yqCt&jDfJWx3C+$ z89OYN@!f2MLEw+56)4N+@4$_*p;#p@pSXD-s&BU*~aPbvru~^8Wr0|M2Ik`d=7^Vn&`U=~hRp{_vj| zVuGcJM&(ySvu4(cHLF8~yA8wEEbPRoZ$1e;T2l#M$9}aR`!&i?SZnP5h@nY_rKO<> zbioZxfiXl38UL<|*YdFu{MAFvpj{|=rqO%#^xVT`bC%{daF*=*Rl}u)cDAU=A@85r*~wvo6oM(QFrV1^k$A}ThHHp`r83Wijx)Nkd3 z8Kf9e1*Ro&$ zzQh;|T3kZz8?jG$JZ6IS&AM|8d50r zkym>CeV@G@K|_Xx5U z_iE{P^`F-iVsu*`R;ax-xJZKtQEE|V7V+3!i?t8<$1+4Lnj zAUzp*d_fVu@Yz_ak#Q zhsrMlNG98+jiD(Qb`%3tp#i!cG>54rT|v3ogp(Zc@&oJ+0HCwDBNr_*e)QtI+0~I+ zLl0W&`Q8A<9?4ccufpNp89JGCWoQ&!L^JSlT{+U+wQ1C?AEXiZmpY*a`8E$q?o^8l zJNC+WNirc8ufg5tVNCpJ1eU`y9vgy{zTmDws0l!R0!6Ox)2pXGZqWgBrIx!!+Sb>; z*P{}oMxvoTBDP!VEkxhR{N77}v7O>7zY-kPL$$C#MCNeujk3+nPM z21A)vmGB03SF{zjW^Y&ecd}rN`Pc{r0M9mi(s)Z!-bS~iN5Lzf>YiPj!ZeGz9b6Ih zKLr+90|D0}ME2{Cg@|gu4Kbpf6eHS6F(Ub?y7|3{oQiL{Yr%^7{k%Mb-=3bp4bw8g z!YDMxcldZbPGB~qw zVl?HBLBG3YM?-Xjp>;g~CT5qnMa?=ZyJJjT7IY|_HG(0TqX=BgKa8_ltd@E(e=Ksxw9p5$8`BEr)0xuJ*|# z>a+TQK)of?1#0qc^^OkRA~?HGjt>gYQ_3j&eF74Co;{0mynZW{PetTX0El1&dLh@^ zmAaS_H`adqQS2mvDQCHofD%s>)&t`(bsk>Bi#&L8QXVnx5AbUO+wjIQCj{dh3`}KI zvM&j%-6Q0!#t=ex&0OaT(u@*9kV{IzoWA#m%*}zh_hQ$qcmk9&=dj5IkO{4nIMGS! zw(bv^4;cn(8~qn|Z%F8rN^kUyT!*aV|Ko--lMFECJ(@b+iEVUy%ko|M@?&#Q8e$10JHCm7PP>h*r*@2DF z{Y+;FMpFCp+QGc)CxVD7Ab07w5)i^(1nH6Bu}Pj(xFbm%?VTV+X=e}TjndCyO+_br#MI%J95Lma7CuQql>GpRF+>DYX{{gQs zKtr~zkr>n1M&4*)X92iz=-n}_^X;&JKqC)BqS@?9xAsY7%$7@X3(QL3-{%)3;^yQ+ z?#Q52J6JM&IZX0R^atRR<0iJzBs4A*ZX_(Zg~n^LIWJce11V256>EJ^eUf&Ii%g&^ zdi7zv@d;*tKe9z^o1lLO($`Ok>$WP{al!BQ@xtoV0e+Het-bfxQdHin_SXsf9 zOg3rZzYGS3BNWpYK10=(l1=4ekZiLoV$?Mow&n-Mcmo76&?f?9FP5Ut#8N7fqOP<~ z7_1Z5!t5b%R;Q|6e!Yo$8H{~OlBMe&MWjf^7IPa$4J2U}%%)hibi`#`ygkTE3a$Yq zQd6I9&mb`%YXoRSdk8GP`D}SJWK#b{h?aDF2^G=pC0K<1+>uJduJusi%Fy2?#PNmh z=XdM~pZ}SkDtam8imPw!7ynrO<=g1!`{k;>{mY+^t8YF7T1u%Y@ezk~uL%5;ZYEq5 z`Mv>0MH(e@n{iwz6}p3wGVI?15JHAOMe4Z4RyUO%Pc+H@Rjg?#SFl~ z!^0nf(cco(+Wjo3wMUn!ub|ei)l+}?>Zx&ta$9>MEWG~vRZpR{QPc6c$WHsN?IJyN zgDu{6Me8`Xfg%zdSIFH_nKTuN)vX3q+pJfPm&aVT}(A2wKSpKK4|WE!Y)1 zD6H82jcpJ(v|QC4dWp|zl>}OV0-Nev-Sj_}QP(5C8JB}PUBZC~dCz~7H0!*TNE1th zV<;ty=Vus}f-Dwz4F-aIgb|oU*qVIWEsH4UTA5lchn0ZLIVk5*%3zIB21|bGvO4zB zW8{3eWG1I#2Z3FDCvazCY<2&pTzlL=;(oEBByw`yY8=Pd6-V5hQH&9y@FsCeff&g! z6U3>bP2rr&=sJoM=O(Gx$~-iQV_y<@ z1HmpnDIJDCW>$T&Xn@(!^)7UbE{NHNFuJNe8l-Wxy8`r0igy#jcOF6V_BC-_{l{(sI2a4fT9Y^oipXMX)^If^Q;$+f1*g$(z2lz5CdkQA94uJnAFj zitXPF7eA5d?y$EOnmeiicoIV-#%bv%ZeRnRB)Js{l@(nlvM8ADL#yO z`6d7)36MSQ0$&A<>dq>86sxbxOM#^e-;w5{fkKHfTWp~wYh`ry<=v{&X>e-oa5xWm zDQ9;MFP#H=j3dxwK{w$O!vH0e_;mo0p)BQ)oGn?zJ2U9@gs2Fjif_nq6=uDhRytsg zS;&dy_6e~#*|((SCWaT510zks(k=2LjVs*iSnsW1S2mI?=ruPew@_=n(2zT+wf2VF zh#a}E=ayTRVMGyd&73A|tdYn>R5aPDGOeXJwYXSYqiu~g>0u^M&h44vAY5$8ThgmN z376Ytu};HJ7nj$PQq6<8`ppxhAZtb7gOwwhsZ*pRWRiTOiOVqnYsuwM2yxCjP7f2^ z!Sp#n0r8F@o~2Nd9_R@SGVn;^V203XW(G}#(Z5NDkSRQ+h}PZ!bU=;PEgqRMO0_|* z#`_bz9ga)s7-Yv+LHr9$Rc?%=3C&2GpzWi~? zTe|#I9)t@^`)j#pd(xFDH|gScZNxK6gnR2pcL&v0BPpb|-4p;zGP~0H0huJC6{e6% zo>3hq(t6oY*QPl2`#kO(l)lA!U!n+$64lI}ztMM4I64a_pbwb!s-I2$47rsa!=xDr$67pG9eQ z-vj_&Febi>Vnkq4xm^-_aTj9dm*v@=AV7r;g3Pehynor#i0pt^s<9P|nFEiBcFSyg z`Bu)!r@ivLfE)@6rDJ2`iJr+BNp4(Ehr&b>MHCrnYs$4e4?xEj4-2ii9g=P=lV70`iIZC=1d3Km<_s-bNy0{gu(^?asT*u_q+Y-;lX$N z$0uJq3EfKxxbjXy5?s*4O6(UT<<+#_mIfeQUwCZX(?%;g z5GFLjqq*H1Mn@6PUQvx6CbKVRO5ps|!M-pv<3U}!l{a#kU#zQ8Z;0|L#@Fa2^U2=vY4SQhI=M8|Y&1#gkY!?_(0)s*BCqCWGOp^{%8bO{jp#SofPOLR z6Ai40_qNE{i_>7)odm!mDh~-ODXf{l0wfR%Y;=m3wOa`{QoV10Alg5?sWd|2wG`yZ zE+}q80cxdG)GZuJY%h@-l5s9nZA;Zk`4+}Db(d2&w=?v`)S@jZuG8k2S-xeHHIpw$ z&Qr0tU>Dyn-p}4i`%yTqmn&Sfmst)@gXj3)9`muH;y@q|(OXK0MMxt5K(PcanQShv zFYama0e?U%+hU56dB5@1pc7V&-SWtt%V1eaGgEsb#ESyHSIl;TMCu@mOKu9-RMPoPjaQtL>TY7f`Uj4gYS#a1O-^dgH(Xrw|dj}%<2>0#9r;r$R* zVU29dx@dHzN~!U^SjmA9t5jN7-OwTtWPt`pUBV;I6ERw{P%;-T_g&OK)} z*9O$tr*1GTN4+N6EQBb-Gj#Rgk`4lQq7`ca21rTl4-Zu?JNSMa~{=>oqaFqF>PRws*7xh_!fD`SeuU9j;7|2Q8|0Qv|^= zh65vt*wx)o-=9OZ^Rd^b%?;lSc0aS6yFV-=Ij2n7(_s7OIZ?$$VMXp6ygS@CAzG2GUN6 z8ykRL=|y}Vz2?~TUtY94;6k$u5C1bE!fA8@)gN5O9fq6 zDif+&TTJo{-ErE#z1_0WLb7@j!bH9lWCe5gUa$uI+Gf(|_eHMXpwC-m!6-~_gg6`zZ z2pmDUK09h7MOx+KGHN@(H08!?RBg>maJHe$a=z{=Tl-%Q28P7ILNn((d_89+KY-ql zun#Lm?Qb{)G2pP-7V4Ku;Kp3hm*>-qUsPW=SnctwtTdQ!LRrWR#lS+z|8n?AMvL|_ z2LCdUZnY*z7SY4OVA7ew^X#OVbjAa8{(3>zt2b|DVwbNdU&mCbE@Z)H{uS#PN@}RHAke#yzdJlSIQjm^8=Wes3X0T9 zGkSBh(hkKCC+v7i1F#mvj;&LR$hY;i+Zv2Udz`f(Lwrl}EzqWdqn=3v>u*SCC zLS;{9F)F*`iuwjI*G63tSuaz?uMyZcD>V@)xMM$!LJIXc8pb7|FqMp5$PAuRS{qjs z_bw_!Yu0DNl!x$j!ElS$T{Q9W+X1yZRs!GIW;~hhPMguE1M76ew{n%PVKj_Uh>tWb&zLYrqzTv zvxpLLV!VB8v~dV!VHdoU=6ja=A{c>y(a-VH4h+UXzNE#Rd0Yj7kU!N zDUy(2A+?jIv5I$1I3dAyi<4R?Sb8p5pJi)ty+f}8 z*}2V^X_~Hf&spCp#WTGF-#A@?y~zThs+M^Z-+Xrhc)d=s2HtGyh?F!19DY>Agm@T4 zvS0+4K&n?WaBNo;9-51&_po5{l@lQr_fE{11bo166t&rGj~Dfb=vsnJ^^*ozqe+mR z-)OuB-M$qEH6kv$)bkL%t3A-(oktxYBt8CaH%8&|V(x1caD60fvepx)^=nC2MO*Mz zo=bZ7TG@${xAlAJOK$yOHfyfCLz{B7&PhG3vUj~NMe4pDbm|(J(W2(@j)H(S_!kAJ zkSZxu@5Tii+}nb_AT4sNCUY*$Wz?xH#LUKZ;cJ^$X(%W(WylQ6$SfW-H%q3`77Q~V zG+t)x@IVl=RyF*uW7smgS-Z{$JcVOFi39g~Rzs*?D0-ckaR5Zs_Yp7#g*`tQ7(sDM zBF5g!C{AVc>`;3i=|P{y@iA7@e!jSP{rt}nouSdHwRn8d$K;Wr5=H1#IrLnG1hA{tu_jx0yE+4gBhQHw~IW275tyo%g)r@Ykg81VH-l51`0Hp9FAVJ)B@wR=LT zT0p7_N#bRK7n<)Sv#(57Yx9G!iU%lKm@>UlC{bmta^OIEHYF0_Yw^rQ`!~ypPM(mS z>%>b|ti-07j~7G&#KtesAxFk;d^9m%bXR&hQg9OMM{3TqebO z0<|q(o&k=z5V;n8FsJ0-yQ9CCsZ#~6_?oEGwU}+5E!23323RCYVU)Hl-bP=m_-%AS z64gGC3KWKgS_cvE`I>Yg-_P2jFY4A z)t-ZFrP>sNfJ72{%{BS0lNZf4Zi6raImthb5L&s!gHZMwp9fuK8<%+4v5*ok{9s#` z*w@-l=Q5B!#?3zN5)b0Lefusk-`8hIZu*ukacwKPF0q}0>%tb+$Z+7jfkTZhXWP;x z9uA>fjE3M6hjm=yf-k(4ON=Y4@7}G5U|g$M1RIvfP+D2tw3WV9_o2{E5|`N5gRF9A zvq{>-rV1uAZcCSV7#D=L6pt;ZvY~N@J3O{(H<7>;-Q9GF2jwpDaL1w)ax3e7IEpL+ zb%_&gU&tk{k-n8noCx2-C9V;(txFu~k!Ov1S5A3*m$*h=`(sv@xJKPAxWoix^ifcg zC%D9Gs`|HZiHU&6Tt>7y2QS*W#Bm4W%Bb~MV0PLiYl%x9d={51UH!k}lE31TzX&dw zR*n)^k2-P0P_J))E>!%6YWZ#_WDiIUa($;Y z`oB0PIhvYE@2y0>0tnfY2%6v6F7OqW#Aa$bx^1!?5srKtE?7b$$GB!zAa3o3t+IW`fz-y^)&?N}9M5`0>WwhHgjbkQ;(;SJPP=={_^ z>*M%gNZK~O=W7)QR~oSa;I*+!>&N4J!{08x*B#L5J>2pw<9oHO?eWCbXjr6VJdx`KZ;(Ik>wvF#a zdPLFOR(!8U-j?yb8g;i2-vdPNHbjKHtf}hXBEF~C{iek^Y#HB+JK(Td#`j9c+ zzO@~;z`6K3kh7&9JQ!F(s}{a1s~Na*Tz&J8)u+u=-Ro@mBe5N`jRbIpN}d-LBA?>I;%Gu2uZtxwetIj$z-* zF!g?`+S*XqA*wv=x_x1XwkGxZ!1fm(P&92YYh+uKV1YkhT`wllhZmPOfl-DMo;V>nu_COh>8eh4t-4# z8hG=+uGJ^F1$)bp!tR(-#-TuvwpW)Opa;W1c^h?^veP*XO9wi}I7nOQQiqRNgxi&~ zlCypw(W$rtxxTm?vQ*4Z7cHi$U}#EMpFdqoO1tFlH<3O0L-c&t-M(Cgp{bg!&>r0p zsBcyZ2pRH@x@mkXZ8R}E3v~i5A)3R_LNukX&sT`%SBT~xAEMdK&;V<2u#Z4Azu3rP z^CIbxdT_G)xH>-g?#b@Sv!ng$=&ZWom}k0gUu#fk)fjD;ajR6rSg#nNal%7FHUFL={-XV({NjP zhw8(Nt%KMPd&kxP-My=C(dqQ!VxeOpWp?OC2-eAzb6Wk|KrR_8(j~g^k{=n(3|20u zt2T4j(%Z+8Lsb|uC?j8ZfB%n~THKXBX4_9KmN{Ydsl^r(jq`fN-Hl;hu{u67wOEat z7BhzjU3|FOCRz_2rtPxKaE@WG7@#SarC}_s46VRyX6)^aEoNe|6qCfrf=EBc;j7|- zaorK&qc~<+6o>(>f?>~8p61x%yYVK3hN$|%hVN+Byo%-aciKqoJ`TEiDRS)k=UG5y&8Z05-0@*RXx#===k zro~BfwV}zu^-lA3e8kh&!N=N>;_Kk!AQAsZ3_b=3fvP&;72w*Q&NdD{=1Mee6rCNm z!W>}w_50Odi!LHVWPB{Hk5Z!#Ar%x+iJ>=xxyGXT}HWRm&I`8n;0%p8P-FKXPd^~7InSY1MH zxJBDw)XLqCGlo?eMxRrZv{?6xi}Me)fr!ER4BnhGa8>qIaUJVZfKAdrGOf2v zQ81buJV$LZ_Q|(CQn@5-PTilT`-hYgVfQt$1E9JFOu zXqw3e7|8miUu9hE{)pa%O2&4!O&?s4EEe~4Yp*isF0D>+d$IggPD^~TSDB&On%G1> z$)(lhv(>|l)s{BV`e7#78t@OTALh7(+;g(SX5p+o%+ZTxgpTPki9JkTORqNmxj~<` zv3>e7mK$nR-jvH4!903lTA=(5M+4BW&N& z$!$|d_tEu*jznK&9Pb?)9r)Rif`c7*Z}}HCS>%|lCAL!U4my`qr|&LkWGbU67>O8u zr9Z9ya)OW6t-d({F;xG>H*cAFc;`{K^I|*uP!T0q&VaPn zEF5iGNypUqQjis55pBoRG|bx64>e0tJ!i!OZZ5!d|W~!|9L%M2K_jj zp1z4Zj2m=a${upaa!-{i5XH{~m%6+aT{?|EnW4BtG|EWrW{u}nHVkN~4^Jh@hL`8l zi(mMctPTt56T-uxT}qU&A>-GN%a12-(2sM1_$S@aW*= z`yZ?ME7HG^qg}$I7)4QEUCvJDujUBcb3_zz!~X+7B;$z=9v=QsE%5%A?fKn$B`DywB0ifJ`@lQ&Ix_G2ic&aA~v1D@N^xhAf^OB*+&X!Vj4fZMHlfMiZh)dA!6;ok!pHL)R{zvMQhg~`YgWf^E_bKThd zbh%`6P(e3LFJ`Z{m_2vd@wRme*v zxV~sBLgR?xqZhf-@e1M4JZ4=RCw|_Y;D^>fBq<$>55z8+nY1C_^{l-X_x8m(q0yBq}0N zqBvtF+USCj&QYkmr~+y;^0N|wct5{-Q$~NkgB=j*=c_b`k=G=gDu~S-ZluSO={UXz zQP(O}K`s)(aU*4Giwx|TQju3rm$ouPcu-neIL3rwwb>rV+T5I}yBRtI72CS^!*G4H8?SWKT+5=m_QbY=x7DZj55qLrf%Ra&R5snKn z%9!bD;$1={>+bJwz%cqR#t>UsFb&m31U}@v+kuGueocTSvsi>RbS(a?!Pw<&b%p1* zl6b5c(74xAig4Y!uFoV|&h8PPG!fNWJyiZVRVFjaC9dZ0X51$*CU3#_5mC=M=BC9) zAGQD{?1s6}iiXTiu{A8V-k1y3%;4xkL^b0U*A2Cof&-!_iu^+?H+zzHW3F;bOO8j` z+LO9PV)g7!PT3o;=8~_ut+_3@#zsB0LKcqj zhgNp1sjZOPoGqE$IGxL)@9VGY1xm7wV!+iU3>Uz(T z>?$QW+Seb5-iVA<+Dj~nDzgcDW3clzVl4j@??4ef+IS(-Bev0PbZnIzUm`EqDr#WIWi&NF5I$ObHm{OaMGZ?Vd^rCpRoY*w>#E95}s5l*~m{MSAI zq61c9$5^T1wuSE05*F4xb_;tGP**@Fhc3er)Rl|$Z9HCDpc>!U`bxDJp{bjE(9qfk z3_`LUW+*KwkfDK~K7?o<#&XC|T8oR!q)zoP6f%`I+QPi>m9{r88nQkZ*tkj24;B)x zBZhLM(KXi?93#s`fb$kv5uhxzQwx;IQ>Q-kCbW_Q0tG>$c%>5ziuIUq#BkhzD@B-P z02}3OwaGadG8UgX)vRapF9cU|miI>Bzz0Kvk`m}@A2aJs1mPRD1j}y^uGD0jbRC0f zw*^;nPAFW74tx=z+zPJbq-yYx)jT{9jIE|2V;8zs@l%H@6`+;;v!c)Gbr){XmqII* zB#`Kh7m@ZIIzD5XM6I3;nRwLDkhI7%WotEd+_u?3jH*F-DFP<~$e zpvickusjJ|+P8Hgz{0pB1g4}>8%RS+ zMab4I%b> zLQ2)6((pkvk#b=+Yn%9;K&7?PzM8jQixT<2N?xe4O1pM|p8swzQ{Q=^X(ni%h+M_+ z@nzbiS2lu7x5e_rMH^PxR%DK>wFGX$Eh2fCBp25WY)r|ERPdQ)h_BtX-vtpnA#kET zafs>b&6|gs7|)8NV~Ewgnm?IqKWK2GQWs3)z~$ntC9NasGx#Mn1j2vKmJ4ls5X03O zinVEG@8Ay`#fD2EtoeBVi4@TYO&dri40^R#RObttEIhySno!QwOcFrU-2AxvZ?$?q zmXWd=iIYBi@c3X)L0>H~65WnX%huSp)>=AcwYuQYdGXBZer*FWjEqyaToSxJr!5a8 zd0ArIX)}Yds?HXbba5oxPm$1KSbngTC-l+J^2QpS;+%RH;QQnA+G7tm!b` zpyum85H!GXWKzy98}4p*u%ls`P)KSIO>@oXcP#N-Lmnh`xrR|FYkQBOjccgcojcVh z{@+>_Y`X`pJ2Kcx@}Rd%(EEC*Kg}k#c|p2ka-#@aB1+u)n4Bzp+9W~m3pSpQE$9nk z;sAo}!6DsoSTnpEzp;;33}2$4udz-MQ!};|7LEhHvJ+ ztd;$5L~q>Ri0=_ss*W`YF!WDAMarp_u}G13+9oN7T=iGl`efxajv`9A6NYQ&I(5le zEOyD-I9Ocgr1q>+SfN`N{HT`k_{nGE@l<{6e2vF{jmQ7-$xO*0-wnf`9kERrEs+`V+@Zp2__uKkYw0e7avfJv!XmKR!Nq@||hCZ~8ij zYo~g`UtkcGcvaPM877i;s@3VDI;=i3p;Q}z_4`hi%-D`()w_-D#M#^4Rr^YVcmie0 zP{12Gd$f2vy`Z62Xy!#TFgmk2YxTD`8-mqho<_7a1(V)AVH3k|7?xps@Qyz6kYXxm zxJoP#P%E&OAg^{?r6k6HnnWK@XO~yz%}A>w{77waKD&4~J73T#OsZ_83oEg}vvUDs zrRp~Ec6ePMiqk^`(aImwudPs?0!tl=a4&;t&HhtyB8!l3P<5*G5}fC5=#)6EmXJnR zl|8Mb;}w4js!k-*nSK(C&zseRV$h_wZ56u;;#12|hqH33`;K%DZR&_n&M)VnIL7~;+aQw$@S9r%aj z_!k%SfVL2LJl#ae>i?3sHpE>7u@XA#$AQUSk3ok6Xu;+%djp{c7g)QKI``Rq!v43KZ4|P-oXR{RI4<-)JGRTXZ*xxMAdat)qv=vwV?ErbC05yt zf)U-CiCn3HE9SWA=iL`9^iL(>9Wx0Y=<3`+Ng#2qBQ>Aj z;VU%Dc)K{GhR+oW0&=dc!^_w&y8(C@vpGWzB<$;M{;l11;%cg*)c8lkK0H1^uI2K~ zF3_5!ef0LoMs+_{yi96^xjWP#E-sjQ^>2qq;m74XCHN52J=Pa9Org=@8 z3fe^#f$`|Y{=@x#OFq>cOau6wEa#W!vwJWlp6k_{AE*2`VJJ$90cs5nDO+(Y%t93&mr+IGEF6%QHSe{vqz(SKJVnQ{B z=7=nmB}AsI6-BDC&}TK;!VyDE*0X4W&YCZ9 zBd$L-JHB&Yd=A`!<{!A}5p4K<=oBpNL4#8;PJM#CX=slo9uW0J!F;atnyu z;_3+km&FuL>cM@KRgN-BBn=t-Qzyy%6elTbwM5g747sSCC+S2qeXOE0GxesskVCP5 zL+2GtQtg5D!WL^i)}e_hW-i4&Q9Mbdf6Clvn&q0sIlrPb?UnRDe~rQbk5T;GD5*QC zU_mVuZBWGv3&P{=?97^%;lc6fQVVyrkiNaB2_YsxQ#2=XqQuE`yZWBQ!VKCB`xviM z7m4jyi`hDmzO$xT0#~I$4@h>K&m@ufoHbpzx_zW`(D9mm4Vgku(q6t*8c&?Ot7 zn`}Ka65PV#y8&KD~Se8??u?cZjy(g-Jmk3@w_sz5wGfmZrMsgo6kcYR+-E4(mzEhDHGK!rO~>^g<4##hZ-^ ztP^emd7o$*3=NKry^{6VM{0TL0hRwzW;e=Z16u3Q3KGOzgj(#!qgN8OVz5k@7|HF0|Q)&7mh zkf{uQxthO~>`u9AR*(dwt?sk!%Dnv`%|n_AK^z5?O_Cj6OqMu7YYM5vex%e21c> zNK`Tei#DdmF&H)<#&Uf=^d&-Yt$rM@WDIf58q-6ufKvJLQt?j~i< ze*(;v$nm=x6dbxQuI}a_h?`UpIpcWN@#hYPOCQD*srA~kz{2s>^7{0u_@m>IIte%j zG5=jYTq*5B8l}V)0mzp3Nl8l)_nhGI2}9P9-rqJ(BMZZumX$jAxGog>QWm?-!)>S4 zAaWudAJSD7?i7;=l6wAo(k*JI7w=ao` z;R@9A_bnu+D-jKm@0$qq1W_-PoW9&ZUzm+ zI4zq{7Oljl7i1BB?ml^V_~VP?lcQ&QC)Kxg4OvEUAD}7}Cn1kfT-CPH{59*~*B-VS zwgy;^$Kkht<%|<7XPjU;@>750n9>jv>Klf@2|~r7HzbfObwem*8CodiIC^V)Y-S7C z=8oAXw~%hwNiX_NdeP;ly4kM0Kr~DUUR`XMwZnr~$S6qnT^2*DD-^_>t4o85~l zT)-V`w@xR|Ak~{ z+3Ldck*Q@_TcH{O*N`ZeY=gI}e10b+V?hqwtx{rEGtKoMD24%aa`-a}{m9G)J5yCA zCf-b~O=7_%Vl1*f@zz+9VVVURe+>x*MI@XAgXpLoIG?4A}ENUgnUM1BgP(o;lKtP2e0Je~l@Q`fF z*}R`}j~qPT_vyhs_`vqvGRq3i`ev|lsR0SQk>C?UBSZqH%jJ~HYK6YYMy?iD1kg5` zT{+bI_mp{_P70B_s5cbq?r*WoG2peljyuqD>Y|9r?1;57{`hpt+rNb z0#Cfc1(<^E5G-M`=&HBZ{EShUv4CAurn_liW$lkrD+shkdVq3GipWy7NdX)Cln7z0 zkEm7RTSryBe;4!+xL$H>OY^AS&jl?QGA+P{&a&d=&J+FkU>LC_%xOVF4mY&am6999 zGUb>m>5=7CLIwvmVwh7LSZ*lj`q`QI`$gQ+9)Tt@iKj+!NziV9^%vR*Nf)cHqGhx{6{ z5j#s~Nk?<8NWW(@{p2;a&UzNVElJPS;;Q|D!B%R4Ra=QSE##&No6@`Q@EUw#_!snt z{dsbK+(zkWK1iiB!*$f;g3sKmdiMS$! zX}`>*BsIn&E9ZqO)+ilWbw;98!<*@-3Tf@5$NF(iXtl_u1k-Mn>T!@e4$U+esL}7;G1zGPmD;4IKmD%S|uTYIb30e8&v#sGdrrHBYo6*#qF)r76%yHX^&mX z(b1pc-cQ%!IK^6-I>BhicMUO~B0(0RhzcL;UB^Sbx;{VuP=Ct`U_1W$;y(1GMlrs= zTSW+ZLn4N8BMD)V2enNkjX*5aNNUka)(?ykM7q7m+8DI(aSu7?%E8axK6c&3?U{GWSeCyVDQV;*|OX!(HWk*H4SX zx}_cTCipLL3u5Y6oUdBFSzMnJ2$)swaL?wi-{4|fqn7FNb!bmlM7UUz1DcZr1HQGC z4ME?sPEdO#_*FkUB?Uo^qGYOb_x$~o!jaFaDpq%l zuO9Of8Vbx=(e204Nj~B5vs^4k*6}Dqy1VFnB}=oA!DbGt!4v4FIg0wr`{# zj(%?B_LpT&o-D5PJ3zC~$yZ*#e$!ALnrGCpvl7|bI6PLal{A;tA+to+tLngd4a7s! z-)oaOv{cj%0M^Jzm4#__17r7ULTe8ZBFb9NwGW~MX=y7le>p#&Uwsf6Q?le^a;>#8 zm0twoq8)OWVAtRO;UE57RsRcc@YCt**~xM`=kwo$|NJW{6#oBLwSZIqO#6oM4*Qe-TQKrFFFZ^+$t*0ctdq7Nm$6_7Yr61lJsh@c7m7Y#zeW z)L-+zG%yX&HwQb|AS4blSnDet%8*Dg=D976HRHg5HFK&cww)Ff)L>i@d%GOBo0byW zXky-gFn$A%vm6&+P_eLaMQBq;C9PTv8T5taJ&W@K+;1@t%dH~LrjXhpU2Ed1Q0pt* zpj&d6d8va2#e&)qp>~REOjeoA4Iulfy$MmixNO7OO2oG$c4Fm&iP%D@aiUS;&~Y_r zj2XW+P-9OBFr z;_WoBLo5V%ekUe=%1;mAnFTt+(AVpWq?<&zLiZqXMk0(k?1j#5=I!Qu)LGq~(D{!> zfKle#R6qOu>Gc4%u~^&!flbLWk?${}iSk(hn}H_IzX-9Ch>=u9jTlOiAx4_er5l?r zC#POSW4}j?rAFg+pkF7N!eKp*$U)0F@CpRXZw`&Vn5ca!waOdX>!){jSv!) z^?WBgDlr<)OS5}&R&)w!k0Q`^r?3xN4(8M;#EQvT(ut&%x}eP?k-Z=x|6I6;pueqK zfVes;7&3?`V0r*W{jmSD%ruI_h-&tNO(SZ&?kLIFl>7Oe3`*8s8hhvu0Kd*p@%6f) zr|nw%R{Om^8x5bS{u~N})C%yLFPI~V3=T zIBZFbjy~6e*HdJCubLA*`G-To&;0iLz4cOOhkGD`_HTXwxSx zbFG^$s=1D@!tN?_TmVLm^Q((VY%U5(V=8Xx7n?hmlcZ)FSpF-hs#7Er5l zX>Y=#%CB%35h{YkiL&ZP09J*k*OggaJEk5e#cC~P_=Q|Bm%iVzxFY)u z%Cl|$cnzP=!r{3HlNGcfTQ0kj6A3L3`Wp~Gtl2Pcwxqgw4<=T( zB=_B_x@r)sjrPswF;=NaeGO?<9IWa~MaLu-7j9$ajDSV3QVh+80b&{>X)(eLYsg^oNR|AVAixp+ymlZQfeq){#|5!bG_GC}0l8}LX)8+i#^z=iuA7(UF zKZ0JR9GW8{SpiD+?G#}9?(yEi!98M(44}&D8s)8;MembbxT5vZPgu zj(W(rE2*coQXMAP35Ru1l7CSP>9iMdV79=VPq1ZPEoi>=Ufh85Ij$BY2x;l>`PsZA z9Yh`K41oSQZ8T+L@)X8D$!}JtOoq}^D<`}@!A={LSb?WeClVk6VwiFxfoRqI!p<5w z$+ArRfCt#kWYt1msmH%?z&O?_D{TJ(?Z|#9+Cx_y>a-+P1hS+p=z@!Qs8Cj$WvS?c zx`l~Vp%L^n|KjMyLlL#v7F+NoL+@Ez(6``{AFdf^z^+7)m(%wu!*WT>PXm=4Yf7wu zn4SrYs&2oL+Jb<(IE$w`0#ti&r%eRyz^#3KF};#jgvdXWjzrODd-1#E4Q$Tac~-{X zMN9>PHc#q=s#UI3M8zSXM$-v$hxB{tA|`4=lde_*4rC_6wK^7kJbLkyPA-S5!d%^O zkb6%XNx5jP4*`eCUe!|x=$>9Nod#Vye+A}1!u#8 zdec-Ughhws{#L4$Hi_m9CW5kC&R>0qAu$)-7R=qD5-Ox5wYEE$0m~0)lTh2(PEq!| z78U3A0TYYQmaHqAZO_2^y80aQcFC$DlXZ1y1vIcR^L0Uf%DQ1yyLe~%V#>d#9nk?P7Ik;2E_x1DWsv#i9;k`wj%U%rshaLsQL- zqm^6K+(-=Y6Zm9dH~sVU9)z4ylkVpN@e_|mZB#9;@&6)&!F)rpUBf^4L0(ymM<(_A z18bPOp3td(I4i4@R_#&yG>FTRDG5s%v6&?tX*J=|uxC7KrgG{e=H_#JT`l79g`qO1 zNGbj89WJ^5?Q@3_-NIIF}GZ)HPc1Uxwar!4gq|6Vm01`QGmV zIR#Q}3pVm-CG@%Jtuj2JeMV3K22S4BYtt~XUNTi^`N34X`Z1uVR~B9EVdXDHLBLOnK=AMCIBW8s^h#9p)xB5bEB@5ise3hx`IBUP=wb4>Z29yQH-e0^mGKRsbC^e6KR`$3-j z)j;~iP6zJUSSf~mE6d(b%c;E|s@)6C{j`X_PSys(X%cJyTi{Q32ofB25GU8fs-bzi{ep6n>wg*y@sFEg37fk^}AHWConoP zW`Q}Z@P?0OE}42~HFqr!rnt7n8_t!-akloYBnt3}s17mP0j(EeLs?6k9EhgK(BY|6 zk5Nh!mWkmrE7hys0F1D=CyT8v5RqoJ~Ke0j24lIhcS*Ms>c$#0mmw1 zO&O;#BzC&7xmwwm5Sbbh9+iRsktaT-9MZGXX5#yd4`RGX(o8y#zGaffTr&0eQsPJC zIP2*oB*XwhK4zgTth@=`DSbfIsm$4%p9kHJsdf*giteb|3y`yrBiOW%A`&X+VU)H8 zcOr5%vdkUzSD=V8vXeVC7P6|kj$R^TVR?(YbK5uK6)7n`e0cEWI}Wwz+j@FkPc~R^ zLh`U+FHp{s0@h@JC1`cDgFN=j+&K>E93}A2bghsJ>TYqdbS4T*X^>1#GEB)Jdmydr zJ|WqeK6tZ80tt-p7lSgC=i?i%AoEG;jie;+8SSX&cVakL>h?GQ4{C@1CZOm)lE0{V z>+%j#RLbgoU7roB9i_qp>dWglLt6Q+;e9Wz^oLT5a7NVNZ2o$-y7B>RE$9g)T^s31 zjdNO9klnH6$5U|D%%QN!z}7O`LxZ%wFvdqTIRcY1gUC&xm;|9{*hVt;Jnledj#(l#{j1SxWw8@zP^`p2y7L1IUj!mDmvyT;yC6!iiU`O)<+v{z1 zFtaNCBz1Bjw83ku{$)+mlc5qJNz)+>irt&QZNiYb%=$|g5PL?9o7g!jI0%x%kKO90 zO|Y!sV06?#{F_k+i6K@5hjT+zOs?L@N*FO-Xut*4YW)Xt ze$UK_BGYgLK!ZtHDy`6ou(41wmmRD}Zh;;tdZu(0&iRDXO2>5SV-vAf{F8J@&SK8j zUYC?sjo_|kOfZP!Bv+yM+>_Cf{yhKrk<-kD)6YcL(@N^rZgLUfOxuxabmz2<-D(nE zxFGB8n2#;?G3Yjq?k(OR{f%#`2@a4XQR&eQQ2z|Fj$=f&Yad5cKr5~_EKqaKFzNNa zenes1t!K9c9i@Ld=s~uH4}5kFdT3hAzP_{$pe_&a`zAle$tSo9|otFXmahe3+y5MA2uxzB34G=5nb z1wExX^2DzmV$ql0D4KK(E^*W3FCv%ev3;jk*k;0Jd!K_}4BBrSq8WB0JaM9J&SjHm ztiK|<`$Gge@wp^x>LQ~@HLw=V?3`wB2+YUAP^G$#Xfw0=tQ`>7#;Tygo{ytNP_$+I z8`zlWwa7yAb!`f|>!0!%TEEW}uNwXI6oxtL^cSC+T#g}4*;IOEv^|S{>a`6YOy=0f zf>{p_zS}=O`RKe$)9*#>R_TxokkM+%x73u83nAlR=db2qC9K2S)7)NsSxH0i|Hmyi_DQM$n9H)7EJ-`%+n>^U7RTSS_uLb4sNMMDC|3w=9r)P2S69Q8pz zh=miTk&i$ZJT4?nJau35wmkL0Ajpdo*@z_tQ7ogBwo_b+xGYic?$~ znj@v@y=&3Lk+=He?5*pUGGcoY?DMrZGI%?($Ke)i6|Wk^RUmNdcol>5(xbAbFw2<7 zh;*)FTn^fTpO&8CHU~WkLK)&!&mKHJ*b5E!qcSffvjcRKk$a}hAyZCNqgAzO-FcKY zjMHH!b->YzScA}z;V1f})mEWyupSDk6%955PF6JtJRn9f0({-8{+fk(6I=yj7__>9>Y)KU?ha>ZFlrBmp%y5FV=tv=fHwKVU! zs;rDU#uKc@70b`!SK$OoBUm&e9M`wARRoJh)@e)PzFGI0PubM6K_ufK3q8?11Fsw< zl_h7;CY*q}8ur~6}tkeyP~5}6);FKG0WfE4Q#Dao?x(sF;{>{Gm)jyL#K5>dy8-^xlxT6w{LY*&=5rUKPHp8D;;(qaYRMJTAuTI~D*&fFS-#ytqd3Llf(?0@KFC?R506C1TkZfvr`!m?{s6nWV z2C@(*+7R_epC-(@tMd<(@$bLbJA87o|K#Kb1u-aKBQt8>=fSG~{V+bJX+fV`Mm2Bx zYlGN6XJ*7&dM6AwQBt!)z%{6YL~ym{R3_W9)u+i343ku1&cB$a1DhPri%8%Lp4Qwz zz8WX8Sk%~0*_%iD;p(3a{LHgLH%h+GZ%O4Ib18xH+ujJlHGAQ*7eth!FC)7@B01oTL-x77V|kIiCW(xx zQ&DyjJ$KG~NxbSwo9DGJb{jwKwbVTcm zZd`mbN8OokC8xtr%c;}dlDl#F?YKMID5>*z|33M9AwS1b{}PvjC~1&pgF18aX-Ope z;2?aR^Ld*IylFAf7h!%|l5e|=L5r8|Qt{HhBD)N$v=WfDH96K0Q$nhV>M{1G-xaD^>xQW31tkPyuRX}sb3++Y--X<%f5gDk4+-)TJ&{) z_XRrZ1x+2rVv)y>)}or*ihsf10}Jj(ggC`oO^kT4M+s;@VAg?wiA$+joQ!4GyoDQ8 zykERU5>UN>sVYz8`6)`^nT0|yKzuC;+=?30p&RNZO5Ynx)JbCiI&WSC(ypp<<0q6z5KT2jqsh;)&;& zo5FKq6ag}w)g?SFCkkU^-E%Z`ph<|^%p9avJqQ{j9(+uah5+QxfwU z>zZAh834c>J9z_2<*(0_N~anYwSvn##W*jCVp?8XVCsH#S}IR6;>}svwOm(zsYs$n z-px7(t=m_~yJUfZ(^@J^*7r(eX`<@D{k@QnO4>W9^Qk{3wHd(8v|8b9!wKWI`8eQE zmR*1Sa=4xLCE-p|lZq>mjRnZ>rUX^l!osjIb!s6JWj+2#LtZj7VE%G`KEEQZB@Mt< z($)Lw4L!4RK2W=IfV3!3iQTcbtlP=E<_Z zqMw-ZH0IBagplQ_{-9H>P8ZdB44fpK83cVb2sWX>C30VShZ$idMJm>ukrV71q`*aU zuf@%wyO*qK6pK`}=}M4JiV8{;Ln5(bO?KBw#NEh|0GHjK1nVM|LZm$x-l3q0RQInH zeM4+HKpLSxK!~*mU#9e=M$Con%S1@K5-ms8`}XOTEbAF$wI&kHh6eQSA+dvQ2Ul4B^9@ID(^-mMv>g; zDUEq-?Mbj=z7V2UZ$2gQK9V{7RKoAc{{F+@Ajg#7x>H+D?Su-`AXE0lK%#UusXdHY zht*705ubJ2!)%1|Ndt`#!Jumi+>k`7H{Jh4rHLuR@K%s3azCfz7cuv1GM&I|iBg>t-ED4j;`cNuY- zbfZ4OC9_O5XxTvg+Z#@Upg}7cpKOxx`Yy}mTvDG@INZi5?0iPJUFQ{^g{12Saq-RK zy^7Xd8@3KRpA>K>yB%|V^{qsl?%$jAu4U^=vm1irj_W~HO4r>&&TU9^RUe4kNgMfc z(0QwAqhT*d>un}s1b6NWL-CEgQ3@Ki64ZVW)K8_liZqqBP94T&p;#_bN*k4?xf<@! z5ak{WZF5s(7*B2V)LQd~m}yC=883uVk15`8TFm)qBAp>AMr6QrhZ@WfW{)dn*~d*c zdN{IKFSixhkthjkMnEPZgc~t~4bMcdG}^e`v_e7@Z+90o3(+-o7vgn?iP{nR4*;^( zS0ao$z}-H{gV8sIXKdF~K11*TZq=hG_&_+74BmVfsw9eom>k7$42#UQ+BzsSVIn*0 zsfs3`UsPX|Bu{&G)X1XZMs~jTz!&+D5(cIi zDzR{@Xj6YcSSV5{f~7=i51I>a>r<<>DI^s=G@RJwyVVOlp<}T{60C8Tlx6CGvKVB+ zPWDK4AYaV#hCY*+lM8cHZZ>fx)*)80YLUN~v-Rdp+9BH%A_z9`GCD9RCs%)`>fw;Q zrawt2m|Dm=22%}IZG!L{1}ZoGr1nqzthdF3&+3T+N7$)=(HNYqJKQt<4hLz}MQW zueDi!_}Z*qCqtR6;gNpl+ANB8x!D_Y5I^kye52|~0x~x$o-_sERXjKTj>jA_nA1$) zq{=KC=(_pK#T8mgZ>=uN?M9Manr z_XL`)*ov8y5^Q3oN>1S!8+~Ct=(8bPijA|L9xW14-F^_m1`DHH7ZQk{LfuzbFflNX ztcK%AZ{HYsw5KL$m&QaX@p#m6jBpLnuarH!nJv{LVs>d0Q6ngs=@l`La>exfg4Myq z!Pz0Bb-0&6_lRopo`gG|v6-4NM~i$}$+>I6H8GKddDpzwnks!aJ6~Kn@Fr{0eDeTD zhKQHf&swoq|Ejmww6c0LeK)%SmPBQRYJKU)qSP=bb+*hqt{PaLDW=R^8YO7I24ka0 z7jX+{bx)QGQPK_=uH=17uN!*^;^1Kehp0%R=2W+#kQPOs6u=KPTiytUwrhM+A|e?ogcJoTIbl){ETq9i=KIchD|42s#d4(cO^q

    hkZAo5=p7Cs}uL1-? z5n~Ww1E6H}#(ektJC8h>RRpEXEJ)TyXz!gFi{PFAwqZ<;^tfn{E6;s-@0Vn+;lcuUqeFC z*bT71Ad3J;H!ahqun`?(uvYEM7cc6 z0D3}Zn4hRmGXsfLkv`Oh`PsBB1G|%QJ)ueJWAw=y8`TcfYy!0)hF`YEMn3^sE9_V< zqZ4Hc2ewsRB5xSrBNG+fqfb*&eWXb|M%w;*iy@i@nFQ?^IUUf9qc3a#Dw1fpx>(FE zWRvJ8Hbe(-g@B0ln07EkX`*j%rcwrEX;Pdm(HIhW^<7uU5(c=*CR=`ZF@Vh4s!5tRN)UssL^JV8AYfOfZl=>`JqN|^%sK?5W+EjRdR zS`JIzhF{ZiU(<45ep;@K5H78du%zX5G@4CJoWM=U8jV)HM$k}4qg8h(fOzNkr^Ova zNbuh_8m%@5oD6pOBa{XD;mPwS#}7}AUOX=_Q=)kC>!TkZKL6o~9O+IyK;i)Z^BiiY zPwichSDQ^Ct)J5A`J(uX{`r4qN=C*=V4dQVUyfg}3&Eok&aYQ9 zI?>j=y0+as!kt?<{~f*q`om~S0shK1m;?NHagIef_an&kw25$K zJ#12hfso)5BtxkaT=h!|n_>FEZarHsp#@GZV9B6kkH>PH&9}47;#3CSZ{dO4!L%%B zv7wr=C_j}M#8Yt)Bw{2d2crB9MEPNks#qRypMFxRClcF9cdXIeht(VGSa+C51$bHy z`9=tJBz)d`KxO0Mh#Gc>Zxy0MO`*ierq-^_ibO$jmc{B7= zrql%S(o&Z+!ywd^c*n1mMsv(W0m-&WgepfUi7h>)bczP`Ev?^T9`n}NGhkX`Pi1qm z6bh;@W~SNUl*Fj`L7!VXr(5)oBUF`y6Gwfhf`(1()A0=krD8A+@a6RtTxSh&c)g)<4&aeXiQbVco?+np zdlJ+baE||m%mSWg3y91)29Ph;Z>IQ17njVH)8d@27Yx0aFVBb%!L@inv-ug_E-{~b zZU8b(N8cyyG31@l4+y4oYEpmEeq%RH-H?Ky>Iey~aeJxF( z))kB=cN9D(@g${_;L3?Z;+iB9GkwN@tg!&`b2k{a{B}wjd%D@t;u;FL<08#$Kz&oO zoBjsgT22vwU!$&Big1{RDKB<;dA(Z5x(9UNPj?r8gO>3sF#yIFxeT7jBpP(Q zyS{q-<3ne=#lSRbmFPbLP-#fVQISx?Wzjlcr&d|uV;SR$4zBMmO1aoK_(uAOVu!M! zPC}E9t{_-8ut58MjpZHgI*j2}!wZ?^(b2k(YlvE6!kbbs1{1pk@CB_PwZQ-&AW`i2 z^&|O)UIcZu$G|lr0U~bKsN|xWF)*5TG-i{z0TpmdfZ9`MqDR1DuPtyY{k-kg;>?N6 z`ompdU$zk72QkwVOwg89?JK7I_`Hmv+Z-8Gzq9Ol8#;&>BC3kCZ0o_6XX;*p?U>%q%;hg+$?AuXUg8(c|+QDQ3fs3@kYW|LlbSH(# zev3;X1TYCCv}A~CP;~l@N;Qxq8ChEI<{*d2CiiK!u*G8d2DUFwUg#n^y}VRRWznWW z1*S|=f)$g<3y`C|w|$45^ON#!M0ZLN^K={v8sJA&S$zi?=WGv9iA2?88aZ+O0ixs+ZuUv zo*jLh-jS*m@*@LOU3wmfMP|fIlOQ1m@{nc|Ln)_;&y$*Ld;nA9fb1WLezrRz#6CwI zBoafhzW}MMCNhuJ2qjt`s}!XczyOuTBCP4sq^M$VbHTG0kAL~;mzS@DGJF>X(BOby zE}ec`=xP8S⁢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

    tV^9&d0_@Nx&-f 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 Xu;d3}RQ>sf{b$d;*50!f^UnVQ>Z>h+ literal 0 HcmV?d00001 diff --git a/docs/rsaeuro.asc b/docs/rsaeuro.asc old mode 100755 new mode 100644 diff --git a/docs/rsaeuro.ps b/docs/rsaeuro.ps deleted file mode 100755 index 04d79c64b65bb1f85725c8765c1a990c5e1c6860..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 266231 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 delta 12187 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 diff --git a/docs/scripts.txt b/docs/scripts.txt old mode 100755 new mode 100644 diff --git a/docs/todo b/docs/todo old mode 100755 new mode 100644 index 4ba6cdc..d1f6c02 --- a/docs/todo +++ b/docs/todo @@ -14,5 +14,5 @@ Well Heres the stuff I have to do. * GSS-API - +* X.509 Certificates diff --git a/install/msdos/makefile.bcc b/install/msdos/makefile.bcc old mode 100755 new mode 100644 index 0d902c4..c410839 --- a/install/msdos/makefile.bcc +++ b/install/msdos/makefile.bcc @@ -1,94 +1,94 @@ -# This is a MAKEFILE for Borland C++ Make - -# extension for object files -O = obj - -# commands -CC = bcc -LIB = tlib - -# name of temporary library script -TEMPFILE = $(TEMP)\temp.mak - -# The places to look for include files (in order). -INCL = -I. -I$(RSAEURODIR) - -# There are no assembler routines for TASM/MASM -# You do have choice to use ansi or not. - -ANSISTD = 0 - -# Utility routines. -del = del -COPY = copy - -# Normal C flags. -# Change -3 to use non 386 instructions. -#CFLAGS = -3 -ml -f- -O -d $(INCL) -c -#CFLAGSx = -3 -ml -f- -O -d $(INCL) - -# Use ANSI ? -# Change -3 to use non 386 instructions. -CFLAGS = -3 -ml -f- -O -d -DUSE_ANSI=$(ANSISTD) $(INCL) -c -CFLAGSx = -3 -ml -f- -O -d -DUSE_ANSI=$(ANSISTD) $(INCL) - -# The location of the common source directory. -RSAEURODIR = ..\source\# - -RSAEUROLIB = rsaeuro.lib - -RSAREFLIB = rsaref.lib - -# The location of the demo source directory. -DEMODIR = ..\demo\# - -all : $(RSAEUROLIB) demo - -$(RSAREFLIB) : $(RSAEUROLIB) - $(COPY) $(RSAEUROLIB) $(RSAREFLIB) - -demo : redemo mdemo randemo - -randemo : randemo.$(O) $(RSAEUROLIB) - $(CC) $(CFLAGSx) randemo.$(O) $(RSAEUROLIB) - -mdemo : mdemo.$(O) $(RSAEUROLIB) - $(CC) $(CFLAGSx) mdemo.$(O) $(RSAEUROLIB) - -redemo : redemo.$(O) $(RSAEUROLIB) - $(CC) $(CFLAGSx) redemo.$(O) $(RSAEUROLIB) - -$(RSAEUROLIB) : desc.$(O) shsc.$(O) md2c.$(O) md4c.$(O) md5c.$(O) nn.$(O) prime.$(O)\ - rsa.$(O) r_encode.$(O) r_dh.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O)\ - r_stdlib.$(O) rsa.rsp - @if NOT EXIST $@ $(LIB) $@ - @$(LIB) $(RSAEUROLIB) /C /E @rsa.rsp - -randemo.$(O) : $(DEMODIR)randemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h - $(CC) $(CFLAGS) $(DEMODIR)randemo.c - -mdemo.$(O) : $(DEMODIR)mdemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h - $(CC) $(CFLAGS) $(DEMODIR)mdemo.c - -redemo.$(O) : $(DEMODIR)redemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h - $(CC) $(CFLAGS) $(DEMODIR)redemo.c - -rsa.rsp : - copy &&| --+desc.obj & --+md2c.obj & --+md4c.obj & --+shsc.obj & --+md5c.obj & --+nn.obj & --+prime.obj & --+rsa.obj & --+r_dh.obj & --+r_encode.obj & --+r_enhanc.obj & --+r_keygen.obj & --+r_random.obj & --+r_stdlib.obj -| rsa.rsp - -!INCLUDE $(RSAEURODIR)targets.mak +# This is a MAKEFILE for Borland C++ Make + +# extension for object files +O = obj + +# commands +CC = bcc +LIB = tlib + +# name of temporary library script +TEMPFILE = $(TEMP)\temp.mak + +# The places to look for include files (in order). +INCL = -I. -I$(RSAEURODIR) + +# There are no assembler routines for TASM/MASM +# You do have choice to use ansi or not. + +ANSISTD = 0 + +# Utility routines. +del = del +COPY = copy + +# Normal C flags. +# Change -3 to use non 386 instructions. +#CFLAGS = -3 -ml -f- -O -d $(INCL) -c +#CFLAGSx = -3 -ml -f- -O -d $(INCL) + +# Use ANSI ? +# Change -3 to use non 386 instructions. +CFLAGS = -3 -ml -f- -O -d -DUSE_ANSI=$(ANSISTD) $(INCL) -c +CFLAGSx = -3 -ml -f- -O -d -DUSE_ANSI=$(ANSISTD) $(INCL) + +# The location of the common source directory. +RSAEURODIR = ..\source\# + +RSAEUROLIB = rsaeuro.lib + +RSAREFLIB = rsaref.lib + +# The location of the demo source directory. +DEMODIR = ..\demo\# + +all : $(RSAEUROLIB) demo + +$(RSAREFLIB) : $(RSAEUROLIB) + $(COPY) $(RSAEUROLIB) $(RSAREFLIB) + +demo : redemo mdemo randemo + +randemo : randemo.$(O) $(RSAEUROLIB) + $(CC) $(CFLAGSx) randemo.$(O) $(RSAEUROLIB) + +mdemo : mdemo.$(O) $(RSAEUROLIB) + $(CC) $(CFLAGSx) mdemo.$(O) $(RSAEUROLIB) + +redemo : redemo.$(O) $(RSAEUROLIB) + $(CC) $(CFLAGSx) redemo.$(O) $(RSAEUROLIB) + +$(RSAEUROLIB) : desc.$(O) shsc.$(O) md2c.$(O) md4c.$(O) md5c.$(O) nn.$(O) prime.$(O)\ + rsa.$(O) r_encode.$(O) r_dh.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O)\ + r_stdlib.$(O) rsa.rsp + @if NOT EXIST $@ $(LIB) $@ + @$(LIB) $(RSAEUROLIB) /C /E @rsa.rsp + +randemo.$(O) : $(DEMODIR)randemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)randemo.c + +mdemo.$(O) : $(DEMODIR)mdemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)mdemo.c + +redemo.$(O) : $(DEMODIR)redemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)redemo.c + +rsa.rsp : + copy &&| +-+desc.obj & +-+md2c.obj & +-+md4c.obj & +-+shsc.obj & +-+md5c.obj & +-+nn.obj & +-+prime.obj & +-+rsa.obj & +-+r_dh.obj & +-+r_encode.obj & +-+r_enhanc.obj & +-+r_keygen.obj & +-+r_random.obj & +-+r_stdlib.obj +| rsa.rsp + +!INCLUDE $(RSAEURODIR)targets.mak diff --git a/install/msdos/makefile.wat b/install/msdos/makefile.wat new file mode 100644 index 0000000..63457e6 --- /dev/null +++ b/install/msdos/makefile.wat @@ -0,0 +1,152 @@ +# This is a makefile for watcom compatible make. +# This seems to work with Version 10.5 of Watcom C/C++ +# It produces DOS4GW executables and character mode Watcom NT executables + +# extension for object files +O = obj + +# commands +CC = wcc386 +LIB = wlib +ASM = as + +# name of temporary library script +TEMPFILE = $(TEMP)\temp.mak + +# Watcom Standard include directory, change to suit +STDINCDIR = \watcom\include + +# The places to look for include files (in order). +INCL = -i. -I$(RSAEURODIR) -I$(STDINCDIR) + +# Extra Defs + +# To select CPU type set CPUT to any of the following +# +# 386 = i386+ processor, 80386 and above processor +# 68k = M680x0 series processor. +# +# Leave empty to disable assembler routines. +# Not Used in Watcom Version. +# CPUT = 386 + +# Set to 1 for ANSI Standard Routine to be Used, only availible +# if assembler routines not it use. +# Dosn't seem to work with Watcom ?? +# ANSISTD = 1 + +# utility routines +del = del +COPY = copy + +# name of main executable to build +PROG = all + +# Standard DOS4GW Executable Flags. Change -3s to -4s for i486 +CFLAGS = $(INCL) -3s -zq -ox -r -sg -zm -zdf -dPROTOTYPES=0 + +# Windows Win32 Executable Flags, works for 10.5 +# CFLAGS = $(INCL) -4s -zq -ox -r -sg -dPROTOTYPES=0 + +ASMFL = $(INCL) -c -Wa,-L +MFLAGS = -I. -I$(RSAEURODIR) + +# The location of the common source directory. +RSAEURODIR = ..\source\ +RSAEUROLIB = rsaeuro.lib +RSAREFLIB = rsaref.lib + +# The location of the demo source directory. +DEMODIR = ..\demo\ + +all : demo $(RSAREFLIB) + +$(RSAREFLIB) : $(RSAEUROLIB) + $(COPY) $(RSAEUROLIB) $(RSAREFLIB) + +demo : redemo mdemo randemo + +randemo.exe : randemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 randemo.$(O) $(RSAEUROLIB) + del *.$(O) + +mdemo.exe : mdemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 mdemo.$(O) $(RSAEUROLIB) + del *.$(O) + +redemo.exe : redemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 redemo.$(O) $(RSAEUROLIB) + del *.$(O) + +$(RSAEUROLIB) : desc.$(O) shsc.$(O) md2c.$(O) md4c.$(O) md5c.$(O) nn.$(O) prime.$(O) rsa.$(O) r_encode.$(O) r_dh.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O) r_stdlib.$(O) + $(LIB) -n $@ @rsa.wat + +randemo.$(O) : $(DEMODIR)randemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)randemo.c + +mdemo.$(O) : $(DEMODIR)mdemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)mdemo.c + +redemo.$(O) : $(DEMODIR)redemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)redemo.c + +desc.$(O) : $(RSAEURODIR)desc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)des.h + $(CC) $(CFLAGS) $(RSAEURODIR)desc.c + echo -+$@ > rsa.wat + +shsc.$(O) : $(RSAEURODIR)shsc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)shs.h + $(CC) $(CFLAGS) $(RSAEURODIR)shsc.c + echo -+$@ >> rsa.wat + +md2c.$(O) : $(RSAEURODIR)md2c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md2.h + $(CC) $(CFLAGS) $(RSAEURODIR)md2c.c + echo -+$@ >> rsa.wat + +md4c.$(O) : $(RSAEURODIR)md4c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md4.h + $(CC) $(CFLAGS) $(RSAEURODIR)md4c.c + echo -+$@ >> rsa.wat + +md5c.$(O) : $(RSAEURODIR)md5c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md5.h + $(CC) $(CFLAGS) $(RSAEURODIR)md5c.c + echo -+$@ >> rsa.wat + +nn.$(O) : $(RSAEURODIR)nn.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)nn.h + $(CC) $(CFLAGS) $(RSAEURODIR)nn.c + echo -+$@ >> rsa.wat + +prime.$(O) : $(RSAEURODIR)prime.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)prime.c + echo -+$@ >> rsa.wat + +rsa.$(O) : $(RSAEURODIR)rsa.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)rsa.h $(RSAEURODIR)nn.h + $(CC) $(CFLAGS) $(RSAEURODIR)rsa.c + echo -+$@ >> rsa.wat + +r_dh.$(O) : $(RSAEURODIR)r_dh.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_dh.c + echo -+$@ >> rsa.wat + +r_encode.$(O) : $(RSAEURODIR)r_encode.c $(RSAEURODIR)rsaeuro.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_encode.c + echo -+$@ >> rsa.wat + +r_enhanc.$(O) : $(RSAEURODIR)r_enhanc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)rsa.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_enhanc.c + echo -+$@ >> rsa.wat + +r_keygen.$(O) : $(RSAEURODIR)r_keygen.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_keygen.c + echo -+$@ >> rsa.wat + +r_random.$(O) : $(RSAEURODIR)r_random.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)md5.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_random.c + echo -+$@ >> rsa.wat + +r_stdlib.$(O) : $(RSAEURODIR)r_stdlib.c $(RSAEURODIR)rsaeuro.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_stdlib.c + echo -+$@ >> rsa.wat + +# Dependencies for header files + +$(RSAREDIR)rsaeuro.h : $(RSAEURODIR)shs.h $(RSAEURODIR)nn.h $(RSAEURODIR)md2.h $(RSAEURODIR)md5.h $(RSAEURODIR)des.h $(RSAEURODIR)global.h + diff --git a/install/readme.txt b/install/readme.txt new file mode 100644 index 0000000..37b8b12 --- /dev/null +++ b/install/readme.txt @@ -0,0 +1,13 @@ +The makefiles in the directories below + +UNIX - Unix GCC/CC type compiler makefile(s) +WIN32 - Win32 Watcom compiler makefile +MSDOS - MS-DOS system type compiler makefile(s) + +This has been tested using the following compilers + +Watcom 10.5 Win32 and Extended DOS +Borland 3.1+ +DJGPP +GCC For HP-UX, SunOS 4.xx, Linux +CC for HP-UX, SunOS 4.xx diff --git a/install/unix/makefile b/install/unix/makefile old mode 100755 new mode 100644 diff --git a/install/win32/makefile.wat b/install/win32/makefile.wat new file mode 100644 index 0000000..cab2db2 --- /dev/null +++ b/install/win32/makefile.wat @@ -0,0 +1,152 @@ +# This is a makefile for watcom compatible make. +# This seems to work with Version 10.5 of Watcom C/C++ +# It produces DOS4GW executables and character mode Watcom NT executables + +# extension for object files +O = obj + +# commands +CC = wcc386 +LIB = wlib +ASM = as + +# name of temporary library script +TEMPFILE = $(TEMP)\temp.mak + +# Watcom Standard include directory, change to suit +STDINCDIR = \watcom\include + +# The places to look for include files (in order). +INCL = -i. -I$(RSAEURODIR) -I$(STDINCDIR) + +# Extra Defs + +# To select CPU type set CPUT to any of the following +# +# 386 = i386+ processor, 80386 and above processor +# 68k = M680x0 series processor. +# +# Leave empty to disable assembler routines. +# Not Used in Watcom Version. +# CPUT = 386 + +# Set to 1 for ANSI Standard Routine to be Used, only availible +# if assembler routines not it use. +# Dosn't seem to work with Watcom ?? +# ANSISTD = 1 + +# utility routines +del = del +COPY = copy + +# name of main executable to build +PROG = all + +# Standard DOS4GW Executable Flags. Change -3s to -4s for i486 +# CFLAGS = $(INCL) -3s -zq -ox -r -sg -zm -zdf -dPROTOTYPES=0 + +# Windows Win32 Executable Flags, works for 10.5 +CFLAGS = $(INCL) -4s -zq -ox -r -sg -dPROTOTYPES=0 + +ASMFL = $(INCL) -c -Wa,-L +MFLAGS = -I. -I$(RSAEURODIR) + +# The location of the common source directory. +RSAEURODIR = ..\source\ +RSAEUROLIB = rsaeuro.lib +RSAREFLIB = rsaref.lib + +# The location of the demo source directory. +DEMODIR = ..\demo\ + +all : demo $(RSAREFLIB) + +$(RSAREFLIB) : $(RSAEUROLIB) + $(COPY) $(RSAEUROLIB) $(RSAREFLIB) + +demo : redemo mdemo randemo + +randemo.exe : randemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 randemo.$(O) $(RSAEUROLIB) + del *.$(O) + +mdemo.exe : mdemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 mdemo.$(O) $(RSAEUROLIB) + del *.$(O) + +redemo.exe : redemo.$(O) $(RSAEUROLIB) + wcl386 -k65535 redemo.$(O) $(RSAEUROLIB) + del *.$(O) + +$(RSAEUROLIB) : desc.$(O) shsc.$(O) md2c.$(O) md4c.$(O) md5c.$(O) nn.$(O) prime.$(O) rsa.$(O) r_encode.$(O) r_dh.$(O) r_enhanc.$(O) r_keygen.$(O) r_random.$(O) r_stdlib.$(O) + $(LIB) -n $@ @rsa.wat + +randemo.$(O) : $(DEMODIR)randemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)randemo.c + +mdemo.$(O) : $(DEMODIR)mdemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)mdemo.c + +redemo.$(O) : $(DEMODIR)redemo.c $(RSAEURODIR)global.h $(RSAEURODIR)rsaref.h + $(CC) $(CFLAGS) $(DEMODIR)redemo.c + +desc.$(O) : $(RSAEURODIR)desc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)des.h + $(CC) $(CFLAGS) $(RSAEURODIR)desc.c + echo -+$@ > rsa.wat + +shsc.$(O) : $(RSAEURODIR)shsc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)shs.h + $(CC) $(CFLAGS) $(RSAEURODIR)shsc.c + echo -+$@ >> rsa.wat + +md2c.$(O) : $(RSAEURODIR)md2c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md2.h + $(CC) $(CFLAGS) $(RSAEURODIR)md2c.c + echo -+$@ >> rsa.wat + +md4c.$(O) : $(RSAEURODIR)md4c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md4.h + $(CC) $(CFLAGS) $(RSAEURODIR)md4c.c + echo -+$@ >> rsa.wat + +md5c.$(O) : $(RSAEURODIR)md5c.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)md5.h + $(CC) $(CFLAGS) $(RSAEURODIR)md5c.c + echo -+$@ >> rsa.wat + +nn.$(O) : $(RSAEURODIR)nn.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)nn.h + $(CC) $(CFLAGS) $(RSAEURODIR)nn.c + echo -+$@ >> rsa.wat + +prime.$(O) : $(RSAEURODIR)prime.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)prime.c + echo -+$@ >> rsa.wat + +rsa.$(O) : $(RSAEURODIR)rsa.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)rsa.h $(RSAEURODIR)nn.h + $(CC) $(CFLAGS) $(RSAEURODIR)rsa.c + echo -+$@ >> rsa.wat + +r_dh.$(O) : $(RSAEURODIR)r_dh.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_dh.c + echo -+$@ >> rsa.wat + +r_encode.$(O) : $(RSAEURODIR)r_encode.c $(RSAEURODIR)rsaeuro.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_encode.c + echo -+$@ >> rsa.wat + +r_enhanc.$(O) : $(RSAEURODIR)r_enhanc.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)rsa.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_enhanc.c + echo -+$@ >> rsa.wat + +r_keygen.$(O) : $(RSAEURODIR)r_keygen.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)nn.h $(RSAEURODIR)prime.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_keygen.c + echo -+$@ >> rsa.wat + +r_random.$(O) : $(RSAEURODIR)r_random.c $(RSAEURODIR)rsaeuro.h $(RSAEURODIR)r_random.h $(RSAEURODIR)md5.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_random.c + echo -+$@ >> rsa.wat + +r_stdlib.$(O) : $(RSAEURODIR)r_stdlib.c $(RSAEURODIR)rsaeuro.h + $(CC) $(CFLAGS) $(RSAEURODIR)r_stdlib.c + echo -+$@ >> rsa.wat + +# Dependencies for header files + +$(RSAREDIR)rsaeuro.h : $(RSAEURODIR)shs.h $(RSAEURODIR)nn.h $(RSAEURODIR)md2.h $(RSAEURODIR)md5.h $(RSAEURODIR)des.h $(RSAEURODIR)global.h + diff --git a/readme b/readme old mode 100755 new mode 100644 index 738198c..0d71c32 --- a/readme +++ b/readme @@ -1,18 +1,18 @@ -RSAEURO Version 1.02 Distribution - -In this distribution the various files are included in the directories -below. - -DOCS - RSAEURO Documentation Directory -DEMO - Demo Applications Directory -SOURCE - Source Code Directory -SCRIPTS - Demo Applications Script Files -INSTALL - Installation Instructions - -The documentation is supplied in both Postscript and ASCII formats. -(At the moment due a problem with Windows Word The main docs are only -availible as Postscript.) - -Please report any problems with the code or documentation to me on -the bug report form. Also any problems you may have in using the -toolkit. Please read the bug report form for more details. +RSAEURO Version 1.03 Distribution + +In this distribution the various files are included in the directories +below. + +DOCS - RSAEURO Documentation Directory +DEMO - Demo Applications Directory +SOURCE - Source Code Directory +SCRIPTS - Demo Applications Script Files +INSTALL - Installation Instructions + +The documentation is supplied in both Postscript and ASCII formats. +(At the moment due a problem with Windows Word The main docs are only +availible as Postscript.) + +Please report any problems with the code or documentation to me on +the bug report form. Also any problems you may have in using the +toolkit. Please read the bug report form for more details. diff --git a/scripts/1024-1.env b/scripts/1024-1.env old mode 100755 new mode 100644 diff --git a/scripts/1024-1.iv b/scripts/1024-1.iv old mode 100755 new mode 100644 diff --git a/scripts/1024-1.key b/scripts/1024-1.key old mode 100755 new mode 100644 diff --git a/scripts/1024-5.sig b/scripts/1024-5.sig old mode 100755 new mode 100644 diff --git a/scripts/1024.in b/scripts/1024.in old mode 100755 new mode 100644 diff --git a/scripts/1024.key b/scripts/1024.key old mode 100755 new mode 100644 diff --git a/scripts/508-1.env b/scripts/508-1.env old mode 100755 new mode 100644 diff --git a/scripts/508-1.iv b/scripts/508-1.iv old mode 100755 new mode 100644 diff --git a/scripts/508-1.key b/scripts/508-1.key old mode 100755 new mode 100644 diff --git a/scripts/508-5.sig b/scripts/508-5.sig old mode 100755 new mode 100644 diff --git a/scripts/508.in b/scripts/508.in old mode 100755 new mode 100644 diff --git a/scripts/508.key b/scripts/508.key old mode 100755 new mode 100644 diff --git a/scripts/512a.in b/scripts/512a.in old mode 100755 new mode 100644 diff --git a/scripts/512a1.env b/scripts/512a1.env old mode 100755 new mode 100644 diff --git a/scripts/512a1.iv b/scripts/512a1.iv old mode 100755 new mode 100644 diff --git a/scripts/512a1.key b/scripts/512a1.key old mode 100755 new mode 100644 diff --git a/scripts/512a1big.env b/scripts/512a1big.env old mode 100755 new mode 100644 diff --git a/scripts/512a1big.iv b/scripts/512a1big.iv old mode 100755 new mode 100644 diff --git a/scripts/512a1big.key b/scripts/512a1big.key old mode 100755 new mode 100644 diff --git a/scripts/512a2.env b/scripts/512a2.env old mode 100755 new mode 100644 diff --git a/scripts/512a2.iv b/scripts/512a2.iv old mode 100755 new mode 100644 diff --git a/scripts/512a2.key b/scripts/512a2.key old mode 100755 new mode 100644 diff --git a/scripts/512a2.sig b/scripts/512a2.sig old mode 100755 new mode 100644 diff --git a/scripts/512a3.env b/scripts/512a3.env old mode 100755 new mode 100644 diff --git a/scripts/512a3.iv b/scripts/512a3.iv old mode 100755 new mode 100644 diff --git a/scripts/512a3.key b/scripts/512a3.key old mode 100755 new mode 100644 diff --git a/scripts/512a5.sig b/scripts/512a5.sig old mode 100755 new mode 100644 diff --git a/scripts/512a5big.sig b/scripts/512a5big.sig old mode 100755 new mode 100644 diff --git a/scripts/512ax.env b/scripts/512ax.env old mode 100755 new mode 100644 diff --git a/scripts/512ax.iv b/scripts/512ax.iv old mode 100755 new mode 100644 diff --git a/scripts/512ax.key b/scripts/512ax.key old mode 100755 new mode 100644 diff --git a/scripts/767-1.env b/scripts/767-1.env old mode 100755 new mode 100644 diff --git a/scripts/767-1.iv b/scripts/767-1.iv old mode 100755 new mode 100644 diff --git a/scripts/767-1.key b/scripts/767-1.key old mode 100755 new mode 100644 diff --git a/scripts/767-5.sig b/scripts/767-5.sig old mode 100755 new mode 100644 diff --git a/scripts/767.in b/scripts/767.in old mode 100755 new mode 100644 diff --git a/scripts/767.key b/scripts/767.key old mode 100755 new mode 100644 diff --git a/scripts/bigfile b/scripts/bigfile old mode 100755 new mode 100644 index 3d4f37b..a655e67 --- a/scripts/bigfile +++ b/scripts/bigfile @@ -1,97 +1,97 @@ -Envelope opened - -This is a big file - - - - - - - - - - - - - - - - - - - - - -Envelope opened - -This is a big file - - - - - - - - - - - - - - - - - - - - - -Envelope opened - -This is a big file - - - - - - - - - - - - - - - - - - - - - -Envelope opened - -This is a big file - - - - - - - - - - - - - - - - - - - - - -Done +Envelope opened + +This is a big file + + + + + + + + + + + + + + + + + + + + + +Envelope opened + +This is a big file + + + + + + + + + + + + + + + + + + + + + +Envelope opened + +This is a big file + + + + + + + + + + + + + + + + + + + + + +Envelope opened + +This is a big file + + + + + + + + + + + + + + + + + + + + + +Done diff --git a/scripts/file b/scripts/file old mode 100755 new mode 100644 index d27e6b2..e20e856 --- a/scripts/file +++ b/scripts/file @@ -1 +1 @@ -Envelope opened. +Envelope opened. diff --git a/source/des.h b/source/des.h old mode 100755 new mode 100644 index 932c290..cda8056 --- a/source/des.h +++ b/source/des.h @@ -1,23 +1,21 @@ /* DES.H - header file for DESC.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid + same naming comventions that RSAREF uses. This should aid direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - DES Code header file. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ #ifndef _DES_H_ diff --git a/source/des386.s b/source/des386.s old mode 100755 new mode 100644 index fc31234..4607040 --- a/source/des386.s +++ b/source/des386.s @@ -1,7 +1,7 @@ /* DES386.S - Data Encryption Standard routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. @@ -26,8 +26,6 @@ 0.91 Current revision some minor bug fixes to original code. Comments revised to reflect original C code. - - 1.00 23/6/95, Final Release Version */ /* Crafty DES Function */ diff --git a/source/desc.c b/source/desc.c old mode 100755 new mode 100644 index 99368fd..79bfda4 --- a/source/desc.c +++ b/source/desc.c @@ -1,797 +1,797 @@ -/* - DESC.C - Data Encryption Standard routines for RSAEURO - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - Based on Outerbridge's D3DES (V5.09) 1992 Vintage. - - DESX(tm) - RSA Data Security. - - DES386 to be define ONLY in conjunction with 386 compiled - code. - - All Trademarks Acknowledged. - - Revision history - 0.90 First revision, this was the original retrofitted D3DES - version. - - 0.91 Second revision, retrofitted new S-box array and new desfunc - routine. Marginally quicker code improves DES throughput. - - 0.92 Current revision, added support for 386 assembler desfunc - routine, with altered S boxes and key generation to support easier - S box look up. Code that uses 386 desfunc is about 80K per sec - faster than RSAREF(tm) code. -*/ - -#include "rsaeuro.h" -#include "des.h" - -static UINT2 bytebit[8] = { - 0200, 0100, 040, 020, 010, 04, 02, 01 -}; - -static UINT4 bigbyte[24] = { - 0x800000L, 0x400000L, 0x200000L, 0x100000L, - 0x80000L, 0x40000L, 0x20000L, 0x10000L, - 0x8000L, 0x4000L, 0x2000L, 0x1000L, - 0x800L, 0x400L, 0x200L, 0x100L, - 0x80L, 0x40L, 0x20L, 0x10L, - 0x8L, 0x4L, 0x2L, 0x1L -}; - -static unsigned char totrot[16] = { - 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 -}; - -static unsigned char pc1[56] = { - 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, - 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, - 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, - 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 -}; - -static unsigned char pc2[48] = { - 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, - 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, - 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, - 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 -}; - -#ifndef DES386 - -UINT4 Spbox[8][64] = { - 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, - 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, - 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, - 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, - 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, - 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, - 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, - 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, - 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, - 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, - 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, - 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, - 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, - 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, - 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, - 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L, - 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, - 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, - 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, - 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, - 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, - 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, - 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, - 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, - 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, - 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, - 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, - 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, - 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, - 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, - 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, - 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L, - 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, - 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, - 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, - 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, - 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, - 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, - 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, - 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, - 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, - 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, - 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, - 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, - 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, - 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, - 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, - 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L, - 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, - 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, - 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, - 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, - 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, - 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, - 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, - 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, - 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, - 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, - 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, - 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, - 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, - 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, - 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, - 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L, - 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, - 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, - 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, - 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, - 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, - 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, - 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, - 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, - 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, - 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, - 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, - 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, - 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, - 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, - 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, - 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L, - 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, - 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, - 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, - 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, - 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, - 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, - 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, - 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, - 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, - 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, - 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, - 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, - 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, - 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, - 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, - 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L, - 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, - 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, - 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, - 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, - 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, - 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, - 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, - 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, - 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, - 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, - 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, - 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, - 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, - 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, - 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, - 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L, - 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, - 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, - 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, - 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, - 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, - 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, - 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, - 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, - 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, - 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, - 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, - 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, - 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, - 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, - 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, - 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L -}; - -#else - /* S box tables for assembler desfunc */ - -unsigned long Spbox[8][64] = { - 0x04041000,0x00000000,0x00040000,0x04041010, - 0x04040010,0x00041010,0x00000010,0x00040000, - 0x00001000,0x04041000,0x04041010,0x00001000, - 0x04001010,0x04040010,0x04000000,0x00000010, - 0x00001010,0x04001000,0x04001000,0x00041000, - 0x00041000,0x04040000,0x04040000,0x04001010, - 0x00040010,0x04000010,0x04000010,0x00040010, - 0x00000000,0x00001010,0x00041010,0x04000000, - 0x00040000,0x04041010,0x00000010,0x04040000, - 0x04041000,0x04000000,0x04000000,0x00001000, - 0x04040010,0x00040000,0x00041000,0x04000010, - 0x00001000,0x00000010,0x04001010,0x00041010, - 0x04041010,0x00040010,0x04040000,0x04001010, - 0x04000010,0x00001010,0x00041010,0x04041000, - 0x00001010,0x04001000,0x04001000,0x00000000, - 0x00040010,0x00041000,0x00000000,0x04040010, - 0x00420082,0x00020002,0x00020000,0x00420080, - 0x00400000,0x00000080,0x00400082,0x00020082, - 0x00000082,0x00420082,0x00420002,0x00000002, - 0x00020002,0x00400000,0x00000080,0x00400082, - 0x00420000,0x00400080,0x00020082,0x00000000, - 0x00000002,0x00020000,0x00420080,0x00400002, - 0x00400080,0x00000082,0x00000000,0x00420000, - 0x00020080,0x00420002,0x00400002,0x00020080, - 0x00000000,0x00420080,0x00400082,0x00400000, - 0x00020082,0x00400002,0x00420002,0x00020000, - 0x00400002,0x00020002,0x00000080,0x00420082, - 0x00420080,0x00000080,0x00020000,0x00000002, - 0x00020080,0x00420002,0x00400000,0x00000082, - 0x00400080,0x00020082,0x00000082,0x00400080, - 0x00420000,0x00000000,0x00020002,0x00020080, - 0x00000002,0x00400082,0x00420082,0x00420000, - 0x00000820,0x20080800,0x00000000,0x20080020, - 0x20000800,0x00000000,0x00080820,0x20000800, - 0x00080020,0x20000020,0x20000020,0x00080000, - 0x20080820,0x00080020,0x20080000,0x00000820, - 0x20000000,0x00000020,0x20080800,0x00000800, - 0x00080800,0x20080000,0x20080020,0x00080820, - 0x20000820,0x00080800,0x00080000,0x20000820, - 0x00000020,0x20080820,0x00000800,0x20000000, - 0x20080800,0x20000000,0x00080020,0x00000820, - 0x00080000,0x20080800,0x20000800,0x00000000, - 0x00000800,0x00080020,0x20080820,0x20000800, - 0x20000020,0x00000800,0x00000000,0x20080020, - 0x20000820,0x00080000,0x20000000,0x20080820, - 0x00000020,0x00080820,0x00080800,0x20000020, - 0x20080000,0x20000820,0x00000820,0x20080000, - 0x00080820,0x00000020,0x20080020,0x00080800, - 0x02008004,0x00008204,0x00008204,0x00000200, - 0x02008200,0x02000204,0x02000004,0x00008004, - 0x00000000,0x02008000,0x02008000,0x02008204, - 0x00000204,0x00000000,0x02000200,0x02000004, - 0x00000004,0x00008000,0x02000000,0x02008004, - 0x00000200,0x02000000,0x00008004,0x00008200, - 0x02000204,0x00000004,0x00008200,0x02000200, - 0x00008000,0x02008200,0x02008204,0x00000204, - 0x02000200,0x02000004,0x02008000,0x02008204, - 0x00000204,0x00000000,0x00000000,0x02008000, - 0x00008200,0x02000200,0x02000204,0x00000004, - 0x02008004,0x00008204,0x00008204,0x00000200, - 0x02008204,0x00000204,0x00000004,0x00008000, - 0x02000004,0x00008004,0x02008200,0x02000204, - 0x00008004,0x00008200,0x02000000,0x02008004, - 0x00000200,0x02000000,0x00008000,0x02008200, - 0x00000400,0x08200400,0x08200000,0x08000401, - 0x00200000,0x00000400,0x00000001,0x08200000, - 0x00200401,0x00200000,0x08000400,0x00200401, - 0x08000401,0x08200001,0x00200400,0x00000001, - 0x08000000,0x00200001,0x00200001,0x00000000, - 0x00000401,0x08200401,0x08200401,0x08000400, - 0x08200001,0x00000401,0x00000000,0x08000001, - 0x08200400,0x08000000,0x08000001,0x00200400, - 0x00200000,0x08000401,0x00000400,0x08000000, - 0x00000001,0x08200000,0x08000401,0x00200401, - 0x08000400,0x00000001,0x08200001,0x08200400, - 0x00200401,0x00000400,0x08000000,0x08200001, - 0x08200401,0x00200400,0x08000001,0x08200401, - 0x08200000,0x00000000,0x00200001,0x08000001, - 0x00200400,0x08000400,0x00000401,0x00200000, - 0x00000000,0x00200001,0x08200400,0x00000401, - 0x80000040,0x81000000,0x00010000,0x81010040, - 0x81000000,0x00000040,0x81010040,0x01000000, - 0x80010000,0x01010040,0x01000000,0x80000040, - 0x01000040,0x80010000,0x80000000,0x00010040, - 0x00000000,0x01000040,0x80010040,0x00010000, - 0x01010000,0x80010040,0x00000040,0x81000040, - 0x81000040,0x00000000,0x01010040,0x81010000, - 0x00010040,0x01010000,0x81010000,0x80000000, - 0x80010000,0x00000040,0x81000040,0x01010000, - 0x81010040,0x01000000,0x00010040,0x80000040, - 0x01000000,0x80010000,0x80000000,0x00010040, - 0x80000040,0x81010040,0x01010000,0x81000000, - 0x01010040,0x81010000,0x00000000,0x81000040, - 0x00000040,0x00010000,0x81000000,0x01010040, - 0x00010000,0x01000040,0x80010040,0x00000000, - 0x81010000,0x80000000,0x01000040,0x80010040, - 0x00800000,0x10800008,0x10002008,0x00000000, - 0x00002000,0x10002008,0x00802008,0x10802000, - 0x10802008,0x00800000,0x00000000,0x10000008, - 0x00000008,0x10000000,0x10800008,0x00002008, - 0x10002000,0x00802008,0x00800008,0x10002000, - 0x10000008,0x10800000,0x10802000,0x00800008, - 0x10800000,0x00002000,0x00002008,0x10802008, - 0x00802000,0x00000008,0x10000000,0x00802000, - 0x10000000,0x00802000,0x00800000,0x10002008, - 0x10002008,0x10800008,0x10800008,0x00000008, - 0x00800008,0x10000000,0x10002000,0x00800000, - 0x10802000,0x00002008,0x00802008,0x10802000, - 0x00002008,0x10000008,0x10802008,0x10800000, - 0x00802000,0x00000000,0x00000008,0x10802008, - 0x00000000,0x00802008,0x10800000,0x00002000, - 0x10000008,0x10002000,0x00002000,0x00800008, - 0x40004100,0x00004000,0x00100000,0x40104100, - 0x40000000,0x40004100,0x00000100,0x40000000, - 0x00100100,0x40100000,0x40104100,0x00104000, - 0x40104000,0x00104100,0x00004000,0x00000100, - 0x40100000,0x40000100,0x40004000,0x00004100, - 0x00104000,0x00100100,0x40100100,0x40104000, - 0x00004100,0x00000000,0x00000000,0x40100100, - 0x40000100,0x40004000,0x00104100,0x00100000, - 0x00104100,0x00100000,0x40104000,0x00004000, - 0x00000100,0x40100100,0x00004000,0x00104100, - 0x40004000,0x00000100,0x40000100,0x40100000, - 0x40100100,0x40000000,0x00100000,0x40004100, - 0x00000000,0x40104100,0x00100100,0x40000100, - 0x40100000,0x40004000,0x40004100,0x00000000, - 0x40104100,0x00104000,0x00104000,0x00004100, - 0x00004100,0x00100100,0x40000000,0x40104000, -}; - -#endif - -void unscrunch PROTO_LIST ((unsigned char *, UINT4 *)); -void scrunch PROTO_LIST ((UINT4 *, unsigned char *)); -void deskey PROTO_LIST ((UINT4 *, unsigned char *, int)); -static void cookey PROTO_LIST ((UINT4 *, UINT4 *, int)); -void desfunc PROTO_LIST ((UINT4 *, UINT4 *)); - -/* Initialize context. Caller must zeroize the context when finished. */ - -void DES_CBCInit(context, key, iv, encrypt) -DES_CBC_CTX *context; /* context */ -unsigned char *key; /* key */ -unsigned char *iv; /* initializing vector */ -int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ -{ - /* Save encrypt flag to context. */ - context->encrypt = encrypt; - - /* Pack initializing vector into context. */ - - scrunch(context->iv, iv); - scrunch(context->originalIV, iv); - - /* Precompute key schedule */ - - deskey(context->subkeys, key, encrypt); -} - -/* DES-CBC block update operation. Continues a DES-CBC encryption - operation, processing eight-byte message blocks, and updating - the context. - - This requires len to be a multiple of 8. -*/ -int DES_CBCUpdate(context, output, input, len) -DES_CBC_CTX *context; /* context */ -unsigned char *output; /* output block */ -unsigned char *input; /* input block */ -unsigned int len; /* length of input and output blocks */ -{ - UINT4 inputBlock[2], work[2]; - unsigned int i; - - if(len % 8) /* block size check */ - return(RE_LEN); - - for(i = 0; i < len/8; i++) { - scrunch(inputBlock, &input[8*i]); - - /* Chain if encrypting. */ - - if(context->encrypt == 0) { - *work = *inputBlock; - *(work+1) = *(inputBlock+1); - }else{ - *work = *inputBlock ^ *context->iv; - *(work+1) = *(inputBlock+1) ^ *(context->iv+1); - } - - desfunc(work, context->subkeys); - - /* Chain if decrypting, then update IV. */ - - if(context->encrypt == 0) { - *work ^= *context->iv; - *(work+1) ^= *(context->iv+1); - *context->iv = *inputBlock; - *(context->iv+1) = *(inputBlock+1); - }else{ - *context->iv = *work; - *(context->iv+1) = *(work+1); - } - unscrunch (&output[8*i], work); - } - - /* Clear sensitive information. */ - - R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); - R_memset((POINTER)work, 0, sizeof(work)); - - return(IDOK); -} - -void DES_CBCRestart(context) -DES_CBC_CTX *context; /* context */ -{ - /* Restore the original IV */ - - *context->iv = *context->originalIV; - *(context->iv+1) = *(context->originalIV+1); -} - -/* Initialize context. Caller should clear the context when finished. - The key has the DES key, input whitener and output whitener concatenated. - This is the RSADSI special DES implementation. -*/ -void DESX_CBCInit(context, key, iv, encrypt) -DESX_CBC_CTX *context; /* context */ -unsigned char *key; /* DES key and whiteners */ -unsigned char *iv; /* DES initializing vector */ -int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ -{ - /* Save encrypt flag to context. */ - - context->encrypt = encrypt; - - /* Pack initializing vector and whiteners into context. */ - - scrunch(context->iv, iv); - scrunch(context->inputWhitener, key + 8); - scrunch(context->outputWhitener, key + 16); - /* Save the IV for use in Restart */ - scrunch(context->originalIV, iv); - - /* Precompute key schedule. */ - - deskey (context->subkeys, key, encrypt); -} - -/* DESX-CBC block update operation. Continues a DESX-CBC encryption - operation, processing eight-byte message blocks, and updating - the context. This is the RSADSI special DES implementation. - - Requires len to a multiple of 8. -*/ - -int DESX_CBCUpdate (context, output, input, len) -DESX_CBC_CTX *context; /* context */ -unsigned char *output; /* output block */ -unsigned char *input; /* input block */ -unsigned int len; /* length of input and output blocks */ -{ - UINT4 inputBlock[2], work[2]; - unsigned int i; - - if(len % 8) /* Length check */ - return(RE_LEN); - - for(i = 0; i < len/8; i++) { - scrunch(inputBlock, &input[8*i]); - - /* Chain if encrypting, and xor with whitener. */ - - if(context->encrypt == 0) { - *work = *inputBlock ^ *context->outputWhitener; - *(work+1) = *(inputBlock+1) ^ *(context->outputWhitener+1); - }else{ - *work = *inputBlock ^ *context->iv ^ *context->inputWhitener; - *(work+1) = *(inputBlock+1) ^ *(context->iv+1) ^ *(context->inputWhitener+1); - } - - desfunc(work, context->subkeys); - - /* Xor with whitener, chain if decrypting, then update IV. */ - - if(context->encrypt == 0) { - *work ^= *context->iv ^ *context->inputWhitener; - *(work+1) ^= *(context->iv+1) ^ *(context->inputWhitener+1); - *(context->iv) = *inputBlock; - *(context->iv+1) = *(inputBlock+1); - }else{ - *work ^= *context->outputWhitener; - *(work+1) ^= *(context->outputWhitener+1); - *context->iv = *work; - *(context->iv+1) = *(work+1); - } - unscrunch(&output[8*i], work); - } - - R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); - R_memset((POINTER)work, 0, sizeof(work)); - - return(IDOK); -} - -void DESX_CBCRestart(context) -DESX_CBC_CTX *context; /* context */ -{ - /* Restore the original IV */ - *context->iv = *context->originalIV; - *(context->iv+1) = *(context->originalIV+1); -} - -/* Initialize context. Caller must zeroize the context when finished. */ - -void DES3_CBCInit(context, key, iv, encrypt) -DES3_CBC_CTX *context; /* context */ -unsigned char *key; /* key */ -unsigned char *iv; /* initializing vector */ -int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ -{ - /* Copy encrypt flag to context. */ - context->encrypt = encrypt; - - /* Pack initializing vector into context. */ - - scrunch(context->iv, iv); - - /* Save the IV for use in Restart */ - scrunch(context->originalIV, iv); - - /* Precompute key schedules. */ - - deskey(context->subkeys[0], encrypt ? key : &key[16], encrypt); - deskey(context->subkeys[1], &key[8], !encrypt); - deskey(context->subkeys[2], encrypt ? &key[16] : key, encrypt); -} - -int DES3_CBCUpdate(context, output, input, len) -DES3_CBC_CTX *context; /* context */ -unsigned char *output; /* output block */ -unsigned char *input; /* input block */ -unsigned int len; /* length of input and output blocks */ -{ - UINT4 inputBlock[2], work[2]; - unsigned int i; - - if(len % 8) /* length check */ - return(RE_LEN); - - for(i = 0; i < len/8; i++) { - scrunch(inputBlock, &input[8*i]); - - /* Chain if encrypting. */ - - if(context->encrypt == 0) { - *work = *inputBlock; - *(work+1) = *(inputBlock+1); - } - else { - *work = *inputBlock ^ *context->iv; - *(work+1) = *(inputBlock+1) ^ *(context->iv+1); - } - - desfunc(work, context->subkeys[0]); - desfunc(work, context->subkeys[1]); - desfunc(work, context->subkeys[2]); - - /* Chain if decrypting, then update IV. */ - - if(context->encrypt == 0) { - *work ^= *context->iv; - *(work+1) ^= *(context->iv+1); - *context->iv = *inputBlock; - *(context->iv+1) = *(inputBlock+1); - } - else { - *context->iv = *work; - *(context->iv+1) = *(work+1); - } - unscrunch(&output[8*i], work); - } - - R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); - R_memset((POINTER)work, 0, sizeof(work)); - - return (0); -} - -void DES3_CBCRestart (context) -DES3_CBC_CTX *context; /* context */ -{ - /* Restore the original IV */ - *context->iv = *context->originalIV; - *(context->iv+1) = *(context->originalIV+1); -} - -void scrunch (into, outof) -UINT4 *into; -unsigned char *outof; -{ - *into = (*outof++ & 0xffL) << 24; - *into |= (*outof++ & 0xffL) << 16; - *into |= (*outof++ & 0xffL) << 8; - *into++ |= (*outof++ & 0xffL); - *into = (*outof++ & 0xffL) << 24; - *into |= (*outof++ & 0xffL) << 16; - *into |= (*outof++ & 0xffL) << 8; - *into |= (*outof & 0xffL); -} - -void unscrunch(into, outof) -unsigned char *into; -UINT4 *outof; -{ - *into++ = (unsigned char)((*outof >> 24) & 0xffL); - *into++ = (unsigned char)((*outof >> 16) & 0xffL); - *into++ = (unsigned char)((*outof >> 8) & 0xffL); - *into++ = (unsigned char)( *outof++ & 0xffL); - *into++ = (unsigned char)((*outof >> 24) & 0xffL); - *into++ = (unsigned char)((*outof >> 16) & 0xffL); - *into++ = (unsigned char)((*outof >> 8) & 0xffL); - *into = (unsigned char)( *outof & 0xffL); -} - -/* Compute DES Subkeys */ - -void deskey(subkeys, key, encrypt) -UINT4 subkeys[32]; -unsigned char key[8]; -int encrypt; -{ - UINT4 kn[32]; - int i, j, l, m, n; - unsigned char pc1m[56], pcr[56]; - - for(j = 0; j < 56; j++) { - l = pc1[j]; - m = l & 07; - pc1m[j] = (unsigned char)((key[l >> 3] & bytebit[m]) ? 1 : 0); - } - for(i = 0; i < 16; i++) { - m = i << 1; - n = m + 1; - kn[m] = kn[n] = 0L; - for(j = 0; j < 28; j++) { - l = j + totrot[i]; - if(l < 28) pcr[j] = pc1m[l]; - else pcr[j] = pc1m[l - 28]; - } - for(j = 28; j < 56; j++) { - l = j + totrot[i]; - if(l < 56) pcr[j] = pc1m[l]; - else pcr[j] = pc1m[l - 28]; - } - for(j = 0; j < 24; j++) { - if(pcr[pc2[j]]) - kn[m] |= bigbyte[j]; - if(pcr[pc2[j+24]]) - kn[n] |= bigbyte[j]; - } - } - cookey(subkeys, kn, encrypt); - -#ifdef DES386 - for(i=0;i < 32;i++) - subkeys[i] <<= 2; -#endif - - R_memset((POINTER)pc1m, 0, sizeof(pc1m)); - R_memset((POINTER)pcr, 0, sizeof(pcr)); - R_memset((POINTER)kn, 0, sizeof(kn)); -} - -static void cookey(subkeys, kn, encrypt) -UINT4 *subkeys; -UINT4 *kn; -int encrypt; -{ - UINT4 *cooked, *raw0, *raw1; - int increment; - unsigned int i; - - raw1 = kn; - cooked = encrypt ? subkeys : &subkeys[30]; - increment = encrypt ? 1 : -3; - - for (i = 0; i < 16; i++, raw1++) { - raw0 = raw1++; - *cooked = (*raw0 & 0x00fc0000L) << 6; - *cooked |= (*raw0 & 0x00000fc0L) << 10; - *cooked |= (*raw1 & 0x00fc0000L) >> 10; - *cooked++ |= (*raw1 & 0x00000fc0L) >> 6; - *cooked = (*raw0 & 0x0003f000L) << 12; - *cooked |= (*raw0 & 0x0000003fL) << 16; - *cooked |= (*raw1 & 0x0003f000L) >> 4; - *cooked |= (*raw1 & 0x0000003fL); - cooked += increment; - } -} - -#ifndef DES386 /* ignore C version in favor of 386 ONLY desfunc */ - -#define F(l,r,key){\ - work = ((r >> 4) | (r << 28)) ^ *key;\ - l ^= Spbox[6][work & 0x3f];\ - l ^= Spbox[4][(work >> 8) & 0x3f];\ - l ^= Spbox[2][(work >> 16) & 0x3f];\ - l ^= Spbox[0][(work >> 24) & 0x3f];\ - work = r ^ *(key+1);\ - l ^= Spbox[7][work & 0x3f];\ - l ^= Spbox[5][(work >> 8) & 0x3f];\ - l ^= Spbox[3][(work >> 16) & 0x3f];\ - l ^= Spbox[1][(work >> 24) & 0x3f];\ -} - -/* This desfunc code is marginally quicker than that uses in - RSAREF(tm) -*/ - -void desfunc(block,ks) -UINT4 *block; /* Data block */ -UINT4 *ks; /* Key schedule */ -{ - unsigned long left,right,work; - - left = block[0]; - right = block[1]; - - work = ((left >> 4) ^ right) & 0x0f0f0f0f; - right ^= work; - left ^= work << 4; - work = ((left >> 16) ^ right) & 0xffff; - right ^= work; - left ^= work << 16; - work = ((right >> 2) ^ left) & 0x33333333; - left ^= work; - right ^= (work << 2); - work = ((right >> 8) ^ left) & 0xff00ff; - left ^= work; - right ^= (work << 8); - right = (right << 1) | (right >> 31); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left << 1) | (left >> 31); - - /* Now do the 16 rounds */ - F(left,right,&ks[0]); - F(right,left,&ks[2]); - F(left,right,&ks[4]); - F(right,left,&ks[6]); - F(left,right,&ks[8]); - F(right,left,&ks[10]); - F(left,right,&ks[12]); - F(right,left,&ks[14]); - F(left,right,&ks[16]); - F(right,left,&ks[18]); - F(left,right,&ks[20]); - F(right,left,&ks[22]); - F(left,right,&ks[24]); - F(right,left,&ks[26]); - F(left,right,&ks[28]); - F(right,left,&ks[30]); - - right = (right << 31) | (right >> 1); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left >> 1) | (left << 31); - work = ((left >> 8) ^ right) & 0xff00ff; - right ^= work; - left ^= work << 8; - work = ((left >> 2) ^ right) & 0x33333333; - right ^= work; - left ^= work << 2; - work = ((right >> 16) ^ left) & 0xffff; - left ^= work; - right ^= work << 16; - work = ((right >> 4) ^ left) & 0x0f0f0f0f; - left ^= work; - right ^= work << 4; - - *block++ = right; - *block = left; -} - -#endif /* DES386 endif */ +/* + DESC.C - Data Encryption Standard routines for RSAEURO + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + Based on Outerbridge's D3DES (V5.09) 1992 Vintage. + + DESX(tm) - RSA Data Security. + + DES386 to be define ONLY in conjunction with 386 compiled + code. + + All Trademarks Acknowledged. + + Revision history + 0.90 First revision, this was the original retrofitted D3DES + version. + + 0.91 Second revision, retrofitted new S-box array and new desfunc + routine. Marginally quicker code improves DES throughput. + + 0.92 Current revision, added support for 386 assembler desfunc + routine, with altered S boxes and key generation to support easier + S box look up. Code that uses 386 desfunc is about 80K per sec + faster than RSAREF(tm) code. +*/ + +#include "rsaeuro.h" +#include "des.h" + +static UINT2 bytebit[8] = { + 0200, 0100, 040, 020, 010, 04, 02, 01 +}; + +static UINT4 bigbyte[24] = { + 0x800000L, 0x400000L, 0x200000L, 0x100000L, + 0x80000L, 0x40000L, 0x20000L, 0x10000L, + 0x8000L, 0x4000L, 0x2000L, 0x1000L, + 0x800L, 0x400L, 0x200L, 0x100L, + 0x80L, 0x40L, 0x20L, 0x10L, + 0x8L, 0x4L, 0x2L, 0x1L +}; + +static unsigned char totrot[16] = { + 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 +}; + +static unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 +}; + +static unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 +}; + +#ifndef DES386 + +UINT4 Spbox[8][64] = { + 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, + 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, + 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, + 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, + 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, + 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, + 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, + 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, + 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, + 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, + 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, + 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, + 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, + 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L, + 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, + 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, + 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, + 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, + 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, + 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, + 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, + 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, + 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, + 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, + 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, + 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, + 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, + 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, + 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, + 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L, + 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, + 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, + 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, + 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, + 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, + 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, + 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, + 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, + 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, + 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, + 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, + 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, + 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, + 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, + 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, + 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, + 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, + 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, + 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, + 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, + 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, + 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, + 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, + 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L, + 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, + 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, + 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, + 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, + 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, + 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, + 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, + 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, + 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, + 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, + 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, + 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, + 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, + 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, + 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, + 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L, + 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, + 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, + 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, + 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, + 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, + 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, + 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, + 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, + 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, + 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, + 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, + 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, + 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, + 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L, + 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, + 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, + 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, + 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, + 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, + 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, + 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, + 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, + 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, + 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, + 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, + 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, + 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, + 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, + 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, + 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L, + 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, + 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, + 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, + 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, + 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, + 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, + 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, + 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, + 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, + 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, + 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, + 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, + 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, + 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, + 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, + 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L +}; + +#else + /* S box tables for assembler desfunc */ + +unsigned long Spbox[8][64] = { + 0x04041000,0x00000000,0x00040000,0x04041010, + 0x04040010,0x00041010,0x00000010,0x00040000, + 0x00001000,0x04041000,0x04041010,0x00001000, + 0x04001010,0x04040010,0x04000000,0x00000010, + 0x00001010,0x04001000,0x04001000,0x00041000, + 0x00041000,0x04040000,0x04040000,0x04001010, + 0x00040010,0x04000010,0x04000010,0x00040010, + 0x00000000,0x00001010,0x00041010,0x04000000, + 0x00040000,0x04041010,0x00000010,0x04040000, + 0x04041000,0x04000000,0x04000000,0x00001000, + 0x04040010,0x00040000,0x00041000,0x04000010, + 0x00001000,0x00000010,0x04001010,0x00041010, + 0x04041010,0x00040010,0x04040000,0x04001010, + 0x04000010,0x00001010,0x00041010,0x04041000, + 0x00001010,0x04001000,0x04001000,0x00000000, + 0x00040010,0x00041000,0x00000000,0x04040010, + 0x00420082,0x00020002,0x00020000,0x00420080, + 0x00400000,0x00000080,0x00400082,0x00020082, + 0x00000082,0x00420082,0x00420002,0x00000002, + 0x00020002,0x00400000,0x00000080,0x00400082, + 0x00420000,0x00400080,0x00020082,0x00000000, + 0x00000002,0x00020000,0x00420080,0x00400002, + 0x00400080,0x00000082,0x00000000,0x00420000, + 0x00020080,0x00420002,0x00400002,0x00020080, + 0x00000000,0x00420080,0x00400082,0x00400000, + 0x00020082,0x00400002,0x00420002,0x00020000, + 0x00400002,0x00020002,0x00000080,0x00420082, + 0x00420080,0x00000080,0x00020000,0x00000002, + 0x00020080,0x00420002,0x00400000,0x00000082, + 0x00400080,0x00020082,0x00000082,0x00400080, + 0x00420000,0x00000000,0x00020002,0x00020080, + 0x00000002,0x00400082,0x00420082,0x00420000, + 0x00000820,0x20080800,0x00000000,0x20080020, + 0x20000800,0x00000000,0x00080820,0x20000800, + 0x00080020,0x20000020,0x20000020,0x00080000, + 0x20080820,0x00080020,0x20080000,0x00000820, + 0x20000000,0x00000020,0x20080800,0x00000800, + 0x00080800,0x20080000,0x20080020,0x00080820, + 0x20000820,0x00080800,0x00080000,0x20000820, + 0x00000020,0x20080820,0x00000800,0x20000000, + 0x20080800,0x20000000,0x00080020,0x00000820, + 0x00080000,0x20080800,0x20000800,0x00000000, + 0x00000800,0x00080020,0x20080820,0x20000800, + 0x20000020,0x00000800,0x00000000,0x20080020, + 0x20000820,0x00080000,0x20000000,0x20080820, + 0x00000020,0x00080820,0x00080800,0x20000020, + 0x20080000,0x20000820,0x00000820,0x20080000, + 0x00080820,0x00000020,0x20080020,0x00080800, + 0x02008004,0x00008204,0x00008204,0x00000200, + 0x02008200,0x02000204,0x02000004,0x00008004, + 0x00000000,0x02008000,0x02008000,0x02008204, + 0x00000204,0x00000000,0x02000200,0x02000004, + 0x00000004,0x00008000,0x02000000,0x02008004, + 0x00000200,0x02000000,0x00008004,0x00008200, + 0x02000204,0x00000004,0x00008200,0x02000200, + 0x00008000,0x02008200,0x02008204,0x00000204, + 0x02000200,0x02000004,0x02008000,0x02008204, + 0x00000204,0x00000000,0x00000000,0x02008000, + 0x00008200,0x02000200,0x02000204,0x00000004, + 0x02008004,0x00008204,0x00008204,0x00000200, + 0x02008204,0x00000204,0x00000004,0x00008000, + 0x02000004,0x00008004,0x02008200,0x02000204, + 0x00008004,0x00008200,0x02000000,0x02008004, + 0x00000200,0x02000000,0x00008000,0x02008200, + 0x00000400,0x08200400,0x08200000,0x08000401, + 0x00200000,0x00000400,0x00000001,0x08200000, + 0x00200401,0x00200000,0x08000400,0x00200401, + 0x08000401,0x08200001,0x00200400,0x00000001, + 0x08000000,0x00200001,0x00200001,0x00000000, + 0x00000401,0x08200401,0x08200401,0x08000400, + 0x08200001,0x00000401,0x00000000,0x08000001, + 0x08200400,0x08000000,0x08000001,0x00200400, + 0x00200000,0x08000401,0x00000400,0x08000000, + 0x00000001,0x08200000,0x08000401,0x00200401, + 0x08000400,0x00000001,0x08200001,0x08200400, + 0x00200401,0x00000400,0x08000000,0x08200001, + 0x08200401,0x00200400,0x08000001,0x08200401, + 0x08200000,0x00000000,0x00200001,0x08000001, + 0x00200400,0x08000400,0x00000401,0x00200000, + 0x00000000,0x00200001,0x08200400,0x00000401, + 0x80000040,0x81000000,0x00010000,0x81010040, + 0x81000000,0x00000040,0x81010040,0x01000000, + 0x80010000,0x01010040,0x01000000,0x80000040, + 0x01000040,0x80010000,0x80000000,0x00010040, + 0x00000000,0x01000040,0x80010040,0x00010000, + 0x01010000,0x80010040,0x00000040,0x81000040, + 0x81000040,0x00000000,0x01010040,0x81010000, + 0x00010040,0x01010000,0x81010000,0x80000000, + 0x80010000,0x00000040,0x81000040,0x01010000, + 0x81010040,0x01000000,0x00010040,0x80000040, + 0x01000000,0x80010000,0x80000000,0x00010040, + 0x80000040,0x81010040,0x01010000,0x81000000, + 0x01010040,0x81010000,0x00000000,0x81000040, + 0x00000040,0x00010000,0x81000000,0x01010040, + 0x00010000,0x01000040,0x80010040,0x00000000, + 0x81010000,0x80000000,0x01000040,0x80010040, + 0x00800000,0x10800008,0x10002008,0x00000000, + 0x00002000,0x10002008,0x00802008,0x10802000, + 0x10802008,0x00800000,0x00000000,0x10000008, + 0x00000008,0x10000000,0x10800008,0x00002008, + 0x10002000,0x00802008,0x00800008,0x10002000, + 0x10000008,0x10800000,0x10802000,0x00800008, + 0x10800000,0x00002000,0x00002008,0x10802008, + 0x00802000,0x00000008,0x10000000,0x00802000, + 0x10000000,0x00802000,0x00800000,0x10002008, + 0x10002008,0x10800008,0x10800008,0x00000008, + 0x00800008,0x10000000,0x10002000,0x00800000, + 0x10802000,0x00002008,0x00802008,0x10802000, + 0x00002008,0x10000008,0x10802008,0x10800000, + 0x00802000,0x00000000,0x00000008,0x10802008, + 0x00000000,0x00802008,0x10800000,0x00002000, + 0x10000008,0x10002000,0x00002000,0x00800008, + 0x40004100,0x00004000,0x00100000,0x40104100, + 0x40000000,0x40004100,0x00000100,0x40000000, + 0x00100100,0x40100000,0x40104100,0x00104000, + 0x40104000,0x00104100,0x00004000,0x00000100, + 0x40100000,0x40000100,0x40004000,0x00004100, + 0x00104000,0x00100100,0x40100100,0x40104000, + 0x00004100,0x00000000,0x00000000,0x40100100, + 0x40000100,0x40004000,0x00104100,0x00100000, + 0x00104100,0x00100000,0x40104000,0x00004000, + 0x00000100,0x40100100,0x00004000,0x00104100, + 0x40004000,0x00000100,0x40000100,0x40100000, + 0x40100100,0x40000000,0x00100000,0x40004100, + 0x00000000,0x40104100,0x00100100,0x40000100, + 0x40100000,0x40004000,0x40004100,0x00000000, + 0x40104100,0x00104000,0x00104000,0x00004100, + 0x00004100,0x00100100,0x40000000,0x40104000, +}; + +#endif + +void unscrunch PROTO_LIST ((unsigned char *, UINT4 *)); +void scrunch PROTO_LIST ((UINT4 *, unsigned char *)); +void deskey PROTO_LIST ((UINT4 *, unsigned char *, int)); +static void cookey PROTO_LIST ((UINT4 *, UINT4 *, int)); +void desfunc PROTO_LIST ((UINT4 *, UINT4 *)); + +/* Initialize context. Caller must zeroize the context when finished. */ + +void DES_CBCInit(context, key, iv, encrypt) +DES_CBC_CTX *context; /* context */ +unsigned char *key; /* key */ +unsigned char *iv; /* initializing vector */ +int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ +{ + /* Save encrypt flag to context. */ + context->encrypt = encrypt; + + /* Pack initializing vector into context. */ + + scrunch(context->iv, iv); + scrunch(context->originalIV, iv); + + /* Precompute key schedule */ + + deskey(context->subkeys, key, encrypt); +} + +/* DES-CBC block update operation. Continues a DES-CBC encryption + operation, processing eight-byte message blocks, and updating + the context. + + This requires len to be a multiple of 8. +*/ +int DES_CBCUpdate(context, output, input, len) +DES_CBC_CTX *context; /* context */ +unsigned char *output; /* output block */ +unsigned char *input; /* input block */ +unsigned int len; /* length of input and output blocks */ +{ + UINT4 inputBlock[2], work[2]; + unsigned int i; + + if(len % 8) /* block size check */ + return(RE_LEN); + + for(i = 0; i < len/8; i++) { + scrunch(inputBlock, &input[8*i]); + + /* Chain if encrypting. */ + + if(context->encrypt == 0) { + *work = *inputBlock; + *(work+1) = *(inputBlock+1); + }else{ + *work = *inputBlock ^ *context->iv; + *(work+1) = *(inputBlock+1) ^ *(context->iv+1); + } + + desfunc(work, context->subkeys); + + /* Chain if decrypting, then update IV. */ + + if(context->encrypt == 0) { + *work ^= *context->iv; + *(work+1) ^= *(context->iv+1); + *context->iv = *inputBlock; + *(context->iv+1) = *(inputBlock+1); + }else{ + *context->iv = *work; + *(context->iv+1) = *(work+1); + } + unscrunch (&output[8*i], work); + } + + /* Clear sensitive information. */ + + R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); + R_memset((POINTER)work, 0, sizeof(work)); + + return(IDOK); +} + +void DES_CBCRestart(context) +DES_CBC_CTX *context; /* context */ +{ + /* Restore the original IV */ + + *context->iv = *context->originalIV; + *(context->iv+1) = *(context->originalIV+1); +} + +/* Initialize context. Caller should clear the context when finished. + The key has the DES key, input whitener and output whitener concatenated. + This is the RSADSI special DES implementation. +*/ +void DESX_CBCInit(context, key, iv, encrypt) +DESX_CBC_CTX *context; /* context */ +unsigned char *key; /* DES key and whiteners */ +unsigned char *iv; /* DES initializing vector */ +int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ +{ + /* Save encrypt flag to context. */ + + context->encrypt = encrypt; + + /* Pack initializing vector and whiteners into context. */ + + scrunch(context->iv, iv); + scrunch(context->inputWhitener, key + 8); + scrunch(context->outputWhitener, key + 16); + /* Save the IV for use in Restart */ + scrunch(context->originalIV, iv); + + /* Precompute key schedule. */ + + deskey (context->subkeys, key, encrypt); +} + +/* DESX-CBC block update operation. Continues a DESX-CBC encryption + operation, processing eight-byte message blocks, and updating + the context. This is the RSADSI special DES implementation. + + Requires len to a multiple of 8. +*/ + +int DESX_CBCUpdate (context, output, input, len) +DESX_CBC_CTX *context; /* context */ +unsigned char *output; /* output block */ +unsigned char *input; /* input block */ +unsigned int len; /* length of input and output blocks */ +{ + UINT4 inputBlock[2], work[2]; + unsigned int i; + + if(len % 8) /* Length check */ + return(RE_LEN); + + for(i = 0; i < len/8; i++) { + scrunch(inputBlock, &input[8*i]); + + /* Chain if encrypting, and xor with whitener. */ + + if(context->encrypt == 0) { + *work = *inputBlock ^ *context->outputWhitener; + *(work+1) = *(inputBlock+1) ^ *(context->outputWhitener+1); + }else{ + *work = *inputBlock ^ *context->iv ^ *context->inputWhitener; + *(work+1) = *(inputBlock+1) ^ *(context->iv+1) ^ *(context->inputWhitener+1); + } + + desfunc(work, context->subkeys); + + /* Xor with whitener, chain if decrypting, then update IV. */ + + if(context->encrypt == 0) { + *work ^= *context->iv ^ *context->inputWhitener; + *(work+1) ^= *(context->iv+1) ^ *(context->inputWhitener+1); + *(context->iv) = *inputBlock; + *(context->iv+1) = *(inputBlock+1); + }else{ + *work ^= *context->outputWhitener; + *(work+1) ^= *(context->outputWhitener+1); + *context->iv = *work; + *(context->iv+1) = *(work+1); + } + unscrunch(&output[8*i], work); + } + + R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); + R_memset((POINTER)work, 0, sizeof(work)); + + return(IDOK); +} + +void DESX_CBCRestart(context) +DESX_CBC_CTX *context; /* context */ +{ + /* Restore the original IV */ + *context->iv = *context->originalIV; + *(context->iv+1) = *(context->originalIV+1); +} + +/* Initialize context. Caller must zeroize the context when finished. */ + +void DES3_CBCInit(context, key, iv, encrypt) +DES3_CBC_CTX *context; /* context */ +unsigned char *key; /* key */ +unsigned char *iv; /* initializing vector */ +int encrypt; /* encrypt flag (1 = encrypt, 0 = decrypt) */ +{ + /* Copy encrypt flag to context. */ + context->encrypt = encrypt; + + /* Pack initializing vector into context. */ + + scrunch(context->iv, iv); + + /* Save the IV for use in Restart */ + scrunch(context->originalIV, iv); + + /* Precompute key schedules. */ + + deskey(context->subkeys[0], encrypt ? key : &key[16], encrypt); + deskey(context->subkeys[1], &key[8], !encrypt); + deskey(context->subkeys[2], encrypt ? &key[16] : key, encrypt); +} + +int DES3_CBCUpdate(context, output, input, len) +DES3_CBC_CTX *context; /* context */ +unsigned char *output; /* output block */ +unsigned char *input; /* input block */ +unsigned int len; /* length of input and output blocks */ +{ + UINT4 inputBlock[2], work[2]; + unsigned int i; + + if(len % 8) /* length check */ + return(RE_LEN); + + for(i = 0; i < len/8; i++) { + scrunch(inputBlock, &input[8*i]); + + /* Chain if encrypting. */ + + if(context->encrypt == 0) { + *work = *inputBlock; + *(work+1) = *(inputBlock+1); + } + else { + *work = *inputBlock ^ *context->iv; + *(work+1) = *(inputBlock+1) ^ *(context->iv+1); + } + + desfunc(work, context->subkeys[0]); + desfunc(work, context->subkeys[1]); + desfunc(work, context->subkeys[2]); + + /* Chain if decrypting, then update IV. */ + + if(context->encrypt == 0) { + *work ^= *context->iv; + *(work+1) ^= *(context->iv+1); + *context->iv = *inputBlock; + *(context->iv+1) = *(inputBlock+1); + } + else { + *context->iv = *work; + *(context->iv+1) = *(work+1); + } + unscrunch(&output[8*i], work); + } + + R_memset((POINTER)inputBlock, 0, sizeof(inputBlock)); + R_memset((POINTER)work, 0, sizeof(work)); + + return (0); +} + +void DES3_CBCRestart (context) +DES3_CBC_CTX *context; /* context */ +{ + /* Restore the original IV */ + *context->iv = *context->originalIV; + *(context->iv+1) = *(context->originalIV+1); +} + +void scrunch (into, outof) +UINT4 *into; +unsigned char *outof; +{ + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into++ |= (*outof++ & 0xffL); + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into |= (*outof & 0xffL); +} + +void unscrunch(into, outof) +unsigned char *into; +UINT4 *outof; +{ + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into++ = (unsigned char)( *outof++ & 0xffL); + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into = (unsigned char)( *outof & 0xffL); +} + +/* Compute DES Subkeys */ + +void deskey(subkeys, key, encrypt) +UINT4 subkeys[32]; +unsigned char key[8]; +int encrypt; +{ + UINT4 kn[32]; + int i, j, l, m, n; + unsigned char pc1m[56], pcr[56]; + + for(j = 0; j < 56; j++) { + l = pc1[j]; + m = l & 07; + pc1m[j] = (unsigned char)((key[l >> 3] & bytebit[m]) ? 1 : 0); + } + for(i = 0; i < 16; i++) { + m = i << 1; + n = m + 1; + kn[m] = kn[n] = 0L; + for(j = 0; j < 28; j++) { + l = j + totrot[i]; + if(l < 28) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for(j = 28; j < 56; j++) { + l = j + totrot[i]; + if(l < 56) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for(j = 0; j < 24; j++) { + if(pcr[pc2[j]]) + kn[m] |= bigbyte[j]; + if(pcr[pc2[j+24]]) + kn[n] |= bigbyte[j]; + } + } + cookey(subkeys, kn, encrypt); + +#ifdef DES386 + for(i=0;i < 32;i++) + subkeys[i] <<= 2; +#endif + + R_memset((POINTER)pc1m, 0, sizeof(pc1m)); + R_memset((POINTER)pcr, 0, sizeof(pcr)); + R_memset((POINTER)kn, 0, sizeof(kn)); +} + +static void cookey(subkeys, kn, encrypt) +UINT4 *subkeys; +UINT4 *kn; +int encrypt; +{ + UINT4 *cooked, *raw0, *raw1; + int increment; + unsigned int i; + + raw1 = kn; + cooked = encrypt ? subkeys : &subkeys[30]; + increment = encrypt ? 1 : -3; + + for (i = 0; i < 16; i++, raw1++) { + raw0 = raw1++; + *cooked = (*raw0 & 0x00fc0000L) << 6; + *cooked |= (*raw0 & 0x00000fc0L) << 10; + *cooked |= (*raw1 & 0x00fc0000L) >> 10; + *cooked++ |= (*raw1 & 0x00000fc0L) >> 6; + *cooked = (*raw0 & 0x0003f000L) << 12; + *cooked |= (*raw0 & 0x0000003fL) << 16; + *cooked |= (*raw1 & 0x0003f000L) >> 4; + *cooked |= (*raw1 & 0x0000003fL); + cooked += increment; + } +} + +#ifndef DES386 /* ignore C version in favor of 386 ONLY desfunc */ + +#define F(l,r,key){\ + work = ((r >> 4) | (r << 28)) ^ *key;\ + l ^= Spbox[6][work & 0x3f];\ + l ^= Spbox[4][(work >> 8) & 0x3f];\ + l ^= Spbox[2][(work >> 16) & 0x3f];\ + l ^= Spbox[0][(work >> 24) & 0x3f];\ + work = r ^ *(key+1);\ + l ^= Spbox[7][work & 0x3f];\ + l ^= Spbox[5][(work >> 8) & 0x3f];\ + l ^= Spbox[3][(work >> 16) & 0x3f];\ + l ^= Spbox[1][(work >> 24) & 0x3f];\ +} + +/* This desfunc code is marginally quicker than that uses in + RSAREF(tm) +*/ + +void desfunc(block,ks) +UINT4 *block; /* Data block */ +UINT4 *ks; /* Key schedule */ +{ + unsigned long left,right,work; + + left = block[0]; + right = block[1]; + + work = ((left >> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= work << 4; + work = ((left >> 16) ^ right) & 0xffff; + right ^= work; + left ^= work << 16; + work = ((right >> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ left) & 0xff00ff; + left ^= work; + right ^= (work << 8); + right = (right << 1) | (right >> 31); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left << 1) | (left >> 31); + + /* Now do the 16 rounds */ + F(left,right,&ks[0]); + F(right,left,&ks[2]); + F(left,right,&ks[4]); + F(right,left,&ks[6]); + F(left,right,&ks[8]); + F(right,left,&ks[10]); + F(left,right,&ks[12]); + F(right,left,&ks[14]); + F(left,right,&ks[16]); + F(right,left,&ks[18]); + F(left,right,&ks[20]); + F(right,left,&ks[22]); + F(left,right,&ks[24]); + F(right,left,&ks[26]); + F(left,right,&ks[28]); + F(right,left,&ks[30]); + + right = (right << 31) | (right >> 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left >> 1) | (left << 31); + work = ((left >> 8) ^ right) & 0xff00ff; + right ^= work; + left ^= work << 8; + work = ((left >> 2) ^ right) & 0x33333333; + right ^= work; + left ^= work << 2; + work = ((right >> 16) ^ left) & 0xffff; + left ^= work; + right ^= work << 16; + work = ((right >> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= work << 4; + + *block++ = right; + *block = left; +} + +#endif /* DES386 endif */ diff --git a/source/global.h b/source/global.h old mode 100755 new mode 100644 index ca4141f..c3cbfbb --- a/source/global.h +++ b/source/global.h @@ -1,23 +1,21 @@ /* GLOBAL.H - RSAEURO types and constants - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid + same naming comventions that RSAREF uses. This should aid direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Global types and contants file. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ #ifndef _GLOBAL_H_ diff --git a/source/md2.h b/source/md2.h old mode 100755 new mode 100644 index caf1bd1..6f5264f --- a/source/md2.h +++ b/source/md2.h @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD2 Component Of RSAEURO using RSA Data Security, Inc. MD2 Message Digest Algorithm. diff --git a/source/md2c.c b/source/md2c.c old mode 100755 new mode 100644 index e3c883c..c20965e --- a/source/md2c.c +++ b/source/md2c.c @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD2 Component Of RSAEURO using RSA Data Security, Inc. MD2 Message Digest Algorithm. diff --git a/source/md4.h b/source/md4.h old mode 100755 new mode 100644 index e9b7675..c914fbc --- a/source/md4.h +++ b/source/md4.h @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD4 Component Of RSAEURO using RSA Data Security, Inc. MD4 Message Digest Algorithm. diff --git a/source/md4c.c b/source/md4c.c old mode 100755 new mode 100644 index c12eb56..f64e634 --- a/source/md4c.c +++ b/source/md4c.c @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD4 Component Of RSAEURO using RSA Data Security, Inc. MD4 Message Digest Algorithm. diff --git a/source/md5.h b/source/md5.h old mode 100755 new mode 100644 index 93de216..a0d4547 --- a/source/md5.h +++ b/source/md5.h @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD5 Component Of RSAEURO using RSA Data Security, Inc. MD5 Message Digest Algorithm. diff --git a/source/md5c.c b/source/md5c.c old mode 100755 new mode 100644 index 656c6dc..d826b1e --- a/source/md5c.c +++ b/source/md5c.c @@ -1,4 +1,4 @@ -/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1995. +/* Modifications Copyright (c) J.S.A.Kapp 1994 - 1996. MD5 Component Of RSAEURO using RSA Data Security, Inc. MD5 Message Digest Algorithm. @@ -305,4 +305,4 @@ unsigned int len; for(i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -} \ No newline at end of file +} diff --git a/source/nn.c b/source/nn.c old mode 100755 new mode 100644 index 3c53b8d..af08ef9 --- a/source/nn.c +++ b/source/nn.c @@ -1,675 +1,692 @@ -/* - NN.C - natural numbers routines - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to you applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - Revision hisitory - 0.90 First revision, this revision was the basic routines. - Routines slower than final revision. - - 0.91 Second revision, this is the current revision, all - routines have been altered for speed increases. Also the - addition of assembler equivalents. -*/ - -#include "rsaeuro.h" -#include "nn.h" - -/* internal static functions */ - -static NN_DIGIT subdigitmult PROTO_LIST - ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); - -static void dmult PROTO_LIST ((NN_DIGIT, NN_DIGIT, NN_DIGIT *, NN_DIGIT *)); - -static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT)); - -#ifndef USEASM -/* Decodes character string b into a, where character string is ordered - from most to least significant. - - Lengths: a[digits], b[len]. - Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most - significant bytes are truncated.) - */ -void NN_Decode (a, digits, b, len) -NN_DIGIT *a; -unsigned char *b; -unsigned int digits, len; -{ - NN_DIGIT t; - int j; - unsigned int i, u; - - for (i = 0, j = len - 1; i < digits && j >= 0; i++) { - t = 0; - for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) - t |= ((NN_DIGIT)b[j]) << u; - a[i] = t; - } - - for (; i < digits; i++) - a[i] = 0; -} - -/* Encodes b into character string a, where character string is ordered - from most to least significant. - - Lengths: a[len], b[digits]. - Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant - digits are truncated.) - */ -void NN_Encode (a, len, b, digits) -NN_DIGIT *b; -unsigned char *a; -unsigned int digits, len; -{ - NN_DIGIT t; - int j; - unsigned int i, u; - - for (i = 0, j = len - 1; i < digits && j >= 0; i++) { - t = b[i]; - for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) - a[j] = (unsigned char)(t >> u); - } - - for (; j >= 0; j--) - a[j] = 0; -} - -/* Assigns a = 0. */ - -void NN_AssignZero (a, digits) -NN_DIGIT *a; -unsigned int digits; -{ - if(digits) { - do { - *a++ = 0; - }while(--digits); - } -} - -#endif - -/* Assigns a = 2^b. - - Lengths: a[digits]. - Requires b < digits * NN_DIGIT_BITS. - */ -void NN_Assign2Exp (a, b, digits) -NN_DIGIT *a; -unsigned int b, digits; -{ - NN_AssignZero (a, digits); - - if (b >= digits * NN_DIGIT_BITS) - return; - - a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS); -} - -/* Computes a = b - c. Returns borrow. - - Lengths: a[digits], b[digits], c[digits]. - */ -NN_DIGIT NN_Sub (a, b, c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - NN_DIGIT temp, borrow = 0; - - if(digits) - do { - if((temp = (*b++) - borrow) == MAX_NN_DIGIT) - temp = MAX_NN_DIGIT - *c++; - else - if((temp -= *c) > (MAX_NN_DIGIT - *c++)) - borrow = 1; - else - borrow = 0; - *a++ = temp; - }while(--digits); - - return(borrow); -} - -/* Computes a = b * c. - - Lengths: a[2*digits], b[digits], c[digits]. - Assumes digits < MAX_NN_DIGITS. -*/ - -void NN_Mult (a, b, c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - NN_DIGIT t[2*MAX_NN_DIGITS]; - NN_DIGIT dhigh, dlow, carry; - unsigned int bDigits, cDigits, i, j; - - NN_AssignZero (t, 2 * digits); - - bDigits = NN_Digits (b, digits); - cDigits = NN_Digits (c, digits); - - for (i = 0; i < bDigits; i++) { - carry = 0; - if(*(b+i) != 0) { - for(j = 0; j < cDigits; j++) { - dmult(*(b+i), *(c+j), &dhigh, &dlow); - if((*(t+(i+j)) = *(t+(i+j)) + carry) < carry) - carry = 1; - else - carry = 0; - if((*(t+(i+j)) += dlow) < dlow) - carry++; - carry += dhigh; - } - } - *(t+(i+cDigits)) += carry; - } - - - NN_Assign(a, t, 2 * digits); -} - -/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. - - Requires c < NN_DIGIT_BITS. */ - -NN_DIGIT NN_LShift (a, b, c, digits) -NN_DIGIT *a, *b; -unsigned int c, digits; -{ - NN_DIGIT temp, carry = 0; - unsigned int t; - - if(c < NN_DIGIT_BITS) - if(digits) { - - t = NN_DIGIT_BITS - c; - - do { - temp = *b++; - *a++ = (temp << c) | carry; - carry = c ? (temp >> t) : 0; - }while(--digits); - } - - return (carry); -} - -/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. - - Requires: c < NN_DIGIT_BITS. */ - -NN_DIGIT NN_RShift (a, b, c, digits) -NN_DIGIT *a, *b; -unsigned int c, digits; -{ - NN_DIGIT temp, carry = 0; - unsigned int t; - - if(c < NN_DIGIT_BITS) - if(digits) { - - t = NN_DIGIT_BITS - c; - - do { - digits--; - temp = *(b+digits); - *(a+digits) = (temp >> c) | carry; - carry = c ? (temp << t) : 0; - }while(digits); - } - - return (carry); -} - -/* Computes a = c div d and b = c mod d. - - Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. - Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, - dDigits < MAX_NN_DIGITS. -*/ - -void NN_Div (a, b, c, cDigits, d, dDigits) -NN_DIGIT *a, *b, *c, *d; -unsigned int cDigits, dDigits; -{ - NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], s; - NN_DIGIT t[2], u, v, *ccptr; - NN_HALF_DIGIT aHigh, aLow, cHigh, cLow; - int i; - unsigned int ddDigits, shift; - - ddDigits = NN_Digits (d, dDigits); - if(ddDigits == 0) - return; - - shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]); - NN_AssignZero (cc, ddDigits); - cc[cDigits] = NN_LShift (cc, c, shift, cDigits); - NN_LShift (dd, d, shift, ddDigits); - s = dd[ddDigits-1]; - - NN_AssignZero (a, cDigits); - - for (i = cDigits-ddDigits; i >= 0; i--) { - if (s == MAX_NN_DIGIT) - ai = cc[i+ddDigits]; - else { - ccptr = &cc[i+ddDigits-1]; - - s++; - cHigh = (NN_HALF_DIGIT)HIGH_HALF (s); - cLow = (NN_HALF_DIGIT)LOW_HALF (s); - - *t = *ccptr; - *(t+1) = *(ccptr+1); - - if (cHigh == MAX_NN_HALF_DIGIT) - aHigh = (NN_HALF_DIGIT)HIGH_HALF (*(t+1)); - else - aHigh = (NN_HALF_DIGIT)(*(t+1) / (cHigh + 1)); - u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow; - v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh; - if ((*t -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u))) - t[1]--; - *(t+1) -= HIGH_HALF (u); - *(t+1) -= v; - - while ((*(t+1) > cHigh) || - ((*(t+1) == cHigh) && (*t >= TO_HIGH_HALF (cLow)))) { - if ((*t -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow)) - t[1]--; - *(t+1) -= cHigh; - aHigh++; - } - - if (cHigh == MAX_NN_HALF_DIGIT) - aLow = (NN_HALF_DIGIT)LOW_HALF (*(t+1)); - else - aLow = - (NN_HALF_DIGIT)((TO_HIGH_HALF (*(t+1)) + HIGH_HALF (*t)) / (cHigh + 1)); - u = (NN_DIGIT)aLow * (NN_DIGIT)cLow; - v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh; - if ((*t -= u) > (MAX_NN_DIGIT - u)) - t[1]--; - if ((*t -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v))) - t[1]--; - *(t+1) -= HIGH_HALF (v); - - while ((*(t+1) > 0) || ((*(t+1) == 0) && *t >= s)) { - if ((*t -= s) > (MAX_NN_DIGIT - s)) - t[1]--; - aLow++; - } - - ai = TO_HIGH_HALF (aHigh) + aLow; - s--; - } - - cc[i+ddDigits] -= subdigitmult(&cc[i], &cc[i], ai, dd, ddDigits); - - while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) { - ai++; - cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits); - } - - a[i] = ai; - } - - NN_AssignZero (b, dDigits); - NN_RShift (b, cc, shift, ddDigits); -} - - -/* Computes a = b mod c. - - Lengths: a[cDigits], b[bDigits], c[cDigits]. - Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS. -*/ -void NN_Mod (a, b, bDigits, c, cDigits) -NN_DIGIT *a, *b, *c; -unsigned int bDigits, cDigits; -{ - NN_DIGIT t[2 * MAX_NN_DIGITS]; - - NN_Div (t, a, b, bDigits, c, cDigits); -} - -/* Computes a = b * c mod d. - - Lengths: a[digits], b[digits], c[digits], d[digits]. - Assumes d > 0, digits < MAX_NN_DIGITS. - */ -void NN_ModMult (a, b, c, d, digits) -NN_DIGIT *a, *b, *c, *d; -unsigned int digits; -{ - NN_DIGIT t[2*MAX_NN_DIGITS]; - - NN_Mult (t, b, c, digits); - NN_Mod (a, t, 2 * digits, d, digits); -} - -/* Computes a = b^c mod d. - - Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits]. - Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS. - */ -void NN_ModExp (a, b, c, cDigits, d, dDigits) -NN_DIGIT *a, *b, *c, *d; -unsigned int cDigits, dDigits; -{ - NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS]; - int i; - unsigned int ciBits, j, s; - - /* Store b, b^2 mod d, and b^3 mod d. - */ - NN_Assign (bPower[0], b, dDigits); - NN_ModMult (bPower[1], bPower[0], b, d, dDigits); - NN_ModMult (bPower[2], bPower[1], b, d, dDigits); - - NN_ASSIGN_DIGIT (t, 1, dDigits); - - cDigits = NN_Digits (c, cDigits); - for (i = cDigits - 1; i >= 0; i--) { - ci = c[i]; - ciBits = NN_DIGIT_BITS; - - /* Scan past leading zero bits of most significant digit. - */ - if (i == (int)(cDigits - 1)) { - while (! DIGIT_2MSB (ci)) { - ci <<= 2; - ciBits -= 2; - } - } - - for (j = 0; j < ciBits; j += 2, ci <<= 2) { - /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci. */ - NN_ModMult (t, t, t, d, dDigits); - NN_ModMult (t, t, t, d, dDigits); - if ((s = DIGIT_2MSB (ci)) != 0) - NN_ModMult (t, t, bPower[s-1], d, dDigits); - } - } - - NN_Assign (a, t, dDigits); -} - -/* Compute a = 1/b mod c, assuming inverse exists. - - Lengths: a[digits], b[digits], c[digits]. - Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS. - */ -void NN_ModInv (a, b, c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS], - u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS], - v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS]; - int u1Sign; - - /* Apply extended Euclidean algorithm, modified to avoid negative - numbers. - */ - NN_ASSIGN_DIGIT (u1, 1, digits); - NN_AssignZero (v1, digits); - NN_Assign (u3, b, digits); - NN_Assign (v3, c, digits); - u1Sign = 1; - - while (! NN_Zero (v3, digits)) { - NN_Div (q, t3, u3, digits, v3, digits); - NN_Mult (w, q, v1, digits); - NN_Add (t1, u1, w, digits); - NN_Assign (u1, v1, digits); - NN_Assign (v1, t1, digits); - NN_Assign (u3, v3, digits); - NN_Assign (v3, t3, digits); - u1Sign = -u1Sign; - } - - /* Negate result if sign is negative. */ - if (u1Sign < 0) - NN_Sub (a, c, u1, digits); - else - NN_Assign (a, u1, digits); -} - -/* Computes a = gcd(b, c). - - Assumes b > c, digits < MAX_NN_DIGITS. -*/ - -#define iplus1 ( i==2 ? 0 : i+1 ) /* used by Euclid algorithms */ -#define iminus1 ( i==0 ? 2 : i-1 ) /* used by Euclid algorithms */ -#define g(i) ( &(t[i][0]) ) - -void NN_Gcd(a ,b ,c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - short i; - NN_DIGIT t[3][MAX_NN_DIGITS]; - - NN_Assign(g(0), c, digits); - NN_Assign(g(1), b, digits); - - i=1; - - while(!NN_Zero(g(i),digits)) { - NN_Mod(g(iplus1), g(iminus1), digits, g(i), digits); - i = iplus1; - } - - NN_Assign(a , g(iminus1), digits); -} - -/* Returns the significant length of a in bits. - - Lengths: a[digits]. */ - -unsigned int NN_Bits (a, digits) -NN_DIGIT *a; -unsigned int digits; -{ - if ((digits = NN_Digits (a, digits)) == 0) - return (0); - - return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1])); -} - -#ifndef USEASM - -/* Returns sign of a - b. */ - -int NN_Cmp (a, b, digits) -NN_DIGIT *a, *b; -unsigned int digits; -{ - - if(digits) { - do { - digits--; - if(*(a+digits) > *(b+digits)) - return(1); - if(*(a+digits) < *(b+digits)) - return(-1); - }while(digits); - } - - return (0); -} - -/* Returns nonzero iff a is zero. */ - -int NN_Zero (a, digits) -NN_DIGIT *a; -unsigned int digits; -{ - if(digits) { - do { - if(*a++) - return(0); - }while(--digits); - } - - return (1); -} - -/* Assigns a = b. */ - -void NN_Assign (a, b, digits) -NN_DIGIT *a, *b; -unsigned int digits; -{ - if(digits) { - do { - *a++ = *b++; - }while(--digits); - } -} - -/* Returns the significant length of a in digits. */ - -unsigned int NN_Digits (a, digits) -NN_DIGIT *a; -unsigned int digits; -{ - - if(digits) { - digits--; - - do { - if(*(a+digits)) - break; - }while(digits--); - - return(digits + 1); - } - - return(digits); -} - -/* Computes a = b + c. Returns carry. - - Lengths: a[digits], b[digits], c[digits]. - */ -NN_DIGIT NN_Add (a, b, c, digits) -NN_DIGIT *a, *b, *c; -unsigned int digits; -{ - NN_DIGIT temp, carry = 0; - - if(digits) - do { - if((temp = (*b++) + carry) < carry) - temp = *c++; - else - if((temp += *c) < *c++) - carry = 1; - else - carry = 0; - *a++ = temp; - }while(--digits); - - return (carry); -} - -#endif - -static NN_DIGIT subdigitmult(a, b, c, d, digits) -NN_DIGIT *a, *b, c, *d; -unsigned int digits; -{ - NN_DIGIT borrow, thigh, tlow; - unsigned int i; - - borrow = 0; - - if(c != 0) { - for(i = 0; i < digits; i++) { - dmult(c, d[i], &thigh, &tlow); - if((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) - borrow = 1; - else - borrow = 0; - if((a[i] -= tlow) > (MAX_NN_DIGIT - tlow)) - borrow++; - borrow += thigh; - } - } - - return (borrow); -} - -/* Returns the significant length of a in bits, where a is a digit. */ - -static unsigned int NN_DigitBits (a) -NN_DIGIT a; -{ - unsigned int i; - - for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1) - if (a == 0) - break; - - return (i); -} - -/* Computes a * b, result stored in high and low. */ - -static void dmult( a, b, high, low) -NN_DIGIT a, b; -NN_DIGIT *high; -NN_DIGIT *low; -{ - NN_HALF_DIGIT al, ah, bl, bh; - NN_DIGIT m1, m2, m, ml, mh, carry = 0; - - al = (NN_HALF_DIGIT)LOW_HALF(a); - ah = (NN_HALF_DIGIT)HIGH_HALF(a); - bl = (NN_HALF_DIGIT)LOW_HALF(b); - bh = (NN_HALF_DIGIT)HIGH_HALF(b); - - *low = (NN_DIGIT) al*bl; - *high = (NN_DIGIT) ah*bh; - - m1 = (NN_DIGIT) al*bh; - m2 = (NN_DIGIT) ah*bl; - m = m1 + m2; - - if(m < m1) - carry = 1L << (NN_DIGIT_BITS / 2); - - ml = (m & MAX_NN_HALF_DIGIT) << (NN_DIGIT_BITS / 2); - mh = m >> (NN_DIGIT_BITS / 2); - - *low += ml; - - if(*low < ml) - carry++; - - *high += carry + mh; -} - +/* + NN.C - natural numbers routines + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to you applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + Revision hisitory + 0.90 First revision, this revision was the basic routines. + Routines slower than final revision. + + 0.91 Second revision, this is the current revision, all + routines have been altered for speed increases. Also the + addition of assembler equivalents. + + 1.02 Third revision, minor bug fixes. + dmult bug fix, Bug reported by Anders Heerfordt . + + 1.03 Fourth revision, SunCompiler patch +*/ + +#include "rsaeuro.h" +#include "nn.h" + +/* internal static functions */ + +static NN_DIGIT subdigitmult PROTO_LIST + ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); + +static void dmult PROTO_LIST ((NN_DIGIT, NN_DIGIT, NN_DIGIT *, NN_DIGIT *)); + +static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT)); + +#ifndef USEASM +/* Decodes character string b into a, where character string is ordered + from most to least significant. + + Lengths: a[digits], b[len]. + Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most + significant bytes are truncated.) + */ +void NN_Decode (a, digits, b, len) +NN_DIGIT *a; +unsigned char *b; +unsigned int digits, len; +{ + NN_DIGIT t; + unsigned int i, j, u; + + for (i = 0, j = len - 1; i < digits && j >= 0; i++) { + t = 0; + for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) + t |= ((NN_DIGIT)b[j]) << u; + a[i] = t; + } + + for (; i < digits; i++) + a[i] = 0; +} + +/* Encodes b into character string a, where character string is ordered + from most to least significant. + + Lengths: a[len], b[digits]. + Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant + digits are truncated.) + */ +void NN_Encode (a, len, b, digits) +NN_DIGIT *b; +unsigned char *a; +unsigned int digits, len; +{ + NN_DIGIT t; + unsigned int i, j, u; + + for (i = 0, j = len - 1; i < digits && j >= 0; i++) { + t = b[i]; + for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) + a[j] = (unsigned char)(t >> u); + } + + for (; j >= 0; j--) + a[j] = 0; +} + +/* Assigns a = 0. */ + +void NN_AssignZero (a, digits) +NN_DIGIT *a; +unsigned int digits; +{ + if(digits) { + do { + *a++ = 0; + }while(--digits); + } +} + +#endif + +/* Assigns a = 2^b. + + Lengths: a[digits]. + Requires b < digits * NN_DIGIT_BITS. + */ +void NN_Assign2Exp (a, b, digits) +NN_DIGIT *a; +unsigned int b, digits; +{ + NN_AssignZero (a, digits); + + if (b >= digits * NN_DIGIT_BITS) + return; + + a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS); +} + +/* Computes a = b - c. Returns borrow. + + Lengths: a[digits], b[digits], c[digits]. + */ +NN_DIGIT NN_Sub (a, b, c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + NN_DIGIT temp, borrow = 0; + + if(digits) + do { + /* Bug fix 16/10/95 - JSK, code below removed, caused bug with + Sun Compiler SC4. + + if((temp = (*b++) - borrow) == MAX_NN_DIGIT) + temp = MAX_NN_DIGIT - *c++; + */ + + temp = *b - borrow; + b++; + if(temp == MAX_NN_DIGIT) { + temp = MAX_NN_DIGIT - *c; + c++; + }else { /* Patch to prevent bug for Sun CC */ + if((temp -= *c) > (MAX_NN_DIGIT - *c)) + borrow = 1; + else + borrow = 0; + c++; + } + *a++ = temp; + }while(--digits); + + return(borrow); +} + +/* Computes a = b * c. + + Lengths: a[2*digits], b[digits], c[digits]. + Assumes digits < MAX_NN_DIGITS. +*/ + +void NN_Mult (a, b, c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + NN_DIGIT t[2*MAX_NN_DIGITS]; + NN_DIGIT dhigh, dlow, carry; + unsigned int bDigits, cDigits, i, j; + + NN_AssignZero (t, 2 * digits); + + bDigits = NN_Digits (b, digits); + cDigits = NN_Digits (c, digits); + + for (i = 0; i < bDigits; i++) { + carry = 0; + if(*(b+i) != 0) { + for(j = 0; j < cDigits; j++) { + dmult(*(b+i), *(c+j), &dhigh, &dlow); + if((*(t+(i+j)) = *(t+(i+j)) + carry) < carry) + carry = 1; + else + carry = 0; + if((*(t+(i+j)) += dlow) < dlow) + carry++; + carry += dhigh; + } + } + *(t+(i+cDigits)) += carry; + } + + + NN_Assign(a, t, 2 * digits); +} + +/* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. + + Requires c < NN_DIGIT_BITS. */ + +NN_DIGIT NN_LShift (a, b, c, digits) +NN_DIGIT *a, *b; +unsigned int c, digits; +{ + NN_DIGIT temp, carry = 0; + unsigned int t; + + if(c < NN_DIGIT_BITS) + if(digits) { + + t = NN_DIGIT_BITS - c; + + do { + temp = *b++; + *a++ = (temp << c) | carry; + carry = c ? (temp >> t) : 0; + }while(--digits); + } + + return (carry); +} + +/* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. + + Requires: c < NN_DIGIT_BITS. */ + +NN_DIGIT NN_RShift (a, b, c, digits) +NN_DIGIT *a, *b; +unsigned int c, digits; +{ + NN_DIGIT temp, carry = 0; + unsigned int t; + + if(c < NN_DIGIT_BITS) + if(digits) { + + t = NN_DIGIT_BITS - c; + + do { + digits--; + temp = *(b+digits); + *(a+digits) = (temp >> c) | carry; + carry = c ? (temp << t) : 0; + }while(digits); + } + + return (carry); +} + +/* Computes a = c div d and b = c mod d. + + Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. + Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, + dDigits < MAX_NN_DIGITS. +*/ + +void NN_Div (a, b, c, cDigits, d, dDigits) +NN_DIGIT *a, *b, *c, *d; +unsigned int cDigits, dDigits; +{ + NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], s; + NN_DIGIT t[2], u, v, *ccptr; + NN_HALF_DIGIT aHigh, aLow, cHigh, cLow; + int i; + unsigned int ddDigits, shift; + + ddDigits = NN_Digits (d, dDigits); + if(ddDigits == 0) + return; + + shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]); + NN_AssignZero (cc, ddDigits); + cc[cDigits] = NN_LShift (cc, c, shift, cDigits); + NN_LShift (dd, d, shift, ddDigits); + s = dd[ddDigits-1]; + + NN_AssignZero (a, cDigits); + + for (i = cDigits-ddDigits; i >= 0; i--) { + if (s == MAX_NN_DIGIT) + ai = cc[i+ddDigits]; + else { + ccptr = &cc[i+ddDigits-1]; + + s++; + cHigh = (NN_HALF_DIGIT)HIGH_HALF (s); + cLow = (NN_HALF_DIGIT)LOW_HALF (s); + + *t = *ccptr; + *(t+1) = *(ccptr+1); + + if (cHigh == MAX_NN_HALF_DIGIT) + aHigh = (NN_HALF_DIGIT)HIGH_HALF (*(t+1)); + else + aHigh = (NN_HALF_DIGIT)(*(t+1) / (cHigh + 1)); + u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow; + v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh; + if ((*t -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u))) + t[1]--; + *(t+1) -= HIGH_HALF (u); + *(t+1) -= v; + + while ((*(t+1) > cHigh) || + ((*(t+1) == cHigh) && (*t >= TO_HIGH_HALF (cLow)))) { + if ((*t -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow)) + t[1]--; + *(t+1) -= cHigh; + aHigh++; + } + + if (cHigh == MAX_NN_HALF_DIGIT) + aLow = (NN_HALF_DIGIT)LOW_HALF (*(t+1)); + else + aLow = + (NN_HALF_DIGIT)((TO_HIGH_HALF (*(t+1)) + HIGH_HALF (*t)) / (cHigh + 1)); + u = (NN_DIGIT)aLow * (NN_DIGIT)cLow; + v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh; + if ((*t -= u) > (MAX_NN_DIGIT - u)) + t[1]--; + if ((*t -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v))) + t[1]--; + *(t+1) -= HIGH_HALF (v); + + while ((*(t+1) > 0) || ((*(t+1) == 0) && *t >= s)) { + if ((*t -= s) > (MAX_NN_DIGIT - s)) + t[1]--; + aLow++; + } + + ai = TO_HIGH_HALF (aHigh) + aLow; + s--; + } + + cc[i+ddDigits] -= subdigitmult(&cc[i], &cc[i], ai, dd, ddDigits); + + while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) { + ai++; + cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits); + } + + a[i] = ai; + } + + NN_AssignZero (b, dDigits); + NN_RShift (b, cc, shift, ddDigits); +} + + +/* Computes a = b mod c. + + Lengths: a[cDigits], b[bDigits], c[cDigits]. + Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS. +*/ +void NN_Mod (a, b, bDigits, c, cDigits) +NN_DIGIT *a, *b, *c; +unsigned int bDigits, cDigits; +{ + NN_DIGIT t[2 * MAX_NN_DIGITS]; + + NN_Div (t, a, b, bDigits, c, cDigits); +} + +/* Computes a = b * c mod d. + + Lengths: a[digits], b[digits], c[digits], d[digits]. + Assumes d > 0, digits < MAX_NN_DIGITS. + */ +void NN_ModMult (a, b, c, d, digits) +NN_DIGIT *a, *b, *c, *d; +unsigned int digits; +{ + NN_DIGIT t[2*MAX_NN_DIGITS]; + + NN_Mult (t, b, c, digits); + NN_Mod (a, t, 2 * digits, d, digits); +} + +/* Computes a = b^c mod d. + + Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits]. + Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS. + */ +void NN_ModExp (a, b, c, cDigits, d, dDigits) +NN_DIGIT *a, *b, *c, *d; +unsigned int cDigits, dDigits; +{ + NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS]; + int i; + unsigned int ciBits, j, s; + + /* Store b, b^2 mod d, and b^3 mod d. + */ + NN_Assign (bPower[0], b, dDigits); + NN_ModMult (bPower[1], bPower[0], b, d, dDigits); + NN_ModMult (bPower[2], bPower[1], b, d, dDigits); + + NN_ASSIGN_DIGIT (t, 1, dDigits); + + cDigits = NN_Digits (c, cDigits); + for (i = cDigits - 1; i >= 0; i--) { + ci = c[i]; + ciBits = NN_DIGIT_BITS; + + /* Scan past leading zero bits of most significant digit. + */ + if (i == (int)(cDigits - 1)) { + while (! DIGIT_2MSB (ci)) { + ci <<= 2; + ciBits -= 2; + } + } + + for (j = 0; j < ciBits; j += 2, ci <<= 2) { + /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci. */ + NN_ModMult (t, t, t, d, dDigits); + NN_ModMult (t, t, t, d, dDigits); + if ((s = DIGIT_2MSB (ci)) != 0) + NN_ModMult (t, t, bPower[s-1], d, dDigits); + } + } + + NN_Assign (a, t, dDigits); +} + +/* Compute a = 1/b mod c, assuming inverse exists. + + Lengths: a[digits], b[digits], c[digits]. + Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS. + */ +void NN_ModInv (a, b, c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS], + u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS], + v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS]; + int u1Sign; + + /* Apply extended Euclidean algorithm, modified to avoid negative + numbers. + */ + NN_ASSIGN_DIGIT (u1, 1, digits); + NN_AssignZero (v1, digits); + NN_Assign (u3, b, digits); + NN_Assign (v3, c, digits); + u1Sign = 1; + + while (! NN_Zero (v3, digits)) { + NN_Div (q, t3, u3, digits, v3, digits); + NN_Mult (w, q, v1, digits); + NN_Add (t1, u1, w, digits); + NN_Assign (u1, v1, digits); + NN_Assign (v1, t1, digits); + NN_Assign (u3, v3, digits); + NN_Assign (v3, t3, digits); + u1Sign = -u1Sign; + } + + /* Negate result if sign is negative. */ + if (u1Sign < 0) + NN_Sub (a, c, u1, digits); + else + NN_Assign (a, u1, digits); +} + +/* Computes a = gcd(b, c). + + Assumes b > c, digits < MAX_NN_DIGITS. +*/ + +#define iplus1 ( i==2 ? 0 : i+1 ) /* used by Euclid algorithms */ +#define iminus1 ( i==0 ? 2 : i-1 ) /* used by Euclid algorithms */ +#define g(i) ( &(t[i][0]) ) + +void NN_Gcd(a ,b ,c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + short i; + NN_DIGIT t[3][MAX_NN_DIGITS]; + + NN_Assign(g(0), c, digits); + NN_Assign(g(1), b, digits); + + i=1; + + while(!NN_Zero(g(i),digits)) { + NN_Mod(g(iplus1), g(iminus1), digits, g(i), digits); + i = iplus1; + } + + NN_Assign(a , g(iminus1), digits); +} + +/* Returns the significant length of a in bits. + + Lengths: a[digits]. */ + +unsigned int NN_Bits (a, digits) +NN_DIGIT *a; +unsigned int digits; +{ + if ((digits = NN_Digits (a, digits)) == 0) + return (0); + + return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1])); +} + +#ifndef USEASM + +/* Returns sign of a - b. */ + +int NN_Cmp (a, b, digits) +NN_DIGIT *a, *b; +unsigned int digits; +{ + + if(digits) { + do { + digits--; + if(*(a+digits) > *(b+digits)) + return(1); + if(*(a+digits) < *(b+digits)) + return(-1); + }while(digits); + } + + return (0); +} + +/* Returns nonzero iff a is zero. */ + +int NN_Zero (a, digits) +NN_DIGIT *a; +unsigned int digits; +{ + if(digits) { + do { + if(*a++) + return(0); + }while(--digits); + } + + return (1); +} + +/* Assigns a = b. */ + +void NN_Assign (a, b, digits) +NN_DIGIT *a, *b; +unsigned int digits; +{ + if(digits) { + do { + *a++ = *b++; + }while(--digits); + } +} + +/* Returns the significant length of a in digits. */ + +unsigned int NN_Digits (a, digits) +NN_DIGIT *a; +unsigned int digits; +{ + + if(digits) { + digits--; + + do { + if(*(a+digits)) + break; + }while(digits--); + + return(digits + 1); + } + + return(digits); +} + +/* Computes a = b + c. Returns carry. + + Lengths: a[digits], b[digits], c[digits]. + */ +NN_DIGIT NN_Add (a, b, c, digits) +NN_DIGIT *a, *b, *c; +unsigned int digits; +{ + NN_DIGIT temp, carry = 0; + + if(digits) + do { + if((temp = (*b++) + carry) < carry) + temp = *c++; + else { /* Patch to prevent bug for Sun CC */ + if((temp += *c) < *c) + carry = 1; + else + carry = 0; + c++; + } + *a++ = temp; + }while(--digits); + + return (carry); +} + +#endif + +static NN_DIGIT subdigitmult(a, b, c, d, digits) +NN_DIGIT *a, *b, c, *d; +unsigned int digits; +{ + NN_DIGIT borrow, thigh, tlow; + unsigned int i; + + borrow = 0; + + if(c != 0) { + for(i = 0; i < digits; i++) { + dmult(c, d[i], &thigh, &tlow); + if((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) + borrow = 1; + else + borrow = 0; + if((a[i] -= tlow) > (MAX_NN_DIGIT - tlow)) + borrow++; + borrow += thigh; + } + } + + return (borrow); +} + +/* Returns the significant length of a in bits, where a is a digit. */ + +static unsigned int NN_DigitBits (a) +NN_DIGIT a; +{ + unsigned int i; + + for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1) + if (a == 0) + break; + + return (i); +} + +/* Computes a * b, result stored in high and low. */ + +static void dmult( a, b, high, low) +NN_DIGIT a, b; +NN_DIGIT *high; +NN_DIGIT *low; +{ + NN_HALF_DIGIT al, ah, bl, bh; + NN_DIGIT m1, m2, m, ml, mh, carry = 0; + + al = (NN_HALF_DIGIT)LOW_HALF(a); + ah = (NN_HALF_DIGIT)HIGH_HALF(a); + bl = (NN_HALF_DIGIT)LOW_HALF(b); + bh = (NN_HALF_DIGIT)HIGH_HALF(b); + + *low = (NN_DIGIT) al*bl; + *high = (NN_DIGIT) ah*bh; + + m1 = (NN_DIGIT) al*bh; + m2 = (NN_DIGIT) ah*bl; + m = m1 + m2; + + if(m < m1) + carry = 1L << (NN_DIGIT_BITS / 2); + + ml = (m & MAX_NN_HALF_DIGIT) << (NN_DIGIT_BITS / 2); + mh = m >> (NN_DIGIT_BITS / 2); + + *low += ml; + + if(*low < ml) + carry++; + + *high += carry + mh; +} + diff --git a/source/nn.h b/source/nn.h old mode 100755 new mode 100644 index 09b1e62..03b7b61 --- a/source/nn.h +++ b/source/nn.h @@ -1,23 +1,21 @@ /* NN.H - header file for NN.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Math Library Routines Header File. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ #ifndef _NN_H_ diff --git a/source/prime.c b/source/prime.c old mode 100755 new mode 100644 index bf9ace6..f671253 --- a/source/prime.c +++ b/source/prime.c @@ -1,285 +1,285 @@ -/* - PRIME.C - primality-testing routines - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - Uses a small primes factor test and the Fermat Test to determine if - the number is probable prime number. - - Future Version may use Radin-Miller Primes Test? - - Revision history - 0.90 First revision, produced to perform just like the - RSAREF(tm) version. - - 0.91 Second revision, modified probableprime routine with - some major revisions. Added large small primes table for - small primes test, altered flow of small primes test. Results - produced a huge speed increase using REDEMO, upwards of 70% - speed increase (1024 bit keys). -*/ - -#include "rsaeuro.h" -#include "r_random.h" -#include "nn.h" -#include "prime.h" - -#define SMALL_PRIME_COUNT 1027 - -static int probableprime PROTO_LIST ((NN_DIGIT *, unsigned int)); - -/* Generates a probable prime a between b and c such that a-1 is - divisible by d. - - Assumes b < c, digits < MAX_NN_DIGITS. - Returns RE_NEED_RANDOM if randomStruct not seeded, RE_DATA if - unsuccessful. -*/ - -int GeneratePrime(a, b, c, d, digits, randomStruct) -NN_DIGIT *a, *b, *c, *d; -unsigned int digits; -R_RANDOM_STRUCT *randomStruct; /* random structure */ -{ - int status; - unsigned char block[MAX_NN_DIGITS * NN_DIGIT_LEN]; - NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; - - /* Generate random number between b and c. */ - - status = R_GenerateBytes(block, digits * NN_DIGIT_LEN, randomStruct); - if(status) - return(status); - - NN_Decode(a, digits, block, digits * NN_DIGIT_LEN); - NN_Sub(t, c, b, digits); - NN_ASSIGN_DIGIT(u, 1, digits); - NN_Add(t, t, u, digits); - NN_Mod(a, a, digits, t, digits); - NN_Add(a, a, b, digits); - - /* Adjust so that a-1 is divisible by d. */ - - NN_Mod(t, a, digits, d, digits); - NN_Sub(a, a, t, digits); - NN_Add(a, a, u, digits); - if(NN_Cmp(a, b, digits) < 0) - NN_Add(a, a, d, digits); - if(NN_Cmp(a, c, digits) > 0) - NN_Sub(a, a, d, digits); - - /* Search to c in steps of d. */ - - NN_Assign(t, c, digits); - NN_Sub(t, t, d, digits); - - while(!probableprime (a, digits)) { - if(NN_Cmp (a, t, digits) > 0) - return(RE_DATA); - NN_Add(a, a, d, digits); - } - - return(IDOK); -} - -/* Returns nonzero iff a is a probable prime. - - Does small factor test and a fermat test witness 2. -*/ - -static int probableprime(a, aDigits) -NN_DIGIT *a; -unsigned int aDigits; -{ - - int status; - NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; - /* This table can be reduced in size but the smaller - the table the slower the testing. - */ - static unsigned int SMALL_PRIMES[] = { - 3, 5, 7, 11, 13, 17, 19, - 23, 29, 31, 37, 41, 43, 47, 53, - 59, 61, 67, 71, 73, 79, 83, 89, - 97, 101, 103, 107, 109, 113, 127, 131, - 137, 139, 149, 151, 157, 163, 167, 173, - 179, 181, 191, 193, 197, 199, 211, 223, - 227, 229, 233, 239, 241, 251, 257, 263, - 269, 271, 277, 281, 283, 293, 307, 311, - 313, 317, 331, 337, 347, 349, 353, 359, - 367, 373, 379, 383, 389, 397, 401, 409, - 419, 421, 431, 433, 439, 443, 449, 457, - 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, - 571, 577, 587, 593, 599, 601, 607, 613, - 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, - 727, 733, 739, 743, 751, 757, 761, 769, - 773, 787, 797, 809, 811, 821, 823, 827, - 829, 839, 853, 857, 859, 863, 877, 881, - 883, 887, 907, 911, 919, 929, 937, 941, - 947, 953, 967, 971, 977, 983, 991, 997, - 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, - 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, - 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, - 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, - 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, - 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, - 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, - 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, - 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, - 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, - 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, - 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, - 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, - 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, - 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, - 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, - 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, - 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, - 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, - 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, - 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, - 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, - 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, - 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, - 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, - 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, - 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, - 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, - 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, - 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, - 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, - 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, - 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, - 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, - 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, - 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, - 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, - 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, - 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, - 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, - 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, - 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, - 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, - 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, - 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, - 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, - 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, - 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, - 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, - 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, - 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, - 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, - 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, - 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, - 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, - 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, - 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, - 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, - 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, - 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, - 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, - 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, - 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, - 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, - 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, - 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, - 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, - 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, - 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, - 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, - 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, - 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, - 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, - 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, - 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, - 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, - 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, - 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, - 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, - 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, - 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, - 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, - 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, - 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, - 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, - 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, - 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, - 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, - 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, - 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, - 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, - 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, - 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, - 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, - 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, - 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, - 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, - 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, - 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, - 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, - 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, - 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, - 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, - 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, - 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, - 8167, 8171, 8179, 8191, 0 - }; - unsigned int i,x; - - status = 1; - - NN_AssignZero(t, aDigits); - - /* Small Primes test, weed out junk numbers before slower Fermat's */ - - for(i = 0; *(SMALL_PRIMES+i); i++) { - *t = *(SMALL_PRIMES+i); - if(aDigits == 1) - if(NN_Cmp (a, t, 1) == 0) - break; - NN_Mod(t, a, aDigits, t, 1); - if(NN_Zero (t, 1)) { - status = 0; - break; - } - } - - /* Clear sensitive information. */ - - i = 0; - R_memset((POINTER)t, 0, sizeof(t)); - - /* Fermat's test for witness 2. - (All primes pass the test, and nearly all composites fail.) - */ - - if(status) { - NN_ASSIGN_DIGIT(t, 2, aDigits); - NN_ModExp(u, t, a, aDigits, a, aDigits); - - status = NN_EQUAL(t, u, aDigits); - - /* Clear sensitive information. */ - - R_memset((POINTER)u, 0, sizeof(u)); - } - - return(status ? TRUE : FALSE); -} - +/* + PRIME.C - primality-testing routines + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + Uses a small primes factor test and the Fermat Test to determine if + the number is probable prime number. + + Future Version may use Radin-Miller Primes Test? + + Revision history + 0.90 First revision, produced to perform just like the + RSAREF(tm) version. + + 0.91 Second revision, modified probableprime routine with + some major revisions. Added large small primes table for + small primes test, altered flow of small primes test. Results + produced a huge speed increase using REDEMO, upwards of 70% + speed increase (1024 bit keys). +*/ + +#include "rsaeuro.h" +#include "r_random.h" +#include "nn.h" +#include "prime.h" + +#define SMALL_PRIME_COUNT 1027 + +static int probableprime PROTO_LIST ((NN_DIGIT *, unsigned int)); + +/* Generates a probable prime a between b and c such that a-1 is + divisible by d. + + Assumes b < c, digits < MAX_NN_DIGITS. + Returns RE_NEED_RANDOM if randomStruct not seeded, RE_DATA if + unsuccessful. +*/ + +int GeneratePrime(a, b, c, d, digits, randomStruct) +NN_DIGIT *a, *b, *c, *d; +unsigned int digits; +R_RANDOM_STRUCT *randomStruct; /* random structure */ +{ + int status; + unsigned char block[MAX_NN_DIGITS * NN_DIGIT_LEN]; + NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; + + /* Generate random number between b and c. */ + + status = R_GenerateBytes(block, digits * NN_DIGIT_LEN, randomStruct); + if(status) + return(status); + + NN_Decode(a, digits, block, digits * NN_DIGIT_LEN); + NN_Sub(t, c, b, digits); + NN_ASSIGN_DIGIT(u, 1, digits); + NN_Add(t, t, u, digits); + NN_Mod(a, a, digits, t, digits); + NN_Add(a, a, b, digits); + + /* Adjust so that a-1 is divisible by d. */ + + NN_Mod(t, a, digits, d, digits); + NN_Sub(a, a, t, digits); + NN_Add(a, a, u, digits); + if(NN_Cmp(a, b, digits) < 0) + NN_Add(a, a, d, digits); + if(NN_Cmp(a, c, digits) > 0) + NN_Sub(a, a, d, digits); + + /* Search to c in steps of d. */ + + NN_Assign(t, c, digits); + NN_Sub(t, t, d, digits); + + while(!probableprime (a, digits)) { + if(NN_Cmp (a, t, digits) > 0) + return(RE_DATA); + NN_Add(a, a, d, digits); + } + + return(IDOK); +} + +/* Returns nonzero iff a is a probable prime. + + Does small factor test and a fermat test witness 2. +*/ + +static int probableprime(a, aDigits) +NN_DIGIT *a; +unsigned int aDigits; +{ + + int status; + NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; + /* This table can be reduced in size but the smaller + the table the slower the testing. + */ + static unsigned int SMALL_PRIMES[] = { + 3, 5, 7, 11, 13, 17, 19, + 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, + 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, + 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, + 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, + 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, + 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, + 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, + 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, + 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, + 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, + 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, + 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, + 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, + 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, + 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, + 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, + 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, + 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, + 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, + 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, + 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, + 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, + 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, + 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, + 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, + 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, + 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, + 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, + 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, + 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, + 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, + 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, + 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, + 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, + 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, + 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, + 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, + 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, + 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, + 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, + 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, + 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, + 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, + 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, + 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, + 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, + 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, + 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, + 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, + 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, + 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, + 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, + 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, + 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, + 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, + 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, + 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, + 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, + 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, + 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, + 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, + 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, + 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, + 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, + 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, + 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, + 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, + 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, + 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, + 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, + 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, + 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, + 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, + 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, + 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, + 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, + 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, + 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, + 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, + 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, + 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, + 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, + 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, + 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, + 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, + 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, + 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, + 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, + 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, + 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, + 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, + 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, + 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, + 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, + 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, + 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, + 8167, 8171, 8179, 8191, 0 + }; + unsigned int i,x; + + status = 1; + + NN_AssignZero(t, aDigits); + + /* Small Primes test, weed out junk numbers before slower Fermat's */ + + for(i = 0; *(SMALL_PRIMES+i); i++) { + *t = *(SMALL_PRIMES+i); + if(aDigits == 1) + if(NN_Cmp (a, t, 1) == 0) + break; + NN_Mod(t, a, aDigits, t, 1); + if(NN_Zero (t, 1)) { + status = 0; + break; + } + } + + /* Clear sensitive information. */ + + i = 0; + R_memset((POINTER)t, 0, sizeof(t)); + + /* Fermat's test for witness 2. + (All primes pass the test, and nearly all composites fail.) + */ + + if(status) { + NN_ASSIGN_DIGIT(t, 2, aDigits); + NN_ModExp(u, t, a, aDigits, a, aDigits); + + status = NN_EQUAL(t, u, aDigits); + + /* Clear sensitive information. */ + + R_memset((POINTER)u, 0, sizeof(u)); + } + + return(status ? TRUE : FALSE); +} + diff --git a/source/prime.h b/source/prime.h old mode 100755 new mode 100644 index 392d5ed..c030afd --- a/source/prime.h +++ b/source/prime.h @@ -1,23 +1,21 @@ /* PRIME.H - header file for PRIME.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Prime Number routines header file. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ int GeneratePrime PROTO_LIST ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, R_RANDOM_STRUCT *)); diff --git a/source/r_dh.c b/source/r_dh.c old mode 100755 new mode 100644 index e438f8d..3f09a2e --- a/source/r_dh.c +++ b/source/r_dh.c @@ -2,7 +2,7 @@ R_DH.C - Diffie-Hellman routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. @@ -23,7 +23,6 @@ Diffie-Hellman key agreement stuff, based heavily on RSAREF(tm) and relies heavily on the NN.C routines. - 1.00 23/6/95, Final Release Version */ #include "rsaeuro.h" @@ -165,4 +164,4 @@ R_DH_PARAMS *params; /* Diffie-Hellman parameters */ R_memset((POINTER)z, 0, sizeof(z)); return(IDOK); -} \ No newline at end of file +} diff --git a/source/r_encode.c b/source/r_encode.c old mode 100755 new mode 100644 index 69fe820..00030f1 --- a/source/r_encode.c +++ b/source/r_encode.c @@ -1,219 +1,219 @@ -/* - R_ENCODE.C - RFC 1113 encoding and decoding routines - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - Based in a similar form to the PGP RFC 1113 coding routines. - - Revision history - 0.90 First revision, based purely on using macros to - en/decode data to RFC 1113 standard. - - 0.91 Initial revision using current system. - - 0.92 Third revision, fixed minor bugs in rev. 0.91 - and better comments updated, plus code layout. - - 1.02 Fourth revision, fixed bug in R_EncodePEMBlock - reported by Wang Wei Jun . -*/ - -#include "rsaeuro.h" - -/* RFC 1113 encoding: - - Value Encoding Value Encoding Value Encoding Value Encoding - 0 A 17 R 34 i 51 z - 1 B 18 S 35 j 52 0 - 2 C 19 T 36 k 53 1 - 3 D 20 U 37 l 54 2 - 4 E 21 V 38 m 55 3 - 5 F 22 W 39 n 56 4 - 6 G 23 X 40 o 57 5 - 7 H 24 Y 41 p 58 6 - 8 I 25 Z 42 q 59 7 - 9 J 26 a 43 r 60 8 - 10 K 27 b 44 s 61 9 - 11 L 28 c 45 t 62 + - 12 M 29 d 46 u 63 / - 13 N 30 e 47 v - 14 O 31 f 48 w (pad) = - 15 P 32 g 49 x - 16 Q 33 h 50 y -*/ - -/* - PEM routines. - This converts a binary file into printable ASCII characters, in a - radix-64 form mostly compatible with the PEM RFC 1113 format. - This makes it easier to send encrypted files over a 7-bit channel. -*/ - -/* ENC is the basic 1 character encoding function to make a char printing */ - -#define ENC(c) ((int)bintoasc[((c) & 077)]) -#define PAD '=' - -/* Index this array by a 6 bit value to get the character corresponding - to that value. */ - -static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ -abcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* Index this array by a 7 bit value to get the 6-bit binary field - corresponding to that value. Any illegal characters return high bit set. */ - -static unsigned char asctobin[] = { - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0200,0200,0200,0200,0200, - 0200,0200,0200,0076,0200,0200,0200,0077, - 0064,0065,0066,0067,0070,0071,0072,0073, - 0074,0075,0200,0200,0200,0200,0200,0200, - 0200,0000,0001,0002,0003,0004,0005,0006, - 0007,0010,0011,0012,0013,0014,0015,0016, - 0017,0020,0021,0022,0023,0024,0025,0026, - 0027,0030,0031,0200,0200,0200,0200,0200, - 0200,0032,0033,0034,0035,0036,0037,0040, - 0041,0042,0043,0044,0045,0046,0047,0050, - 0051,0052,0053,0054,0055,0056,0057,0060, - 0061,0062,0063,0200,0200,0200,0200,0200 -}; - -static void encode PROTO_LIST((unsigned char [4], unsigned char [3], int )); - -/* This will always returns 0. It is an int function for future compatibility, - done to provide compatibility with RSAREF(tm). */ - -int R_EncodePEMBlock(encodedBlock, encodedBlockLen, block, blockLen) -unsigned char *encodedBlock; /* encoded block */ -unsigned int *encodedBlockLen; /* length of encoded block */ -unsigned char *block; /* block */ -unsigned int blockLen; /* length of block */ -{ - unsigned int i, lastLen; - - if(blockLen < 1) { - *encodedBlockLen = 0; - return (IDOK); - } - - *encodedBlockLen = 0; - - /* Bug Fixed By SK 02/09/95 */ - for (i = 0, lastLen = blockLen; i < blockLen; i += 3) { - encode(&encodedBlock[4*i/3], &block[i], (lastLen >= 3 ? 3 : lastLen)); - lastLen -= 3; - *encodedBlockLen += 4; - } - - return(IDOK); -} - -int R_DecodePEMBlock (outbuf, outlength, inbuf, inlength) -unsigned char *outbuf; /* block */ -unsigned int *outlength; /* length of block */ -unsigned char *inbuf; /* encoded block */ -unsigned int inlength; /* length of encoded block */ -{ - unsigned char *bp; - int length; - unsigned int c1,c2,c3,c4; - register int j; - - if(inlength % 4) - return (RE_ENCODING); - - if(inlength < 1) { - *outlength = 0; - return (IDOK); - } - - - length = 0; - bp = (unsigned char *)inbuf; - - /* FOUR input characters go into each THREE output charcters */ - - while(inlength > 0) { - if(*bp&0x80 || (c1=asctobin[*bp])&0x80) - return(RE_ENCODING); - ++bp; - if(*bp&0x80 || (c2=asctobin[*bp])&0x80) - return(RE_ENCODING); - if(*++bp == PAD){ - c3 = c4 = 0; - length += 1; - if(*++bp != PAD) - return(RE_ENCODING); - } - else if(*bp&0x80 || (c3=asctobin[*bp])&0x80) - return(RE_ENCODING); - else { - if(*++bp == PAD) { - c4 = 0; - length += 2; - } - else if (*bp&0x80 || (c4=asctobin[*bp])&0x80) - return(RE_ENCODING); - else - length += 3; - } - ++bp; - j = (c1 << 2) | (c2 >> 4); - *outbuf++=j; - j = (c2 << 4) | (c3 >> 2); - *outbuf++=j; - j = (c3 << 6) | c4; - *outbuf++=j; - inlength -= 4; - } - - *outlength = length; - return(IDOK); /* normal return */ - -} - -/* - Output one group of up to 3 bytes, pointed at by p, to buffer at f. - If fewer than 3 are present, the 1 or two extras must be zeros. -*/ - -static void encode(f, p, count) -unsigned char *f; /* output buffer */ -unsigned char *p; /* input buffer */ -int count; /* count */ -{ - int c1, c2, c3, c4; - - c1 = *p >> 2; - c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017); - c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); - c4 = p[2] & 077; - *f++ = ENC(c1); - *f++ = ENC(c2); - if (count == 1) - { - *f++ = PAD; - *f++ = PAD; - }else{ - *f++ = ENC(c3); - if(count == 2) *f++ = PAD; - else *f++ = ENC(c4); - } -} - +/* + R_ENCODE.C - RFC 1113 encoding and decoding routines + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + Based in a similar form to the PGP RFC 1113 coding routines. + + Revision history + 0.90 First revision, based purely on using macros to + en/decode data to RFC 1113 standard. + + 0.91 Initial revision using current system. + + 0.92 Third revision, fixed minor bugs in rev. 0.91 + and better comments updated, plus code layout. + + 1.02 Fourth revision, fixed bug in R_EncodePEMBlock + reported by Wang Wei Jun . +*/ + +#include "rsaeuro.h" + +/* RFC 1113 encoding: + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y +*/ + +/* + PEM routines. + This converts a binary file into printable ASCII characters, in a + radix-64 form mostly compatible with the PEM RFC 1113 format. + This makes it easier to send encrypted files over a 7-bit channel. +*/ + +/* ENC is the basic 1 character encoding function to make a char printing */ + +#define ENC(c) ((int)bintoasc[((c) & 077)]) +#define PAD '=' + +/* Index this array by a 6 bit value to get the character corresponding + to that value. */ + +static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ +abcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* Index this array by a 7 bit value to get the 6-bit binary field + corresponding to that value. Any illegal characters return high bit set. */ + +static unsigned char asctobin[] = { + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0200,0200,0200,0200,0200, + 0200,0200,0200,0076,0200,0200,0200,0077, + 0064,0065,0066,0067,0070,0071,0072,0073, + 0074,0075,0200,0200,0200,0200,0200,0200, + 0200,0000,0001,0002,0003,0004,0005,0006, + 0007,0010,0011,0012,0013,0014,0015,0016, + 0017,0020,0021,0022,0023,0024,0025,0026, + 0027,0030,0031,0200,0200,0200,0200,0200, + 0200,0032,0033,0034,0035,0036,0037,0040, + 0041,0042,0043,0044,0045,0046,0047,0050, + 0051,0052,0053,0054,0055,0056,0057,0060, + 0061,0062,0063,0200,0200,0200,0200,0200 +}; + +static void encode PROTO_LIST((unsigned char [4], unsigned char [3], int )); + +/* This will always returns 0. It is an int function for future compatibility, + done to provide compatibility with RSAREF(tm). */ + +int R_EncodePEMBlock(encodedBlock, encodedBlockLen, block, blockLen) +unsigned char *encodedBlock; /* encoded block */ +unsigned int *encodedBlockLen; /* length of encoded block */ +unsigned char *block; /* block */ +unsigned int blockLen; /* length of block */ +{ + unsigned int i, lastLen; + + if(blockLen < 1) { + *encodedBlockLen = 0; + return (IDOK); + } + + *encodedBlockLen = 0; + + /* Bug Fixed By SK 02/09/95 */ + for (i = 0, lastLen = blockLen; i < blockLen; i += 3) { + encode(&encodedBlock[4*i/3], &block[i], (lastLen >= 3 ? 3 : lastLen)); + lastLen -= 3; + *encodedBlockLen += 4; + } + + return(IDOK); +} + +int R_DecodePEMBlock (outbuf, outlength, inbuf, inlength) +unsigned char *outbuf; /* block */ +unsigned int *outlength; /* length of block */ +unsigned char *inbuf; /* encoded block */ +unsigned int inlength; /* length of encoded block */ +{ + unsigned char *bp; + int length; + unsigned int c1,c2,c3,c4; + register int j; + + if(inlength % 4) + return (RE_ENCODING); + + if(inlength < 1) { + *outlength = 0; + return (IDOK); + } + + + length = 0; + bp = (unsigned char *)inbuf; + + /* FOUR input characters go into each THREE output charcters */ + + while(inlength > 0) { + if(*bp&0x80 || (c1=asctobin[*bp])&0x80) + return(RE_ENCODING); + ++bp; + if(*bp&0x80 || (c2=asctobin[*bp])&0x80) + return(RE_ENCODING); + if(*++bp == PAD){ + c3 = c4 = 0; + length += 1; + if(*++bp != PAD) + return(RE_ENCODING); + } + else if(*bp&0x80 || (c3=asctobin[*bp])&0x80) + return(RE_ENCODING); + else { + if(*++bp == PAD) { + c4 = 0; + length += 2; + } + else if (*bp&0x80 || (c4=asctobin[*bp])&0x80) + return(RE_ENCODING); + else + length += 3; + } + ++bp; + j = (c1 << 2) | (c2 >> 4); + *outbuf++=j; + j = (c2 << 4) | (c3 >> 2); + *outbuf++=j; + j = (c3 << 6) | c4; + *outbuf++=j; + inlength -= 4; + } + + *outlength = length; + return(IDOK); /* normal return */ + +} + +/* + Output one group of up to 3 bytes, pointed at by p, to buffer at f. + If fewer than 3 are present, the 1 or two extras must be zeros. +*/ + +static void encode(f, p, count) +unsigned char *f; /* output buffer */ +unsigned char *p; /* input buffer */ +int count; /* count */ +{ + int c1, c2, c3, c4; + + c1 = *p >> 2; + c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017); + c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); + c4 = p[2] & 077; + *f++ = ENC(c1); + *f++ = ENC(c2); + if (count == 1) + { + *f++ = PAD; + *f++ = PAD; + }else{ + *f++ = ENC(c3); + if(count == 2) *f++ = PAD; + else *f++ = ENC(c4); + } +} + diff --git a/source/r_enhanc.c b/source/r_enhanc.c old mode 100755 new mode 100644 index 03e4d4f..d7611ff --- a/source/r_enhanc.c +++ b/source/r_enhanc.c @@ -1,930 +1,931 @@ -/* - R_ENHANC.C - cryptographic enhancements for RSAEURO - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - Cryptographic Enhancements. - - Revision history - 0.90 First revision, initial production of file. - - 0.91 Second revision, altered to incorporate the addition of - the SHS hashing algorithm to the toolkit. Waiting for OBJ ID - for SHS Signature. - - 0.92 Third revision, modified Digest, Signing and Verifying - routines with improved error checking, to prevent SHS digest - being used for signing data. R_VerifyFinal altered to check - that same digest used in original signature was used in verify - doesn't verify signature if they don't match. - - 1.02 Fourth revision, R_SealUpdate Bug fixed, Bug Reported by - Anders Heerfordt . -*/ - -#include "rsaeuro.h" -#include "r_random.h" -#include "rsa.h" - -/* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 or 4 (for MD2/MD5/MD4), - then DIGEST_INFO_B, then 16-byte message digest. */ - -/* Using the Original RSAREF/PKCS Object Indentifier, for signatures */ - -static unsigned char DIGEST_INFO_A[] = { - 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x02 -}; - -#define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A) - -static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 }; - -#define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B) - -#define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16) - -static unsigned char *PADDING[] = { - (unsigned char *)"", (unsigned char *)"\01", (unsigned char *)"\02\02", - (unsigned char *)"\03\03\03", (unsigned char *)"\04\04\04\04", - (unsigned char *)"\05\05\05\05\05", - (unsigned char *)"\06\06\06\06\06\06", - (unsigned char *)"\07\07\07\07\07\07\07", - (unsigned char *)"\08\08\08\08\08\08\08\08" -}; - -#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN - -static void R_EncodeDigestInfo PROTO_LIST((unsigned char *, int, unsigned char *)); -static int R_CheckDigestInfo PROTO_LIST ((unsigned char *, unsigned char *)); - - /* encrypt prototypes */ - -static int CipherInit PROTO_LIST((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int)); -static void EncryptBlk PROTO_LIST((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int)); -static void RestartCipher PROTO_LIST((R_ENVELOPE_CTX *)); - -int R_DigestInit(context, digesttype) -R_DIGEST_CTX *context; /* new context */ -int digesttype; /* message-digest algorithm */ -{ - context->digestAlgorithm = digesttype; - - switch(digesttype) { - case DA_SHS: - SHSInit(&context->context.shs); - break; - - case DA_MD2: - MD2Init(&context->context.md2); - break; - - case DA_MD4: - MD4Init(&context->context.md4); - break; - - case DA_MD5: - MD5Init(&context->context.md5); - break; - - default: - return(RE_DIGEST_ALGORITHM); - } - - return(IDOK); -} - -int R_DigestUpdate(context, partIn, partInLen) -R_DIGEST_CTX *context; /* context */ -unsigned char *partIn; /* next data part */ -unsigned int partInLen; /* length of next data part */ -{ - switch(context->digestAlgorithm) { - case DA_SHS: - SHSUpdate(&context->context.shs, partIn, partInLen); - break; - - case DA_MD2: - MD2Update(&context->context.md2, partIn, partInLen); - break; - - case DA_MD4: - MD4Update(&context->context.md4, partIn, partInLen); - break; - - case DA_MD5: - MD5Update(&context->context.md5, partIn, partInLen); - break; - - default: - return(RE_DIGEST_ALGORITHM); - } - - return(IDOK); -} - -int R_DigestFinal(context, digest, digestLen) -R_DIGEST_CTX *context; /* context */ -unsigned char *digest; /* message digest */ -unsigned int *digestLen; /* length of message digest */ -{ - *digestLen = context->digestAlgorithm == DA_SHS ? 20 : 16; - - switch(context->digestAlgorithm) { - case DA_SHS: - SHSFinal(&context->context.shs); /* doesn't output as chars */ - break; - - case DA_MD2: - MD2Final(digest, &context->context.md2); - break; - - case DA_MD4: - MD4Final(digest, &context->context.md4); - break; - - case DA_MD5: - MD5Final(digest, &context->context.md5); - break; - - default: - return(RE_DIGEST_ALGORITHM); - } - - return(IDOK); -} - -/* Signing a file using SHS is not allowed for now */ - -int R_SignInit(context, digesttype) -R_SIGNATURE_CTX *context; /* new context */ -int digesttype; /* message-digest algorithm */ -{ - return((digesttype == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digesttype)); -} - -int R_SignUpdate(context, partIn, partInLen) -R_SIGNATURE_CTX *context; /* context */ -unsigned char *partIn; /* next data part */ -unsigned int partInLen; /* length of next data part */ -{ - return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen)); -} - -int R_SignFinal(context, signature, signatureLen, privateKey) -R_SIGNATURE_CTX *context; /* context */ -unsigned char *signature; /* signature */ -unsigned int *signatureLen; /* length of signature */ -R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ -{ - int status; - unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN]; - unsigned int digestLen; - - if(context->digestContext.digestAlgorithm == DA_SHS) - status = RE_DIGEST_ALGORITHM; - else { - if((status = R_DigestFinal(&context->digestContext, digest, &digestLen)) == 0) { - R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest); - - if(RSAPrivateEncrypt(signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey) != 0) { - status = RE_PRIVATE_KEY; - }else{ - /* Reset for another verification. */ - R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm); - } - } - /* Clear sensitive information. */ - R_memset(digest, 0, sizeof(digest)); - R_memset(digestInfo, 0, sizeof(digestInfo)); - } - - return(status); -} - -int R_VerifyInit(context, digestAlgorithm) -R_SIGNATURE_CTX *context; /* new context */ -int digestAlgorithm; /* message-digest algorithm */ -{ - return((digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digestAlgorithm)); -} - -int R_VerifyUpdate(context, partIn, partInLen) -R_SIGNATURE_CTX *context; /* context */ -unsigned char *partIn; /* next data part */ -unsigned int partInLen; /* length of next data part */ -{ - return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen)); -} - -int R_VerifyFinal(context, signature, signatureLen, publicKey) -R_SIGNATURE_CTX *context; /* context */ -unsigned char *signature; /* signature */ -unsigned int signatureLen; /* length of signature */ -R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ -{ - int status; - unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN], - originalDigestInfo[MAX_SIGNATURE_LEN]; - unsigned int originalDigestInfoLen, digestLen; - - status = 0; - if(signatureLen > MAX_SIGNATURE_LEN) - status = RE_LEN; - - if(context->digestContext.digestAlgorithm == DA_SHS) - status = RE_DIGEST_ALGORITHM; - - if(!status) { - if((status = R_DigestFinal (&context->digestContext, digest, &digestLen)) == 0) { - R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest); - - if(RSAPublicDecrypt(originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, publicKey) != 0) { - status = RE_PUBLIC_KEY; - }else{ /* Check the digest out */ - if((originalDigestInfoLen != DIGEST_INFO_LEN) || R_CheckDigestInfo(originalDigestInfo, digestInfo) || (R_memcmp((POINTER)originalDigestInfo, (POINTER)digestInfo, DIGEST_INFO_LEN))) - status = RE_SIGNATURE; - else - /* Reset for another verification. */ - R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm); - } - } - - /* Clear sensitive information. */ - R_memset(digest, 0, sizeof(digest)); - R_memset(digestInfo, 0, sizeof(digestInfo)); - R_memset(originalDigestInfo, 0, sizeof(originalDigestInfo)); - } - - return(status); -} - -/* Caller must ASCII encode the encrypted keys if required. */ - -int R_SealInit(context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys, - encryptionAlgorithm, randomStruct) -R_ENVELOPE_CTX *context; /* new context */ -unsigned char **encryptedKeys; /* encrypted keys */ -unsigned int *encryptedKeyLens; /* lengths of encrypted keys */ -unsigned char iv[8]; /* initialization vector */ -unsigned int publicKeyCount; /* number of public keys */ -R_RSA_PUBLIC_KEY **publicKeys; /* public keys */ -int encryptionAlgorithm; /* data encryption algorithm */ -R_RANDOM_STRUCT *randomStruct; /* random structure */ -{ - int status; - unsigned char key[24]; - unsigned int keyLen, i; - - context->encryptionAlgorithm = encryptionAlgorithm; - - keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24; - - if((status = R_GenerateBytes (key, keyLen, randomStruct)) == 0) { - if((status = R_GenerateBytes (iv, 8, randomStruct)) == 0) { - if(encryptionAlgorithm == EA_DES_EDE2_CBC) - /* Make both E keys the same */ - R_memcpy ((POINTER)(key + 16), (POINTER)key, 8); - - if((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) == 0) { - for(i = 0; i < publicKeyCount; ++i) { - if(RSAPublicEncrypt(encryptedKeys[i], &encryptedKeyLens[i], key, keyLen, - publicKeys[i], randomStruct)) { - status = RE_PUBLIC_KEY; - break; - } - } - } - if(status == 0) - context->bufferLen = 0; - } - } - - /* Clear sensitive information. */ - - R_memset(key, 0, sizeof(key)); - - return(status); -} - -/* partOut buffer should be at least partInLen + 7 */ - -int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *partOut; /* next encrypted data part */ -unsigned int *partOutLen; /* length of next encrypted data part */ -unsigned char *partIn; /* next data part */ -unsigned int partInLen; /* length of next data part */ -{ - unsigned int temp; - - temp = 8 - context->bufferLen; - if(partInLen < temp) { - /* Just accumulate into buffer. */ - *partOutLen = 0; - R_memcpy((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, partInLen); - context->bufferLen += partInLen; /* Bug Fix - 02/09/95, SK */ - return(IDOK); - } - - /* Fill the buffer and encrypt. */ - - R_memcpy((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, temp); - EncryptBlk(context, partOut, context->buffer, 8); - partOut += 8; - *partOutLen = 8; - partIn += temp; - partInLen -= temp; - - /* Encrypt as many 8-byte blocks as possible. */ - - temp = 8 * (partInLen / 8); - EncryptBlk(context, partOut, partIn, temp); - *partOutLen += temp; - partIn += temp; - partInLen -= temp; - - - /* Length now less than 8, so copy remainder to buffer for next time. */ - R_memcpy((POINTER)context->buffer, partIn, context->bufferLen = partInLen); - - return(IDOK); -} - -/* Assume partOut buffer is at least 8 bytes. */ - -int R_SealFinal(context, partOut, partOutLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *partOut; /* last encrypted data part */ -unsigned int *partOutLen; /* length of last encrypted data part */ -{ - unsigned int padLen; - - /* Pad and encrypt final block. */ - - padLen = 8 - context->bufferLen; /* little trick to pad the block */ - R_memset((POINTER)(context->buffer + context->bufferLen), (int)padLen, padLen); - EncryptBlk(context, partOut, context->buffer, 8); - *partOutLen = 8; - - /* Restart the context. */ - - RestartCipher(context); - context->bufferLen = 0; - - return(IDOK); -} - -/* Assume caller has already ASCII decoded the encryptedKey if necessary. */ - -int R_OpenInit(context, encryptionAlgorithm, encryptedKey, encryptedKeyLen, iv, privateKey) -R_ENVELOPE_CTX *context; /* new context */ -int encryptionAlgorithm; /* data encryption algorithm */ -unsigned char *encryptedKey; /* encrypted data encryption key */ -unsigned int encryptedKeyLen; /* length of encrypted key */ -unsigned char iv[8]; /* initialization vector */ -R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ -{ - int status; - unsigned char key[MAX_ENCRYPTED_KEY_LEN]; - unsigned int keyLen; - - if(encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN) - return(RE_LEN); - - context->encryptionAlgorithm = encryptionAlgorithm; - - if(RSAPrivateDecrypt(key, &keyLen, encryptedKey, encryptedKeyLen, privateKey)) { - status = RE_PRIVATE_KEY; - }else{ - if(encryptionAlgorithm == EA_DES_CBC) { - if(keyLen != 8) status = RE_PRIVATE_KEY; - else{ - if((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) == 0) - context->bufferLen = 0; - } - }else{ - if(keyLen != 24) status = RE_PRIVATE_KEY; - else { - if((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) == 0) - context->bufferLen = 0; - } - } - } - - /* Clear sensitive information. */ - - R_memset(key, 0, sizeof(key)); - - return(status); -} - -/* Assume partOut buffer is at least partInLen + 7. - Always leaves at least one byte in buffer. */ - -int R_OpenUpdate(context, partOut, partOutLen, partIn, partInLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *partOut; /* next recovered data part */ -unsigned int *partOutLen; /* length of next recovered data part */ -unsigned char *partIn; /* next encrypted data part */ -unsigned int partInLen; /* length of next encrypted data part */ -{ - unsigned int tempLen; - - tempLen = 8 - context->bufferLen; - if (partInLen <= tempLen) { - /* Just accumulate into buffer. */ - *partOutLen = 0; - R_memcpy((POINTER)(context->buffer + context->bufferLen), partIn, partInLen); - context->bufferLen += partInLen; - return(IDOK); - } - - /* Fill the buffer and decrypt. We know that there will be more left - in partIn after decrypting the buffer. */ - - R_memcpy((POINTER)(context->buffer + context->bufferLen), partIn, tempLen); - - EncryptBlk (context, partOut, context->buffer, 8); - partOut += 8; - *partOutLen = 8; - partIn += tempLen; - partInLen -= tempLen; - - /* Decrypt as many 8 byte blocks as possible, leaving at least one byte - in partIn. */ - - tempLen = 8 * ((partInLen - 1) / 8); - EncryptBlk (context, partOut, partIn, tempLen); - partIn += tempLen; - *partOutLen += tempLen; - partInLen -= tempLen; - - /* Length is between 1 and 8, so copy into buffer. */ - - R_memcpy((POINTER)context->buffer, partIn, context->bufferLen = partInLen); - - return (IDOK); -} - -/* Assume partOut buffer is at least 7 bytes. */ - -int R_OpenFinal(context, partOut, partOutLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *partOut; /* last recovered data part */ -unsigned int *partOutLen; /* length of last recovered data part */ -{ - int status; - unsigned char lastPart[8]; - unsigned int padLen; - - status = 0; - - if(context->bufferLen == 0) - /* There was no input data to decrypt */ - *partOutLen = 0; - else { - if(context->bufferLen != 8) { - status = RE_KEY; - }else{ - - /* Decrypt and strip any padding from the final block. */ - - EncryptBlk (context, lastPart, context->buffer, 8); - - padLen = lastPart[7]; - - if(padLen == 0 || padLen > 8) - status = RE_KEY; - else{ - if(R_memcmp((POINTER)&lastPart[8 - padLen], PADDING[padLen], padLen) != 0) - status = RE_KEY; - else - R_memcpy (partOut, lastPart, *partOutLen = 8 - padLen); - } - /* Restart the context. */ - if(status == 0) { - RestartCipher(context); - context->bufferLen = 0; - } - } - } - - /* Clear sensitive information. */ - - R_memset(lastPart, 0, sizeof(lastPart)); - - return (status); -} - -/**/ - -int R_SignPEMBlock(encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen, - content, contentLen, recode, digestAlgorithm, privateKey) -unsigned char *encodedContent; /* encoded content */ -unsigned int *encodedContentLen; /* length of encoded content */ -unsigned char *encodedSignature; /* encoded signature */ -unsigned int *encodedSignatureLen; /* length of encoded signature */ -unsigned char *content; /* content */ -unsigned int contentLen; /* length of content */ -int recode; /* recoding flag */ -int digestAlgorithm; /* message-digest algorithm */ -R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ -{ - int status; - unsigned char signature[MAX_SIGNATURE_LEN]; - unsigned int signatureLen; - - if((status = R_SignBlock(signature, &signatureLen, content, contentLen, digestAlgorithm, privateKey)) != 0) - return(status); - - if(recode) - R_EncodePEMBlock(encodedContent, encodedContentLen, content, contentLen); - - R_EncodePEMBlock(encodedSignature, encodedSignatureLen, signature, signatureLen); - - return(IDOK); -} - -int R_SignBlock(signature, signatureLen, block, blockLen, digestAlgorithm, privateKey) -unsigned char *signature; /* signature */ -unsigned int *signatureLen; /* length of signature */ -unsigned char *block; /* block */ -unsigned int blockLen; /* length of block */ -int digestAlgorithm; /* message-digest algorithm */ -R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ -{ - R_SIGNATURE_CTX context; - int status; - - if((status = R_SignInit(&context, digestAlgorithm)) == 0) - if((status = R_SignUpdate(&context, block, blockLen)) == 0) - status = R_SignFinal(&context, signature, signatureLen, privateKey); - - /* Clear sensitive information. */ - R_memset((POINTER)&context, 0, sizeof(context)); - - return(status); -} - -int R_VerifyPEMSignature(content, contentLen, encodedContent, encodedContentLen, encodedSignature, - encodedSignatureLen, recode, digestAlgorithm, publicKey) -unsigned char *content; /* content */ -unsigned int *contentLen; /* length of content */ -unsigned char *encodedContent; /* (possibly) encoded content */ -unsigned int encodedContentLen; /* length of encoded content */ -unsigned char *encodedSignature; /* encoded signature */ -unsigned int encodedSignatureLen; /* length of encoded signature */ -int recode; /* recoding flag */ -int digestAlgorithm; /* message-digest algorithm */ -R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ -{ - unsigned char signature[MAX_SIGNATURE_LEN]; - unsigned int signatureLen; - - if(encodedSignatureLen > MAX_PEM_SIGNATURE_LEN) - return(RE_SIGNATURE_ENCODING); - - if(recode) { - if(R_DecodePEMBlock(content, contentLen, encodedContent, encodedContentLen)) - return(RE_CONTENT_ENCODING); - }else{ - *contentLen = encodedContentLen; - content = encodedContent; - } - - if(R_DecodePEMBlock(signature, &signatureLen, encodedSignature, encodedSignatureLen)) - return (RE_SIGNATURE_ENCODING); - - return(R_VerifyBlockSignature(content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey)); -} - -int R_VerifyBlockSignature(block, blockLen, signature, signatureLen, digestAlgorithm, publicKey) -unsigned char *block; /* block */ -unsigned int blockLen; /* length of block */ -unsigned char *signature; /* signature */ -unsigned int signatureLen; /* length of signature */ -int digestAlgorithm; /* message-digest algorithm */ -R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ -{ - R_SIGNATURE_CTX context; - int status; - - if((status = R_VerifyInit(&context, digestAlgorithm)) == 0) - if((status = R_VerifyUpdate(&context, block, blockLen)) == 0) - status = R_VerifyFinal(&context, signature, signatureLen, publicKey); - - /* Clear sensitive information. */ - R_memset((POINTER)&context, 0, sizeof(context)); - - return(status); -} - -int R_SealPEMBlock(encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen, - encryptedSignature, encryptedSignatureLen, iv, content, contentLen, - digestAlgorithm, publicKey, privateKey, randomStruct) -unsigned char *encryptedContent; /* encoded, encrypted content */ -unsigned int *encryptedContentLen; /* length */ -unsigned char *encryptedKey; /* encoded, encrypted key */ -unsigned int *encryptedKeyLen; /* length */ -unsigned char *encryptedSignature; /* encoded, encrypted signature */ -unsigned int *encryptedSignatureLen; /* length */ -unsigned char iv[8]; /* DES initialization vector */ -unsigned char *content; /* content */ -unsigned int contentLen; /* length of content */ -int digestAlgorithm; /* message-digest algorithms */ -R_RSA_PUBLIC_KEY *publicKey; /* recipient's RSA public key */ -R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ -R_RANDOM_STRUCT *randomStruct; /* random structure */ -{ - R_ENVELOPE_CTX context; - R_RSA_PUBLIC_KEY *publicKeys[1]; - int status; - unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], - signature[MAX_SIGNATURE_LEN], *encryptedKeys[1]; - unsigned int signatureLen, encryptedKeyBlockLen; - - if((status = R_SignBlock(signature, &signatureLen, content, contentLen, - digestAlgorithm, privateKey)) == 0) { - - encryptedKeys[0] = encryptedKeyBlock; - publicKeys[0] = publicKey; - - if((status = R_SealInit(&context, encryptedKeys, &encryptedKeyBlockLen, iv, 1, publicKeys, EA_DES_CBC, randomStruct)) == 0) { - - R_EncodePEMBlock(encryptedKey, encryptedKeyLen, encryptedKeyBlock, - encryptedKeyBlockLen); - - R_EncryptOpenPEMBlock(&context, encryptedContent, encryptedContentLen, - content, contentLen); - - R_EncryptOpenPEMBlock(&context, encryptedSignature, encryptedSignatureLen, - signature, signatureLen); - } - } - - /* Clear sensitive information. */ - R_memset((POINTER)&context, 0, sizeof(context)); - R_memset(signature, 0, sizeof(signature)); - - return (status); -} - -int R_OpenPEMBlock(content, contentLen, encryptedContent, encryptedContentLen, encryptedKey, - encryptedKeyLen, encryptedSignature, encryptedSignatureLen, - iv, digestAlgorithm, privateKey, publicKey) -unsigned char *content; /* content */ -unsigned int *contentLen; /* length of content */ -unsigned char *encryptedContent; /* encoded, encrypted content */ -unsigned int encryptedContentLen; /* length */ -unsigned char *encryptedKey; /* encoded, encrypted key */ -unsigned int encryptedKeyLen; /* length */ -unsigned char *encryptedSignature; /* encoded, encrypted signature */ -unsigned int encryptedSignatureLen; /* length */ -unsigned char iv[8]; /* DES initialization vector */ -int digestAlgorithm; /* message-digest algorithms */ -R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ -R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ -{ - R_ENVELOPE_CTX context; - int status; - unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], - signature[MAX_SIGNATURE_LEN]; - unsigned int encryptedKeyBlockLen, signatureLen; - - if(encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN) - return(RE_SIGNATURE_ENCODING); - - if(encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN) - return(RE_KEY_ENCODING); - - if(R_DecodePEMBlock(encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey, encryptedKeyLen) != 0) { - status = RE_KEY_ENCODING; - }else{ - if((status = R_OpenInit(&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen, iv, privateKey)) == 0) { - - if((status = R_DecryptOpenPEMBlock(&context, content, contentLen, encryptedContent, encryptedContentLen)) != 0) { - if((status == RE_LEN || status == RE_ENCODING)) - status = RE_CONTENT_ENCODING; - else - status = RE_KEY; - }else{ - - status = R_DecryptOpenPEMBlock(&context, signature, &signatureLen, encryptedSignature, encryptedSignatureLen); - - if(status) { - if((status == RE_LEN || status == RE_ENCODING)) - status = RE_SIGNATURE_ENCODING; - else - status = RE_KEY; - }else - status = R_VerifyBlockSignature(content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey); - } - } - } - /* Clear sensitive information. */ - - R_memset((POINTER)&context, 0, sizeof(context)); - R_memset(signature, 0, sizeof(signature)); - - return(status); -} - -int R_DigestBlock(digest, digestLen, block, blockLen, digestAlgorithm) -unsigned char *digest; /* message digest */ -unsigned int *digestLen; /* length of message digest */ -unsigned char *block; /* block */ -unsigned int blockLen; /* length of block */ -int digestAlgorithm; /* message-digest algorithm */ -{ - R_DIGEST_CTX context; - int status; - - if((status = R_DigestInit(&context, digestAlgorithm)) == 0) - if((status = R_DigestUpdate(&context, block, blockLen)) == 0) - status = R_DigestFinal(&context, digest, digestLen); - - /* Clear sensitive information. */ - - R_memset((POINTER)&context, 0, sizeof(context)); - - return(status); -} - -int R_DecryptOpenPEMBlock(context, output, outputLen, input, inputLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *output; /* decoded, decrypted block */ -unsigned int *outputLen; /* length of output */ -unsigned char *input; /* encrypted, encoded block */ -unsigned int inputLen; /* length */ -{ - int status; - unsigned char encryptedPart[24]; - unsigned int i, len; - - *outputLen = 0; - - for (i = 0; i < inputLen/32; i++) { - /* len is always 24 */ - if ((status = R_DecodePEMBlock(encryptedPart, &len, &input[32*i], 32)) != 0) - break; - - R_OpenUpdate (context, output, &len, encryptedPart, 24); - *outputLen += len; - output += len; - } - - if(!status) /* Decode the last block. */ - if((status = R_DecodePEMBlock(encryptedPart, &len, &input[32*i], inputLen - 32*i)) == 0) { - /* Decrypt the last block. */ - R_OpenUpdate (context, output, &len, encryptedPart, len); - output += len; - *outputLen += len; - if((status = R_OpenFinal (context, output, &len)) == 0) - *outputLen += len; - } - - /* Clear sensitive information. */ - - R_memset((POINTER)&context, 0, sizeof(context)); - R_memset(encryptedPart, 0, sizeof(encryptedPart)); - - return(status); -} - -int R_EncryptOpenPEMBlock(context, output, outputLen, input, inputLen) -R_ENVELOPE_CTX *context; /* context */ -unsigned char *output; /* encrypted, encoded block */ -unsigned int *outputLen; /* length of output */ -unsigned char *input; /* block to encrypt */ -unsigned int inputLen; /* length */ -{ - unsigned char encryptedPart[24]; - unsigned int i, lastPartLen, tempLen, len; - - /* Encrypt and encode as many 24-byte blocks as possible. */ - - for (i = 0; i < inputLen / 24; ++i) { - /* Assume part out length will equal part in length since it is - a multiple of 8. Also assume no error output. */ - R_SealUpdate (context, encryptedPart, &tempLen, &input[24*i], 24); - - /* len will always be 32 */ - R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24); - } - - /* Encrypt the last part into encryptedPart. */ - - R_SealUpdate(context, encryptedPart, &lastPartLen, &input[24*i], inputLen - 24*i); - R_SealFinal(context, encryptedPart + lastPartLen, &len); - lastPartLen += len; - - R_EncodePEMBlock(&output[32*i], &len, encryptedPart, lastPartLen); - *outputLen = 32*i + len; - - /* Clear sensitive information. */ - - R_memset(encryptedPart, 0, sizeof(encryptedPart)); - - return(IDOK); -} - -/* Assumes that digestAlgorithm is DA_MD2, DA_MD4 or DA_MD5 and - the digest length must be 16. SHS Not supported here. */ - -static void R_EncodeDigestInfo(digestInfo, digestAlgorithm, digest) -unsigned char *digestInfo; -int digestAlgorithm; -unsigned char *digest; -{ - if(!(digestAlgorithm == DA_SHS)) { - digestInfo[DIGEST_INFO_A_LEN] = digestAlgorithm; - - R_memcpy((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B, DIGEST_INFO_B_LEN); - R_memcpy((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN); - R_memcpy((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN], (POINTER)digest, 16); - } -} - -/* Quick check to correct digest was used to verify */ - -static int R_CheckDigestInfo(originaldigestInfo, digestInfo) -unsigned char *originaldigestInfo; -unsigned char *digestInfo; -{ - return((originaldigestInfo[DIGEST_INFO_A_LEN] == - digestInfo[DIGEST_INFO_A_LEN]) ? IDOK : RE_SIGNATURE); -} - -static int CipherInit(context, encryptionAlgorithm, key, iv, encrypt) -R_ENVELOPE_CTX *context; -int encryptionAlgorithm; -unsigned char *key; -unsigned char *iv; -int encrypt; -{ - switch(encryptionAlgorithm) { - case EA_DES_CBC: - DES_CBCInit (&context->cipherContext.des, key, iv, encrypt); - break; - case EA_DESX_CBC: - DESX_CBCInit (&context->cipherContext.desx, key, iv, encrypt); - break; - case EA_DES_EDE2_CBC: - case EA_DES_EDE3_CBC: - DES3_CBCInit (&context->cipherContext.des3, key, iv, encrypt); - break; - default: - return (RE_ENCRYPTION_ALGORITHM); - } - return(IDOK); -} - -/* Assume len is a multiple of 8. - */ -static void EncryptBlk(context, output, input, len) -R_ENVELOPE_CTX *context; -unsigned char *output; -unsigned char *input; -unsigned int len; -{ - switch(context->encryptionAlgorithm) { - case EA_DES_CBC: - DES_CBCUpdate (&context->cipherContext.des, output, input, len); - break; - case EA_DESX_CBC: - DESX_CBCUpdate (&context->cipherContext.desx, output, input, len); - break; - case EA_DES_EDE2_CBC: - case EA_DES_EDE3_CBC: - DES3_CBCUpdate (&context->cipherContext.des3, output, input, len); - } -} - -static void RestartCipher(context) -R_ENVELOPE_CTX *context; -{ - switch(context->encryptionAlgorithm) { - case EA_DES_CBC: - DES_CBCRestart (&context->cipherContext.des); - break; - case EA_DESX_CBC: - DESX_CBCRestart (&context->cipherContext.desx); - break; - case EA_DES_EDE2_CBC: - case EA_DES_EDE3_CBC: - DES3_CBCRestart (&context->cipherContext.des3); - } -} +/* + R_ENHANC.C - cryptographic enhancements for RSAEURO + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + Cryptographic Enhancements. + + Revision history + 0.90 First revision, initial production of file. + + 0.91 Second revision, altered to incorporate the addition of + the SHS hashing algorithm to the toolkit. Waiting for OBJ ID + for SHS Signature. + + 0.92 Third revision, modified Digest, Signing and Verifying + routines with improved error checking, to prevent SHS digest + being used for signing data. R_VerifyFinal altered to check + that same digest used in original signature was used in verify + doesn't verify signature if they don't match. + + 1.02 Fourth revision, R_SealUpdate Bug fixed, Bug Reported by + Anders Heerfordt . PADDING problem array incorrectly + setup, reported by Anders Heerfordt . +*/ + +#include "rsaeuro.h" +#include "r_random.h" +#include "rsa.h" + +/* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 or 4 (for MD2/MD5/MD4), + then DIGEST_INFO_B, then 16-byte message digest. */ + +/* Using the Original RSAREF/PKCS Object Indentifier, for signatures */ + +static unsigned char DIGEST_INFO_A[] = { + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x02 +}; + +#define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A) + +static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 }; + +#define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B) + +#define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16) + +static unsigned char *PADDING[] = { + (unsigned char *)"", (unsigned char *)"\01", (unsigned char *)"\02\02", + (unsigned char *)"\03\03\03", (unsigned char *)"\04\04\04\04", + (unsigned char *)"\05\05\05\05\05", + (unsigned char *)"\06\06\06\06\06\06", + (unsigned char *)"\07\07\07\07\07\07\07", + (unsigned char *)"\08\08\08\08\08\08\08\08" +}; + +#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN + +static void R_EncodeDigestInfo PROTO_LIST((unsigned char *, int, unsigned char *)); +static int R_CheckDigestInfo PROTO_LIST ((unsigned char *, unsigned char *)); + + /* encrypt prototypes */ + +static int CipherInit PROTO_LIST((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int)); +static void EncryptBlk PROTO_LIST((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int)); +static void RestartCipher PROTO_LIST((R_ENVELOPE_CTX *)); + +int R_DigestInit(context, digesttype) +R_DIGEST_CTX *context; /* new context */ +int digesttype; /* message-digest algorithm */ +{ + context->digestAlgorithm = digesttype; + + switch(digesttype) { + case DA_SHS: + SHSInit(&context->context.shs); + break; + + case DA_MD2: + MD2Init(&context->context.md2); + break; + + case DA_MD4: + MD4Init(&context->context.md4); + break; + + case DA_MD5: + MD5Init(&context->context.md5); + break; + + default: + return(RE_DIGEST_ALGORITHM); + } + + return(IDOK); +} + +int R_DigestUpdate(context, partIn, partInLen) +R_DIGEST_CTX *context; /* context */ +unsigned char *partIn; /* next data part */ +unsigned int partInLen; /* length of next data part */ +{ + switch(context->digestAlgorithm) { + case DA_SHS: + SHSUpdate(&context->context.shs, partIn, partInLen); + break; + + case DA_MD2: + MD2Update(&context->context.md2, partIn, partInLen); + break; + + case DA_MD4: + MD4Update(&context->context.md4, partIn, partInLen); + break; + + case DA_MD5: + MD5Update(&context->context.md5, partIn, partInLen); + break; + + default: + return(RE_DIGEST_ALGORITHM); + } + + return(IDOK); +} + +int R_DigestFinal(context, digest, digestLen) +R_DIGEST_CTX *context; /* context */ +unsigned char *digest; /* message digest */ +unsigned int *digestLen; /* length of message digest */ +{ + *digestLen = context->digestAlgorithm == DA_SHS ? 20 : 16; + + switch(context->digestAlgorithm) { + case DA_SHS: + SHSFinal(digest, &context->context.shs); /* doesn't output as chars */ + break; + + case DA_MD2: + MD2Final(digest, &context->context.md2); + break; + + case DA_MD4: + MD4Final(digest, &context->context.md4); + break; + + case DA_MD5: + MD5Final(digest, &context->context.md5); + break; + + default: + return(RE_DIGEST_ALGORITHM); + } + + return(IDOK); +} + +/* Signing a file using SHS is not allowed for now */ + +int R_SignInit(context, digesttype) +R_SIGNATURE_CTX *context; /* new context */ +int digesttype; /* message-digest algorithm */ +{ + return((digesttype == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digesttype)); +} + +int R_SignUpdate(context, partIn, partInLen) +R_SIGNATURE_CTX *context; /* context */ +unsigned char *partIn; /* next data part */ +unsigned int partInLen; /* length of next data part */ +{ + return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen)); +} + +int R_SignFinal(context, signature, signatureLen, privateKey) +R_SIGNATURE_CTX *context; /* context */ +unsigned char *signature; /* signature */ +unsigned int *signatureLen; /* length of signature */ +R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ +{ + int status; + unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN]; + unsigned int digestLen; + + if(context->digestContext.digestAlgorithm == DA_SHS) + status = RE_DIGEST_ALGORITHM; + else { + if((status = R_DigestFinal(&context->digestContext, digest, &digestLen)) == 0) { + R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest); + + if(RSAPrivateEncrypt(signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey) != 0) { + status = RE_PRIVATE_KEY; + }else{ + /* Reset for another verification. */ + R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm); + } + } + /* Clear sensitive information. */ + R_memset(digest, 0, sizeof(digest)); + R_memset(digestInfo, 0, sizeof(digestInfo)); + } + + return(status); +} + +int R_VerifyInit(context, digestAlgorithm) +R_SIGNATURE_CTX *context; /* new context */ +int digestAlgorithm; /* message-digest algorithm */ +{ + return((digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestInit(&context->digestContext, digestAlgorithm)); +} + +int R_VerifyUpdate(context, partIn, partInLen) +R_SIGNATURE_CTX *context; /* context */ +unsigned char *partIn; /* next data part */ +unsigned int partInLen; /* length of next data part */ +{ + return((context->digestContext.digestAlgorithm == DA_SHS) ? RE_DIGEST_ALGORITHM : R_DigestUpdate(&context->digestContext, partIn, partInLen)); +} + +int R_VerifyFinal(context, signature, signatureLen, publicKey) +R_SIGNATURE_CTX *context; /* context */ +unsigned char *signature; /* signature */ +unsigned int signatureLen; /* length of signature */ +R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ +{ + int status; + unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN], + originalDigestInfo[MAX_SIGNATURE_LEN]; + unsigned int originalDigestInfoLen, digestLen; + + status = 0; + if(signatureLen > MAX_SIGNATURE_LEN) + status = RE_LEN; + + if(context->digestContext.digestAlgorithm == DA_SHS) + status = RE_DIGEST_ALGORITHM; + + if(!status) { + if((status = R_DigestFinal (&context->digestContext, digest, &digestLen)) == 0) { + R_EncodeDigestInfo(digestInfo, context->digestContext.digestAlgorithm, digest); + + if(RSAPublicDecrypt(originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, publicKey) != 0) { + status = RE_PUBLIC_KEY; + }else{ /* Check the digest out */ + if((originalDigestInfoLen != DIGEST_INFO_LEN) || R_CheckDigestInfo(originalDigestInfo, digestInfo) || (R_memcmp((POINTER)originalDigestInfo, (POINTER)digestInfo, DIGEST_INFO_LEN))) + status = RE_SIGNATURE; + else + /* Reset for another verification. */ + R_DigestInit(&context->digestContext, context->digestContext.digestAlgorithm); + } + } + + /* Clear sensitive information. */ + R_memset(digest, 0, sizeof(digest)); + R_memset(digestInfo, 0, sizeof(digestInfo)); + R_memset(originalDigestInfo, 0, sizeof(originalDigestInfo)); + } + + return(status); +} + +/* Caller must ASCII encode the encrypted keys if required. */ + +int R_SealInit(context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys, + encryptionAlgorithm, randomStruct) +R_ENVELOPE_CTX *context; /* new context */ +unsigned char **encryptedKeys; /* encrypted keys */ +unsigned int *encryptedKeyLens; /* lengths of encrypted keys */ +unsigned char iv[8]; /* initialization vector */ +unsigned int publicKeyCount; /* number of public keys */ +R_RSA_PUBLIC_KEY **publicKeys; /* public keys */ +int encryptionAlgorithm; /* data encryption algorithm */ +R_RANDOM_STRUCT *randomStruct; /* random structure */ +{ + int status; + unsigned char key[24]; + unsigned int keyLen, i; + + context->encryptionAlgorithm = encryptionAlgorithm; + + keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24; + + if((status = R_GenerateBytes (key, keyLen, randomStruct)) == 0) { + if((status = R_GenerateBytes (iv, 8, randomStruct)) == 0) { + if(encryptionAlgorithm == EA_DES_EDE2_CBC) + /* Make both E keys the same */ + R_memcpy ((POINTER)(key + 16), (POINTER)key, 8); + + if((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) == 0) { + for(i = 0; i < publicKeyCount; ++i) { + if(RSAPublicEncrypt(encryptedKeys[i], &encryptedKeyLens[i], key, keyLen, + publicKeys[i], randomStruct)) { + status = RE_PUBLIC_KEY; + break; + } + } + } + if(status == 0) + context->bufferLen = 0; + } + } + + /* Clear sensitive information. */ + + R_memset(key, 0, sizeof(key)); + + return(status); +} + +/* partOut buffer should be at least partInLen + 7 */ + +int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *partOut; /* next encrypted data part */ +unsigned int *partOutLen; /* length of next encrypted data part */ +unsigned char *partIn; /* next data part */ +unsigned int partInLen; /* length of next data part */ +{ + unsigned int temp; + + temp = 8 - context->bufferLen; + if(partInLen < temp) { + /* Just accumulate into buffer. */ + *partOutLen = 0; + R_memcpy((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, partInLen); + context->bufferLen += partInLen; /* Bug Fix - 02/09/95, SK */ + return(IDOK); + } + + /* Fill the buffer and encrypt. */ + + R_memcpy((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn, temp); + EncryptBlk(context, partOut, context->buffer, 8); + partOut += 8; + *partOutLen = 8; + partIn += temp; + partInLen -= temp; + + /* Encrypt as many 8-byte blocks as possible. */ + + temp = 8 * (partInLen / 8); + EncryptBlk(context, partOut, partIn, temp); + *partOutLen += temp; + partIn += temp; + partInLen -= temp; + + + /* Length now less than 8, so copy remainder to buffer for next time. */ + R_memcpy((POINTER)context->buffer, partIn, context->bufferLen = partInLen); + + return(IDOK); +} + +/* Assume partOut buffer is at least 8 bytes. */ + +int R_SealFinal(context, partOut, partOutLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *partOut; /* last encrypted data part */ +unsigned int *partOutLen; /* length of last encrypted data part */ +{ + unsigned int padLen; + + /* Pad and encrypt final block. */ + + padLen = 8 - context->bufferLen; /* little trick to pad the block */ + R_memset((POINTER)(context->buffer + context->bufferLen), (int)padLen, padLen); + EncryptBlk(context, partOut, context->buffer, 8); + *partOutLen = 8; + + /* Restart the context. */ + + RestartCipher(context); + context->bufferLen = 0; + + return(IDOK); +} + +/* Assume caller has already ASCII decoded the encryptedKey if necessary. */ + +int R_OpenInit(context, encryptionAlgorithm, encryptedKey, encryptedKeyLen, iv, privateKey) +R_ENVELOPE_CTX *context; /* new context */ +int encryptionAlgorithm; /* data encryption algorithm */ +unsigned char *encryptedKey; /* encrypted data encryption key */ +unsigned int encryptedKeyLen; /* length of encrypted key */ +unsigned char iv[8]; /* initialization vector */ +R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ +{ + int status; + unsigned char key[MAX_ENCRYPTED_KEY_LEN]; + unsigned int keyLen; + + if(encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN) + return(RE_LEN); + + context->encryptionAlgorithm = encryptionAlgorithm; + + if(RSAPrivateDecrypt(key, &keyLen, encryptedKey, encryptedKeyLen, privateKey)) { + status = RE_PRIVATE_KEY; + }else{ + if(encryptionAlgorithm == EA_DES_CBC) { + if(keyLen != 8) status = RE_PRIVATE_KEY; + else{ + if((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) == 0) + context->bufferLen = 0; + } + }else{ + if(keyLen != 24) status = RE_PRIVATE_KEY; + else { + if((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) == 0) + context->bufferLen = 0; + } + } + } + + /* Clear sensitive information. */ + + R_memset(key, 0, sizeof(key)); + + return(status); +} + +/* Assume partOut buffer is at least partInLen + 7. + Always leaves at least one byte in buffer. */ + +int R_OpenUpdate(context, partOut, partOutLen, partIn, partInLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *partOut; /* next recovered data part */ +unsigned int *partOutLen; /* length of next recovered data part */ +unsigned char *partIn; /* next encrypted data part */ +unsigned int partInLen; /* length of next encrypted data part */ +{ + unsigned int tempLen; + + tempLen = 8 - context->bufferLen; + if (partInLen <= tempLen) { + /* Just accumulate into buffer. */ + *partOutLen = 0; + R_memcpy((POINTER)(context->buffer + context->bufferLen), partIn, partInLen); + context->bufferLen += partInLen; + return(IDOK); + } + + /* Fill the buffer and decrypt. We know that there will be more left + in partIn after decrypting the buffer. */ + + R_memcpy((POINTER)(context->buffer + context->bufferLen), partIn, tempLen); + + EncryptBlk (context, partOut, context->buffer, 8); + partOut += 8; + *partOutLen = 8; + partIn += tempLen; + partInLen -= tempLen; + + /* Decrypt as many 8 byte blocks as possible, leaving at least one byte + in partIn. */ + + tempLen = 8 * ((partInLen - 1) / 8); + EncryptBlk (context, partOut, partIn, tempLen); + partIn += tempLen; + *partOutLen += tempLen; + partInLen -= tempLen; + + /* Length is between 1 and 8, so copy into buffer. */ + + R_memcpy((POINTER)context->buffer, partIn, context->bufferLen = partInLen); + + return (IDOK); +} + +/* Assume partOut buffer is at least 7 bytes. */ + +int R_OpenFinal(context, partOut, partOutLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *partOut; /* last recovered data part */ +unsigned int *partOutLen; /* length of last recovered data part */ +{ + int status; + unsigned char lastPart[8]; + unsigned int padLen; + + status = 0; + + if(context->bufferLen == 0) + /* There was no input data to decrypt */ + *partOutLen = 0; + else { + if(context->bufferLen != 8) { + status = RE_KEY; + }else{ + + /* Decrypt and strip any padding from the final block. */ + + EncryptBlk (context, lastPart, context->buffer, 8); + + padLen = lastPart[7]; + + if(padLen == 0 || padLen > 8) + status = RE_KEY; + else{ + if(R_memcmp((POINTER)&lastPart[8 - padLen], PADDING[padLen], padLen) != 0) + status = RE_KEY; + else + R_memcpy (partOut, lastPart, *partOutLen = 8 - padLen); + } + /* Restart the context. */ + if(status == 0) { + RestartCipher(context); + context->bufferLen = 0; + } + } + } + + /* Clear sensitive information. */ + + R_memset(lastPart, 0, sizeof(lastPart)); + + return (status); +} + +/**/ + +int R_SignPEMBlock(encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen, + content, contentLen, recode, digestAlgorithm, privateKey) +unsigned char *encodedContent; /* encoded content */ +unsigned int *encodedContentLen; /* length of encoded content */ +unsigned char *encodedSignature; /* encoded signature */ +unsigned int *encodedSignatureLen; /* length of encoded signature */ +unsigned char *content; /* content */ +unsigned int contentLen; /* length of content */ +int recode; /* recoding flag */ +int digestAlgorithm; /* message-digest algorithm */ +R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ +{ + int status; + unsigned char signature[MAX_SIGNATURE_LEN]; + unsigned int signatureLen; + + if((status = R_SignBlock(signature, &signatureLen, content, contentLen, digestAlgorithm, privateKey)) != 0) + return(status); + + if(recode) + R_EncodePEMBlock(encodedContent, encodedContentLen, content, contentLen); + + R_EncodePEMBlock(encodedSignature, encodedSignatureLen, signature, signatureLen); + + return(IDOK); +} + +int R_SignBlock(signature, signatureLen, block, blockLen, digestAlgorithm, privateKey) +unsigned char *signature; /* signature */ +unsigned int *signatureLen; /* length of signature */ +unsigned char *block; /* block */ +unsigned int blockLen; /* length of block */ +int digestAlgorithm; /* message-digest algorithm */ +R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ +{ + R_SIGNATURE_CTX context; + int status; + + if((status = R_SignInit(&context, digestAlgorithm)) == 0) + if((status = R_SignUpdate(&context, block, blockLen)) == 0) + status = R_SignFinal(&context, signature, signatureLen, privateKey); + + /* Clear sensitive information. */ + R_memset((POINTER)&context, 0, sizeof(context)); + + return(status); +} + +int R_VerifyPEMSignature(content, contentLen, encodedContent, encodedContentLen, encodedSignature, + encodedSignatureLen, recode, digestAlgorithm, publicKey) +unsigned char *content; /* content */ +unsigned int *contentLen; /* length of content */ +unsigned char *encodedContent; /* (possibly) encoded content */ +unsigned int encodedContentLen; /* length of encoded content */ +unsigned char *encodedSignature; /* encoded signature */ +unsigned int encodedSignatureLen; /* length of encoded signature */ +int recode; /* recoding flag */ +int digestAlgorithm; /* message-digest algorithm */ +R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ +{ + unsigned char signature[MAX_SIGNATURE_LEN]; + unsigned int signatureLen; + + if(encodedSignatureLen > MAX_PEM_SIGNATURE_LEN) + return(RE_SIGNATURE_ENCODING); + + if(recode) { + if(R_DecodePEMBlock(content, contentLen, encodedContent, encodedContentLen)) + return(RE_CONTENT_ENCODING); + }else{ + *contentLen = encodedContentLen; + content = encodedContent; + } + + if(R_DecodePEMBlock(signature, &signatureLen, encodedSignature, encodedSignatureLen)) + return (RE_SIGNATURE_ENCODING); + + return(R_VerifyBlockSignature(content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey)); +} + +int R_VerifyBlockSignature(block, blockLen, signature, signatureLen, digestAlgorithm, publicKey) +unsigned char *block; /* block */ +unsigned int blockLen; /* length of block */ +unsigned char *signature; /* signature */ +unsigned int signatureLen; /* length of signature */ +int digestAlgorithm; /* message-digest algorithm */ +R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ +{ + R_SIGNATURE_CTX context; + int status; + + if((status = R_VerifyInit(&context, digestAlgorithm)) == 0) + if((status = R_VerifyUpdate(&context, block, blockLen)) == 0) + status = R_VerifyFinal(&context, signature, signatureLen, publicKey); + + /* Clear sensitive information. */ + R_memset((POINTER)&context, 0, sizeof(context)); + + return(status); +} + +int R_SealPEMBlock(encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen, + encryptedSignature, encryptedSignatureLen, iv, content, contentLen, + digestAlgorithm, publicKey, privateKey, randomStruct) +unsigned char *encryptedContent; /* encoded, encrypted content */ +unsigned int *encryptedContentLen; /* length */ +unsigned char *encryptedKey; /* encoded, encrypted key */ +unsigned int *encryptedKeyLen; /* length */ +unsigned char *encryptedSignature; /* encoded, encrypted signature */ +unsigned int *encryptedSignatureLen; /* length */ +unsigned char iv[8]; /* DES initialization vector */ +unsigned char *content; /* content */ +unsigned int contentLen; /* length of content */ +int digestAlgorithm; /* message-digest algorithms */ +R_RSA_PUBLIC_KEY *publicKey; /* recipient's RSA public key */ +R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ +R_RANDOM_STRUCT *randomStruct; /* random structure */ +{ + R_ENVELOPE_CTX context; + R_RSA_PUBLIC_KEY *publicKeys[1]; + int status; + unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], + signature[MAX_SIGNATURE_LEN], *encryptedKeys[1]; + unsigned int signatureLen, encryptedKeyBlockLen; + + if((status = R_SignBlock(signature, &signatureLen, content, contentLen, + digestAlgorithm, privateKey)) == 0) { + + encryptedKeys[0] = encryptedKeyBlock; + publicKeys[0] = publicKey; + + if((status = R_SealInit(&context, encryptedKeys, &encryptedKeyBlockLen, iv, 1, publicKeys, EA_DES_CBC, randomStruct)) == 0) { + + R_EncodePEMBlock(encryptedKey, encryptedKeyLen, encryptedKeyBlock, + encryptedKeyBlockLen); + + R_EncryptOpenPEMBlock(&context, encryptedContent, encryptedContentLen, + content, contentLen); + + R_EncryptOpenPEMBlock(&context, encryptedSignature, encryptedSignatureLen, + signature, signatureLen); + } + } + + /* Clear sensitive information. */ + R_memset((POINTER)&context, 0, sizeof(context)); + R_memset(signature, 0, sizeof(signature)); + + return (status); +} + +int R_OpenPEMBlock(content, contentLen, encryptedContent, encryptedContentLen, encryptedKey, + encryptedKeyLen, encryptedSignature, encryptedSignatureLen, + iv, digestAlgorithm, privateKey, publicKey) +unsigned char *content; /* content */ +unsigned int *contentLen; /* length of content */ +unsigned char *encryptedContent; /* encoded, encrypted content */ +unsigned int encryptedContentLen; /* length */ +unsigned char *encryptedKey; /* encoded, encrypted key */ +unsigned int encryptedKeyLen; /* length */ +unsigned char *encryptedSignature; /* encoded, encrypted signature */ +unsigned int encryptedSignatureLen; /* length */ +unsigned char iv[8]; /* DES initialization vector */ +int digestAlgorithm; /* message-digest algorithms */ +R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ +R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ +{ + R_ENVELOPE_CTX context; + int status; + unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], + signature[MAX_SIGNATURE_LEN]; + unsigned int encryptedKeyBlockLen, signatureLen; + + if(encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN) + return(RE_SIGNATURE_ENCODING); + + if(encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN) + return(RE_KEY_ENCODING); + + if(R_DecodePEMBlock(encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey, encryptedKeyLen) != 0) { + status = RE_KEY_ENCODING; + }else{ + if((status = R_OpenInit(&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen, iv, privateKey)) == 0) { + + if((status = R_DecryptOpenPEMBlock(&context, content, contentLen, encryptedContent, encryptedContentLen)) != 0) { + if((status == RE_LEN || status == RE_ENCODING)) + status = RE_CONTENT_ENCODING; + else + status = RE_KEY; + }else{ + + status = R_DecryptOpenPEMBlock(&context, signature, &signatureLen, encryptedSignature, encryptedSignatureLen); + + if(status) { + if((status == RE_LEN || status == RE_ENCODING)) + status = RE_SIGNATURE_ENCODING; + else + status = RE_KEY; + }else + status = R_VerifyBlockSignature(content, *contentLen, signature, signatureLen, digestAlgorithm, publicKey); + } + } + } + /* Clear sensitive information. */ + + R_memset((POINTER)&context, 0, sizeof(context)); + R_memset(signature, 0, sizeof(signature)); + + return(status); +} + +int R_DigestBlock(digest, digestLen, block, blockLen, digestAlgorithm) +unsigned char *digest; /* message digest */ +unsigned int *digestLen; /* length of message digest */ +unsigned char *block; /* block */ +unsigned int blockLen; /* length of block */ +int digestAlgorithm; /* message-digest algorithm */ +{ + R_DIGEST_CTX context; + int status; + + if((status = R_DigestInit(&context, digestAlgorithm)) == 0) + if((status = R_DigestUpdate(&context, block, blockLen)) == 0) + status = R_DigestFinal(&context, digest, digestLen); + + /* Clear sensitive information. */ + + R_memset((POINTER)&context, 0, sizeof(context)); + + return(status); +} + +int R_DecryptOpenPEMBlock(context, output, outputLen, input, inputLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *output; /* decoded, decrypted block */ +unsigned int *outputLen; /* length of output */ +unsigned char *input; /* encrypted, encoded block */ +unsigned int inputLen; /* length */ +{ + int status; + unsigned char encryptedPart[24]; + unsigned int i, len; + + *outputLen = 0; + + for (i = 0; i < inputLen/32; i++) { + /* len is always 24 */ + if ((status = R_DecodePEMBlock(encryptedPart, &len, &input[32*i], 32)) != 0) + break; + + R_OpenUpdate (context, output, &len, encryptedPart, 24); + *outputLen += len; + output += len; + } + + if(!status) /* Decode the last block. */ + if((status = R_DecodePEMBlock(encryptedPart, &len, &input[32*i], inputLen - 32*i)) == 0) { + /* Decrypt the last block. */ + R_OpenUpdate (context, output, &len, encryptedPart, len); + output += len; + *outputLen += len; + if((status = R_OpenFinal (context, output, &len)) == 0) + *outputLen += len; + } + + /* Clear sensitive information. */ + + R_memset((POINTER)&context, 0, sizeof(context)); + R_memset(encryptedPart, 0, sizeof(encryptedPart)); + + return(status); +} + +int R_EncryptOpenPEMBlock(context, output, outputLen, input, inputLen) +R_ENVELOPE_CTX *context; /* context */ +unsigned char *output; /* encrypted, encoded block */ +unsigned int *outputLen; /* length of output */ +unsigned char *input; /* block to encrypt */ +unsigned int inputLen; /* length */ +{ + unsigned char encryptedPart[24]; + unsigned int i, lastPartLen, tempLen, len; + + /* Encrypt and encode as many 24-byte blocks as possible. */ + + for (i = 0; i < inputLen / 24; ++i) { + /* Assume part out length will equal part in length since it is + a multiple of 8. Also assume no error output. */ + R_SealUpdate (context, encryptedPart, &tempLen, &input[24*i], 24); + + /* len will always be 32 */ + R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24); + } + + /* Encrypt the last part into encryptedPart. */ + + R_SealUpdate(context, encryptedPart, &lastPartLen, &input[24*i], inputLen - 24*i); + R_SealFinal(context, encryptedPart + lastPartLen, &len); + lastPartLen += len; + + R_EncodePEMBlock(&output[32*i], &len, encryptedPart, lastPartLen); + *outputLen = 32*i + len; + + /* Clear sensitive information. */ + + R_memset(encryptedPart, 0, sizeof(encryptedPart)); + + return(IDOK); +} + +/* Assumes that digestAlgorithm is DA_MD2, DA_MD4 or DA_MD5 and + the digest length must be 16. SHS Not supported here. */ + +static void R_EncodeDigestInfo(digestInfo, digestAlgorithm, digest) +unsigned char *digestInfo; +int digestAlgorithm; +unsigned char *digest; +{ + if(!(digestAlgorithm == DA_SHS)) { + digestInfo[DIGEST_INFO_A_LEN] = digestAlgorithm; + + R_memcpy((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B, DIGEST_INFO_B_LEN); + R_memcpy((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN); + R_memcpy((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN], (POINTER)digest, 16); + } +} + +/* Quick check to correct digest was used to verify */ + +static int R_CheckDigestInfo(originaldigestInfo, digestInfo) +unsigned char *originaldigestInfo; +unsigned char *digestInfo; +{ + return((originaldigestInfo[DIGEST_INFO_A_LEN] == + digestInfo[DIGEST_INFO_A_LEN]) ? IDOK : RE_SIGNATURE); +} + +static int CipherInit(context, encryptionAlgorithm, key, iv, encrypt) +R_ENVELOPE_CTX *context; +int encryptionAlgorithm; +unsigned char *key; +unsigned char *iv; +int encrypt; +{ + switch(encryptionAlgorithm) { + case EA_DES_CBC: + DES_CBCInit (&context->cipherContext.des, key, iv, encrypt); + break; + case EA_DESX_CBC: + DESX_CBCInit (&context->cipherContext.desx, key, iv, encrypt); + break; + case EA_DES_EDE2_CBC: + case EA_DES_EDE3_CBC: + DES3_CBCInit (&context->cipherContext.des3, key, iv, encrypt); + break; + default: + return (RE_ENCRYPTION_ALGORITHM); + } + return(IDOK); +} + +/* Assume len is a multiple of 8. + */ +static void EncryptBlk(context, output, input, len) +R_ENVELOPE_CTX *context; +unsigned char *output; +unsigned char *input; +unsigned int len; +{ + switch(context->encryptionAlgorithm) { + case EA_DES_CBC: + DES_CBCUpdate (&context->cipherContext.des, output, input, len); + break; + case EA_DESX_CBC: + DESX_CBCUpdate (&context->cipherContext.desx, output, input, len); + break; + case EA_DES_EDE2_CBC: + case EA_DES_EDE3_CBC: + DES3_CBCUpdate (&context->cipherContext.des3, output, input, len); + } +} + +static void RestartCipher(context) +R_ENVELOPE_CTX *context; +{ + switch(context->encryptionAlgorithm) { + case EA_DES_CBC: + DES_CBCRestart (&context->cipherContext.des); + break; + case EA_DESX_CBC: + DESX_CBCRestart (&context->cipherContext.desx); + break; + case EA_DES_EDE2_CBC: + case EA_DES_EDE3_CBC: + DES3_CBCRestart (&context->cipherContext.des3); + } +} diff --git a/source/r_keygen.c b/source/r_keygen.c old mode 100755 new mode 100644 index 24eda19..6e47806 --- a/source/r_keygen.c +++ b/source/r_keygen.c @@ -1,7 +1,7 @@ /* R_KEYGEN.C - key-pair generation for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. diff --git a/source/r_random.c b/source/r_random.c old mode 100755 new mode 100644 index 3bd8346..0fe523d --- a/source/r_random.c +++ b/source/r_random.c @@ -1,222 +1,222 @@ -/* - R_RANDOM.C - random objects for RSAEURO - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - Random Objects routines, based heavily on RSAREF(tm) random objects - code. New routines REQUIRE and ANSI Standard C compiler that has - clock() and time() functions. - - All Trademarks Acknowledged. - - Revisions History. - 0.90 First revision, initial version relied heavily - on RSAREF(tm) compatible code. - - 0.91 Current revision, minor improvements to original - version. New routines added. - R_RandomCreate, R_RandomMix - Compiler must has ANSI standard time routines for new routines - to operate fully. - - 1.01 Modifications to R_RandomCreate and R_RandomMix to - introduce better random number creation system. The old - R_RandomMix had a minor flaw as it didn't flush the old output - from the object, second added that little extra to the seed - for R_RandomCreate. -*/ - -#include -#include - -#ifdef MSDOS - #include -#endif - -#include "rsaeuro.h" -#include "r_random.h" - -#define RANDOM_BYTES_RQ 256 - /* We use more seed data for an internally created object */ -#define RANDOM_BYTES_RQINT 512 - -#define MIX_CNT 16 - -/* Set up, random object ready for seeding. */ - -int R_RandomInit(random) -R_RANDOM_STRUCT *random; /* new random structure */ -{ - /* clear and setup object for seeding */ - R_memset((POINTER)random->state, 0, sizeof(random->state)); - random->outputAvailable = 0; - random->bytesNeeded = RANDOM_BYTES_RQ; - - return(IDOK); -} - - - -int R_RandomUpdate(random, block, len) -R_RANDOM_STRUCT *random; /* random structure */ -unsigned char *block; /* block of values to mix in */ -unsigned int len; /* length of block */ -{ - MD5_CTX context; - BYTE digest[16]; - unsigned int i, j; - - MD5Init(&context); - MD5Update(&context, block, len); - MD5Final(digest, &context); - - /* add digest to state */ - - for(j = 0, i = 16; i > 0; i--) { - j += random->state[i-1] + digest[i-1]; - random->state[i-1] = (BYTE)j; - j >>= 8; - } - - if(random->bytesNeeded < len) - random->bytesNeeded = 0; - else - random->bytesNeeded -= len; - - /* Clear sensitive information. */ - - R_memset((POINTER)digest, 0, sizeof (digest)); - j = 0; - - return(IDOK); -} - -/* Get the number of seed byte still required by the object */ - -int R_GetRandomBytesNeeded(bytesNeeded, random) -unsigned int *bytesNeeded; /* number of mix-in bytes needed */ -R_RANDOM_STRUCT *random; /* random structure */ -{ - *bytesNeeded = random->bytesNeeded; - - return(IDOK); -} - -int R_GenerateBytes(block, len, random) -unsigned char *block; /* block */ -unsigned int len; /* length of block */ -R_RANDOM_STRUCT *random; /* random structure */ -{ - MD5_CTX context; - unsigned int avail, i; - - if(random->bytesNeeded) - return(RE_NEED_RANDOM); - - avail = random->outputAvailable; - - while(avail < len) { - R_memcpy((POINTER)block, (POINTER)&random->output[16-avail], avail); - len -= avail; - block += avail; - - /* generate new output */ - - MD5Init(&context); - MD5Update(&context, random->state, 16); - MD5Final(random->output, &context); - avail = 16; - - /* increment state */ - for(i = 16; i > 0; i--) - if(random->state[i-1]++) - break; - } - - R_memcpy((POINTER)block, (POINTER)&random->output[16-avail], len); - random->outputAvailable = avail - len; - - return(IDOK); -} - -/* Clear Random object when finished. */ - -void R_RandomFinal(random) -R_RANDOM_STRUCT *random; /* random structure */ -{ - R_memset((POINTER)random, 0, sizeof(R_RANDOM_STRUCT)); -} - -/* Create Random object, seed ready for use. - Requires ANSI Standard time routines to provide seed data. -*/ - -void R_RandomCreate(random) -R_RANDOM_STRUCT *random; /* random structure */ -{ - unsigned int bytes; - clock_t cnow; - time_t t; - struct tm *gmt; - - /* clear and setup object for seeding */ - R_memset((POINTER)random->state, 0, sizeof(random->state)); - random->outputAvailable = 0; - random->bytesNeeded = RANDOM_BYTES_RQINT; /* using internal value */ - - /* Add data to random object */ - while(random->bytesNeeded) { - t = time(NULL); /* use for seed data */ - gmt = gmtime(&t); - cnow = clock(); - - R_RandomUpdate(random, (POINTER)gmt, sizeof(struct tm)); - R_RandomUpdate(random, &cnow, sizeof(clock_t)); - } - - /* Clean Up time data */ - R_memset((POINTER)gmt, 0, sizeof(struct tm)); - cnow = 0; - t = 0; -} - -/* Mix up state of the current random structure. - Again requires both clock functions this just adds something - extra to the state, then refreshes the output. -*/ - -void R_RandomMix(random) -R_RANDOM_STRUCT *random; -{ - unsigned int i; - MD5_CTX context; - - for(i = 0; i < 16; i++) { - random->state[i] ^= (char) clock(); - random->state[15-i] ^= (char) time(NULL); - } - - /* Clear any old state with new data */ - - MD5Init(&context); - MD5Update(&context, random->state, 16); - MD5Final(random->output, &context); - - /* tell R_GenerateBytes there is new output */ - - random->outputAvailable = 16; - -} - - - +/* + R_RANDOM.C - random objects for RSAEURO + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + Random Objects routines, based heavily on RSAREF(tm) random objects + code. New routines REQUIRE and ANSI Standard C compiler that has + clock() and time() functions. + + All Trademarks Acknowledged. + + Revisions History. + 0.90 First revision, initial version relied heavily + on RSAREF(tm) compatible code. + + 0.91 Current revision, minor improvements to original + version. New routines added. + R_RandomCreate, R_RandomMix + Compiler must has ANSI standard time routines for new routines + to operate fully. + + 1.01 Modifications to R_RandomCreate and R_RandomMix to + introduce better random number creation system. The old + R_RandomMix had a minor flaw as it didn't flush the old output + from the object, second added that little extra to the seed + for R_RandomCreate. +*/ + +#include +#include + +#ifdef MSDOS + #include +#endif + +#include "rsaeuro.h" +#include "r_random.h" + +#define RANDOM_BYTES_RQ 256 + /* We use more seed data for an internally created object */ +#define RANDOM_BYTES_RQINT 512 + +#define MIX_CNT 16 + +/* Set up, random object ready for seeding. */ + +int R_RandomInit(random) +R_RANDOM_STRUCT *random; /* new random structure */ +{ + /* clear and setup object for seeding */ + R_memset((POINTER)random->state, 0, sizeof(random->state)); + random->outputAvailable = 0; + random->bytesNeeded = RANDOM_BYTES_RQ; + + return(IDOK); +} + + + +int R_RandomUpdate(random, block, len) +R_RANDOM_STRUCT *random; /* random structure */ +unsigned char *block; /* block of values to mix in */ +unsigned int len; /* length of block */ +{ + MD5_CTX context; + BYTE digest[16]; + unsigned int i, j; + + MD5Init(&context); + MD5Update(&context, block, len); + MD5Final(digest, &context); + + /* add digest to state */ + + for(j = 0, i = 16; i > 0; i--) { + j += random->state[i-1] + digest[i-1]; + random->state[i-1] = (BYTE)j; + j >>= 8; + } + + if(random->bytesNeeded < len) + random->bytesNeeded = 0; + else + random->bytesNeeded -= len; + + /* Clear sensitive information. */ + + R_memset((POINTER)digest, 0, sizeof (digest)); + j = 0; + + return(IDOK); +} + +/* Get the number of seed byte still required by the object */ + +int R_GetRandomBytesNeeded(bytesNeeded, random) +unsigned int *bytesNeeded; /* number of mix-in bytes needed */ +R_RANDOM_STRUCT *random; /* random structure */ +{ + *bytesNeeded = random->bytesNeeded; + + return(IDOK); +} + +int R_GenerateBytes(block, len, random) +unsigned char *block; /* block */ +unsigned int len; /* length of block */ +R_RANDOM_STRUCT *random; /* random structure */ +{ + MD5_CTX context; + unsigned int avail, i; + + if(random->bytesNeeded) + return(RE_NEED_RANDOM); + + avail = random->outputAvailable; + + while(avail < len) { + R_memcpy((POINTER)block, (POINTER)&random->output[16-avail], avail); + len -= avail; + block += avail; + + /* generate new output */ + + MD5Init(&context); + MD5Update(&context, random->state, 16); + MD5Final(random->output, &context); + avail = 16; + + /* increment state */ + for(i = 16; i > 0; i--) + if(random->state[i-1]++) + break; + } + + R_memcpy((POINTER)block, (POINTER)&random->output[16-avail], len); + random->outputAvailable = avail - len; + + return(IDOK); +} + +/* Clear Random object when finished. */ + +void R_RandomFinal(random) +R_RANDOM_STRUCT *random; /* random structure */ +{ + R_memset((POINTER)random, 0, sizeof(R_RANDOM_STRUCT)); +} + +/* Create Random object, seed ready for use. + Requires ANSI Standard time routines to provide seed data. +*/ + +void R_RandomCreate(random) +R_RANDOM_STRUCT *random; /* random structure */ +{ + unsigned int bytes; + clock_t cnow; + time_t t; + struct tm *gmt; + + /* clear and setup object for seeding */ + R_memset((POINTER)random->state, 0, sizeof(random->state)); + random->outputAvailable = 0; + random->bytesNeeded = RANDOM_BYTES_RQINT; /* using internal value */ + + /* Add data to random object */ + while(random->bytesNeeded) { + t = time(NULL); /* use for seed data */ + gmt = gmtime(&t); + cnow = clock(); + + R_RandomUpdate(random, (POINTER)gmt, sizeof(struct tm)); + R_RandomUpdate(random, (POINTER)&cnow, sizeof(clock_t)); + } + + /* Clean Up time data */ + R_memset((POINTER)gmt, 0, sizeof(struct tm)); + cnow = 0; + t = 0; +} + +/* Mix up state of the current random structure. + Again requires both clock functions this just adds something + extra to the state, then refreshes the output. +*/ + +void R_RandomMix(random) +R_RANDOM_STRUCT *random; +{ + unsigned int i; + MD5_CTX context; + + for(i = 0; i < 16; i++) { + random->state[i] ^= (unsigned char) clock(); + random->state[15-i] ^= (unsigned char) time(NULL); + } + + /* Clear any old state with new data */ + + MD5Init(&context); + MD5Update(&context, random->state, 16); + MD5Final(random->output, &context); + + /* tell R_GenerateBytes there is new output */ + + random->outputAvailable = 16; + +} + + + diff --git a/source/r_random.h b/source/r_random.h old mode 100755 new mode 100644 index a0b8328..f9ee5f3 --- a/source/r_random.h +++ b/source/r_random.h @@ -1,23 +1,21 @@ /* R_RANDOM.H - header file for R_RANDOM.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Random Number Routines Header File. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ int R_GenerateBytes PROTO_LIST diff --git a/source/r_stdlib.c b/source/r_stdlib.c old mode 100755 new mode 100644 index d68624e..29a2d4d --- a/source/r_stdlib.c +++ b/source/r_stdlib.c @@ -1,7 +1,7 @@ /* R_STDLIB.C - platform-specific C library routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. @@ -26,15 +26,13 @@ 0.92 Current revision, modified to allow use of assembler versions or the ANSI standard equivalent versions. - - 1.00 23/6/95, Final Release Version */ #include "rsaeuro.h" /* Library Copyright Message */ -BYTE *Copyright[] = { "Copyright (c) J.S.A.Kapp 1994." }; +BYTE *Copyright[] = { "Copyright (c) J.S.A.Kapp 94-96." }; #ifndef USE_ANSI /* Secure memset routine */ @@ -87,4 +85,4 @@ unsigned int len; /* length of blocks */ } #endif /* USEASM */ -#endif /* USE_ANSI */ \ No newline at end of file +#endif /* USE_ANSI */ diff --git a/source/rsa.c b/source/rsa.c old mode 100755 new mode 100644 index 212fb9a..7d4ed06 --- a/source/rsa.c +++ b/source/rsa.c @@ -1,357 +1,363 @@ -/* - RSA.C - RSA routines for RSAEURO - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - All Trademarks Acknowledged. - - RSA encryption performed as defined in the PKCS (#1) by RSADSI. - - Revision history - 0.90 First revision, code produced very similar to that - of RSAREF(tm), still it worked fine. - - 0.91 Current revision, code altered to aid speeding up. - Used pointer accesses to arrays to speed up some parts, - mainly during the loops. -*/ - -#include "rsaeuro.h" -#include "r_random.h" -#include "rsa.h" -#include "nn.h" - -static int rsapublicfunc PROTO_LIST((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *)); -static int rsaprivatefunc PROTO_LIST((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *)); - -/* RSA encryption, according to RSADSI's PKCS #1. */ - -int RSAPublicEncrypt(output, outputLen, input, inputLen, publicKey, randomStruct) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ -R_RANDOM_STRUCT *randomStruct; /* random structure */ -{ - int status; - unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN]; - unsigned int i, modulusLen; - - modulusLen = (publicKey->bits + 7) / 8; - - if(inputLen + 11 > modulusLen) - return(RE_LEN); - - *pkcsBlock = 0; /* PKCS Block Makeup */ - - /* block type 2 */ - *(pkcsBlock+1) = 2; - - for(i = 2; i < modulusLen - inputLen - 1; i++) { - /* Find nonzero random byte. */ - do { /* random bytes used to pad the PKCS Block */ - R_GenerateBytes(&byte, 1, randomStruct); - }while(byte == 0); - *(pkcsBlock+i) = byte; - } - /* separator */ - pkcsBlock[i++] = 0; - - R_memcpy((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); - - status = rsapublicfunc(output, outputLen, pkcsBlock, modulusLen, publicKey); - - /* Clear sensitive information. */ - - byte = 0; - R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); - - return(status); -} - -/* RSA decryption, according to RSADSI's PKCS #1. */ - -int RSAPublicDecrypt(output, outputLen, input, inputLen, publicKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ -{ - int status; - unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; - unsigned int i, modulusLen, pkcsBlockLen; - - modulusLen = (publicKey->bits + 7) / 8; - - if(inputLen > modulusLen) - return(RE_LEN); - - status = rsapublicfunc(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey); - if(status) - return(status); - - if(pkcsBlockLen != modulusLen) - return(RE_LEN); - - /* Require block type 1. */ - - if((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1)) - return(RE_DATA); - - for(i = 2; i < modulusLen-1; i++) - if(*(pkcsBlock+i) != 0xff) - break; - - /* separator check */ - - if(pkcsBlock[i++] != 0) - return(RE_DATA); - - *outputLen = modulusLen - i; - - if(*outputLen + 11 > modulusLen) - return(RE_DATA); - - R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); - - /* Clear sensitive information. */ - - R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); - - return(IDOK); -} - -/* RSA encryption, according to RSADSI's PKCS #1. */ - -int RSAPrivateEncrypt(output, outputLen, input, inputLen, privateKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ -{ - int status; - unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; - unsigned int i, modulusLen; - - modulusLen = (privateKey->bits + 7) / 8; - - if(inputLen + 11 > modulusLen) - return (RE_LEN); - - *pkcsBlock = 0; - /* block type 1 */ - *(pkcsBlock+1) = 1; - - for (i = 2; i < modulusLen - inputLen - 1; i++) - *(pkcsBlock+i) = 0xff; - - /* separator */ - pkcsBlock[i++] = 0; - - R_memcpy((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); - - status = rsaprivatefunc(output, outputLen, pkcsBlock, modulusLen, privateKey); - - /* Clear sensitive information. */ - - R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); - - return(status); -} - -/* RSA decryption, according to RSADSI's PKCS #1. */ - -int RSAPrivateDecrypt(output, outputLen, input, inputLen, privateKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ -{ - int status; - unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; - unsigned int i, modulusLen, pkcsBlockLen; - - modulusLen = (privateKey->bits + 7) / 8; - - if(inputLen > modulusLen) - return (RE_LEN); - - status = rsaprivatefunc(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey); - if(status) - return (status); - - if(pkcsBlockLen != modulusLen) - return (RE_LEN); - - /* We require block type 2. */ - - if((*pkcsBlock != 0) || (*(pkcsBlock+1) != 2)) - return (RE_DATA); - - for(i = 2; i < modulusLen-1; i++) - /* separator */ - if (*(pkcsBlock+i) == 0) - break; - - i++; - if(i >= modulusLen) - return(RE_DATA); - - *outputLen = modulusLen - i; - - if(*outputLen + 11 > modulusLen) - return(RE_DATA); - - R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); - - /* Clear sensitive information. */ - R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); - - return(IDOK); -} - -/* Raw RSA public-key operation. Output has same length as modulus. - - Requires input < modulus. -*/ -static int rsapublicfunc(output, outputLen, input, inputLen, publicKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ -{ - NN_DIGIT c[MAX_NN_DIGITS], e[MAX_NN_DIGITS], m[MAX_NN_DIGITS], - n[MAX_NN_DIGITS]; - unsigned int eDigits, nDigits; - - - /* decode the required RSA function input data */ - NN_Decode(m, MAX_NN_DIGITS, input, inputLen); - NN_Decode(n, MAX_NN_DIGITS, publicKey->modulus, MAX_RSA_MODULUS_LEN); - NN_Decode(e, MAX_NN_DIGITS, publicKey->exponent, MAX_RSA_MODULUS_LEN); - - nDigits = NN_Digits(n, MAX_NN_DIGITS); - eDigits = NN_Digits(e, MAX_NN_DIGITS); - - if(NN_Cmp(m, n, nDigits) >= 0) - return(RE_DATA); - - *outputLen = (publicKey->bits + 7) / 8; - - /* Compute c = m^e mod n. To perform actual RSA calc.*/ - - NN_ModExp (c, m, e, eDigits, n, nDigits); - - /* encode output to standard form */ - NN_Encode (output, *outputLen, c, nDigits); - - /* Clear sensitive information. */ - - R_memset((POINTER)c, 0, sizeof(c)); - R_memset((POINTER)m, 0, sizeof(m)); - - return(IDOK); -} - -/* Raw RSA private-key operation. Output has same length as modulus. - - Requires input < modulus. -*/ - -static int rsaprivatefunc(output, outputLen, input, inputLen, privateKey) -unsigned char *output; /* output block */ -unsigned int *outputLen; /* length of output block */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ -{ - NN_DIGIT c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS], - dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS], - mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS], - qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; - unsigned int cDigits, nDigits, pDigits; - - /* decode required input data from standard form */ - NN_Decode(c, MAX_NN_DIGITS, input, inputLen); /* input */ - - /* private key data */ - NN_Decode(p, MAX_NN_DIGITS, privateKey->prime[0], MAX_RSA_PRIME_LEN); - NN_Decode(q, MAX_NN_DIGITS, privateKey->prime[1], MAX_RSA_PRIME_LEN); - NN_Decode(dP, MAX_NN_DIGITS, privateKey->primeExponent[0], MAX_RSA_PRIME_LEN); - NN_Decode(dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], MAX_RSA_PRIME_LEN); - NN_Decode(n, MAX_NN_DIGITS, privateKey->modulus, MAX_RSA_MODULUS_LEN); - NN_Decode(qInv, MAX_NN_DIGITS, privateKey->coefficient, MAX_RSA_PRIME_LEN); - /* work out lengths of input components */ - - cDigits = NN_Digits(c, MAX_NN_DIGITS); - pDigits = NN_Digits(p, MAX_NN_DIGITS); - nDigits = NN_Digits(n, MAX_NN_DIGITS); - - - if(NN_Cmp(c, n, nDigits) >= 0) - return(RE_DATA); - - *outputLen = (privateKey->bits + 7) / 8; - - /* Compute mP = cP^dP mod p and mQ = cQ^dQ mod q. (Assumes q has - length at most pDigits, i.e., p > q.) - */ - - NN_Mod(cP, c, cDigits, p, pDigits); - NN_Mod(cQ, c, cDigits, q, pDigits); - - NN_AssignZero(mP, nDigits); - NN_ModExp(mP, cP, dP, pDigits, p, pDigits); - - NN_AssignZero(mQ, nDigits); - NN_ModExp(mQ, cQ, dQ, pDigits, q, pDigits); - - /* Chinese Remainder Theorem: - m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ. - */ - - if(NN_Cmp(mP, mQ, pDigits) >= 0) { - NN_Sub(t, mP, mQ, pDigits); - }else{ - NN_Sub(t, mQ, mP, pDigits); - NN_Sub(t, p, t, pDigits); - } - - NN_ModMult(t, t, qInv, p, pDigits); - NN_Mult(t, t, q, pDigits); - NN_Add(t, t, mQ, nDigits); - - /* encode output to standard form */ - NN_Encode (output, *outputLen, t, nDigits); - - /* Clear sensitive information. */ -/* - R_memset((POINTER)c, 0, sizeof(c)); - R_memset((POINTER)cP, 0, sizeof(cP)); - R_memset((POINTER)cQ, 0, sizeof(cQ)); - R_memset((POINTER)dP, 0, sizeof(dP)); - R_memset((POINTER)dQ, 0, sizeof(dQ)); - R_memset((POINTER)mP, 0, sizeof(mP)); - R_memset((POINTER)mQ, 0, sizeof(mQ)); - R_memset((POINTER)p, 0, sizeof(p)); - R_memset((POINTER)q, 0, sizeof(q)); - R_memset((POINTER)qInv, 0, sizeof(qInv)); - R_memset((POINTER)t, 0, sizeof(t)); -*/ - return(IDOK); -} +/* + RSA.C - RSA routines for RSAEURO + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + All Trademarks Acknowledged. + + RSA encryption performed as defined in the PKCS (#1) by RSADSI. + + Revision history + 0.90 First revision, code produced very similar to that + of RSAREF(tm), still it worked fine. + + 0.91 Second revision, code altered to aid speeding up. + Used pointer accesses to arrays to speed up some parts, + mainly during the loops. + + 1.03 Third revision, Random Structure initialization + double check, RSAPublicEncrypt can now return RE_NEED_RANDOM. +*/ + +#include "rsaeuro.h" +#include "r_random.h" +#include "rsa.h" +#include "nn.h" + +static int rsapublicfunc PROTO_LIST((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PUBLIC_KEY *)); +static int rsaprivatefunc PROTO_LIST((unsigned char *, unsigned int *, unsigned char *, unsigned int, R_RSA_PRIVATE_KEY *)); + +/* RSA encryption, according to RSADSI's PKCS #1. */ + +int RSAPublicEncrypt(output, outputLen, input, inputLen, publicKey, randomStruct) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ +R_RANDOM_STRUCT *randomStruct; /* random structure */ +{ + int status; + unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN]; + unsigned int i, modulusLen; + + modulusLen = (publicKey->bits + 7) / 8; + + if(inputLen + 11 > modulusLen) + return(RE_LEN); + + R_GetRandomBytesNeeded(&i, randomStruct); + if(i != 0) + return(RE_NEED_RANDOM); + + *pkcsBlock = 0; /* PKCS Block Makeup */ + + /* block type 2 */ + *(pkcsBlock+1) = 2; + + for(i = 2; i < modulusLen - inputLen - 1; i++) { + /* Find nonzero random byte. */ + do { /* random bytes used to pad the PKCS Block */ + R_GenerateBytes(&byte, 1, randomStruct); + }while(byte == 0); + *(pkcsBlock+i) = byte; + } + + /* separator */ + pkcsBlock[i++] = 0; + + R_memcpy((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); + + status = rsapublicfunc(output, outputLen, pkcsBlock, modulusLen, publicKey); + + /* Clear sensitive information. */ + + byte = 0; + R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); + + return(status); +} + +/* RSA decryption, according to RSADSI's PKCS #1. */ + +int RSAPublicDecrypt(output, outputLen, input, inputLen, publicKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ +{ + int status; + unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; + unsigned int i, modulusLen, pkcsBlockLen; + + modulusLen = (publicKey->bits + 7) / 8; + + if(inputLen > modulusLen) + return(RE_LEN); + + status = rsapublicfunc(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey); + if(status) + return(status); + + if(pkcsBlockLen != modulusLen) + return(RE_LEN); + + /* Require block type 1. */ + + if((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1)) + return(RE_DATA); + + for(i = 2; i < modulusLen-1; i++) + if(*(pkcsBlock+i) != 0xff) + break; + + /* separator check */ + + if(pkcsBlock[i++] != 0) + return(RE_DATA); + + *outputLen = modulusLen - i; + + if(*outputLen + 11 > modulusLen) + return(RE_DATA); + + R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); + + /* Clear sensitive information. */ + + R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); + + return(IDOK); +} + +/* RSA encryption, according to RSADSI's PKCS #1. */ + +int RSAPrivateEncrypt(output, outputLen, input, inputLen, privateKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ +{ + int status; + unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; + unsigned int i, modulusLen; + + modulusLen = (privateKey->bits + 7) / 8; + + if(inputLen + 11 > modulusLen) + return (RE_LEN); + + *pkcsBlock = 0; + /* block type 1 */ + *(pkcsBlock+1) = 1; + + for (i = 2; i < modulusLen - inputLen - 1; i++) + *(pkcsBlock+i) = 0xff; + + /* separator */ + pkcsBlock[i++] = 0; + + R_memcpy((POINTER)&pkcsBlock[i], (POINTER)input, inputLen); + + status = rsaprivatefunc(output, outputLen, pkcsBlock, modulusLen, privateKey); + + /* Clear sensitive information. */ + + R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); + + return(status); +} + +/* RSA decryption, according to RSADSI's PKCS #1. */ + +int RSAPrivateDecrypt(output, outputLen, input, inputLen, privateKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ +{ + int status; + unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN]; + unsigned int i, modulusLen, pkcsBlockLen; + + modulusLen = (privateKey->bits + 7) / 8; + + if(inputLen > modulusLen) + return (RE_LEN); + + status = rsaprivatefunc(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey); + if(status) + return (status); + + if(pkcsBlockLen != modulusLen) + return (RE_LEN); + + /* We require block type 2. */ + + if((*pkcsBlock != 0) || (*(pkcsBlock+1) != 2)) + return (RE_DATA); + + for(i = 2; i < modulusLen-1; i++) + /* separator */ + if (*(pkcsBlock+i) == 0) + break; + + i++; + if(i >= modulusLen) + return(RE_DATA); + + *outputLen = modulusLen - i; + + if(*outputLen + 11 > modulusLen) + return(RE_DATA); + + R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen); + + /* Clear sensitive information. */ + R_memset((POINTER)pkcsBlock, 0, sizeof(pkcsBlock)); + + return(IDOK); +} + +/* Raw RSA public-key operation. Output has same length as modulus. + + Requires input < modulus. +*/ +static int rsapublicfunc(output, outputLen, input, inputLen, publicKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PUBLIC_KEY *publicKey; /* RSA public key */ +{ + NN_DIGIT c[MAX_NN_DIGITS], e[MAX_NN_DIGITS], m[MAX_NN_DIGITS], + n[MAX_NN_DIGITS]; + unsigned int eDigits, nDigits; + + + /* decode the required RSA function input data */ + NN_Decode(m, MAX_NN_DIGITS, input, inputLen); + NN_Decode(n, MAX_NN_DIGITS, publicKey->modulus, MAX_RSA_MODULUS_LEN); + NN_Decode(e, MAX_NN_DIGITS, publicKey->exponent, MAX_RSA_MODULUS_LEN); + + nDigits = NN_Digits(n, MAX_NN_DIGITS); + eDigits = NN_Digits(e, MAX_NN_DIGITS); + + if(NN_Cmp(m, n, nDigits) >= 0) + return(RE_DATA); + + *outputLen = (publicKey->bits + 7) / 8; + + /* Compute c = m^e mod n. To perform actual RSA calc.*/ + + NN_ModExp (c, m, e, eDigits, n, nDigits); + + /* encode output to standard form */ + NN_Encode (output, *outputLen, c, nDigits); + + /* Clear sensitive information. */ + + R_memset((POINTER)c, 0, sizeof(c)); + R_memset((POINTER)m, 0, sizeof(m)); + + return(IDOK); +} + +/* Raw RSA private-key operation. Output has same length as modulus. + + Requires input < modulus. +*/ + +static int rsaprivatefunc(output, outputLen, input, inputLen, privateKey) +unsigned char *output; /* output block */ +unsigned int *outputLen; /* length of output block */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +R_RSA_PRIVATE_KEY *privateKey; /* RSA private key */ +{ + NN_DIGIT c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS], + dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS], + mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], q[MAX_NN_DIGITS], + qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; + unsigned int cDigits, nDigits, pDigits; + + /* decode required input data from standard form */ + NN_Decode(c, MAX_NN_DIGITS, input, inputLen); /* input */ + + /* private key data */ + NN_Decode(p, MAX_NN_DIGITS, privateKey->prime[0], MAX_RSA_PRIME_LEN); + NN_Decode(q, MAX_NN_DIGITS, privateKey->prime[1], MAX_RSA_PRIME_LEN); + NN_Decode(dP, MAX_NN_DIGITS, privateKey->primeExponent[0], MAX_RSA_PRIME_LEN); + NN_Decode(dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], MAX_RSA_PRIME_LEN); + NN_Decode(n, MAX_NN_DIGITS, privateKey->modulus, MAX_RSA_MODULUS_LEN); + NN_Decode(qInv, MAX_NN_DIGITS, privateKey->coefficient, MAX_RSA_PRIME_LEN); + /* work out lengths of input components */ + + cDigits = NN_Digits(c, MAX_NN_DIGITS); + pDigits = NN_Digits(p, MAX_NN_DIGITS); + nDigits = NN_Digits(n, MAX_NN_DIGITS); + + + if(NN_Cmp(c, n, nDigits) >= 0) + return(RE_DATA); + + *outputLen = (privateKey->bits + 7) / 8; + + /* Compute mP = cP^dP mod p and mQ = cQ^dQ mod q. (Assumes q has + length at most pDigits, i.e., p > q.) + */ + + NN_Mod(cP, c, cDigits, p, pDigits); + NN_Mod(cQ, c, cDigits, q, pDigits); + + NN_AssignZero(mP, nDigits); + NN_ModExp(mP, cP, dP, pDigits, p, pDigits); + + NN_AssignZero(mQ, nDigits); + NN_ModExp(mQ, cQ, dQ, pDigits, q, pDigits); + + /* Chinese Remainder Theorem: + m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ. + */ + + if(NN_Cmp(mP, mQ, pDigits) >= 0) { + NN_Sub(t, mP, mQ, pDigits); + }else{ + NN_Sub(t, mQ, mP, pDigits); + NN_Sub(t, p, t, pDigits); + } + + NN_ModMult(t, t, qInv, p, pDigits); + NN_Mult(t, t, q, pDigits); + NN_Add(t, t, mQ, nDigits); + + /* encode output to standard form */ + NN_Encode (output, *outputLen, t, nDigits); + + /* Clear sensitive information. */ + R_memset((POINTER)c, 0, sizeof(c)); + R_memset((POINTER)cP, 0, sizeof(cP)); + R_memset((POINTER)cQ, 0, sizeof(cQ)); + R_memset((POINTER)dP, 0, sizeof(dP)); + R_memset((POINTER)dQ, 0, sizeof(dQ)); + R_memset((POINTER)mP, 0, sizeof(mP)); + R_memset((POINTER)mQ, 0, sizeof(mQ)); + R_memset((POINTER)p, 0, sizeof(p)); + R_memset((POINTER)q, 0, sizeof(q)); + R_memset((POINTER)qInv, 0, sizeof(qInv)); + R_memset((POINTER)t, 0, sizeof(t)); + return(IDOK); +} diff --git a/source/rsa.h b/source/rsa.h old mode 100755 new mode 100644 index 55eadb2..d6b8c5e --- a/source/rsa.h +++ b/source/rsa.h @@ -1,23 +1,21 @@ /* RSA.H - header file for RSA.C - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - RSA Routines Header File. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ int RSAPublicEncrypt PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, diff --git a/source/rsa386.s b/source/rsa386.s old mode 100755 new mode 100644 index ff57daa..9ce6e6f --- a/source/rsa386.s +++ b/source/rsa386.s @@ -1,7 +1,7 @@ /* RSA386.s - processor-specific C library routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF 2.0. @@ -31,8 +31,6 @@ Some speed increases where noticed with the addition of these functions. - - 1.00 23/6/95, Final Release Version */ /* Multipresecion Math Routines */ diff --git a/source/rsa68k.s b/source/rsa68k.s old mode 100755 new mode 100644 index ff51a43..baeb72c --- a/source/rsa68k.s +++ b/source/rsa68k.s @@ -1,7 +1,7 @@ /* RSA68K.S - processor-specific C library routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF 2.0. @@ -34,8 +34,6 @@ Some speed increases where noticed with the addition of these functions. - - 1.00 23/6/95, Final Release Version */ /* R_STDLIB Routines */ diff --git a/source/rsaeuro.h b/source/rsaeuro.h old mode 100755 new mode 100644 index 26bbca0..5528f68 --- a/source/rsaeuro.h +++ b/source/rsaeuro.h @@ -1,311 +1,311 @@ -/* - RSAEURO.H - header file for RSAEURO cryptographic toolkit - - Copyright (c) J.S.A.Kapp 1994 - 1995. - - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. - - All functions prototypes are the Same as for RSAREF(tm). - To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. - - This library is legal everywhere outside the US. And should - NOT be imported to the US and used there. - - This header file contains prototypes, and other definitions used - in and by RSAEURO. - - Revision history - 0.90 First revision, implements all of RSAREF.H plus some minor - changes. - - 0.91 Second revision, Fixed a couple of problems. SHS support - added to header file, digest contexts altered. - - 0.92 Third revision, add support at this level for the assembler - routines and the implementation of some routines using the ANSI C - equivalent. - - 0.93 Fourth revision, Library details section added, MD4 details - added to header file, digest contexts altered. -*/ - -#ifndef _RSAEURO_H_ -#define _RSAEURO_H_ - -#include - -#include "global.h" -#include "md2.h" /* allow access to others */ -#include "md4.h" -#include "md5.h" -#include "shs.h" -#include "nn.h" -#include "des.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Message-digest algorithms. */ - -#define DA_MD2 2 -#define DA_MD4 4 -#define DA_MD5 5 -#define DA_SHS 3 - -/* Encryption algorithms to be ored with digest algorithm in Seal and Open. */ - -#define EA_DES_CBC 1 -#define EA_DES_EDE2_CBC 2 -#define EA_DES_EDE3_CBC 3 -#define EA_DESX_CBC 4 - -/* RSA key lengths. */ - -#define MIN_RSA_MODULUS_BITS 508 -/* - PGP 2.6.2 Now allows 2048-bit keys changing below will allow this. - It does lengthen key generation slightly if the value is increased. -*/ -#define MAX_RSA_MODULUS_BITS 1024 -#define MAX_RSA_MODULUS_LEN ((MAX_RSA_MODULUS_BITS + 7) / 8) -#define MAX_RSA_PRIME_BITS ((MAX_RSA_MODULUS_BITS + 1) / 2) -#define MAX_RSA_PRIME_LEN ((MAX_RSA_PRIME_BITS + 7) / 8) - -/* Maximum lengths of encoded and encrypted content, as a function of - content length len. Also, inverse functions. */ - -#define ENCODED_CONTENT_LEN(len) (4*(len)/3 + 3) -#define ENCRYPTED_CONTENT_LEN(len) ENCODED_CONTENT_LEN ((len)+8) -#define DECODED_CONTENT_LEN(len) (3*(len)/4 + 1) -#define DECRYPTED_CONTENT_LEN(len) (DECODED_CONTENT_LEN (len) - 1) - -/* Maximum lengths of signatures, encrypted keys, encrypted - signatures, and message digests. */ - -#define MAX_SIGNATURE_LEN MAX_RSA_MODULUS_LEN -#define MAX_PEM_SIGNATURE_LEN ENCODED_CONTENT_LEN(MAX_SIGNATURE_LEN) -#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN -#define MAX_PEM_ENCRYPTED_KEY_LEN ENCODED_CONTENT_LEN(MAX_ENCRYPTED_KEY_LEN) -#define MAX_PEM_ENCRYPTED_SIGNATURE_LEN ENCRYPTED_CONTENT_LEN(MAX_SIGNATURE_LEN) -#define MAX_DIGEST_LEN 20 - -/* Maximum length of Diffie-Hellman parameters. */ - -#define DH_PRIME_LEN(bits) (((bits) + 7) / 8) - -/* Error codes. */ - -#define RE_CONTENT_ENCODING 0x0400 -#define RE_DATA 0x0401 -#define RE_DIGEST_ALGORITHM 0x0402 -#define RE_ENCODING 0x0403 -#define RE_KEY 0x0404 -#define RE_KEY_ENCODING 0x0405 -#define RE_LEN 0x0406 -#define RE_MODULUS_LEN 0x0407 -#define RE_NEED_RANDOM 0x0408 -#define RE_PRIVATE_KEY 0x0409 -#define RE_PUBLIC_KEY 0x040a -#define RE_SIGNATURE 0x040b -#define RE_SIGNATURE_ENCODING 0x040c -#define RE_ENCRYPTION_ALGORITHM 0x040d - -/* Library details. */ - -#define RSAEURO_VER_MAJ 1 -#define RSAEURO_VER_MIN 02 -#define RSAEURO_IDENT "RSAEURO" -#define RSAEURO_DATE "21/08/94" - -/* Internal Error Codes */ - -#define IDOK 0 -#define IDERROR 1 - -/* Internal defs. */ - -#define TRUE 1 -#define FALSE 0 - -/* Random structure. */ - -typedef struct { - unsigned int bytesNeeded; /* seed bytes required */ - unsigned char state[16]; /* state of object */ - unsigned int outputAvailable; /* number byte available */ - unsigned char output[16]; /* output bytes */ -} R_RANDOM_STRUCT; - -/* RSA public and private key. */ - -typedef struct { - unsigned short int bits; /* length in bits of modulus */ - unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */ - unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* public exponent */ -} R_RSA_PUBLIC_KEY; - -typedef struct { - unsigned short int bits; /* length in bits of modulus */ - unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */ - unsigned char publicExponent[MAX_RSA_MODULUS_LEN]; /* public exponent */ - unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* private exponent */ - unsigned char prime[2][MAX_RSA_PRIME_LEN]; /* prime factors */ - unsigned char primeExponent[2][MAX_RSA_PRIME_LEN]; /* exponents for CRT */ - unsigned char coefficient[MAX_RSA_PRIME_LEN]; /* CRT coefficient */ -} R_RSA_PRIVATE_KEY; - -/* RSA prototype key. */ - -typedef struct { - unsigned int bits; /* length in bits of modulus */ - int useFermat4; /* public exponent (1 = F4, 0 = 3) */ -} R_RSA_PROTO_KEY; - -/* Diffie-Hellman parameters. */ - -typedef struct { - unsigned char *prime; /* prime */ - unsigned int primeLen; /* length of prime */ - unsigned char *generator; /* generator */ - unsigned int generatorLen; /* length of generator */ -} R_DH_PARAMS; - -/* digest algorithm context */ - -typedef struct { - int digestAlgorithm; /* digest type */ - union { /* digest sub-context */ - MD2_CTX md2; - MD4_CTX md4; - MD5_CTX md5; - SHS_CTX shs; - } context; -} R_DIGEST_CTX; - -/* signature context */ - -typedef struct { - R_DIGEST_CTX digestContext; -} R_SIGNATURE_CTX; - -/* envelope context */ - -typedef struct { - int encryptionAlgorithm; /* encryption type */ - union { /* encryption sub-context */ - DES_CBC_CTX des; - DES3_CBC_CTX des3; - DESX_CBC_CTX desx; - } cipherContext; - - unsigned char buffer[8]; /* data buffer */ - unsigned int bufferLen; /* buffer length */ -} R_ENVELOPE_CTX; - -/* Random Structures Routines. */ - -int R_RandomInit PROTO_LIST ((R_RANDOM_STRUCT *)); -int R_RandomUpdate PROTO_LIST ((R_RANDOM_STRUCT *, unsigned char *, unsigned int)); -int R_GetRandomBytesNeeded PROTO_LIST ((unsigned int *, R_RANDOM_STRUCT *)); -void R_RandomFinal PROTO_LIST ((R_RANDOM_STRUCT *)); -void R_RandomCreate PROTO_LIST ((R_RANDOM_STRUCT *random)); -void R_RandomMix PROTO_LIST ((R_RANDOM_STRUCT *random)); -int R_GenerateBytes(unsigned char *block, unsigned int len, - R_RANDOM_STRUCT *random); - -/* Cryptographic procedures. */ - -int R_DigestInit PROTO_LIST ((R_DIGEST_CTX *, int)); -int R_DigestUpdate PROTO_LIST ((R_DIGEST_CTX *, unsigned char *, - unsigned int)); -int R_DigestFinal PROTO_LIST ((R_DIGEST_CTX *, unsigned char *, - unsigned int *)); -int R_SignInit PROTO_LIST ((R_SIGNATURE_CTX *, int)); -int R_SignUpdate PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, - unsigned int)); -int R_SignFinal PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, - unsigned int *, R_RSA_PRIVATE_KEY *)); -int R_VerifyInit PROTO_LIST ((R_SIGNATURE_CTX *, int)); -int R_VerifyUpdate PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, - unsigned int)); -int R_VerifyFinal PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, - unsigned int, R_RSA_PUBLIC_KEY *)); -int R_SealInit PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char **, unsigned int *, unsigned char [8], - unsigned int, R_RSA_PUBLIC_KEY **, int, R_RANDOM_STRUCT *)); -int R_SealUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *, unsigned char *, unsigned int)); -int R_SealFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *)); -int R_OpenInit PROTO_LIST ((R_ENVELOPE_CTX *, int, unsigned char *, - unsigned int, unsigned char [8], R_RSA_PRIVATE_KEY *)); -int R_OpenUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *, unsigned char *, unsigned int)); -int R_OpenFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *)); - -/* Cryptographic enhancements. */ - -int R_SignPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, - unsigned char *, unsigned int, int, int, R_RSA_PRIVATE_KEY *)); -int R_SignBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, int, - R_RSA_PRIVATE_KEY *)); -int R_VerifyPEMSignature PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, - unsigned char *, unsigned int, int, int, R_RSA_PUBLIC_KEY *)); -int R_VerifyBlockSignature PROTO_LIST ((unsigned char *, unsigned int, - unsigned char *, unsigned int, int, R_RSA_PUBLIC_KEY *)); -int R_SealPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, - unsigned char *, unsigned int *, unsigned char [8], unsigned char *, - unsigned int, int, R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, - R_RANDOM_STRUCT *)); -int R_OpenPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, - unsigned char *, unsigned int, unsigned char *, unsigned int, - unsigned char [8], int, R_RSA_PRIVATE_KEY *, R_RSA_PUBLIC_KEY *)); -int R_DigestBlock PROTO_LIST ((unsigned char *, unsigned int *, - unsigned char *, unsigned int, int)); - -int R_DecryptOpenPEMBlock PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *, unsigned char *, unsigned int)); -int R_EncryptOpenPEMBlock PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, - unsigned int *, unsigned char *, unsigned int)); - -/* Printable ASCII encoding and decoding. */ - -int R_EncodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, - unsigned char *, unsigned int)); -int R_DecodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, - unsigned char *, unsigned int)); - -/* Key-pair generation. */ - -int R_GeneratePEMKeys PROTO_LIST ((R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, - R_RSA_PROTO_KEY *, R_RANDOM_STRUCT *)); - -/* Diffie-Hellman key agreement. */ - -int R_GenerateDHParams PROTO_LIST ((R_DH_PARAMS *, unsigned int, - unsigned int, R_RANDOM_STRUCT *)); -int R_SetupDHAgreement PROTO_LIST ((unsigned char *, unsigned char *, - unsigned int, R_DH_PARAMS *, R_RANDOM_STRUCT *)); -int R_ComputeDHAgreedKey PROTO_LIST ((unsigned char *, unsigned char *, - unsigned char *, unsigned int, R_DH_PARAMS *)); - -/* Standard library routines. */ - -#ifdef USE_ANSI -#define R_memset(x, y, z) memset(x, y, z) -#define R_memcpy(x, y, z) memcpy(x, y, z) -#define R_memcmp(x, y, z) memcmp(x, y, z) -#else -void R_memset PROTO_LIST ((POINTER, int, unsigned int)); -void R_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); -int R_memcmp PROTO_LIST ((POINTER, POINTER, unsigned int)); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _RSAEURO_H_ */ +/* + RSAEURO.H - header file for RSAEURO cryptographic toolkit + + Copyright (c) J.S.A.Kapp 1994 - 1996. + + RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + + All functions prototypes are the Same as for RSAREF(tm). + To aid compatiblity the source and the files follow the + same naming comventions that RSAREF(tm) uses. This should aid + direct importing to your applications. + + This library is legal everywhere outside the US. And should + NOT be imported to the US and used there. + + This header file contains prototypes, and other definitions used + in and by RSAEURO. + + Revision history + 0.90 First revision, implements all of RSAREF.H plus some minor + changes. + + 0.91 Second revision, Fixed a couple of problems. SHS support + added to header file, digest contexts altered. + + 0.92 Third revision, add support at this level for the assembler + routines and the implementation of some routines using the ANSI C + equivalent. + + 0.93 Fourth revision, Library details section added, MD4 details + added to header file, digest contexts altered. +*/ + +#ifndef _RSAEURO_H_ +#define _RSAEURO_H_ + +#include + +#include "global.h" +#include "md2.h" /* allow access to others */ +#include "md4.h" +#include "md5.h" +#include "shs.h" +#include "nn.h" +#include "des.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Message-digest algorithms. */ + +#define DA_MD2 2 +#define DA_MD4 4 +#define DA_MD5 5 +#define DA_SHS 3 + +/* Encryption algorithms to be ored with digest algorithm in Seal and Open. */ + +#define EA_DES_CBC 1 +#define EA_DES_EDE2_CBC 2 +#define EA_DES_EDE3_CBC 3 +#define EA_DESX_CBC 4 + +/* RSA key lengths. */ + +#define MIN_RSA_MODULUS_BITS 508 +/* + PGP 2.6.2 Now allows 2048-bit keys changing below will allow this. + It does lengthen key generation slightly if the value is increased. +*/ +#define MAX_RSA_MODULUS_BITS 1024 +#define MAX_RSA_MODULUS_LEN ((MAX_RSA_MODULUS_BITS + 7) / 8) +#define MAX_RSA_PRIME_BITS ((MAX_RSA_MODULUS_BITS + 1) / 2) +#define MAX_RSA_PRIME_LEN ((MAX_RSA_PRIME_BITS + 7) / 8) + +/* Maximum lengths of encoded and encrypted content, as a function of + content length len. Also, inverse functions. */ + +#define ENCODED_CONTENT_LEN(len) (4*(len)/3 + 3) +#define ENCRYPTED_CONTENT_LEN(len) ENCODED_CONTENT_LEN ((len)+8) +#define DECODED_CONTENT_LEN(len) (3*(len)/4 + 1) +#define DECRYPTED_CONTENT_LEN(len) (DECODED_CONTENT_LEN (len) - 1) + +/* Maximum lengths of signatures, encrypted keys, encrypted + signatures, and message digests. */ + +#define MAX_SIGNATURE_LEN MAX_RSA_MODULUS_LEN +#define MAX_PEM_SIGNATURE_LEN ENCODED_CONTENT_LEN(MAX_SIGNATURE_LEN) +#define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN +#define MAX_PEM_ENCRYPTED_KEY_LEN ENCODED_CONTENT_LEN(MAX_ENCRYPTED_KEY_LEN) +#define MAX_PEM_ENCRYPTED_SIGNATURE_LEN ENCRYPTED_CONTENT_LEN(MAX_SIGNATURE_LEN) +#define MAX_DIGEST_LEN 20 + +/* Maximum length of Diffie-Hellman parameters. */ + +#define DH_PRIME_LEN(bits) (((bits) + 7) / 8) + +/* Error codes. */ + +#define RE_CONTENT_ENCODING 0x0400 +#define RE_DATA 0x0401 +#define RE_DIGEST_ALGORITHM 0x0402 +#define RE_ENCODING 0x0403 +#define RE_KEY 0x0404 +#define RE_KEY_ENCODING 0x0405 +#define RE_LEN 0x0406 +#define RE_MODULUS_LEN 0x0407 +#define RE_NEED_RANDOM 0x0408 +#define RE_PRIVATE_KEY 0x0409 +#define RE_PUBLIC_KEY 0x040a +#define RE_SIGNATURE 0x040b +#define RE_SIGNATURE_ENCODING 0x040c +#define RE_ENCRYPTION_ALGORITHM 0x040d + +/* Library details. */ + +#define RSAEURO_VER_MAJ 1 +#define RSAEURO_VER_MIN 02 +#define RSAEURO_IDENT "RSAEURO" +#define RSAEURO_DATE "21/08/94" + +/* Internal Error Codes */ + +#define IDOK 0 +#define IDERROR 1 + +/* Internal defs. */ + +#define TRUE 1 +#define FALSE 0 + +/* Random structure. */ + +typedef struct { + unsigned int bytesNeeded; /* seed bytes required */ + unsigned char state[16]; /* state of object */ + unsigned int outputAvailable; /* number byte available */ + unsigned char output[16]; /* output bytes */ +} R_RANDOM_STRUCT; + +/* RSA public and private key. */ + +typedef struct { + unsigned short int bits; /* length in bits of modulus */ + unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */ + unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* public exponent */ +} R_RSA_PUBLIC_KEY; + +typedef struct { + unsigned short int bits; /* length in bits of modulus */ + unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */ + unsigned char publicExponent[MAX_RSA_MODULUS_LEN]; /* public exponent */ + unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* private exponent */ + unsigned char prime[2][MAX_RSA_PRIME_LEN]; /* prime factors */ + unsigned char primeExponent[2][MAX_RSA_PRIME_LEN]; /* exponents for CRT */ + unsigned char coefficient[MAX_RSA_PRIME_LEN]; /* CRT coefficient */ +} R_RSA_PRIVATE_KEY; + +/* RSA prototype key. */ + +typedef struct { + unsigned int bits; /* length in bits of modulus */ + int useFermat4; /* public exponent (1 = F4, 0 = 3) */ +} R_RSA_PROTO_KEY; + +/* Diffie-Hellman parameters. */ + +typedef struct { + unsigned char *prime; /* prime */ + unsigned int primeLen; /* length of prime */ + unsigned char *generator; /* generator */ + unsigned int generatorLen; /* length of generator */ +} R_DH_PARAMS; + +/* digest algorithm context */ + +typedef struct { + int digestAlgorithm; /* digest type */ + union { /* digest sub-context */ + MD2_CTX md2; + MD4_CTX md4; + MD5_CTX md5; + SHS_CTX shs; + } context; +} R_DIGEST_CTX; + +/* signature context */ + +typedef struct { + R_DIGEST_CTX digestContext; +} R_SIGNATURE_CTX; + +/* envelope context */ + +typedef struct { + int encryptionAlgorithm; /* encryption type */ + union { /* encryption sub-context */ + DES_CBC_CTX des; + DES3_CBC_CTX des3; + DESX_CBC_CTX desx; + } cipherContext; + + unsigned char buffer[8]; /* data buffer */ + unsigned int bufferLen; /* buffer length */ +} R_ENVELOPE_CTX; + +/* Random Structures Routines. */ + +int R_RandomInit PROTO_LIST ((R_RANDOM_STRUCT *)); +int R_RandomUpdate PROTO_LIST ((R_RANDOM_STRUCT *, unsigned char *, unsigned int)); +int R_GetRandomBytesNeeded PROTO_LIST ((unsigned int *, R_RANDOM_STRUCT *)); +void R_RandomFinal PROTO_LIST ((R_RANDOM_STRUCT *)); +void R_RandomCreate PROTO_LIST ((R_RANDOM_STRUCT *random)); +void R_RandomMix PROTO_LIST ((R_RANDOM_STRUCT *random)); +int R_GenerateBytes(unsigned char *block, unsigned int len, + R_RANDOM_STRUCT *random); + +/* Cryptographic procedures. */ + +int R_DigestInit PROTO_LIST ((R_DIGEST_CTX *, int)); +int R_DigestUpdate PROTO_LIST ((R_DIGEST_CTX *, unsigned char *, + unsigned int)); +int R_DigestFinal PROTO_LIST ((R_DIGEST_CTX *, unsigned char *, + unsigned int *)); +int R_SignInit PROTO_LIST ((R_SIGNATURE_CTX *, int)); +int R_SignUpdate PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, + unsigned int)); +int R_SignFinal PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, + unsigned int *, R_RSA_PRIVATE_KEY *)); +int R_VerifyInit PROTO_LIST ((R_SIGNATURE_CTX *, int)); +int R_VerifyUpdate PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, + unsigned int)); +int R_VerifyFinal PROTO_LIST ((R_SIGNATURE_CTX *, unsigned char *, + unsigned int, R_RSA_PUBLIC_KEY *)); +int R_SealInit PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char **, unsigned int *, unsigned char [8], + unsigned int, R_RSA_PUBLIC_KEY **, int, R_RANDOM_STRUCT *)); +int R_SealUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *, unsigned char *, unsigned int)); +int R_SealFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *)); +int R_OpenInit PROTO_LIST ((R_ENVELOPE_CTX *, int, unsigned char *, + unsigned int, unsigned char [8], R_RSA_PRIVATE_KEY *)); +int R_OpenUpdate PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *, unsigned char *, unsigned int)); +int R_OpenFinal PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *)); + +/* Cryptographic enhancements. */ + +int R_SignPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, + unsigned char *, unsigned int, int, int, R_RSA_PRIVATE_KEY *)); +int R_SignBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, int, + R_RSA_PRIVATE_KEY *)); +int R_VerifyPEMSignature PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, + unsigned char *, unsigned int, int, int, R_RSA_PUBLIC_KEY *)); +int R_VerifyBlockSignature PROTO_LIST ((unsigned char *, unsigned int, + unsigned char *, unsigned int, int, R_RSA_PUBLIC_KEY *)); +int R_SealPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int *, + unsigned char *, unsigned int *, unsigned char [8], unsigned char *, + unsigned int, int, R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, + R_RANDOM_STRUCT *)); +int R_OpenPEMBlock PROTO_LIST ((unsigned char *, unsigned int *, unsigned char *, unsigned int, + unsigned char *, unsigned int, unsigned char *, unsigned int, + unsigned char [8], int, R_RSA_PRIVATE_KEY *, R_RSA_PUBLIC_KEY *)); +int R_DigestBlock PROTO_LIST ((unsigned char *, unsigned int *, + unsigned char *, unsigned int, int)); + +int R_DecryptOpenPEMBlock PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *, unsigned char *, unsigned int)); +int R_EncryptOpenPEMBlock PROTO_LIST ((R_ENVELOPE_CTX *, unsigned char *, + unsigned int *, unsigned char *, unsigned int)); + +/* Printable ASCII encoding and decoding. */ + +int R_EncodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, + unsigned char *, unsigned int)); +int R_DecodePEMBlock PROTO_LIST ((unsigned char *, unsigned int *, + unsigned char *, unsigned int)); + +/* Key-pair generation. */ + +int R_GeneratePEMKeys PROTO_LIST ((R_RSA_PUBLIC_KEY *, R_RSA_PRIVATE_KEY *, + R_RSA_PROTO_KEY *, R_RANDOM_STRUCT *)); + +/* Diffie-Hellman key agreement. */ + +int R_GenerateDHParams PROTO_LIST ((R_DH_PARAMS *, unsigned int, + unsigned int, R_RANDOM_STRUCT *)); +int R_SetupDHAgreement PROTO_LIST ((unsigned char *, unsigned char *, + unsigned int, R_DH_PARAMS *, R_RANDOM_STRUCT *)); +int R_ComputeDHAgreedKey PROTO_LIST ((unsigned char *, unsigned char *, + unsigned char *, unsigned int, R_DH_PARAMS *)); + +/* Standard library routines. */ + +#ifdef USE_ANSI +#define R_memset(x, y, z) memset(x, y, z) +#define R_memcpy(x, y, z) memcpy(x, y, z) +#define R_memcmp(x, y, z) memcmp(x, y, z) +#else +void R_memset PROTO_LIST ((POINTER, int, unsigned int)); +void R_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); +int R_memcmp PROTO_LIST ((POINTER, POINTER, unsigned int)); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _RSAEURO_H_ */ diff --git a/source/rsaref.h b/source/rsaref.h old mode 100755 new mode 100644 index 4f47eb9..3d13f68 --- a/source/rsaref.h +++ b/source/rsaref.h @@ -1,24 +1,22 @@ /* RSAREF.H - header file for RSAEURO cryptographic toolkit - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - This header file is used to launch the RSAEURO.H header file. - Provided for compatiblity with RSAREF(tm). + Provided for compatiblity with RSAREF. - Revision 1.00 - JSAK 23/6/95, Final Release Version + Revision 1.00 - JSAK. */ #ifndef _RSAREF_H_ diff --git a/source/rsasparc.s b/source/rsasparc.s old mode 100755 new mode 100644 index d69c92c..71f0605 --- a/source/rsasparc.s +++ b/source/rsasparc.s @@ -1,7 +1,7 @@ /* RSASPARC.S - processor-specific C library routines for RSAEURO - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF 2.0. @@ -30,7 +30,7 @@ _NN_Encode, _NN_AssignZero, _NN_Zero, _NN_Cmp. - 1.00 23/6/95, Final Release Version + */ /* Math Routines */ diff --git a/source/shs.h b/source/shs.h old mode 100755 new mode 100644 index 78f64e8..f149815 --- a/source/shs.h +++ b/source/shs.h @@ -1,23 +1,23 @@ /* SHS.H - header file for Secure Hash Standard Code - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. - RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. + RSAEURO - RSA Library compatible with RSAREF 2.0. - All functions prototypes are the Same as for RSAREF(tm). + All functions prototypes are the Same as for RSAREF. To aid compatiblity the source and the files follow the - same naming comventions that RSAREF(tm) uses. This should aid - direct importing to your applications. + same naming comventions that RSAREF uses. This should aid + direct importing to your applications. This library is legal everywhere outside the US. And should NOT be imported to the US and used there. - All Trademarks Acknowledged. - Secure Hash Standard Code header file. - Revision 1.00. - JSAK 23/6/95, Final Release Version + Revision 1.00. - JSAK + + Revision 1.03. - JSAK */ #ifndef _SHS_H_ @@ -43,8 +43,8 @@ typedef struct { } SHS_CTX; void SHSInit PROTO_LIST ((SHS_CTX *)); -void SHSUpdate PROTO_LIST ((SHS_CTX *, BYTE *, int )); -void SHSFinal PROTO_LIST ((SHS_CTX *)); +void SHSUpdate PROTO_LIST ((SHS_CTX *, unsigned char *, int )); +void SHSFinal PROTO_LIST ((unsigned char *, SHS_CTX *)); #ifdef __cplusplus } diff --git a/source/shsc.c b/source/shsc.c old mode 100755 new mode 100644 index 5c7143b..3113263 --- a/source/shsc.c +++ b/source/shsc.c @@ -1,7 +1,7 @@ /* SHSC.C - Secure Hash Standard Code - Copyright (c) J.S.A.Kapp 1994 - 1995. + Copyright (c) J.S.A.Kapp 1994 - 1996. RSAEURO - RSA Library compatible with RSAREF(tm) 2.0. @@ -19,7 +19,8 @@ 0.90 first revision, initial implementation of the secure hash standard FIPS PUB 180. - 1.00 23/6/95, Final Release Version + 1.03 second revision, SHSFinal modified to output to a char + array specified by the user. */ @@ -31,22 +32,22 @@ #define K1 0x5A827999L /* Rounds 0-19 */ #define K2 0x6ED9EBA1L /* Rounds 20-39 */ #define K3 0x8F1BBCDCL /* Rounds 40-59 */ -#define K4 0xCA62C1D6L /* Rounds 60-79 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ /* SHS initial values */ #define Ainit 0x67452301L #define Binit 0xEFCDAB89L -#define Cinit 0x98BADCFEL -#define Dinit 0x10325476L -#define Einit 0xC3D2E1F0L +#define Cinit 0x98BADCFEL +#define Dinit 0x10325476L +#define Einit 0xC3D2E1F0L /* The SHS f()-functions */ -#define f1(x,y,z) (( x & y ) | ( ~x & z )) /* Rounds 0-19 */ +#define f1(x,y,z) (( x & y ) | ( ~x & z )) /* Rounds 0-19 */ #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ #define f3(x,y,z) (( x & y ) | ( x & z ) | ( y & z )) /* Rounds 40-59 */ -#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ /* 32-bit rotate - kludged with shifts */ @@ -105,6 +106,7 @@ UINT4 A, B, C, D, E; static void byteReverse PROTO_LIST ((UINT4 *, int )); static void SHSTransform PROTO_LIST ((SHS_CTX *)); +static void Encode PROTO_LIST((unsigned char *, UINT4 *, unsigned int)); /* Initialize the SHS values */ @@ -124,8 +126,8 @@ SHS_CTX *context; /* context */ /* Update SHS for a block of data. - This code assumes that the buffer size is a multiple of - SHS_BLOCKSIZE bytes long. + This code assumes that the buffer size is a multiple of + SHS_BLOCKSIZE bytes long. */ void SHSUpdate(context, buffer, count) @@ -153,11 +155,12 @@ int count; /* length of input block */ R_memcpy((POINTER)context->data, buffer, count); } -/* Finalize SHS hash, doesn't output a char value as yet. - That is on the todo list. +/* Finalize SHS hash, outputs to a unsigned char array. + array must be > 20 bytes in length. */ -void SHSFinal(context) +void SHSFinal(digest, context) +BYTE *digest; SHS_CTX *context; /* context */ { int count; @@ -190,6 +193,10 @@ SHS_CTX *context; /* context */ SHSTransform(context); byteReverse(context->data, SHS_DIGESTSIZE); + + Encode(digest, context->digest, 20); + + R_memset((POINTER)context, 0, sizeof(SHS_CTX)); } static void byteReverse(buffer, byteCount) @@ -281,6 +288,24 @@ SHS_CTX *context; context->digest[3] += D; context->digest[4] += E; + /* Clear sensitive information */ + R_memset((POINTER) W, 0, sizeof(W)); } +/* Encode SHS output in char array */ + +static void Encode(output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for(i = 0, j = 0; j < len; i++, j += 4) { + output[j+3] = (unsigned char)(input[i] & 0xff); + output[j+2] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+1] = (unsigned char)((input[i] >> 16) & 0xff); + output[j] = (unsigned char)((input[i] >> 24) & 0xff); + } +} diff --git a/source/targets.mak b/source/targets.mak old mode 100755 new mode 100644