diff options
Diffstat (limited to '')
141 files changed, 61196 insertions, 0 deletions
diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/.travis.yml b/debian/vendor-h2o/deps/picotls/deps/cifra/.travis.yml new file mode 100644 index 0000000..44b1a26 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/.travis.yml @@ -0,0 +1,29 @@ +language: c + +before_install: + - sudo pip install cpp-coveralls + +script: + - cd src + - make clean + - make test + +after_success: + - coveralls --exclude src/ext --gcov-options '\-lp' + +compiler: + - gcc + +env: + global: + - secure: "W9IUnUWNc03gIBGLPOxXCVJUOb3RY2fS4lgOo+wIsCSk0rsJAB6gruAZDoz1sMxCJyBhCv0dKV5WPkAxkZ0y55wiuUcCepgR0qis6S6rJxldPdEWc3RQaeU9LbVRKRBYUBqSsFlXr5pdOvl0CBDWmx8lhcRxAw8z+JVDrAGVsTQ=" + +addons: + coverity_scan: + project: + name: "ctz/cifra" + description: "Cifra is a collection of cryptographic primitives targeted at embedded use." + notification_email: jpixton@gmail.com + build_command_prepend: "cd src ; make clean" + build_command: "make" + branch_pattern: coverity-scan diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/COPYING b/debian/vendor-h2o/deps/picotls/deps/cifra/COPYING new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/COPYING @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/README.md b/debian/vendor-h2o/deps/picotls/deps/cifra/README.md new file mode 100644 index 0000000..e972912 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/README.md @@ -0,0 +1,246 @@ +# Cifra +Cifra is a collection of cryptographic primitives targeted at embedded use. + +[![Build Status](https://travis-ci.org/ctz/cifra.svg?branch=master)](https://travis-ci.org/ctz/cifra) + +[![Documentation](https://readthedocs.org/projects/pip/badge/)](https://cifra.readthedocs.org/en/latest/) + +[![Analysis Status](https://scan.coverity.com/projects/4324/badge.svg)](https://scan.coverity.com/projects/4324) + +[![Coverage Status](https://coveralls.io/repos/ctz/cifra/badge.svg?branch=coveralls-scan)](https://coveralls.io/r/ctz/cifra?branch=coveralls-scan) + +## Aims +In order of descending emphasis, cifra aims for: + +* **Clarity** and **simplicity**. +* Countermeasures for side channel leaks inherent in some + algorithms. +* Suitability for embedded use. Particularly: cifra uses an + absolute minimum of the standard C library and is reasonably + efficient with respect to code and data space. + +## Features +* **AES** in the **GCM**, **CCM**, **EAX** and **OCB** authenticated encryption modes. +* **NORX** authenticated encryption system. +* **SHA224**, **SHA256**, **SHA384** and **SHA512** hash functions (including **HMAC** and **PBKDF2**). +* **SHA3-224**, **SHA3-256**, **SHA3-384**, **SHA3-512** hash functions (FIPS 202 compatible). +* **ChaCha20** and **Salsa20** stream ciphers. +* **Poly1305** one time MAC. +* 100% code coverage by line, zero static analysis defects, valgrind-clean. + +Additionally cifra imports curve25519 from elsewhere (μNaCl, NaCl, tweetNaCl, +Adam Langley's curve25519-donna) for comparison between various implementations +on embedded targets. + +## Documentation +Available at [Read the Docs](https://cifra.readthedocs.org/en/latest/). + +## Testing +There is quite a lot of testing available: + +* **Host builds**: run `make test` in the `src` directory. This builds and + runs assorted test programs. +* **Emulated embedded builds**: run `make test` in the `src/arm` directory. This + expects to find `qemu-system-gnuarmeclipse` on the path. These tests assume + a Cortex-M3 target. +* **Cortex-M0 on-target tests**: run `make test.stm32f0` in the `src/arm` directory. + This expects to find `openocd` on the path, with an STM32F0xx attached via + stlinkv2. It uses ARM semihosting to report results. +* **Cortex-M3/4 on-target tests**: run `make test.stm32f1` or `make test.stm32f3` as above. + +Additionally all embedded targets expect to find the `arm-none-eabi` toolchain +to be on the path. + +## Measurements +All measurements performed at `-Os` (optimise for space), on the following MCUs: + +Core | Part number | Price (1s) | Max clock | Flash | SRAM +---------- | ------------- | ------------ | ---------- | ----- | ----- +Cortex-M0 | STM32F030F4P6 | 1.17EUR | 48MHz | 16KB | 4KB +Cortex-M3 | STM32F103C8T6 | 2.87EUR | 72MHz | 64KB | 20KB +Cortex-M4F | STM32F303K6T6 | 4.53EUR | 72MHz | 32KB | 12KB + +More measurements are available for AEAD modes on my blog post: +[Benchmarking Modern Authenticated Encryption on €1 devices](http://jbp.io/2015/06/01/modern-authenticated-encryption-for-1-euro/). + +## AES +This test does a key schedule, then encrypts one block. + +### 128-bit key +Core | Cycles (key schedule + block) | Cycles (key schedule) | Cycles (block) | Stack | Code size +---------- | ----------------------------- | --------------------- | -------------- | ----- | --------- +Cortex-M0 | 7156 | 2147 | 5009 | 312B | 1020B +Cortex-M3 | 4692 | 1591 | 3101 | 300B | 960B +Cortex-M4F | 4591 | 1571 | 3020 | 300B | 960B + +### 256-bit key +Core | Cycles (key schedule + block) | Cycles (key schedule) | Cycles (block) | Stack | Code size +---------- | ----------------------------- | --------------------- | -------------- | ----- | --------- +Cortex-M0 | 10611 | 3650 | 6961 | 396B | 1100B +Cortex-M3 | 6735 | 2450 | 4285 | 380B | 1048B +Cortex-M4F | 6588 | 2416 | 4172 | 380B | 1048B + +## AES128-GCM +This test encrypts and authenticates a 16 byte message, +with 16 bytes additionally authenticated data. It includes +the initial key schedule. + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 57022 | 796B | 2600B +Cortex-M3 | 44306 | 812B | 2644B +Cortex-M4F | 43657 | 812B | 2644B + +## AES128-EAX +This test encrypts and authenticates a 16 byte message, +with 16 bytes additionally authenticated data. It includes +the initial key schedule. + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 50564 | 932B | 2836B +Cortex-M3 | 32855 | 932B | 2780B +Cortex-M4F | 32159 | 932B | 2780B + +## AES128-CCM +This test encrypts and authenticates a 16 byte message, +with 16 bytes additionally authenticated data. It includes +the initial key schedule. + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 37677 | 772B | 2280B +Cortex-M3 | 24462 | 780B | 2256B +Cortex-M4F | 23949 | 780B | 2256B + +## NORX32 +This test encrypts and authenticates a 16 byte message, +with 16 bytes additionally authenticated data. + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 10692 | 320B | 1636B +Cortex-M3 | 6909 | 320B | 1820B +Cortex-M4F | 6855 | 320B | 1820B + +## ChaCha20 +This test encrypts a 64 byte message. + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 5981 | 564B | 1416B +Cortex-M3 | 3487 | 544B | 1328B +Cortex-M4F | 3468 | 544B | 1328B + +(For comparison with AES, add an AES256 key schedule plus 4 blocks. +That's about 33K cycles.) + +## Salsa20 +This test encrypts a 64 byte message. + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 6173 | 560B | 1412B +Cortex-M3 | 3320 | 552B | 1272B +Cortex-M4F | 3311 | 552B | 1272B + +## SHA256 +This test hashes the empty string (one compression function invocation). + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 11561 | 312B | 1760B +Cortex-M3 | 6530 | 300B | 1708B +Cortex-M4F | 6278 | 300B | 1708B + +## SHA512 +This test hashes the empty string (one compression function invocation). + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 38447 | 796B | 2888B +Cortex-M3 | 28771 | 836B | 2988B +Cortex-M4F | 28777 | 836B | 2980B + +## SHA3-256 +This test hashes the empty string (one sponge permutation). + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 93648 | 848B | 2212B +Cortex-M3 | 74321 | 856B | 2164B +Cortex-M4F | 72215 | 856B | 2140B + +## SHA3-512 +This test hashes the empty string (one sponge permutation). + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 92565 | 880B | 2212B +Cortex-M3 | 73509 | 888B | 2164B +Cortex-M4F | 71419 | 888B | 2140B + +## HMAC-SHA256 +This test computes a MAC with a 32 byte key over the +message "hello world". + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 48924 | 1328B | 2200B +Cortex-M3 | 28333 | 1324B | 2132B +Cortex-M4F | 27337 | 1324B | 2132B + +## Poly1305-AES +This test computes a MAC with a 32 byte key over the +message "hello world". It includes the AES nonce +processing. + +Core | Cycles | Stack | Code size +---------- | ------ | ----- | --------- +Cortex-M0 | 15719 | 704B | 1920B +Cortex-M3 | 11328 | 696B | 1964B +Cortex-M4F | 10706 | 696B | 1932B + +## Curve25519 +This test is one point multiplication. + +This uses the implementation from [μNaCl](http://munacl.cryptojedi.org/curve25519-cortexm0.shtml) +by Düll, Haase, Hinterwälder, Hutter, Paar, Sánchez and Schwabe. + +Core | Cycles | Stack | Code size +---------- | ------- | ----- | --------- +Cortex-M0 | 4070271 | 464B | 5596B +Cortex-M3 | 3720363 | 448B | 5536B +Cortex-M4F | 3720105 | 448B | 5536B + +See [curve25519-shootout](curve25519-shootout.md) for comparitive measurements +for other curve25519 implementations. + +## C library requirements +Cifra requires `memcpy`, `memset`, and `abort`. + +## Future +* ~~Keccak hash function (aka SHA3)~~. +* ~~Poly1305 one-time MAC~~. +* Constant time curve25519 for Cortex-M4F using the FPU. +* Constant time curve25519 for Cortex-M3 (avoiding the variable-time multiplier). + +## Notable past bugs/advisories +* [Issue #2](https://github.com/ctz/cifra/issues/2): in all versions before commit + [d62aa26e](https://github.com/ctz/cifra/commit/d62aa26e2c3c49e5b8a4298644cff290406d9357) + (September 16th 2015) too much padding was added when hashing messages of certain + lengths. Specifically, messages whose length satisfied `len % 64 = 55` for + SHA1/SHA224/SHA256 or `len % 128 = 119` for SHA384/SHA512. SHA3 was not affected. + Better testing is now in place. +* [Issue #3](https://github.com/ctz/cifra/issues/3): in all versions before commit + [82d77cd8](https://github.com/ctz/cifra/commit/82d77cd8323f6d4473fcb68517752a778970138d) + (April 16th 2016) EAX would produce wrong tags for empty AADs or messages. The + underlying CMAC is now more resistant to this case. + +## License +[CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +Please attribute the author. This is a request only, and not a license term. + +## Author +Joseph Birr-Pixton <jpixton@gmail.com> diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/curve25519-shootout.md b/debian/vendor-h2o/deps/picotls/deps/cifra/curve25519-shootout.md new file mode 100644 index 0000000..6f05758 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/curve25519-shootout.md @@ -0,0 +1,16 @@ +## Curve25519 on Cortex-M0 shootout +Implementation | Optimisation | Cycles | Code size | Stack usage +-------------- | ------------ | --------- | --------- | ----------- +donna | `-Os` | 15748K | 7.4KB | 3148B +donna | `-O2` | 15218K | 7.9KB | 3148B +donna | `-O3` | 12907K | 16KB | 3380B +naclref | `-Os` | 47813K | 3.2KB | 4012B +naclref | `-O2` | 34309K | 3.5KB | 4036B +naclref | `-O3` | 35059K | 4.1KB | 4044B +tweetnacl | `-Os` | 75979K | 2.8KB | 2244B +tweetnacl | `-O2` | 68876K | 3.0KB | 2268B +tweetnacl | `-O3` | 69622K | 8.9KB | 2900B + +naclref at -O2 seems to give a good balance. If you can spare the flash, +donna is quite significantly quicker. + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/doc/Makefile b/debian/vendor-h2o/deps/picotls/deps/cifra/doc/Makefile new file mode 100644 index 0000000..2b7f5c0 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/doc/Makefile @@ -0,0 +1,3 @@ +default: all +all: + sphinx-build -b html . _build diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/doc/build.py b/debian/vendor-h2o/deps/picotls/deps/cifra/doc/build.py new file mode 100644 index 0000000..0b00682 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/doc/build.py @@ -0,0 +1,274 @@ +""" +Extracts documentation from cifra headers. + +We want to embed documentation in headers for good +locality. But want to write rst for formatting by sphinx. +This is a problem. + +'Breathe' provides a bridge between doxygen and sphinx, +but doxygen's documentation markup is pretty awful. + +Therefore, we write rst directly in C headers, and then +extract it here. The rules are: a C block comment +starting exactly '/* .. ' is dedented, and then included +verbatim. The convention is that the documentation +preceeds the C declarations they apply to, and that struct +members are documented before the struct they are contained +within. eg: + +/* .. c:function:: int foo(int bar) + * Foos a bar, returning the foo coefficient. + */ +int foo(int bar); + +/* .. c:type:: thing + * Container for things. + * + * .. c:member:: int thing.foo + * Count of foos. + * + * .. c:member:: int thing.bar + * Count of bars. + */ +typedef struct +{ + int foo; + int bar; +} thing; + +As a special effect, the following tokens are replaced +in the comments: + + - $DECL: the immediately following function declaration +""" + +import glob +import re +import StringIO + +# We know which headers constitute the external interface. +EXTERNAL = """ +aes +cf_config +chash +hmac +modes +pbkdf2 +prp +salsa20 +sha1 +sha2 +sha3 +norx +poly1305 +chacha20poly1305 +drbg +""".split() + +# Basic idea of a C identifier +C_IDENTIFIER = '[a-zA-Z_][a-zA-Z0-9_]+' + +DECL_RE = re.compile(r'^\s*(.+?' + C_IDENTIFIER + '\(.+?\));', re.MULTILINE | re.DOTALL) +COMMENT_RE = re.compile(r'^\s*\/\* (\.\..*?) \*\/$', re.MULTILINE | re.DOTALL) +INTRO_RE = re.compile(r'^\s*\/\*\*(.*?)\*\/$', re.MULTILINE | re.DOTALL) +NEW_SECTION_RE = re.compile(r'^..+\n(==+|--+)$', re.MULTILINE) + +class section(object): + def __init__(self): + self.intro = [] + self.macros = [] + self.types = [] + self.functions = [] + self.values = [] + + def __repr__(self): + return repr(self.format()[:30]) + + def __str__(self): + return repr(self.format()[:30]) + + def format(self): + f = StringIO.StringIO() + + def emit(title, section): + if len(section) == 0: + return + + if title: + print >>f, title + print >>f, '*' * len(title) + print >>f + + for s in section: + print >>f, s.getvalue() + + emit(None, self.intro) + emit('Macros', self.macros) + emit('Types', self.types) + emit('Functions', self.functions) + emit('Values', self.values) + + return f.getvalue() + + def is_empty(self): + items = len(self.intro) + len(self.macros) + len(self.types) + \ + len(self.functions) + len(self.values) + return 0 == items + + def add_item(self, sec): + f = StringIO.StringIO() + sec.append(f) + return f + +def massage_decl(decl): + """ + Tart-up a C function declaration: remove storage qualifiers, + smush onto one line, escape asterisks. + """ + for storage in 'extern static inline'.split(): + decl = decl.replace(storage + ' ', '') + + fixed_lines = ' '.join(line.strip() for line in decl.splitlines()) + + return fixed_lines.replace('*', '\\*') + +def replace_decl(comment, comment_match, header): + if '$DECL' not in comment: + return comment + + start = comment_match.end(0) + 1 + decl_match = DECL_RE.match(header, start) + + if decl_match is None: + print 'Cause:', comment + print 'Trailer:', header[start:start+60] + raise IOError('$DECL present but cannot find following DECL') + + decl = decl_match.group(1) + decl = massage_decl(decl) + return comment.replace('$DECL', decl) + +def decomment(lines): + for i in range(len(lines)): + if lines[i].startswith(' *'): + lines[i] = lines[i][3:] + lines[i] = lines[i].strip() + +def drop_empty_prefix(lines): + while len(lines) and lines[0] == '': + lines.pop(0) + +def starts_new_section(lines): + txt = '\n'.join(lines) + r = NEW_SECTION_RE.search(txt) is not None + return r + +def process(header, rst): + """ + Converts a header into restructured text. + + header is a file-like opened to read the header. + rst is a file-like opened to write the rst results. + """ + + hh = header.read() + + # Collect definitions into sections + sec = None + all_sections = [] + intro, macros, types, functions, values = [], [], [], [], [] + + def add_section(): + if sec and not sec.is_empty(): + all_sections.append(sec) + return section() + + sec = add_section() + + offs = 0 + + while True: + intro_match = INTRO_RE.search(hh, offs) + comment_match = COMMENT_RE.search(hh, offs) + + if intro_match is None and comment_match is None: + break + + # process earliest occuring + if intro_match is not None and (comment_match is None or intro_match.start(0) < comment_match.start(0)): + txt = intro_match.group(1) + + lines = txt.splitlines() + decomment(lines) + drop_empty_prefix(lines) + + if starts_new_section(lines): + sec = add_section() + + outf = sec.add_item(sec.intro) + + for l in lines: + print >>outf, l + offs = intro_match.end(0) + 1 + continue + + if comment_match is not None and (intro_match is None or comment_match.start(0) < intro_match.start(0)): + txt = comment_match.group(1) + + # work out which section this goes into + outf = None + if '.. c:macro::' in txt: + outf = sec.add_item(sec.macros) + elif '.. c:type::' in txt: + outf = sec.add_item(sec.types) + elif '.. c:var::' in txt: + outf = sec.add_item(sec.values) + elif '.. c:function::' in txt: + outf = sec.add_item(sec.functions) + elif '.. c:member::' in txt: + if len(types) == 0: + raise IOError('c:member must come after a c:type') + outf = types[-1] + else: + raise IOError('Cannot categorise item: ' + txt) + + # expand $DECL + txt = replace_decl(txt, comment_match, hh) + + # decomment lines + lines = txt.splitlines() + decomment(lines) + + # domain lines are unindented + while lines and lines[0].startswith('.. '): + print >>outf, lines.pop(0) + print >>outf + + # empty prefix lines are stripped + drop_empty_prefix(lines) + + # other lines are indented + for line in lines: + if len(line): + line = ' ' + line + print >>outf, line + + offs = comment_match.end(0) + 1 + continue + + add_section() + + for sec in all_sections: + rst.write(sec.format()) + +def run(): + for fn in EXTERNAL: + print '** build', fn + header = '../src/' + fn + '.h' + rst = fn + '.rst' + with open(header, 'r') as fh: + with open(rst, 'w') as fr: + process(fh, fr) + +if __name__ == '__main__': + run() diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/doc/conf.py b/debian/vendor-h2o/deps/picotls/deps/cifra/doc/conf.py new file mode 100644 index 0000000..8354354 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/doc/conf.py @@ -0,0 +1,263 @@ +# -*- coding: utf-8 -*- +# +# Cifra documentation build configuration file, created by +# sphinx-quickstart on Sat Feb 21 18:02:37 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('.')) + +import build +build.run() + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.mathjax', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Cifra' +copyright = u'2015, Joseph Birr-Pixton' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.1' +# The full version, including alpha/beta/rc tags. +release = '0.1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Cifradoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'Cifra.tex', u'Cifra Documentation', + u'Joseph Birr-Pixton', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'cifra', u'Cifra Documentation', + [u'Joseph Birr-Pixton'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Cifra', u'Cifra Documentation', + u'Joseph Birr-Pixton', 'Cifra', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/doc/index.rst b/debian/vendor-h2o/deps/picotls/deps/cifra/doc/index.rst new file mode 100644 index 0000000..e853de4 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/doc/index.rst @@ -0,0 +1,33 @@ +.. Cifra documentation master file, created by + sphinx-quickstart on Sat Feb 21 18:02:37 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Cifra's documentation! +================================= + +Contents: + +.. toctree:: + :maxdepth: 2 + + cf_config + prp + chash + aes + norx + salsa20 + modes + hmac + poly1305 + chacha20poly1305 + pbkdf2 + sha1 + sha2 + sha3 + drbg + +Index +----- +* :ref:`genindex` + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/Makefile b/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/Makefile new file mode 100644 index 0000000..065721c --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/Makefile @@ -0,0 +1,13 @@ +CFLAGS += -std=gnu99 -O0 -g -Wall -Werror + +all: run + +openssl-hash: openssl-hash.c + $(CC) $(CFLAGS) -o $@ $^ -lcrypto + +run: openssl-hash + ./openssl-hash + python python-hash.py + +clean: + rm -rf *.o openssl-hash diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/README.md b/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/README.md new file mode 100644 index 0000000..a7d3828 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/README.md @@ -0,0 +1,2 @@ +This directory contains assorted programs for generating test vectors +from other crypto libraries, like OpenSSL. diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/openssl-hash.c b/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/openssl-hash.c new file mode 100644 index 0000000..9df6856 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/openssl-hash.c @@ -0,0 +1,60 @@ +#include <stdint.h> +#include <stdio.h> + +#include <openssl/evp.h> + +#define MAX_LENGTH 1024 + +static void printhex(const uint8_t *buf, size_t len) +{ + for (size_t i = 0; i < len; i++) + printf("%02x", buf[i]); +} + +/* This test produces a single hash value which depends on + * hashes with all preimage lengths up to max. + * + * It emits + * H(H(t(0)) || H(t(1)) || ... || H(t(max-1)))) + * where + * t(n) = (n % 256) ^ n + * (informally, t(n) is a n-length octet string of octets with value n mod 256) + */ +static void emit_length_test(const char *name, const EVP_MD *h, size_t max) +{ + EVP_MD_CTX outer, inner; + EVP_DigestInit(&outer, h); + uint8_t digest[EVP_MAX_MD_SIZE]; + unsigned int digestlen; + + for (size_t n = 0; n < max; n++) + { + EVP_DigestInit(&inner, h); + for (size_t i = 0; i < n; i++) + { + uint8_t byte = n & 0xff; + EVP_DigestUpdate(&inner, &byte, 1); + } + digestlen = sizeof digest; + EVP_DigestFinal(&inner, digest, &digestlen); + + EVP_DigestUpdate(&outer, digest, digestlen); + } + + digestlen = sizeof digest; + EVP_DigestFinal(&outer, digest, &digestlen); + + printf("%s(%zu) = ", name, max); + printhex(digest, (size_t) digestlen); + printf("\n"); +} + +int main(void) +{ + emit_length_test("SHA1", EVP_sha1(), MAX_LENGTH); + emit_length_test("SHA224", EVP_sha224(), MAX_LENGTH); + emit_length_test("SHA256", EVP_sha256(), MAX_LENGTH); + emit_length_test("SHA384", EVP_sha384(), MAX_LENGTH); + emit_length_test("SHA512", EVP_sha512(), MAX_LENGTH); + return 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/python-hash.py b/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/python-hash.py new file mode 100644 index 0000000..90aa248 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/extra_vecs/python-hash.py @@ -0,0 +1,38 @@ +#!/usr/bin/python2 + +# +# see openssl-hash for details of what this is computing +# you'll need python-sha3 from https://github.com/bjornedstrom/python-sha3 +# + +import hashlib +import sha3 + +# check sha3 at least works; pysha3 *DOES NOT* (it is keccak, not sha3) +assert '3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532' == hashlib.sha3_256('abc').hexdigest() + +def hh(x): + return ''.join(['\\x' + x[y:y+2] for y in range(0, len(x), 2)]) + +def len_test(name, H, max): + outer = H() + + for n in range(max): + inner = H() + inner.update(chr(n & 0xff) * n) + outer.update(inner.digest()) + + result = outer.hexdigest() + print '%s(%d) = %s or %s' % (name, max, result, hh(result)) + +if __name__ == '__main__': + MAX = 1024 + len_test('SHA1', hashlib.sha1, MAX) + len_test('SHA224', hashlib.sha224, MAX) + len_test('SHA256', hashlib.sha256, MAX) + len_test('SHA384', hashlib.sha384, MAX) + len_test('SHA512', hashlib.sha512, MAX) + len_test('SHA3-224', hashlib.sha3_224, MAX) + len_test('SHA3-256', hashlib.sha3_256, MAX) + len_test('SHA3-384', hashlib.sha3_384, MAX) + len_test('SHA3-512', hashlib.sha3_512, MAX) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/Makefile b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/Makefile new file mode 100644 index 0000000..ccbda7e --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/Makefile @@ -0,0 +1,17 @@ +CFLAGS += -g -O0 -std=gnu99 -fPIC -Wall -Wextra -Werror -Wno-unused-parameter +CPPFLAGS += -I../src -I../../bignum/out -I../../shitlisp/out + +all: cifra.so + +SOURCES = aes.o sha256.o sha512.o chash.o hmac.o pbkdf2.o modes.o eax.o \ + blockwise.o cmac.o salsa20.o chacha20.o curve25519.o + +cifra.so: $(addprefix ../src/, $(SOURCES)) sl-cifra.o + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ -shared + +clean: + rm -f *.o *.pyc $(TARGETS) *.gcov *.gcda *.gcno + +test: $(wildcard test-*.sl) cifra.so + ../../shitlisp/out/shitlisp --mod=./cifra.so $(wildcard test-*.sl) + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/sl-cifra.c b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/sl-cifra.c new file mode 100644 index 0000000..6d7b944 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/sl-cifra.c @@ -0,0 +1,206 @@ +#include "handy.h" +#include "dstr.h" +#include "shitlisp.h" +#include "aes.h" +#include "sha2.h" +#include "hmac.h" +#include "pbkdf2.h" + +#include <assert.h> + +static sl_value * aes_block_fn(sl_value *self, sl_value *args, sl_symboltab *tab, + void (*blockfn)(const cf_aes_context *ctx, + const uint8_t *in, + uint8_t *out)) +{ + sl_iter it = sl_iter_start(args); + sl_value *key = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab); + sl_value *block = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab); + + sl_value *ret = NULL; + + if (!key || !block || + (key->u.bytes.len != 16 && key->u.bytes.len != 24 && key->u.bytes.len != 32) || + block->u.bytes.len != AES_BLOCKSZ) + { + ret = sl_get_nil(); + goto x_err; + } + + cf_aes_context ctx; + cf_aes_init(&ctx, key->u.bytes.buf, key->u.bytes.len); + uint8_t blockout[AES_BLOCKSZ]; + blockfn(&ctx, block->u.bytes.buf, blockout); + ret = sl_new_bytes(blockout, AES_BLOCKSZ); + cf_aes_finish(&ctx); + +x_err: + sl_decref(key); + sl_decref(block); + return ret; +} + +static sl_value * aes_block_encrypt(sl_value *self, sl_value *args, sl_symboltab *tab) +{ + return aes_block_fn(self, args, tab, cf_aes_encrypt); +} + +static sl_value * aes_block_decrypt(sl_value *self, sl_value *args, sl_symboltab *tab) +{ + return aes_block_fn(self, args, tab, cf_aes_decrypt); +} + +/* Hashing */ +static sl_value * hash_fn(sl_value *self, sl_value *args, sl_symboltab *tab, const cf_chash *h) +{ + sl_iter it = sl_iter_start(args); + sl_value *msg = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab); + + if (!msg) + return sl_get_nil(); + + cf_chash_ctx ctx; + assert(h->ctxsz <= CF_CHASH_MAXCTX); + h->init(&ctx); + h->update(&ctx, msg->u.bytes.buf, msg->u.bytes.len); + sl_decref(msg); + + uint8_t result[CF_MAXHASH]; + assert(h->hashsz <= CF_MAXHASH); + h->digest(&ctx, result); + + return sl_new_bytes(result, h->hashsz); +} + +static sl_value * sha224(sl_value *self, sl_value *args, sl_symboltab *tab) +{ + return hash_fn(self, args, tab, &cf_sha224); +} + +static sl_value * sha256(sl_value *self, sl_value *args, sl_symboltab *tab) +{ + return hash_fn(self, args, tab, &cf_sha256); +} + +static sl_value * sha384(sl_value *self, sl_value *args, sl_symboltab *tab) +{ + return hash_fn(self, args, tab, &cf_sha384); +} + +static sl_value * sha512(sl_value *self, sl_value *args, sl_symboltab *tab) +{ + return hash_fn(self, args, tab, &cf_sha512); +} + +/* HMAC */ +static sl_value * hmac_fn(sl_value *self, sl_value *args, sl_symboltab *tab, const cf_chash *h) +{ + sl_iter it = sl_iter_start(args); + sl_value *key = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab); + sl_value *msg = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab); + + if (!key || !msg) + { + sl_decref(key); + sl_decref(msg); + return sl_get_nil(); + } + + uint8_t result[CF_MAXHASH]; + cf_hmac(key->u.bytes.buf, key->u.bytes.len, + msg->u.bytes.buf, msg->u.bytes.len, + result, + h); + + sl_decref(key); + sl_decref(msg); + return sl_new_bytes(result, h->hashsz); +} + +static sl_value * hmac_sha224(sl_value *self, sl_value *args, sl_symboltab *tab) +{ return hmac_fn(self, args, tab, &cf_sha224); } + +static sl_value * hmac_sha256(sl_value *self, sl_value *args, sl_symboltab *tab) +{ return hmac_fn(self, args, tab, &cf_sha256); } + +static sl_value * hmac_sha384(sl_value *self, sl_value *args, sl_symboltab *tab) +{ return hmac_fn(self, args, tab, &cf_sha384); } + +static sl_value * hmac_sha512(sl_value *self, sl_value *args, sl_symboltab *tab) +{ return hmac_fn(self, args, tab, &cf_sha512); } + + +/* PBKDF2 */ +static sl_value * do_pbkdf2(const cf_chash *h, sl_value *pw, sl_value *salt, + uint32_t iterations, uint32_t outlen) +{ + dstr out; + dstr_init(&out); + if (dstr_expand(&out, outlen)) + return NULL; + + cf_pbkdf2_hmac(pw->u.bytes.buf, pw->u.bytes.len, + salt->u.bytes.buf, salt->u.bytes.len, + iterations, + (uint8_t *) out.start, outlen, + h); + + sl_value *ret = sl_new_bytes((uint8_t *) out.start, outlen); + dstr_free(&out); + return ret; +} + +static sl_value * pbkdf2_fn(sl_value *self, sl_value *args, sl_symboltab *tab, const cf_chash *h) +{ + sl_iter it = sl_iter_start(args); + sl_value *pw = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab); + sl_value *salt = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab); + sl_value *iterations = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_integer, tab); + sl_value *outlen = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_integer, tab); + + sl_value *ret; + + if (!pw || !salt || !iterations || !outlen) + ret = sl_get_nil(); + else + { + assert(bignum_len_words(&iterations->u.integer.bn) == 1); + assert(bignum_len_words(&outlen->u.integer.bn) == 1); + ret = do_pbkdf2(h, pw, salt, + iterations->u.integer.bn.v[0], + outlen->u.integer.bn.v[0]); + } + + sl_decref(pw); + sl_decref(salt); + sl_decref(iterations); + sl_decref(outlen); + return ret; +} + +static sl_value * pbkdf2_sha224(sl_value *self, sl_value *args, sl_symboltab *tab) +{ + return pbkdf2_fn(self, args, tab, &cf_sha224); +} + +static sl_value * pbkdf2_sha256(sl_value *self, sl_value *args, sl_symboltab *tab) +{ + return pbkdf2_fn(self, args, tab, &cf_sha256); +} + +int SL_MODULE_ENTRY(sl_symboltab *tab) +{ + ER(sl_symboltab_add_name_native(tab, "aes-encrypt", aes_block_encrypt)); + ER(sl_symboltab_add_name_native(tab, "aes-decrypt", aes_block_decrypt)); + ER(sl_symboltab_add_name_native(tab, "sha224", sha224)); + ER(sl_symboltab_add_name_native(tab, "sha256", sha256)); + ER(sl_symboltab_add_name_native(tab, "sha384", sha384)); + ER(sl_symboltab_add_name_native(tab, "sha512", sha512)); + ER(sl_symboltab_add_name_native(tab, "hmac-sha224", hmac_sha224)); + ER(sl_symboltab_add_name_native(tab, "hmac-sha256", hmac_sha256)); + ER(sl_symboltab_add_name_native(tab, "hmac-sha384", hmac_sha384)); + ER(sl_symboltab_add_name_native(tab, "hmac-sha512", hmac_sha512)); + ER(sl_symboltab_add_name_native(tab, "pbkdf2-sha224", pbkdf2_sha224)); + ER(sl_symboltab_add_name_native(tab, "pbkdf2-sha256", pbkdf2_sha256)); + return 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-aes.sl b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-aes.sl new file mode 100644 index 0000000..5535c5d --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-aes.sl @@ -0,0 +1,91 @@ +(def check-aes (key pt ct) + (+ + (assert (= + ct + (aes-encrypt key pt))) + (assert (= + pt + (aes-decrypt key ct))) + ) +) + +(check-aes + [000102030405060708090a0b0c0d0e0f] + [00112233445566778899aabbccddeeff] + [69c4e0d86a7b0430d8cdb78070b4c55a] +) +(check-aes + [000102030405060708090a0b0c0d0e0f1011121314151617] + [00112233445566778899aabbccddeeff] + [dda97ca4864cdfe06eaf70a0ec0d7191] +) +(check-aes + [000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f] + [00112233445566778899aabbccddeeff] + [8ea2b7ca516745bfeafc49904b496089] +) + +(check-aes + [2b7e151628aed2a6abf7158809cf4f3c] + [6bc1bee22e409f96e93d7e117393172a] + [3ad77bb40d7a3660a89ecaf32466ef97] +) +(check-aes + [2b7e151628aed2a6abf7158809cf4f3c] + [ae2d8a571e03ac9c9eb76fac45af8e51] + [f5d3d58503b9699de785895a96fdbaaf] +) +(check-aes + [2b7e151628aed2a6abf7158809cf4f3c] + [30c81c46a35ce411e5fbc1191a0a52ef] + [43b1cd7f598ece23881b00e3ed030688] +) +(check-aes + [2b7e151628aed2a6abf7158809cf4f3c] + [f69f2445df4f9b17ad2b417be66c3710] + [7b0c785e27e8ad3f8223207104725dd4] +) + +(check-aes + [8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b] + [6bc1bee22e409f96e93d7e117393172a] + [bd334f1d6e45f25ff712a214571fa5cc] +) +(check-aes + [8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b] + [ae2d8a571e03ac9c9eb76fac45af8e51] + [974104846d0ad3ad7734ecb3ecee4eef] +) +(check-aes + [8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b] + [30c81c46a35ce411e5fbc1191a0a52ef] + [ef7afd2270e2e60adce0ba2face6444e] +) +(check-aes + [8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b] + [f69f2445df4f9b17ad2b417be66c3710] + [9a4b41ba738d6c72fb16691603c18e0e] +) + +(check-aes + [603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4] + [6bc1bee22e409f96e93d7e117393172a] + [f3eed1bdb5d2a03c064b5a7e3db181f8] +) +(check-aes + [603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4] + [ae2d8a571e03ac9c9eb76fac45af8e51] + [591ccb10d410ed26dc5ba74a31362870] +) +(check-aes + [603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4] + [30c81c46a35ce411e5fbc1191a0a52ef] + [b6ed21b99ca6f4f9f153e7b1beafed1d] +) +(check-aes + [603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4] + [f69f2445df4f9b17ad2b417be66c3710] + [23304b7a39f9f3ff067d8d8f9e24ecc7] +) + +(puts success) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-pbkdf2.sl b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-pbkdf2.sl new file mode 100644 index 0000000..b87f397 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-pbkdf2.sl @@ -0,0 +1,36 @@ +(assert (= + (pbkdf2-sha256 (bytes "password") (bytes "salt") 1 32) + [120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b]) +) + +(assert (= + (pbkdf2-sha256 (bytes "password") (bytes "salt") 2 32) + [ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43]) +) + +(assert (= + (pbkdf2-sha256 (bytes "password") (bytes "salt") 4096 32) + [c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a]) +) + +(assert (= + (pbkdf2-sha256 (bytes "passwordPASSWORDpassword") (bytes "saltSALTsaltSALTsaltSALTsaltSALTsalt") 4096 40) + [348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9]) +) + +(assert (= + (pbkdf2-sha256 [] (bytes "salt") 1024 32) + [9e83f279c040f2a11aa4a02b24c418f2d3cb39560c9627fa4f47e3bcc2897c3d]) +) + +(assert (= + (pbkdf2-sha256 (bytes "password") [] 1024 32) + [ea5808411eb0c7e830deab55096cee582761e22a9bc034e3ece925225b07bf46]) +) + +(assert (= + (pbkdf2-sha256 [7061737300776f7264] [7361006c74] 4096 16) + [89b69d0516f829893c696226650a8687]) +) + +(puts success) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha224.sl b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha224.sl new file mode 100644 index 0000000..5de9e15 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha224.sl @@ -0,0 +1,41 @@ +(assert (= + (sha224 (bytes "abc")) + [23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7]) +) + +(assert (= + (sha224 []) + [d14a028c 2a3a2bc9 476102bb 288234c4 15a2b01f 828ea62a c5b3e42f]) +) + +(assert (= + (hmac-sha224 (* [0b] 20) (bytes "Hi There")) + [896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22]) +) + +(assert (= + (hmac-sha224 (bytes "Jefe") (bytes "what do ya want for nothing?")) + [a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44]) +) + +(assert (= + (hmac-sha224 (* [aa] 20) (* [dd] 50)) + [7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea]) +) + +(assert (= + (hmac-sha224 [0102030405060708090a0b0c0d0e0f10111213141516171819] (* [cd] 50)) + [6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a]) +) + +(assert (= + (hmac-sha224 (* [aa] 131) (bytes "Test Using Larger Than Block-Size Key - Hash Key First")) + [95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e]) +) + +(assert (= + (hmac-sha224 (* [aa] 131) (bytes "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.")) + [3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1]) +) + +(puts success) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha256.sl b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha256.sl new file mode 100644 index 0000000..83c0457 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha256.sl @@ -0,0 +1,62 @@ +(assert (= + (sha256 (bytes "abc")) + [ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad]) +) + +(assert (= + (sha256 (bytes "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")) + [248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1]) +) + +(assert (= + (sha256 (* (bytes "a") 1000000)) + [cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0]) +) + +(assert (= + (sha256 (bytes "The quick brown fox jumps over the lazy dog")) + [d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592]) +) + +(assert (= + (sha256 (bytes "The quick brown fox jumps over the lazy cog")) + [e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be]) +) + +(assert (= + (sha256 []) + [e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855]) +) + +(assert (= + (hmac-sha256 (* [0b] 20) (bytes "Hi There")) + [b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7]) +) + +(assert (= + (hmac-sha256 (bytes "Jefe") (bytes "what do ya want for nothing?")) + [5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843]) +) + +(assert (= + (hmac-sha256 (* [aa] 20) (* [dd] 50)) + [773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe]) +) + +(assert (= + (hmac-sha256 [0102030405060708090a0b0c0d0e0f10111213141516171819] (* [cd] 50)) + [82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b]) +) + +(assert (= + (hmac-sha256 (* [aa] 131) (bytes "Test Using Larger Than Block-Size Key - Hash Key First")) + [60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54]) +) + +(assert (= + (hmac-sha256 (* [aa] 131) (bytes "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.")) + [9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2]) +) + + +(puts success) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha384.sl b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha384.sl new file mode 100644 index 0000000..33a00ee --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha384.sl @@ -0,0 +1,67 @@ +(assert (= + (sha384 (bytes "abc")) + [cb00753f45a35e8b b5a03d699ac65007 272c32ab0eded163 1a8b605a43ff5bed 8086072ba1e7cc23 58baeca134c825a7]) +) + +(assert (= + (sha384 (bytes "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")) + [3391fdddfc8dc739 3707a65b1b470939 7cf8b1d162af05ab fe8f450de5f36bc6 b0455a8520bc4e6f 5fe95b1fe3c8452b]) +) + +(assert (= + (sha384 (bytes "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")) + [09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039]) +) + +(assert (= + (sha384 (* (bytes "a") 1000000)) + [9d0e1809716474cb 086e834e310a4a1c ed149e9c00f24852 7972cec5704c2a5b 07b8b3dc38ecc4eb ae97ddd87f3d8985]) +) + +(assert (= + (sha384 (bytes "The quick brown fox jumps over the lazy dog")) + [ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1]) +) + +(assert (= + (sha384 (bytes "The quick brown fox jumps over the lazy cog")) + [098cea620b0978caa5f0befba6ddcf22764bea977e1c70b3483edfdf1de25f4b40d6cea3cadf00f809d422feb1f0161b]) +) + +(assert (= + (sha384 []) + [38b060a751ac9638 4cd9327eb1b1e36a 21fdb71114be0743 4c0cc7bf63f6e1da 274edebfe76f65fb d51ad2f14898b95b]) +) + +(assert (= + (hmac-sha384 (* [0b] 20) (bytes "Hi There")) + [afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6]) +) + +(assert (= + (hmac-sha384 (bytes "Jefe") (bytes "what do ya want for nothing?")) + [af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649]) +) + +(assert (= + (hmac-sha384 (* [aa] 20) (* [dd] 50)) + [88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27]) +) + +(assert (= + (hmac-sha384 [0102030405060708090a0b0c0d0e0f10111213141516171819] (* [cd] 50)) + [3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb]) +) + +(assert (= + (hmac-sha384 (* [aa] 131) (bytes "Test Using Larger Than Block-Size Key - Hash Key First")) + [4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952]) +) + +(assert (= + (hmac-sha384 (* [aa] 131) (bytes "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.")) + [6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e]) +) + + +(puts success) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha512.sl b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha512.sl new file mode 100644 index 0000000..4201019 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/shitlisp/test-sha512.sl @@ -0,0 +1,67 @@ +(assert (= + (sha512 (bytes "abc")) + [ddaf35a193617aba cc417349ae204131 12e6fa4e89a97ea2 0a9eeee64b55d39a 2192992a274fc1a8 36ba3c23a3feebbd 454d4423643ce80e 2a9ac94fa54ca49f]) +) + +(assert (= + (sha512 (bytes "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")) + [204a8fc6dda82f0a 0ced7beb8e08a416 57c16ef468b228a8 279be331a703c335 96fd15c13b1b07f9 aa1d3bea57789ca0 31ad85c7a71dd703 54ec631238ca3445]) +) + +(assert (= + (sha512 (bytes "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")) + [8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909]) +) + +(assert (= + (sha512 (* (bytes "a") 1000000)) + [e718483d0ce76964 4e2e42c7bc15b463 8e1f98b13b204428 5632a803afa973eb de0ff244877ea60a 4cb0432ce577c31b eb009c5c2c49aa2e 4eadb217ad8cc09b]) +) + +(assert (= + (sha512 (bytes "The quick brown fox jumps over the lazy dog")) + [07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6]) +) + +(assert (= + (sha512 (bytes "The quick brown fox jumps over the lazy cog")) + [3eeee1d0 e11733ef 152a6c29 503b3ae2 0c4f1f3c da4cb26f 1bc1a41f 91c7fe4a b3bd8649 4049e201 c4bd5155 f31ecb7a 3c860684 3c4cc8df cab7da11 c8ae5045]) +) + +(assert (= + (sha512 []) + [cf83e1357eefb8bd f1542850d66d8007 d620e4050b5715dc 83f4a921d36ce9ce 47d0d13c5d85f2b0 ff8318d2877eec2f 63b931bd47417a81 a538327af927da3e]) +) + +(assert (= + (hmac-sha512 (* [0b] 20) (bytes "Hi There")) + [87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854]) +) + +(assert (= + (hmac-sha512 (bytes "Jefe") (bytes "what do ya want for nothing?")) + [164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737]) +) + +(assert (= + (hmac-sha512 (* [aa] 20) (* [dd] 50)) + [fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb]) +) + +(assert (= + (hmac-sha512 [0102030405060708090a0b0c0d0e0f10111213141516171819] (* [cd] 50)) + [b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd]) +) + +(assert (= + (hmac-sha512 (* [aa] 131) (bytes "Test Using Larger Than Block-Size Key - Hash Key First")) + [80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598]) +) + +(assert (= + (hmac-sha512 (* [aa] 131) (bytes "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.")) + [e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58]) +) + + +(puts success) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/Makefile b/debian/vendor-h2o/deps/picotls/deps/cifra/src/Makefile new file mode 100644 index 0000000..451548d --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/Makefile @@ -0,0 +1,54 @@ +CFLAGS += -g -O0 -std=gnu99 -fPIC -Wall -Wextra -Werror \ + -Wno-unused-parameter -Wno-missing-field-initializers +CPPFLAGS += -I./ext + +ifdef WITH_ASAN + LDFLAGS += -fsanitize=address + CFLAGS += -fsanitize=address +endif + +ifdef WITH_COVERAGE + LDFLAGS += -coverage + CFLAGS += -coverage +endif + +ifdef WITH_VALGRIND + VALGRIND := valgrind --leak-check=full --show-reachable=yes --track-origins=yes + TEST_OPT := --no-exec +endif + +TARGETS = testaes testmodes testsha1 testsha2 testsha3 testsalsa20 \ + testcurve25519 testpoly1305 testnorx testchacha20poly1305 \ + testdrbg +all: $(TARGETS) + +SOURCES = aes.o sha256.o sha512.o chash.o hmac.o pbkdf2.o modes.o eax.o \ + gf128.o blockwise.o cmac.o salsa20.o chacha20.o curve25519.o \ + gcm.o cbcmac.o ccm.o sha3.o sha1.o poly1305.o \ + norx.o chacha20poly1305.o drbg.o ocb.o + +testaes: $(SOURCES) testaes.o +testmodes: $(SOURCES) testmodes.o +testsha1: $(SOURCES) testsha1.o +testsha2: $(SOURCES) testsha2.o +testsha3: $(SOURCES) testsha3.o +testsalsa20: $(SOURCES) testsalsa20.o +testcurve25519: $(SOURCES) testcurve25519.o +testpoly1305: $(SOURCES) testpoly1305.o +testnorx: $(SOURCES) testnorx.o +testchacha20poly1305: $(SOURCES) testchacha20poly1305.o +testdrbg: $(SOURCES) testdrbg.o + +clean: + rm -f *.o *.pyc $(TARGETS) *.gcov *.gcda *.gcno + +test: $(TARGETS) + for x in $(TARGETS) ; do \ + echo "Running $$x" ; \ + $(VALGRIND) ./$$x $(TEST_OPT) ; \ + done + +cover: test + gcov *.c + echo 'Lines with missing coverage:' + grep '#####' *.gcov | grep -vE '(cutest|testutil).h.gcov' diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/aes.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/aes.c new file mode 100644 index 0000000..545588e --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/aes.c @@ -0,0 +1,419 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include <string.h> +#include <stdlib.h> + +#include "cf_config.h" +#include "aes.h" +#include "handy.h" +#include "bitops.h" +#include "tassert.h" + +static const uint8_t S[256] = +{ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, + 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, + 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, + 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, + 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, + 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, + 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, + 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, + 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, + 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, + 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, + 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, + 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, + 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, + 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, + 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, + 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +static const uint8_t Rcon[11] = +{ + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 +}; + +#ifdef INLINE_FUNCS +static inline uint32_t word4(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) +{ + return b0 << 24 | b1 << 16 | b2 << 8 | b3; +} + +static inline uint8_t byte(uint32_t w, unsigned x) +{ + /* nb. bytes are numbered 0 (leftmost, top) + * to 3 (rightmost). */ + x = 3 - x; + return (w >> (x * 8)) & 0xff; +} + +static uint32_t round_constant(uint32_t i) +{ + return Rcon[i] << 24; +} + +static uint32_t rot_word(uint32_t w) +{ + /* Takes + * word [a0,a1,a2,a3] + * returns + * word [a1,a2,a3,a0] + * + */ + return rotl32(w, 8); +} +#endif + +#define word4(a, b, c, d) (((uint32_t)(a) << 24) | ((uint32_t)(b) << 16) | ((uint32_t)(c) << 8) | (d)) +#define byte(w, x) ((w >> ((3 - (x)) << 3)) & 0xff) +#define round_constant(i) ((uint32_t)(Rcon[i]) << 24) +#define rot_word(w) rotl32((w), 8) + +static uint32_t sub_word(uint32_t w, const uint8_t *sbox) +{ + uint8_t a = byte(w, 0), + b = byte(w, 1), + c = byte(w, 2), + d = byte(w, 3); +#if CF_CACHE_SIDE_CHANNEL_PROTECTION + select_u8x4(&a, &b, &c, &d, sbox, 256); +#else + a = sbox[a]; + b = sbox[b]; + c = sbox[c]; + d = sbox[d]; +#endif + return word4(a, b, c, d); +} + +static void aes_schedule(cf_aes_context *ctx, const uint8_t *key, size_t nkey) +{ + size_t i, + nb = AES_BLOCKSZ / 4, + nk = nkey / 4, + n = nb * (ctx->rounds + 1); + uint32_t *w = ctx->ks; + + /* First words are just the key. */ + for (i = 0; i < nk; i++) + { + w[i] = read32_be(key + i * 4); + } + + uint32_t i_div_nk = 1; + uint32_t i_mod_nk = 0; + + for (; i < n; i++, i_mod_nk++) + { + uint32_t temp = w[i - 1]; + + if (i_mod_nk == nk) + { + i_div_nk++; + i_mod_nk = 0; + } + + if (i_mod_nk == 0) + temp = sub_word(rot_word(temp), S) ^ round_constant(i_div_nk); + else if (nk > 6 && i_mod_nk == 4) + temp = sub_word(temp, S); + + w[i] = w[i - nk] ^ temp; + } +} + +void cf_aes_init(cf_aes_context *ctx, const uint8_t *key, size_t nkey) +{ + memset(ctx, 0, sizeof *ctx); + + switch (nkey) + { +#if CF_AES_MAXROUNDS >= AES128_ROUNDS + case 16: + ctx->rounds = AES128_ROUNDS; + aes_schedule(ctx, key, nkey); + break; +#endif + +#if CF_AES_MAXROUNDS >= AES192_ROUNDS + case 24: + ctx->rounds = AES192_ROUNDS; + aes_schedule(ctx, key, nkey); + break; +#endif + +#if CF_AES_MAXROUNDS >= AES256_ROUNDS + case 32: + ctx->rounds = AES256_ROUNDS; + aes_schedule(ctx, key, nkey); + break; +#endif + + default: + abort(); + } +} + +static void add_round_key(uint32_t state[4], const uint32_t rk[4]) +{ + state[0] ^= rk[0]; + state[1] ^= rk[1]; + state[2] ^= rk[2]; + state[3] ^= rk[3]; +} + +static void sub_block(uint32_t state[4]) +{ + state[0] = sub_word(state[0], S); + state[1] = sub_word(state[1], S); + state[2] = sub_word(state[2], S); + state[3] = sub_word(state[3], S); +} + +static void shift_rows(uint32_t state[4]) +{ + uint32_t u, v, x, y; + + u = word4(byte(state[0], 0), + byte(state[1], 1), + byte(state[2], 2), + byte(state[3], 3)); + + v = word4(byte(state[1], 0), + byte(state[2], 1), + byte(state[3], 2), + byte(state[0], 3)); + + x = word4(byte(state[2], 0), + byte(state[3], 1), + byte(state[0], 2), + byte(state[1], 3)); + + y = word4(byte(state[3], 0), + byte(state[0], 1), + byte(state[1], 2), + byte(state[2], 3)); + + state[0] = u; + state[1] = v; + state[2] = x; + state[3] = y; +} + +static uint32_t gf_poly_mul2(uint32_t x) +{ + return + ((x & 0x7f7f7f7f) << 1) ^ + (((x & 0x80808080) >> 7) * 0x1b); +} + +static uint32_t mix_column(uint32_t x) +{ + uint32_t x2 = gf_poly_mul2(x); + return x2 ^ rotr32(x ^ x2, 24) ^ rotr32(x, 16) ^ rotr32(x, 8); +} + +static void mix_columns(uint32_t state[4]) +{ + state[0] = mix_column(state[0]); + state[1] = mix_column(state[1]); + state[2] = mix_column(state[2]); + state[3] = mix_column(state[3]); +} + +void cf_aes_encrypt(const cf_aes_context *ctx, + const uint8_t in[AES_BLOCKSZ], + uint8_t out[AES_BLOCKSZ]) +{ + assert(ctx->rounds == AES128_ROUNDS || + ctx->rounds == AES192_ROUNDS || + ctx->rounds == AES256_ROUNDS); + + uint32_t state[4] = { + read32_be(in + 0), + read32_be(in + 4), + read32_be(in + 8), + read32_be(in + 12) + }; + + const uint32_t *round_keys = ctx->ks; + add_round_key(state, round_keys); + round_keys += 4; + + uint32_t round; + for (round = 1; round < ctx->rounds; round++) + { + sub_block(state); + shift_rows(state); + mix_columns(state); + add_round_key(state, round_keys); + round_keys += 4; + } + + sub_block(state); + shift_rows(state); + add_round_key(state, round_keys); + + write32_be(state[0], out + 0); + write32_be(state[1], out + 4); + write32_be(state[2], out + 8); + write32_be(state[3], out + 12); +} + +#if CF_AES_ENCRYPT_ONLY == 0 +static const uint8_t S_inv[256] = +{ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, + 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, + 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, + 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, + 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, + 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, + 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, + 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, + 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, + 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, + 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, + 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, + 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, + 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, + 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, + 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, + 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, + 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +}; + +static void inv_sub_block(uint32_t state[4]) +{ + state[0] = sub_word(state[0], S_inv); + state[1] = sub_word(state[1], S_inv); + state[2] = sub_word(state[2], S_inv); + state[3] = sub_word(state[3], S_inv); +} + +static void inv_shift_rows(uint32_t state[4]) +{ + uint32_t u, v, x, y; + + u = word4(byte(state[0], 0), + byte(state[3], 1), + byte(state[2], 2), + byte(state[1], 3)); + + v = word4(byte(state[1], 0), + byte(state[0], 1), + byte(state[3], 2), + byte(state[2], 3)); + + x = word4(byte(state[2], 0), + byte(state[1], 1), + byte(state[0], 2), + byte(state[3], 3)); + + y = word4(byte(state[3], 0), + byte(state[2], 1), + byte(state[1], 2), + byte(state[0], 3)); + + state[0] = u; + state[1] = v; + state[2] = x; + state[3] = y; +} + +static uint32_t inv_mix_column(uint32_t x) +{ + uint32_t x2 = gf_poly_mul2(x), + x4 = gf_poly_mul2(x2), + x9 = x ^ gf_poly_mul2(x4), + x11 = x2 ^ x9, + x13 = x4 ^ x9; + + return x ^ x2 ^ x13 ^ rotr32(x11, 24) ^ rotr32(x13, 16) ^ rotr32(x9, 8); +} + +static void inv_mix_columns(uint32_t state[4]) +{ + state[0] = inv_mix_column(state[0]); + state[1] = inv_mix_column(state[1]); + state[2] = inv_mix_column(state[2]); + state[3] = inv_mix_column(state[3]); +} + +void cf_aes_decrypt(const cf_aes_context *ctx, + const uint8_t in[AES_BLOCKSZ], + uint8_t out[AES_BLOCKSZ]) +{ + assert(ctx->rounds == AES128_ROUNDS || + ctx->rounds == AES192_ROUNDS || + ctx->rounds == AES256_ROUNDS); + + uint32_t state[4] = { + read32_be(in + 0), + read32_be(in + 4), + read32_be(in + 8), + read32_be(in + 12) + }; + + const uint32_t *round_keys = &ctx->ks[ctx->rounds << 2]; + add_round_key(state, round_keys); + round_keys -= 4; + + uint32_t round; + for (round = ctx->rounds - 1; round != 0; round--) + { + inv_shift_rows(state); + inv_sub_block(state); + add_round_key(state, round_keys); + inv_mix_columns(state); + round_keys -= 4; + } + + inv_shift_rows(state); + inv_sub_block(state); + add_round_key(state, round_keys); + + write32_be(state[0], out + 0); + write32_be(state[1], out + 4); + write32_be(state[2], out + 8); + write32_be(state[3], out + 12); +} +#else +void cf_aes_decrypt(const cf_aes_context *ctx, + const uint8_t in[AES_BLOCKSZ], + uint8_t out[AES_BLOCKSZ]) +{ + abort(); +} +#endif + +void cf_aes_finish(cf_aes_context *ctx) +{ + mem_clean(ctx, sizeof *ctx); +} + +const cf_prp cf_aes = { + .blocksz = AES_BLOCKSZ, + .encrypt = (cf_prp_block) cf_aes_encrypt, + .decrypt = (cf_prp_block) cf_aes_decrypt +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/aes.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/aes.h new file mode 100644 index 0000000..2ee7f46 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/aes.h @@ -0,0 +1,152 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +/** + * The AES block cipher + * ==================== + * + * This is a small, simple implementation of AES. Key expansion is done + * first, filling in a :c:type:`cf_aes_context`. Then encryption and + * decryption can be performed as desired. + * + * Usually you don't want to use AES directly; you should use it via + * a :doc:`block cipher mode <modes>`. + */ + +#ifndef AES_H +#define AES_H + +#include <stddef.h> +#include <stdint.h> + +#include "prp.h" + +/* .. c:macro:: AES_BLOCKSZ + * AES has a 128-bit block size. This quantity is in bytes. + */ +#define AES_BLOCKSZ 16 + +/* --- Size configuration --- */ + +/* .. c:macro:: AES128_ROUNDS + * .. c:macro:: AES192_ROUNDS + * .. c:macro:: AES256_ROUNDS + * + * Round counts for different key sizes. + */ +#define AES128_ROUNDS 10 +#define AES192_ROUNDS 12 +#define AES256_ROUNDS 14 + +/* .. c:macro:: CF_AES_MAXROUNDS + * + * You can reduce the maximum number of rounds this implementation + * supports. This reduces the storage needed by :c:type:`cf_aes_context`. + * + * The default is :c:macro:`AES256_ROUNDS` and is good for all key + * sizes. + */ +#ifndef CF_AES_MAXROUNDS +# define CF_AES_MAXROUNDS AES256_ROUNDS +#endif + +/* .. c:macro:: CF_AES_ENCRYPT_ONLY + * + * Define this to 1 if you don't need to decrypt anything. + * This saves space. :c:func:`cf_aes_decrypt` calls `abort(3)`. + */ +#ifndef CF_AES_ENCRYPT_ONLY +# define CF_AES_ENCRYPT_ONLY 0 +#endif + +/* .. c:type:: cf_aes_context + * This type represents an expanded AES key. Create one + * using :c:func:`cf_aes_init`, make use of one using + * :c:func:`cf_aes_encrypt` or :c:func:`cf_aes_decrypt`. + * + * The contents of this structure are equivalent to the + * original key material. You should clean the + * contents of this structure with :c:func:`cf_aes_finish` + * when you're done. + * + * .. c:member:: cf_aes_context.rounds + * + * Number of rounds to use, set by :c:func:`cf_aes_init`. + * + * This depends on the original key size, and will be + * :c:macro:`AES128_ROUNDS`, :c:macro:`AES192_ROUNDS` or + * :c:macro:`AES256_ROUNDS`. + * + * .. c:member:: cf_aes_context.ks + * + * Expanded key material. Filled in by :c:func:`cf_aes_init`. + */ +typedef struct +{ + uint32_t rounds; + uint32_t ks[AES_BLOCKSZ / 4 * (CF_AES_MAXROUNDS + 1)]; +} cf_aes_context; + +/* .. c:function:: $DECL + * This function does AES key expansion. It destroys + * existing contents of :c:data:`ctx`. + * + * :param ctx: expanded key context, filled in by this function. + * :param key: pointer to key material, of :c:data:`nkey` bytes. + * :param nkey: length of key material. Must be `16`, `24` or `32`. + */ +extern void cf_aes_init(cf_aes_context *ctx, + const uint8_t *key, + size_t nkey); + +/* .. c:function:: $DECL + * Encrypts the given block, from :c:data:`in` to :c:data:`out`. + * These may alias. + * + * Fails at runtime if :c:data:`ctx` is invalid. + * + * :param ctx: expanded key context + * :param in: input block (read) + * :param out: output block (written) + */ +extern void cf_aes_encrypt(const cf_aes_context *ctx, + const uint8_t in[AES_BLOCKSZ], + uint8_t out[AES_BLOCKSZ]); + +/* .. c:function:: $DECL + * Decrypts the given block, from :c:data:`in` to :c:data:`out`. + * These may alias. + * + * Fails at runtime if :c:data:`ctx` is invalid. + * + * :param ctx: expanded key context + * :param in: input block (read) + * :param out: output block (written) + */ +extern void cf_aes_decrypt(const cf_aes_context *ctx, + const uint8_t in[AES_BLOCKSZ], + uint8_t out[AES_BLOCKSZ]); + +/* .. c:function:: $DECL + * Erase scheduled key material. + * + * Call this when you're done to erase the round keys. */ +extern void cf_aes_finish(cf_aes_context *ctx); + +/* .. c:var:: const cf_prp cf_aes + * Abstract interface to AES. See :c:type:`cf_prp` for + * more information. */ +extern const cf_prp cf_aes; + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/Makefile b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/Makefile new file mode 100644 index 0000000..7be9a53 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/Makefile @@ -0,0 +1,184 @@ +FUNCS = do_nothing stack_8w stack_64w \ + hashtest_sha256 hashtest_sha512 \ + hashtest_sha3_256 hashtest_sha3_512 \ + aes128block_test aes128sched_test \ + aes256block_test aes256sched_test \ + aes128gcm_test aes128eax_test \ + aes128ccm_test \ + salsa20_test chacha20_test \ + poly1305_test hmacsha256_test \ + curve25519_test \ + norx_test + +AEADS = aeadperf_aes128gcm \ + aeadperf_aes128ccm \ + aeadperf_aes128eax \ + aeadperf_aes256gcm \ + aeadperf_aes256ccm \ + aeadperf_aes256eax \ + aeadperf_norx \ + aeadperf_chacha20poly1305 +TESTS = testcurve25519 testaes testmodes testsalsa20 testsha1 testsha2 \ + testsha3 testpoly1305 testnorx testchacha20poly1305 testdrbg +ARCHS = stm32f0 stm32f1 stm32f3 efm32 qemucm3 + +all: $(patsubst %,%.stm32f0.bin,$(FUNCS) $(AEADS) $(TESTS)) \ + $(patsubst %,%.stm32f1.bin,$(FUNCS) $(AEADS) $(TESTS)) \ + $(patsubst %,%.stm32f3.bin,$(FUNCS) $(AEADS) $(TESTS)) \ + $(patsubst %,%.efm32.bin,$(FUNCS) $(AEADS) $(TESTS)) \ + $(patsubst %,%.qemucm3.bin,$(FUNCS) $(AEADS) $(TESTS)) + +%.stm32f0.elf: + arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.stm32f0.ld -mcpu=cortex-m0 -DCORTEX_M0 -o $@ $^ -DTEST=$* -lgcc + +%.stm32f1.elf: + arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.stm32f1.ld -mcpu=cortex-m3 -DCORTEX_M3 -o $@ $^ -DTEST=$* -lgcc + +%.stm32f3.elf: + arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.stm32f3.ld -mcpu=cortex-m4 -DCORTEX_M4 -o $@ $^ -DTEST=$* -lgcc + +%.efm32.elf: + arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.efm32.ld -mcpu=cortex-m0 -DCORTEX_M0 -o $@ $^ -DTEST=$* -lgcc + +%.qemucm3.elf: + arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.qemucm3.ld -mcpu=cortex-m3 -DCORTEX_M3 -o $@ $^ -DTEST=$* -lgcc + +%.bin: %.elf + arm-none-eabi-objcopy -O binary $< $@ +.PRECIOUS: %.bin + +AES_OPTIONS = -DCF_AES_ENCRYPT_ONLY=1 -DCF_SIDE_CHANNEL_PROTECTION=0 +AES128_OPTIONS = -DCF_AES_MAXROUNDS=AES128_ROUNDS +AES256_OPTIONS = -DCF_AES_MAXROUNDS=AES256_ROUNDS + +AEADPERF_BRACKET = -DBRACKET_MODE=1 -DBRACKET_START=0 -DBRACKET_END=256 -DBRACKET_STEP=4 + +CFLAGS_aes128block_test = $(AES_OPTIONS) $(AES128_OPTIONS) +CFLAGS_aes128sched_test = $(AES_OPTIONS) $(AES128_OPTIONS) +CFLAGS_aes128gcm_test = $(AES_OPTIONS) $(AES128_OPTIONS) +CFLAGS_aes128eax_test = $(AES_OPTIONS) $(AES128_OPTIONS) +CFLAGS_aes128ccm_test = $(AES_OPTIONS) $(AES128_OPTIONS) +CFLAGS_poly1305_test = $(AES_OPTIONS) $(AES128_OPTIONS) + +CFLAGS_aeadperf_aes128gcm = $(AES_OPTIONS) $(AES128_OPTIONS) $(AEADPERF_BRACKET) +CFLAGS_aeadperf_aes128eax = $(AES_OPTIONS) $(AES128_OPTIONS) $(AEADPERF_BRACKET) +CFLAGS_aeadperf_aes128ccm = $(AES_OPTIONS) $(AES128_OPTIONS) $(AEADPERF_BRACKET) +CFLAGS_aeadperf_aes256gcm = $(AES_OPTIONS) $(AES256_OPTIONS) $(AEADPERF_BRACKET) +CFLAGS_aeadperf_aes256eax = $(AES_OPTIONS) $(AES256_OPTIONS) $(AEADPERF_BRACKET) +CFLAGS_aeadperf_aes256ccm = $(AES_OPTIONS) $(AES256_OPTIONS) $(AEADPERF_BRACKET) +CFLAGS_aeadperf_norx = $(AEADPERF_BRACKET) +CFLAGS_aeadperf_chacha20poly1305 = $(AEADPERF_BRACKET) + +CFLAGS_aes256block_test = $(AES_OPTIONS) $(AES256_OPTIONS) +CFLAGS_aes256sched_test = $(AES_OPTIONS) $(AES256_OPTIONS) + +CFLAGS_testaes = -DCF_SIDE_CHANNEL_PROTECTION=0 + +CFLAGS = -I./ext -I../ext -I.. -Os -ffunction-sections -g \ + -Wall -Werror -std=gnu99 -mthumb +LDFLAGS = -nostartfiles -nostdlib -Wl,-gc-sections +CURVESRCS = unacl/cortex_m0_mpy121666.s unacl/cortex_m0_reduce25519.s unacl/mul.s unacl/sqr.s +SRCS = boot.c memcpy.s memset.s semihost.c semihost.s \ + ../sha1.c ../sha256.c ../sha512.c ../sha3.c ../blockwise.c ../chash.c \ + ../curve25519.c ../poly1305.c \ + ../aes.c ../eax.c ../gcm.c ../cbcmac.c ../ccm.c \ + ../modes.c ../cmac.c ../gf128.c \ + ../hmac.c ../pbkdf2.c ../salsa20.c ../chacha20.c \ + ../norx.c ../chacha20poly1305.c ../drbg.c + +$(patsubst %,%.stm32f0.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS) +$(patsubst %,%.stm32f1.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS) +$(patsubst %,%.stm32f3.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS) +$(patsubst %,%.efm32.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS) +$(patsubst %,%.qemucm3.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS) + +$(patsubst %,testcurve25519.%.elf, $(ARCHS)): $(SRCS) $(CURVESRCS) ../testcurve25519.c +$(patsubst %,testaes.%.elf, $(ARCHS)): $(SRCS) ../testaes.c +$(patsubst %,testmodes.%.elf, $(ARCHS)): $(SRCS) ../testmodes.c +$(patsubst %,testsalsa20.%.elf, $(ARCHS)): $(SRCS) ../testsalsa20.c +$(patsubst %,testsha1.%.elf, $(ARCHS)): $(SRCS) ../testsha1.c +$(patsubst %,testsha2.%.elf, $(ARCHS)): $(SRCS) ../testsha2.c +$(patsubst %,testsha3.%.elf, $(ARCHS)): $(SRCS) ../testsha3.c +$(patsubst %,testpoly1305.%.elf, $(ARCHS)): $(SRCS) ../testpoly1305.c +$(patsubst %,testnorx.%.elf, $(ARCHS)): $(SRCS) ../testnorx.c +$(patsubst %,testchacha20poly1305.%.elf, $(ARCHS)): $(SRCS) ../testchacha20poly1305.c +$(patsubst %,testdrbg.%.elf, $(ARCHS)): $(SRCS) ../testdrbg.c + +run.%.qemucm3: %.qemucm3.bin + arm-none-eabi-readelf -l $(patsubst %.bin,%.elf,$^) > $@.log + qemu-system-gnuarmeclipse -verbose -verbose -M STM32-P103 -kernel $^ -semihosting -nographic -monitor null -serial null 2>> $@.log + cat $@.log + +run.%.efm32: %.efm32.elf + arm-none-eabi-readelf -l $^ > $@.log + echo '-----' >> $@.log + openocd -f openocd.efm32.cfg >> $@.log & + arm-none-eabi-gdb --quiet --batch-silent \ + $^ \ + -ex 'target remote :3333' \ + -ex 'monitor reset halt' \ + -ex 'load' \ + -ex 'monitor arm semihosting enable' \ + -ex 'monitor reset run' \ + -ex 'monitor wait_halt 720000' \ + -ex 'monitor shutdown' + +run.%.stm32f0: %.stm32f0.elf + arm-none-eabi-readelf -l $^ > $@.log + echo '-----' >> $@.log + openocd -f openocd.stm32f0.cfg >> $@.log & + arm-none-eabi-gdb --quiet --batch-silent \ + $^ \ + -ex 'target remote :3333' \ + -ex 'monitor reset halt' \ + -ex 'load' \ + -ex 'monitor arm semihosting enable' \ + -ex 'monitor reset run' \ + -ex 'monitor wait_halt 720000' \ + -ex 'monitor shutdown' + +run.%.stm32f1: %.stm32f1.elf + arm-none-eabi-readelf -l $^ > $@.log + echo '-----' >> $@.log + openocd -f openocd.stm32f1.cfg >> $@.log & + arm-none-eabi-gdb --quiet --batch-silent \ + $^ \ + -ex 'target remote :3333' \ + -ex 'monitor reset halt' \ + -ex 'load' \ + -ex 'monitor arm semihosting enable' \ + -ex 'monitor reset run' \ + -ex 'monitor wait_halt 720000' \ + -ex 'monitor shutdown' + +run.%.stm32f3: %.stm32f3.elf + arm-none-eabi-readelf -l $^ > $@.log + echo '-----' >> $@.log + openocd -f openocd.stm32f3.cfg >> $@.log & + arm-none-eabi-gdb --quiet --batch-silent \ + $^ \ + -ex 'target remote :3333' \ + -ex 'monitor reset halt' \ + -ex 'load' \ + -ex 'monitor arm semihosting enable' \ + -ex 'monitor reset run' \ + -ex 'monitor wait_halt 720000' \ + -ex 'monitor shutdown' + +test: $(patsubst %,run.%.qemucm3,$(FUNCS) $(TESTS)) +.PHONY: test + +perf.stm32f0: $(patsubst %,run.%.stm32f0,$(FUNCS)) +.PHONY: perf.stm32f0 + +test.stm32f0: $(patsubst %,run.%.stm32f0,$(FUNCS) $(TESTS)) +.PHONY: test.stm32f0 + +test.stm32f1: $(patsubst %,run.%.stm32f1,$(FUNCS) $(TESTS)) +.PHONY: test.stm32f1 + +test.stm32f3: $(patsubst %,run.%.stm32f3,$(FUNCS) $(TESTS)) +.PHONY: test.stm32f3 + +clean: + rm -rf *.log *.elf *.bin diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/analyse.py b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/analyse.py new file mode 100644 index 0000000..d2c456f --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/analyse.py @@ -0,0 +1,207 @@ +import subprocess +import sys +import re + +function_intro_re = re.compile(r'^(?P<addr>[0-9a-fA-F]{8}) <(?P<name>[a-zA-Z0-9\._]+)>:$') +insn_re = re.compile(r'^\s+(?P<addr>[0-9a-fA-F]+):\s+(?P<insn>[0-9a-fA-F ]+)\s+\t(?P<op>.*)$') + +class Instruction: + def __init__(self, addr, insn, op): + self.addr = long(addr, 16) + self.insn = insn + + args = op.split('\t', 1) + + self.op = args[0].strip() + if len(args) == 2: + comment = args[1].strip().split(';', 1) + else: + comment = args + + self.args = comment[0].strip() + + if len(comment) == 2: + self.comment = comment[1].strip() + else: + self.comment = '' + + def __repr__(self): + return '<insn %r>' % (self.__dict__) + + +def literal_branch_target(t): + return ' <' in t + +class Function: + def __init__(self, addr, name): + self.name = name + self.addr = long(addr, 16) + self.insns = [] + self.calls = [] + + def __repr__(self): + return '<%s %d instructions>' % (self.name, len(self.insns)) + + def add_insn(self, insn): + self.insns.append(Instruction(**insn)) + + def contains_addr(self, addr): + if self.insns: + return addr >= self.addr and addr <= self.insns[-1].addr + else: + return addr == self.addr + + def dump(self): + print self.name + ':' + for insn in self.insns: + print ' ', '%04x' % insn.addr + ':', insn.op, insn.args, '\t;', insn.comment + + def get_literal_word(self, addr): + for insn in self.insns: + if insn.addr == addr and insn.op == '.word': + w = int(insn.args, 16) + if w & 0x80000000: + w = -(w ^ 0xffffffff) + 1 + return w + return None + + def analyse(self, prog): + self.stack_guess = None + regs = {} + + for insn in self.insns: + # stack adjustment with literal + if insn.op == 'sub' and insn.args.startswith('sp, ') and self.stack_guess is None: + sz = int(insn.args.split('#', 1)[1]) + self.stack_guess = sz + + # literal pool loads + if insn.op == 'ldr' and ', [pc, #' in insn.args: + reg, offset = insn.args.split(', [pc, #') + offset = int(offset.replace(']', '')) + word = self.get_literal_word(insn.addr + offset + 2) + if word is not None: + regs[reg] = word + + if insn.op == 'add' and insn.args.startswith('sp, r') and self.stack_guess is None: + reg = insn.args.split(', ')[1] + if reg in regs: + self.stack_guess = regs[reg] + + # static branches + if insn.op[0] == 'b' and literal_branch_target(insn.args): + target = long(insn.args.split(' <', 1)[0], 16) + + targetf = prog.function_at_addr(target) + + if targetf and targetf != self: + self.calls.append(targetf) + + if self.stack_guess is None: + self.stack_guess = 0 + + def stack_usage(self, hints, warns, prog, depth = 0): + hinted_calls = [] + if self.stack_guess: + print ' ' * depth, 'stack:', self.name, self.stack_guess, 'bytes' + + our_hints = [h for h in hints if h and h[0] == self.name] + if our_hints: + hints = [h[1:] for h in our_hints] + hinted_calls = [prog.function_by_name(h[0]) for h in hints if h] + else: + if self.name in warns: + print ' WARN: no calls hints for fn-ptr caller', self.name + + if self.calls + hinted_calls: + call_usage = max([f.stack_usage(hints, warns, prog, depth + 1) for f in self.calls + hinted_calls]) + else: + call_usage = 0 + return self.stack_guess + call_usage + +class Program: + def __init__(self): + self.functions = [] + + # sequence of tuples naming a call sequence known to occur + # this allows working out calls through pointers + self.call_hints = [] + + # function names to warn on if we don't have callees + self.call_warns = set() + + def read_elf(self, elf): + current_fn = None + + for x in subprocess.Popen(['arm-none-eabi-objdump', '-d', elf], + stdout = subprocess.PIPE).stdout: + x = x.rstrip('\n') + m = function_intro_re.match(x) + if m: + fn = Function(**m.groupdict()) + current_fn = fn + self.functions.append(fn) + + m = insn_re.match(x) + if m: + assert current_fn + current_fn.add_insn(m.groupdict()) + + def analyse(self): + for f in self.functions: + f.analyse(self) + + def function_by_name(self, name): + fns = [fn for fn in self.functions if fn.name == name] + if len(fns) == 0: + return None + elif len(fns) == 1: + return fns[0] + else: + print 'warn: more than one function named', name + return None + + def function_at_addr(self, addr): + for f in self.functions: + if f.addr == addr: + return f + return None + + def add_call_hint(self, *seq): + self.call_hints.append(seq) + + def add_call_warn(self, fn): + self.call_warns.add(fn) + + def measure_stack(self, name): + fn = self.function_by_name(name) + if fn is None: + return 0 + + return fn.stack_usage(self.call_hints, self.call_warns, self) + +_, exe, fn = sys.argv + +p = Program() +p.read_elf(exe) + +p.analyse() + +# calls which indirect through fn ptrs +p.add_call_warn('cf_blockwise_accumulate') +p.add_call_warn('cf_blockwise_accumulate_final') + +# hints to resolve those +p.add_call_hint('cf_sha224_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'sha256_update_block') +p.add_call_hint('cf_sha256_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'sha256_update_block') +p.add_call_hint('cf_sha384_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'sha512_update_block') +p.add_call_hint('cf_sha512_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'sha512_update_block') +p.add_call_hint('cf_norx32_encrypt', 'input', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'input_block') +p.add_call_hint('cf_norx32_decrypt', 'input', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'input_block') +p.add_call_hint('cf_cbcmac_stream_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'cbcmac_process') +p.add_call_hint('cf_cmac_stream_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'cmac_process_final_pad') +p.add_call_hint('cf_cmac_stream_update', 'cf_blockwise_accumulate_final', 'cmac_process') +p.add_call_hint('cf_cmac_stream_update', 'cf_blockwise_accumulate_final', 'cmac_process_final_nopad') + + +print 'stack', fn, '=', p.measure_stack(fn) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/boot.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/boot.c new file mode 100644 index 0000000..d2a8e40 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/boot.c @@ -0,0 +1,144 @@ +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +extern int main(void); + +/* --- Defined by link script --- */ +extern uint32_t __etext; /* End of text/start of data. */ +extern uint32_t __data_start__, __data_end__; /* Data addresses in RAM */ +extern uint32_t __bss_start__, __bss_end__; /* BSS addresses in RAM */ +extern uint32_t __StackTop; /* End of stack in RAM */ + +#define ATTR_SECTION(sec) __attribute__ ((section (sec))) + +/* --- Interrupt vector table. --- */ +void Reset_Handler(void); +void SysTick_Handler(void); +void infinite_loop(void); +void do_nothing(void); + +typedef void (*vector_fn)(void); + +typedef struct { + uint32_t *stack_top; + vector_fn reset, nmi, hard_fault, mmu_fault, bus_fault, usage_fault; + vector_fn reserved0[4]; + vector_fn svc, debug_monitor; + vector_fn reserved1; + vector_fn pendsv, systick; + vector_fn irq[128]; +} vectors_t; + +#define COPY2(v) v, v +#define COPY4(v) COPY2(v), COPY2(v) +#define COPY8(v) COPY4(v), COPY4(v) +#define COPY16(v) COPY8(v), COPY8(v) +#define COPY32(v) COPY16(v), COPY16(v) +#define COPY64(v) COPY32(v), COPY32(v) +#define COPY128(v) COPY64(v), COPY64(v) + +vectors_t vectors ATTR_SECTION(".isr_vector") = { + .stack_top = &__StackTop, + .reset = Reset_Handler, + .nmi = do_nothing, + .hard_fault = infinite_loop, + .mmu_fault = infinite_loop, + .bus_fault = infinite_loop, + .usage_fault = infinite_loop, + .svc = do_nothing, + .debug_monitor = do_nothing, + .pendsv = do_nothing, + .systick = SysTick_Handler, + .irq = { COPY128(do_nothing) } +}; + +/* --- ISRs --- */ +void Reset_Handler(void) +{ + /* Copy data segment contents from flash to RAM. */ + uint32_t data_bytes = (&__data_end__ - &__data_start__) * 4; + memcpy(&__etext, &__data_start__, data_bytes); + + /* Zero BSS. */ + uint32_t bss_bytes = (&__bss_end__ - &__bss_start__) * 4; + memset(&__bss_start__, 0, bss_bytes); + + main(); + while (1) + ; +} + +void __assert_func(const char *file, int line, const char *func, const char *expr) +{ + while (1) + ; +} + +void infinite_loop(void) +{ + while (1) + ; +} + +void do_nothing(void) +{ +} + +uint32_t ticks = 0; + +void SysTick_Handler(void) +{ + ticks++; +} + +uint32_t get_ticks(void) +{ + return ticks; +} + +void reset_ticks(void) +{ + ticks = 0; +} + +void *memmove(void *vtarg, const void *vsrc, size_t len) +{ + if (vsrc > vtarg) + return memcpy(vtarg, vsrc, len); + else if (vsrc == vtarg) + return vtarg; + + uint8_t *targ = vtarg; + const uint8_t *src = vsrc; + + for (size_t i = len; i != 0; i++) + targ[i - 1] = src[i - 1]; + return vtarg; +} + +int memcmp(const void *va, const void *vb, size_t len) +{ + const uint8_t *a = va, *b = vb; + + for (size_t i = 0; i < len; i++) + { + if (a[i] != b[i]) + return a[i] < b[i] ? -1 : 1; + } + + return 0; +} + +size_t strlen(const char *c) +{ + size_t r = 0; + while (*c++) r++; + return r; +} + +void abort(void) +{ + while (1) + ; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/curve25519-results.txt b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/curve25519-results.txt new file mode 100644 index 0000000..968e40e --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/curve25519-results.txt @@ -0,0 +1,22 @@ +STM32F0 +donna-before-opt: 12907000c +donna-after-opt: 17294000c +donna-reset-opt: 12947000c +~20k + +donna -O2 -Os: 15268000c +donna -O2 -Os noasm: 20453000c +donna -Os: 15748000c +7.4k + +donna -O3: 12907000c 16KB 3380b +donna -Os: 15748000c 7.4KB 3148b +donna -O2: 15218000c 7.9KB 3148b + +tweetnacl -O2: 68876000c 3.0KB 2268b +tweetnacl -Os: 75979000c 2.8KB 2244b +tweetnacl -O3: 69622000c 8.9KB 2900b + +naclref -Os: 47813000c 3.2KB 4012b +naclref -O3: 35059000c 4.1KB 4044b +naclref -O2: 34309000c 3.5KB 4036b diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/ext/cutest.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/ext/cutest.h new file mode 100644 index 0000000..fa3c5d8 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/ext/cutest.h @@ -0,0 +1,55 @@ +/* cutest, for embedded targets. */ + +#ifndef CUTEST_H +#define CUTEST_H + +/* Main interface. */ +#define TEST_LIST const struct test__ test_list__[] +#define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, #cond) +/* no TEST_CHECK_ -- we don't have a good enough printf */ + +/* Implementation */ +#include "../semihost.h" + +struct test__ +{ + const char *name; + void (*func)(void); +}; + +extern const struct test__ test_list__[]; + +static void test_check__(int cond, const char *file, int line, const char *expr) +{ + if (cond) + return; /* pass */ + + emit("Failed!\n"); + emit("File: "); emit(file); emit("\n"); + emit("Line: "); emit_uint32(line); emit("\n"); + emit("Expr: "); emit(expr); emit("\n"); + quit_failure(); +} + +static void run_test__(const struct test__ *t) +{ + emit(" "); emit(t->name); emit(": "); + t->func(); + emit("OK\n"); +} + +int main(void) +{ + emit("Running tests:\n"); + + for (const struct test__ *t = test_list__; + t->name; + t++) + { + run_test__(t); + } + emit("Success\n"); + quit_success(); +} + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.efm32.ld b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.efm32.ld new file mode 100644 index 0000000..8b9a6bf --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.efm32.ld @@ -0,0 +1,8 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 8K +} + +INCLUDE linkscript.std.ld + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.lm3s6965evb.ld b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.lm3s6965evb.ld new file mode 100644 index 0000000..14fdac4 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.lm3s6965evb.ld @@ -0,0 +1,7 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K +} + +INCLUDE linkscript.std.ld diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.qemucm3.ld b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.qemucm3.ld new file mode 100644 index 0000000..2826467 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.qemucm3.ld @@ -0,0 +1,8 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +INCLUDE linkscript.std.ld + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.std.ld b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.std.ld new file mode 100644 index 0000000..c08d7be --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.std.ld @@ -0,0 +1,172 @@ + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + __copy_table_end__ = .; + } > FLASH + + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + __zero_table_end__ = .; + } > FLASH + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f0.ld b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f0.ld new file mode 100644 index 0000000..c7a3bd8 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f0.ld @@ -0,0 +1,8 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE linkscript.std.ld + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f1.ld b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f1.ld new file mode 100644 index 0000000..d13f58d --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f1.ld @@ -0,0 +1,8 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 8K +} + +INCLUDE linkscript.std.ld + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f3.ld b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f3.ld new file mode 100644 index 0000000..92eee46 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f3.ld @@ -0,0 +1,8 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 12K +} + +INCLUDE linkscript.std.ld + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/main.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/main.c new file mode 100644 index 0000000..5b7cbf2 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/main.c @@ -0,0 +1,447 @@ +#ifndef TEST +# error You must select a function to test. +#endif + +#include "semihost.h" +#include "aes.h" +#include "hmac.h" +#include "sha2.h" +#include "sha3.h" +#include "modes.h" +#include "salsa20.h" +#include "curve25519.h" +#include "poly1305.h" +#include "norx.h" +#include "chacha20poly1305.h" + +#include <stdio.h> + +typedef void (*measure_fn)(void); +static uint32_t bracket; /* bracket mode parameter */ + +static void do_nothing(void) +{ +} + +static void stack_64w(void) +{ + volatile uint32_t words[64]; + words[0] = 0; + words[63] = 0; + (void) words[63]; +} + +static void stack_8w(void) +{ + volatile uint32_t words[8]; + words[0] = 0; + words[7] = 0; + (void) words[7]; +} + +static void hashtest_sha256(void) +{ + uint8_t hash[CF_SHA256_HASHSZ]; + cf_sha256_context ctx; + cf_sha256_init(&ctx); + cf_sha256_update(&ctx, "", 0); + cf_sha256_digest_final(&ctx, hash); +} + +static void hashtest_sha512(void) +{ + uint8_t hash[CF_SHA512_HASHSZ]; + cf_sha512_context ctx; + cf_sha512_init(&ctx); + cf_sha512_update(&ctx, "", 0); + cf_sha512_digest_final(&ctx, hash); +} + +static void hashtest_sha3_256(void) +{ + uint8_t hash[CF_SHA3_256_HASHSZ]; + cf_sha3_context ctx; + cf_sha3_256_init(&ctx); + cf_sha3_256_update(&ctx, "", 0); + cf_sha3_256_digest_final(&ctx, hash); +} + +static void hashtest_sha3_512(void) +{ + uint8_t hash[CF_SHA3_512_HASHSZ]; + cf_sha3_context ctx; + cf_sha3_512_init(&ctx); + cf_sha3_512_update(&ctx, "", 0); + cf_sha3_512_digest_final(&ctx, hash); +} + +static void aes128block_test(void) +{ + uint8_t key[16] = { 0 }, block[16] = { 0 }; + cf_aes_context ctx; + cf_aes_init(&ctx, key, sizeof key); + cf_aes_encrypt(&ctx, block, block); +} + +static void aes128sched_test(void) +{ + uint8_t key[16] = { 0 }; + cf_aes_context ctx; + cf_aes_init(&ctx, key, sizeof key); +} + +static void aes256block_test(void) +{ + uint8_t key[32] = { 0 }, block[16] = { 0 }; + cf_aes_context ctx; + cf_aes_init(&ctx, key, sizeof key); + cf_aes_encrypt(&ctx, block, block); +} + +static void aes256sched_test(void) +{ + uint8_t key[32] = { 0 }; + cf_aes_context ctx; + cf_aes_init(&ctx, key, sizeof key); +} + +static void aes128gcm_test(void) +{ + uint8_t key[16] = { 0 }; + cf_aes_context ctx; + cf_aes_init(&ctx, key, sizeof key); + + uint8_t msg[16] = { 0 }; + uint8_t aad[16] = { 0 }; + uint8_t nonce[12] = { 0 }; + uint8_t cipher[16] = { 0 }; + uint8_t tag[16] = { 0 }; + + cf_gcm_encrypt(&cf_aes, &ctx, + msg, sizeof msg, + aad, sizeof aad, + nonce, sizeof nonce, + cipher, + tag, sizeof tag); +} + +static void aes128eax_test(void) +{ + uint8_t key[16] = { 0 }; + cf_aes_context ctx; + cf_aes_init(&ctx, key, sizeof key); + + uint8_t msg[16] = { 0 }; + uint8_t aad[16] = { 0 }; + uint8_t nonce[12] = { 0 }; + uint8_t cipher[16] = { 0 }; + uint8_t tag[16] = { 0 }; + + cf_eax_encrypt(&cf_aes, &ctx, + msg, sizeof msg, + aad, sizeof aad, + nonce, sizeof nonce, + cipher, + tag, sizeof tag); +} + +static void aes128ccm_test(void) +{ + uint8_t key[16] = { 0 }; + cf_aes_context ctx; + cf_aes_init(&ctx, key, sizeof key); + + uint8_t msg[16] = { 0 }; + uint8_t aad[16] = { 0 }; + uint8_t nonce[11] = { 0 }; + uint8_t cipher[16] = { 0 }; + uint8_t tag[16] = { 0 }; + + cf_ccm_encrypt(&cf_aes, &ctx, + msg, sizeof msg, 4, + aad, sizeof aad, + nonce, sizeof nonce, + cipher, + tag, sizeof tag); +} + +static void salsa20_test(void) +{ + uint8_t key[32] = { 0 }; + uint8_t nonce[8] = { 0 }; + uint8_t msg[64] = { 0 }; + uint8_t cipher[64] = { 0 }; + + cf_salsa20_ctx ctx; + cf_salsa20_init(&ctx, key, sizeof key, nonce); + cf_salsa20_cipher(&ctx, msg, cipher, sizeof msg); +} + +static void chacha20_test(void) +{ + uint8_t key[32] = { 0 }; + uint8_t nonce[8] = { 0 }; + uint8_t msg[64] = { 0 }; + uint8_t cipher[64] = { 0 }; + + cf_chacha20_ctx ctx; + cf_chacha20_init(&ctx, key, sizeof key, nonce); + cf_chacha20_cipher(&ctx, msg, cipher, sizeof msg); +} + +static void curve25519_test(void) +{ + uint8_t secret[32] = { 1 }; + uint8_t pubkey[32]; + cf_curve25519_mul_base(pubkey, secret); +} + +static const uint8_t *mac_message = (const uint8_t *) "hello world"; +static const size_t mac_message_len = 11; + +static void poly1305_test(void) +{ + uint8_t key[32] = { 0 }, + nonce[16] = { 0 }, + encnonce[16], + mac[16]; + + cf_aes_context aes; + cf_aes_init(&aes, key, 16); + cf_aes_encrypt(&aes, nonce, encnonce); + + cf_poly1305 poly; + cf_poly1305_init(&poly, key + 16, encnonce); + cf_poly1305_update(&poly, mac_message, mac_message_len); + cf_poly1305_finish(&poly, mac); +} + +static void hmacsha256_test(void) +{ + uint8_t key[32] = { 0 }, + mac[32] = { 0 }; + + cf_hmac_ctx ctx; + cf_hmac_init(&ctx, &cf_sha256, key, sizeof key); + cf_hmac_update(&ctx, mac_message, mac_message_len); + cf_hmac_finish(&ctx, mac); +} + +static void norx_test(void) +{ + uint8_t key[16] = { 0 }; + uint8_t msg[16] = { 0 }; + uint8_t aad[16] = { 0 }; + uint8_t nonce[8] = { 0 }; + uint8_t cipher[16] = { 0 }; + uint8_t tag[16] = { 0 }; + + cf_norx32_encrypt(key, + nonce, + aad, sizeof aad, + msg, sizeof msg, + NULL, 0, + cipher, + tag); +} + +#ifndef BRACKET_MODE +# define AEADPERF_LEN 1 +#else +# define AEADPERF_LEN BRACKET_END +#endif + +static uint8_t aead_msg[AEADPERF_LEN] = { 0 }; +static uint8_t aead_cipher[AEADPERF_LEN] = { 0 }; +static uint8_t aead_aad[16] = { 0 }; +static uint8_t aead_key[32] = { 0 }; +static uint8_t aead_nonce[16] = { 0 }; +static uint8_t aead_tag[16] = { 0 }; + +static void aeadperf_norx(void) +{ + cf_norx32_encrypt(aead_key, aead_nonce, + aead_aad, sizeof aead_aad, + aead_msg, bracket, + NULL, 0, + aead_cipher, aead_tag); +} + +static void aeadperf_chacha20poly1305(void) +{ + cf_chacha20poly1305_encrypt(aead_key, aead_nonce, + aead_aad, sizeof aead_aad, + aead_msg, bracket, + aead_cipher, aead_tag); +} +static void aeadperf_aes128gcm(void) +{ + cf_aes_context ctx; + cf_aes_init(&ctx, aead_key, 16); + + cf_gcm_encrypt(&cf_aes, &ctx, + aead_msg, bracket, + aead_aad, sizeof aead_aad, + aead_nonce, 12, + aead_cipher, + aead_tag, 16); +} + +static void aeadperf_aes128ccm(void) +{ + cf_aes_context ctx; + cf_aes_init(&ctx, aead_key, 16); + + cf_ccm_encrypt(&cf_aes, &ctx, + aead_msg, bracket, + 4, + aead_aad, sizeof aead_aad, + aead_nonce, 11, + aead_cipher, + aead_tag, 16); +} + +static void aeadperf_aes128eax(void) +{ + cf_aes_context ctx; + cf_aes_init(&ctx, aead_key, 16); + + cf_eax_encrypt(&cf_aes, &ctx, + aead_msg, bracket, + aead_aad, sizeof aead_aad, + aead_nonce, 12, + aead_cipher, + aead_tag, 16); +} + +static void aeadperf_aes256gcm(void) +{ + cf_aes_context ctx; + cf_aes_init(&ctx, aead_key, 32); + + cf_gcm_encrypt(&cf_aes, &ctx, + aead_msg, bracket, + aead_aad, sizeof aead_aad, + aead_nonce, 12, + aead_cipher, + aead_tag, 16); +} + +static void aeadperf_aes256ccm(void) +{ + cf_aes_context ctx; + cf_aes_init(&ctx, aead_key, 32); + + cf_ccm_encrypt(&cf_aes, &ctx, + aead_msg, bracket, + 4, + aead_aad, sizeof aead_aad, + aead_nonce, 11, + aead_cipher, + aead_tag, 16); +} + +static void aeadperf_aes256eax(void) +{ + cf_aes_context ctx; + cf_aes_init(&ctx, aead_key, 32); + + cf_eax_encrypt(&cf_aes, &ctx, + aead_msg, bracket, + aead_aad, sizeof aead_aad, + aead_nonce, 12, + aead_cipher, + aead_tag, 16); +} + +/* Provided by linkscript */ +extern uint32_t __HeapLimit; + +#define STACK_MAGIC 0x57ac34df + +static __attribute__((noinline)) void clear_stack(void) +{ + uint32_t *stack_start = &__HeapLimit; + uint32_t ss = 0, *stack_stop = &ss; + size_t words = stack_stop - stack_start; + for (size_t i = 0; i < words; i++) + stack_start[i] = STACK_MAGIC; +} + +static __attribute__((noinline)) uint32_t measure_stack(void) +{ + uint32_t *stack_start = &__HeapLimit; + uint32_t ss, *stack_stop = &ss; + size_t words = stack_stop - stack_start; + for (size_t i = 0; i < words; i++) + if (stack_start[i] != STACK_MAGIC) + return words - i + 4; /* we used 4 words for ourselves, roughly */ + + return 0; +} + +static void measure(measure_fn fn) +{ + clear_stack(); + uint32_t start_cycles = reset_cycles(); + fn(); + uint32_t end_cycles = get_cycles(); + uint32_t stack_words = measure_stack(); + + emit("cycles = "); + emit_uint32(end_cycles - start_cycles); + emit("\n"); + emit("stack = "); + emit_uint32(stack_words << 2); + emit("\n"); +} + +#define STRING_(x) #x +#define STRING(x) STRING_(x) + +int main(void) +{ + emit(STRING(TEST) "\n"); +#ifdef BRACKET_MODE + for (bracket = BRACKET_START; bracket <= BRACKET_END; bracket += BRACKET_STEP) + { + emit("bracket = "); + emit_uint32(bracket); + emit("\n"); + measure(TEST); + } +#else + measure(TEST); +#endif + quit_success(); + + (void) bracket; + (void) do_nothing; + (void) stack_8w; + (void) stack_64w; + (void) hashtest_sha256; + (void) hashtest_sha512; + (void) hashtest_sha3_256; + (void) hashtest_sha3_512; + (void) aes128block_test; + (void) aes128sched_test; + (void) aes256block_test; + (void) aes256sched_test; + (void) aes128gcm_test; + (void) aes128eax_test; + (void) aes128ccm_test; + (void) salsa20_test; + (void) chacha20_test; + (void) curve25519_test; + (void) poly1305_test; + (void) hmacsha256_test; + (void) norx_test; + (void) aeadperf_norx; + (void) aeadperf_chacha20poly1305; + (void) aeadperf_aes128gcm; + (void) aeadperf_aes128ccm; + (void) aeadperf_aes128eax; + (void) aeadperf_aes256gcm; + (void) aeadperf_aes256ccm; + (void) aeadperf_aes256eax; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/memcpy.s b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/memcpy.s new file mode 100644 index 0000000..63406fe --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/memcpy.s @@ -0,0 +1,49 @@ + .text + .syntax unified + .global memcpy + .func memcpy + .thumb_func + +memcpy: + /* on entry + * r0 = targ + * r1 = src + * r2 = len (bytes) + * on exit + * r0 = targ (unchanged) + */ + push {r0, r4, lr} + + /* If targ or src are unaligned, drop to byte + * processing. */ + mov r3, r0 + movs r4, #3 + orrs r3, r1 + ands r3, r4 + bne L_bytewise + + /* Process words */ +L_wordwise: + cmp r2, #4 + blo L_bytewise + ldr r4, [r1] + adds r1, #4 + str r4, [r0] + adds r0, #4 + subs r2, #4 + b L_wordwise + + /* Process bytes */ +L_bytewise: + cmp r2, #0 + beq L_fin + ldrb r4, [r1] + adds r1, #1 + strb r4, [r0] + adds r0, #1 + subs r2, #1 + b L_bytewise + +L_fin: + pop {r0, r4, pc} + .endfunc diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/memset.s b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/memset.s new file mode 100644 index 0000000..a501966 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/memset.s @@ -0,0 +1,50 @@ + .text + .syntax unified + .global memset + .func memset + .thumb_func + +memset: + /* on entry + * r0 = targ + * r1 = value + * r2 = len (bytes) + * on exit + * r0 = targ (unchanged) + */ + push {r0, r4, lr} + + /* If targ is unaligned, drop to byte + * processing. */ + movs r3, #3 + ands r3, r0 + bne L_bytewise + + /* Process words */ + /* Build r4 by repeating r1. */ + uxtb r4, r1 + lsls r3, r4, #8 + orrs r4, r3 + lsls r3, r4, #16 + orrs r4, r3 + +L_wordwise: + cmp r2, #4 + blo L_bytewise + str r4, [r0] + adds r0, #4 + subs r2, #4 + b L_wordwise + + /* Process bytes */ +L_bytewise: + cmp r2, #0 + beq L_fin + strb r1, [r0] + adds r0, #1 + subs r2, #1 + b L_bytewise + +L_fin: + pop {r0, r4, pc} + .endfunc diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/merge.py b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/merge.py new file mode 100644 index 0000000..71d5089 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/merge.py @@ -0,0 +1,26 @@ +import sys + +def extract_results(results): + index = 0 + while index < len(results): + if results[index].startswith('## '): + end = results.index('\n', index) + yield results[index:end] + index += 1 + +def merge(readme, res): + title, table = res[0], res[1:] + assert title in readme, 'Section ' + title + ' missing from README.md' + secindex = readme.index(title) + hdrindex = [i for i in range(secindex, len(readme)) if readme[i].startswith('---------- | ')][0] + start = hdrindex - 1 + end = readme.index('\n', start) + table = [t.rstrip() + '\n' for t in table] + return readme[:start] + table + readme[end:] + +results = sys.stdin.readlines() +readme = open('../../README.md').readlines() + +for res in extract_results(results): + readme = merge(readme, res) +print ''.join(readme).rstrip() diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.efm32.cfg b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.efm32.cfg new file mode 100644 index 0000000..85af473 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.efm32.cfg @@ -0,0 +1,3 @@ +source [find interface/jlink.cfg] +transport select swd +source [find target/efm32.cfg] diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f0.cfg b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f0.cfg new file mode 100644 index 0000000..e9356f7 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f0.cfg @@ -0,0 +1,3 @@ +source [find interface/stlink-v2.cfg] +transport select hla_swd +source [find target/stm32f0x.cfg] diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f1.cfg b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f1.cfg new file mode 100644 index 0000000..1108ea0 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f1.cfg @@ -0,0 +1,3 @@ +source [find interface/stlink-v2.cfg] +transport select hla_swd +source [find target/stm32f1x.cfg] diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f3.cfg b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f3.cfg new file mode 100644 index 0000000..de023b8 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f3.cfg @@ -0,0 +1,3 @@ +source [find interface/stlink-v2.cfg] +transport select hla_swd +source [find target/stm32f3x.cfg] diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/report.py b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/report.py new file mode 100644 index 0000000..718ab24 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/report.py @@ -0,0 +1,276 @@ +""" +Interprets logs from test runs. Outputs ASCII +tables containing results, json data, etc. +""" + +import json +import sys + +archs = 'stm32f0 stm32f1 stm32f3'.split() +tests = """ +aes128block_test +aes256block_test +aes128sched_test +aes256sched_test +hashtest_sha256 +hashtest_sha512 +hashtest_sha3_256 +hashtest_sha3_512 +aes128gcm_test +aes128eax_test +aes128ccm_test +norx_test +salsa20_test +chacha20_test +poly1305_test +hmacsha256_test +curve25519_test +aeadperf_norx +aeadperf_aes128gcm +aeadperf_aes128eax +aeadperf_aes128ccm +aeadperf_aes256gcm +aeadperf_aes256eax +aeadperf_aes256ccm +aeadperf_chacha20poly1305 +do_nothing +""".split() + +arch_names = dict( + stm32f0 = 'Cortex-M0', + stm32f1 = 'Cortex-M3', + stm32f3 = 'Cortex-M4F' + ) + +base_test = 'do_nothing' + +def extract(arch, test): + fn = 'run.%s.%s.log' % (test, arch) + + code_size = 0 + data_size = 0 + cycle_count = None + stack_usage = None + brackets = None + current_bracket = None + + try: + lines = open(fn).readlines() + except IOError: + return None + + for l in lines: + if 'LOAD' in l: + parts = l.split() + assert len(parts) >= 8 + assert 'LOAD' == parts[0] + if parts[6] == 'RWE': + code_size += long(parts[5], 16) + if parts[6] == 'RW': + data_size += long(parts[5], 16) + + if l.startswith('bracket = '): + bracket = long(l.split(' = ')[1].strip(), 16) + current_bracket = bracket + if brackets is None: + brackets = {} + brackets[current_bracket] = dict() + + if l.startswith('cycles = '): + cycle_count = long(l.split(' = ')[1].strip(), 16) + if current_bracket is not None: + brackets[current_bracket]['cycle_count'] = cycle_count + + if l.startswith('stack = '): + stack_usage = long(l.split(' = ')[1].strip(), 16) + if current_bracket is not None: + brackets[current_bracket]['stack_usage'] = stack_usage + + return dict( + code_size = code_size, + data_size = data_size, + cycle_count = cycle_count, + stack_usage = stack_usage, + brackets = brackets + ) + +def print_table(rows): + header, rows = rows[0], rows[1:] + assert not [True for r in rows if len(r) != len(header)] + widths = [] + for i, h in enumerate(header): + widths.append(max([len(h)] + [len(r[i]) for r in rows])) + + def print_row(row): + print ' | '.join(c + (' ' * (widths[i] - len(c))) for i, c in enumerate(row)) + + print_row(header) + print_row(['-' * w for w in widths]) + for r in rows: + print_row(r) + +results = {} + +for arch in archs: + for test in tests: + inf = extract(arch, test) + if inf: + results.setdefault(arch, {})[test] = inf + +for arch in results.keys(): + if base_test not in results[arch]: + print 'need', base_test, 'results to report for', arch + continue + + base_result = results[arch][base_test] + + for test in results[arch].keys(): + if test == base_test: + continue + + results[arch][test]['code_size'] -= base_result['code_size'] + +def tabulate_aes(arch, block_result, sched_result, table = None): + if table is None: + table = [] + table.append(( + 'Core', + 'Cycles (key schedule + block)', + 'Cycles (key schedule)', + 'Cycles (block)', + 'Stack', + 'Code size' + )) + + table.append( + ( + arch_names[arch], + '%d' % block_result['cycle_count'], + '%d' % sched_result['cycle_count'], + '%d' % (block_result['cycle_count'] - sched_result['cycle_count']), + '%dB' % block_result['stack_usage'], + '%dB' % block_result['code_size'] + )) + + return table + +def print_std(result): + print """* **Cycles**: %(cycle_count)d +* **Stack**: %(stack_usage)dB +* **Code size**: %(code_size)dB +""" % result + +def tabulate_std(arch, result, table = None): + if table is None: + table = [] + table.append(('Core', 'Cycles', 'Stack', 'Code size')) + + table.append( + ( + arch_names[arch], + '%d' % result['cycle_count'], + '%dB' % result['stack_usage'], + '%dB' % result['code_size'] + )) + + return table + +def tabulate(mktab): + table = None + for arch in archs: + if arch not in results: + continue + table = mktab(arch, table) + print_table(table) + +def convert_brackets(metric, tests): + for arch in archs: + arch_result = {} + + # collect results for each test + for t in tests: + if arch not in results or t not in results[arch]: + print 'missing', arch, t + continue + data = results[arch][t]['brackets'] + arch_result[t] = [[b, data[b][metric]] for b in sorted(data.keys())] + + # convert into list of [bracket, test-1, test-2, ...] lists + out = [] + if len(arch_result) == 0: + continue + first_row = arch_result.values()[0] + + for i in range(len(first_row)): + row = [ first_row[i][0] ] + + for k in sorted(arch_result.keys()): + if len(arch_result[k]) != len(first_row): + print 'warn:', 'test', k, 'did not complete?' + rr = arch_result[k][i] + row.append(rr[1]) + + out.append(row) + + print json.dumps(out) + +convert_brackets('cycle_count', + [ + 'aeadperf_norx', + 'aeadperf_aes128gcm', + 'aeadperf_aes128eax', + 'aeadperf_aes128ccm', + 'aeadperf_aes256gcm', + 'aeadperf_aes256eax', + 'aeadperf_aes256ccm', + 'aeadperf_chacha20poly1305' + ]) +convert_brackets('stack_usage', + [ + 'aeadperf_norx', + 'aeadperf_aes128gcm', + 'aeadperf_aes128eax', + 'aeadperf_aes128ccm', + 'aeadperf_aes256gcm', + 'aeadperf_aes256eax', + 'aeadperf_aes256ccm', + 'aeadperf_chacha20poly1305' + ]) + +# screwed if we need other block ciphers +print '###', '128-bit key' +tabulate(lambda arch, table: tabulate_aes(arch, results[arch]['aes128block_test'], results[arch]['aes128sched_test'], table)) +print + +print '###', '256-bit key' +tabulate(lambda arch, table: tabulate_aes(arch, results[arch]['aes256block_test'], results[arch]['aes256sched_test'], table)) +print + +def do_table(title, test): + print '##', title + tabulate(lambda arch, table: tabulate_std(arch, results[arch][test], table)) + print + +do_table('AES128-GCM', 'aes128gcm_test') +do_table('AES128-EAX', 'aes128eax_test') +do_table('AES128-CCM', 'aes128ccm_test') +do_table('NORX32', 'norx_test') +do_table('ChaCha20', 'chacha20_test') +do_table('Salsa20', 'salsa20_test') +do_table('SHA256', 'hashtest_sha256') +do_table('SHA512', 'hashtest_sha512') +do_table('SHA3-256', 'hashtest_sha3_256') +do_table('SHA3-512', 'hashtest_sha3_512') +do_table('HMAC-SHA256', 'hmacsha256_test') +do_table('Poly1305-AES', 'poly1305_test') +do_table('Curve25519', 'curve25519_test') + +if '--aead' in sys.argv: + do_table('AEAD-Shootout: NORX', 'aeadperf_norx') + do_table('AEAD-Shootout: AES-128-GCM', 'aeadperf_aes128gcm') + do_table('AEAD-Shootout: AES-128-EAX', 'aeadperf_aes128eax') + do_table('AEAD-Shootout: AES-128-CCM', 'aeadperf_aes128ccm') + do_table('AEAD-Shootout: AES-256-GCM', 'aeadperf_aes256gcm') + do_table('AEAD-Shootout: AES-256-EAX', 'aeadperf_aes256eax') + do_table('AEAD-Shootout: AES-256-CCM', 'aeadperf_aes256ccm') + do_table('AEAD-Shootout: ChaCha20-Poly1305', 'aeadperf_chacha20poly1305') diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.c new file mode 100644 index 0000000..cbe5aa2 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.c @@ -0,0 +1,170 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "semihost.h" + +#define OP_WRITE0 0x04 +#define OP_EXIT 0x18 +#define OP_EXIT_ARG_FAILURE 0x0 +#define OP_EXIT_ARG_SUCCESS 0x20026 + +extern uint32_t semihost(uint32_t, volatile void *); + +__attribute__((noreturn)) +void quit_success(void) +{ + semihost(OP_EXIT, (void *) OP_EXIT_ARG_SUCCESS); + while (1) + ; +} + +__attribute__((noreturn)) +void quit_failure(void) +{ + semihost(OP_EXIT, (void *) OP_EXIT_ARG_FAILURE); + while (1) + ; +} + +void emit(const char *buf) +{ + semihost(OP_WRITE0, (volatile void *) buf); +} + +static void emit_extent(const char *start, const char *end) +{ + char buf[32+1]; + size_t bufmax = sizeof(buf) - 1; + buf[32] = 0; + + size_t bytes = end - start + 1; + + while (bytes >= bufmax) + { + memcpy(buf, start, bufmax); + emit(buf); + bytes -= bufmax; + start += bufmax; + } + + if (bytes == 0) + return; + + memcpy(buf, start, bytes); + buf[bytes] = 0; + emit(buf); +} + +void emitf(const char *fmt, ...) +{ + const char *start = fmt, *end = fmt; + + va_list args; + va_start(args, fmt); + + while (*fmt) + { + switch (*fmt) + { + case '%': + emit_extent(start, end); + + switch (fmt[1]) + { + case '%': + emit("%"); + break; + + case 'u': + emit_uint32(va_arg(args, uint32_t)); + break; + + case 's': + emit(va_arg(args, const char *)); + break; + } + start = end = fmt + 2; + break; + + default: + end = fmt; + break; + } + + fmt++; + } + + va_end(args); + emit_extent(start, end); +} + +static const char *hex_chars = "0123456789abcdef"; + +void emit_hex(const void *ptr, size_t len) +{ + const uint8_t *bb = ptr; + char byte[3]; + + byte[2] = 0; + + for (size_t i = 0; i < len; i++) + { + byte[0] = hex_chars[(bb[i] >> 4) & 0xf]; + byte[1] = hex_chars[bb[i] & 0xf]; + emit(byte); + } +} + +void emit_uint32(uint32_t x) +{ + char buf[sizeof "0x11223344"]; + buf[0] = '0'; + buf[1] = 'x'; + buf[2] = hex_chars[(x >> 28) & 0xf]; + buf[3] = hex_chars[(x >> 24) & 0xf]; + buf[4] = hex_chars[(x >> 20) & 0xf]; + buf[5] = hex_chars[(x >> 16) & 0xf]; + buf[6] = hex_chars[(x >> 12) & 0xf]; + buf[7] = hex_chars[(x >> 8) & 0xf]; + buf[8] = hex_chars[(x >> 4) & 0xf]; + buf[9] = hex_chars[x & 0xf]; + buf[10] = 0; + + emit(buf); +} + +typedef struct +{ + volatile uint32_t ctrl; + volatile uint32_t reload; + volatile uint32_t current; +} systick; + +#define SysTick ((systick *)0xe000e010) + +#define STCTRL_SYSCLOCK 0x04 +#define STCTRL_TICKINT 0x02 +#define STCTRL_ENABLE 0x01 + +#define STCTRL_MAX 0xffffff +#define STCTRL_SHIFT 24 + +extern uint32_t get_ticks(void); +extern void reset_ticks(void); + +uint32_t reset_cycles(void) +{ + SysTick->reload = STCTRL_MAX; + SysTick->ctrl = STCTRL_SYSCLOCK | STCTRL_TICKINT | STCTRL_ENABLE; + SysTick->current = 0; + reset_ticks(); + return get_ticks(); +} + +uint32_t get_cycles(void) +{ + return (get_ticks() << STCTRL_SHIFT) + (STCTRL_MAX - SysTick->current); +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.h new file mode 100644 index 0000000..cf6f01a --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.h @@ -0,0 +1,40 @@ +#ifndef SEMIHOST_H +#define SEMIHOST_H + +#include <stdint.h> +#include <stdlib.h> + +/* Exits emulator with success (or merely hangs). */ +__attribute__((noreturn)) +void quit_success(void); + +/* Exits emulator with failure (or merely hangs). */ +__attribute__((noreturn)) +void quit_failure(void); + +/* Writes zero terminated string to debug output */ +void emit(const char *buf); + +/* Writes a formatting string to debug output. + * + * Supported: + * %u - uint32_t argument, same as emit_uint32 + * %s - const char * argument, same as emit + */ +void emitf(const char *fmt, ...); + +/* Writes hex dump of len bytes at ptr to debug output. */ +void emit_hex(const void *ptr, size_t len); + +/* Writes value v in hex to debug output, in format: + * 0xHHHHHHHH (equivalent to printf 0x%08x). */ +void emit_uint32(uint32_t v); + +/* Reset cycle counter to 0. Returns the current value + * (just after resetting it). */ +uint32_t reset_cycles(void); + +/* Return the value of the cycle counter. */ +uint32_t get_cycles(void); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.s b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.s new file mode 100644 index 0000000..0fddf04 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/semihost.s @@ -0,0 +1,15 @@ + .text + .syntax unified + .global semihost + .func semihost + .thumb_func + +semihost: + /* on entry + * r0 = op + * r1 = arg */ + push {r7, lr} + bkpt 0xab + pop {r7, pc} + + .endfunc diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_mpy121666.s b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_mpy121666.s new file mode 100644 index 0000000..49e3b5d --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_mpy121666.s @@ -0,0 +1,199 @@ +// Implementation of multiplication of an fe25519 bit value with the curve constant 121666. +// +// B. Haase, Endress + Hauser Conducta GmbH & Ko. KG +// public domain. +// +// gnu assembler format. +// +// Generated and tested with C++ functions in the test subdirectory. +// +// ATTENTION: +// Not yet tested on target hardware. + + + .cpu cortex-m0 + .fpu softvfp + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 1 + .eabi_attribute 30, 2 + .eabi_attribute 34, 0 + .eabi_attribute 18, 4 + .code 16 + + .file "cortex_m0_reduce25519.s" + + .text + .align 2 + + .global fe25519_mpyWith121666_asm + .code 16 + .thumb_func + .type fe25519_mpyWith121666_asm, %function + +fe25519_mpyWith121666_asm: + push {r4,r5,r6,r7,r14} + ldr r7,__label_for_immediate_56130 + ldr r2,[r1,#28] + lsl r5,r2,#16 + lsr r6,r2,#16 + lsr r3,r2,#16 + uxth r2,r2 + mul r2,r7 + mul r3,r7 + add r5,r2 + mov r2,#0 + adc r6,r2 + lsl r2,r3,#16 + lsr r3,r3,#16 + add r5,r2 + adc r6,r3 + lsl r2,r5,#1 + lsr r2,r2,#1 + str r2,[r0,#28] + lsr r5,r5,#31 + lsl r6,r6,#1 + orr r5,r6 + mov r6,#19 + mul r5,r6 + mov r6,#0 + ldr r2,[r1,#0] + lsl r3,r2,#16 + lsr r4,r2,#16 + add r5,r3 + adc r6,r4 + lsr r3,r2,#16 + uxth r2,r2 + mul r2,r7 + mul r3,r7 + add r5,r2 + mov r2,#0 + adc r6,r2 + lsl r2,r3,#16 + lsr r3,r3,#16 + add r5,r2 + adc r6,r3 + str r5,[r0,#0] + mov r5,#0 + ldr r2,[r1,#4] + lsl r3,r2,#16 + lsr r4,r2,#16 + add r6,r3 + adc r5,r4 + lsr r3,r2,#16 + uxth r2,r2 + mul r2,r7 + mul r3,r7 + add r6,r2 + mov r2,#0 + adc r5,r2 + lsl r2,r3,#16 + lsr r3,r3,#16 + add r6,r2 + adc r5,r3 + str r6,[r0,#4] + mov r6,#0 + ldr r2,[r1,#8] + lsl r3,r2,#16 + lsr r4,r2,#16 + add r5,r3 + adc r6,r4 + lsr r3,r2,#16 + uxth r2,r2 + mul r2,r7 + mul r3,r7 + add r5,r2 + mov r2,#0 + adc r6,r2 + lsl r2,r3,#16 + lsr r3,r3,#16 + add r5,r2 + adc r6,r3 + str r5,[r0,#8] + mov r5,#0 + ldr r2,[r1,#12] + lsl r3,r2,#16 + lsr r4,r2,#16 + add r6,r3 + adc r5,r4 + lsr r3,r2,#16 + uxth r2,r2 + mul r2,r7 + mul r3,r7 + add r6,r2 + mov r2,#0 + adc r5,r2 + lsl r2,r3,#16 + lsr r3,r3,#16 + add r6,r2 + adc r5,r3 + str r6,[r0,#12] + mov r6,#0 + ldr r2,[r1,#16] + lsl r3,r2,#16 + lsr r4,r2,#16 + add r5,r3 + adc r6,r4 + lsr r3,r2,#16 + uxth r2,r2 + mul r2,r7 + mul r3,r7 + add r5,r2 + mov r2,#0 + adc r6,r2 + lsl r2,r3,#16 + lsr r3,r3,#16 + add r5,r2 + adc r6,r3 + str r5,[r0,#16] + mov r5,#0 + ldr r2,[r1,#20] + lsl r3,r2,#16 + lsr r4,r2,#16 + add r6,r3 + adc r5,r4 + lsr r3,r2,#16 + uxth r2,r2 + mul r2,r7 + mul r3,r7 + add r6,r2 + mov r2,#0 + adc r5,r2 + lsl r2,r3,#16 + lsr r3,r3,#16 + add r6,r2 + adc r5,r3 + str r6,[r0,#20] + mov r6,#0 + ldr r2,[r1,#24] + lsl r3,r2,#16 + lsr r4,r2,#16 + add r5,r3 + adc r6,r4 + lsr r3,r2,#16 + uxth r2,r2 + mul r2,r7 + mul r3,r7 + add r5,r2 + mov r2,#0 + adc r6,r2 + lsl r2,r3,#16 + lsr r3,r3,#16 + add r5,r2 + adc r6,r3 + str r5,[r0,#24] + mov r5,#0 + ldr r2,[r0,#28] + add r6,r2 + str r6,[r0,#28] + pop {r4,r5,r6,r7,r15} + + .align 2 +__label_for_immediate_56130: + .word 56130 + + .size fe25519_mpyWith121666_asm, .-fe25519_mpyWith121666_asm + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_reduce25519.s b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_reduce25519.s new file mode 100644 index 0000000..4c09f5e --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_reduce25519.s @@ -0,0 +1,176 @@ +// Implementation of a partial reduction modulo 2^255 - 38. +// +// B. Haase, Endress + Hauser Conducta GmbH & Ko. KG +// public domain. +// +// gnu assembler format. +// +// Generated and tested with C++ functions in the test subdirectory and on the target. +// + + .cpu cortex-m0 + .fpu softvfp + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 1 + .eabi_attribute 30, 2 + .eabi_attribute 34, 0 + .eabi_attribute 18, 4 + .code 16 + + .file "cortex_m0_reduce25519.s" + + .text + .align 2 + + .global fe25519_reduceTo256Bits_asm + .code 16 + .thumb_func + .type fe25519_reduceTo256Bits_asm, %function + +fe25519_reduceTo256Bits_asm: + push {r4,r5,r6,r7,r14} + ldr r2,[r1,#60] + lsr r3,r2,#16 + uxth r2,r2 + mov r7,#38 + mul r2,r7 + mul r3,r7 + ldr r4,[r1,#28] + lsr r5,r3,#16 + lsl r3,r3,#16 + mov r6,#0 + add r4,r2 + adc r5,r6 + add r4,r3 + adc r5,r6 + lsl r2,r4,#1 + lsr r2,r2,#1 + str r2,[r0,#28] + lsr r4,r4,#31 + lsl r5,r5,#1 + orr r4,r5 + mov r2,#19 + mul r2,r4 + ldr r4,[r1,#0] + add r2,r4 + mov r3,#0 + adc r3,r6 + ldr r4,[r1,#32] + lsr r5,r4,#16 + uxth r4,r4 + mul r5,r7 + mul r4,r7 + add r2,r4 + adc r3,r6 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + str r2,[r0,#0] + ldr r4,[r1,#4] + add r3,r4 + mov r2,#0 + adc r2,r6 + ldr r4,[r1,#36] + lsr r5,r4,#16 + uxth r4,r4 + mul r5,r7 + mul r4,r7 + add r3,r4 + adc r2,r6 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r3,r4 + adc r2,r5 + str r3,[r0,#4] + ldr r4,[r1,#8] + add r2,r4 + mov r3,#0 + adc r3,r6 + ldr r4,[r1,#40] + lsr r5,r4,#16 + uxth r4,r4 + mul r5,r7 + mul r4,r7 + add r2,r4 + adc r3,r6 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + str r2,[r0,#8] + ldr r4,[r1,#12] + add r3,r4 + mov r2,#0 + adc r2,r6 + ldr r4,[r1,#44] + lsr r5,r4,#16 + uxth r4,r4 + mul r5,r7 + mul r4,r7 + add r3,r4 + adc r2,r6 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r3,r4 + adc r2,r5 + str r3,[r0,#12] + ldr r4,[r1,#16] + add r2,r4 + mov r3,#0 + adc r3,r6 + ldr r4,[r1,#48] + lsr r5,r4,#16 + uxth r4,r4 + mul r5,r7 + mul r4,r7 + add r2,r4 + adc r3,r6 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + str r2,[r0,#16] + ldr r4,[r1,#20] + add r3,r4 + mov r2,#0 + adc r2,r6 + ldr r4,[r1,#52] + lsr r5,r4,#16 + uxth r4,r4 + mul r5,r7 + mul r4,r7 + add r3,r4 + adc r2,r6 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r3,r4 + adc r2,r5 + str r3,[r0,#20] + ldr r4,[r1,#24] + add r2,r4 + mov r3,#0 + adc r3,r6 + ldr r4,[r1,#56] + lsr r5,r4,#16 + uxth r4,r4 + mul r5,r7 + mul r4,r7 + add r2,r4 + adc r3,r6 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + str r2,[r0,#24] + ldr r4,[r0,#28] + add r4,r3 + str r4,[r0,#28] + pop {r4,r5,r6,r7,r15} + + .size fe25519_reduceTo256Bits_asm, .-fe25519_reduceTo256Bits_asm + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/mul.s b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/mul.s new file mode 100644 index 0000000..155674c --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/mul.s @@ -0,0 +1,1109 @@ + .align 2 + .global multiply256x256_asm + .type multiply256x256_asm, %function +multiply256x256_asm: + push {r4-r7,lr} + mov r3, r8 + mov r4, r9 + mov r5, r10 + mov r6, r11 + push {r0-r6} + mov r12, r0 + mov r10, r2 + mov r11, r1 + mov r0,r2 + ldm r0!, {r4,r5,r6,r7} + ldm r1!, {r2,r3,r6,r7} + push {r0,r1} + /////////BEGIN LOW PART ////////////////////// + /////////MUL128///////////// + //MUL64 + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + ////////////////////////// + mov r4, r12 + stm r4!, {r0,r1} + push {r4} + push {r0,r1} + mov r1, r10 + mov r10, r2 + ldm r1, {r0, r1, r4, r5} + mov r2, r4 + mov r7, r5 + sub r2, r0 + sbc r7, r1 + sbc r6, r6 + eor r2, r6 + eor r7, r6 + sub r2, r6 + sbc r7, r6 + push {r2, r7} + mov r2, r11 + mov r11, r3 + ldm r2, {r0, r1, r2, r3} + sub r0, r2 + sbc r1, r3 + sbc r7, r7 + eor r0, r7 + eor r1, r7 + sub r0, r7 + sbc r1, r7 + eor r7, r6 + mov r12, r7 + push {r0, r1} + //MUL64 + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + mov r4, r10 + mov r5, r11 + eor r6, r6 + add r0, r4 + adc r1, r5 + adc r2, r6 + adc r3, r6 + mov r10, r2 + mov r11, r3 + pop {r2-r5} + push {r0, r1} + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + pop {r4, r5} + mov r6, r12 + mov r7, r12 + eor r0, r6 + eor r1, r6 + eor r2, r6 + eor r3, r6 + asr r6, r6, #1 + adc r0, r4 + adc r1, r5 + adc r4, r2 + adc r5, r3 + eor r2, r2 + adc r6,r2 + adc r7,r2 + pop {r2, r3} + mov r8, r2 + mov r9, r3 + add r2, r0 + adc r3, r1 + mov r0, r10 + mov r1, r11 + adc r4, r0 + adc r5, r1 + adc r6, r0 + adc r7, r1 + ////////END LOW PART///////////////////// + pop {r0} + stm r0!, {r2,r3} + pop {r1,r2} + push {r0} + push {r4-r7} + mov r10, r1 + mov r11, r2 + ldm r1!, {r4, r5} + ldm r2, {r2, r3} + /////////BEGIN HIGH PART//////////////// + /////////MUL128///////////// + //MUL64 + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + push {r0,r1} + mov r1, r10 + mov r10, r2 + ldm r1, {r0, r1, r4, r5} + mov r2, r4 + mov r7, r5 + sub r2, r0 + sbc r7, r1 + sbc r6, r6 + eor r2, r6 + eor r7, r6 + sub r2, r6 + sbc r7, r6 + push {r2, r7} + mov r2, r11 + mov r11, r3 + ldm r2, {r0, r1, r2, r3} + sub r0, r2 + sbc r1, r3 + sbc r7, r7 + eor r0, r7 + eor r1, r7 + sub r0, r7 + sbc r1, r7 + eor r7, r6 + mov r12, r7 + push {r0, r1} + //MUL64 + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + mov r4, r10 + mov r5, r11 + eor r6, r6 + add r0, r4 + adc r1, r5 + adc r2, r6 + adc r3, r6 + mov r10, r2 + mov r11, r3 + pop {r2-r5} + push {r0, r1} + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + pop {r4, r5} + mov r6, r12 + mov r7, r12 + eor r0, r6 + eor r1, r6 + eor r2, r6 + eor r3, r6 + asr r6, r6, #1 + adc r0, r4 + adc r1, r5 + adc r4, r2 + adc r5, r3 + eor r2, r2 + adc r6,r2 //0,1 + adc r7,r2 + pop {r2, r3} + mov r8, r2 + mov r9, r3 + add r2, r0 + adc r3, r1 + mov r0, r10 + mov r1, r11 + adc r4, r0 + adc r5, r1 + adc r6, r0 + adc r7, r1 + ////////END HIGH PART///////////////////// + mov r0, r8 + mov r1, r9 + mov r8, r6 + mov r9, r7 + pop {r6, r7} + add r0, r6 + adc r1, r7 + pop {r6, r7} + adc r2, r6 + adc r3, r7 + pop {r7} + stm r7!, {r0-r3} + mov r10, r7 + eor r0,r0 + mov r6, r8 + mov r7, r9 + adc r4, r0 + adc r5, r0 + adc r6, r0 + adc r7, r0 + pop {r0,r1,r2} + mov r12, r2 + push {r0, r4-r7} + ldm r1, {r0-r7} + sub r0, r4 + sbc r1, r5 + sbc r2, r6 + sbc r3, r7 + eor r4, r4 + sbc r4, r4 + eor r0, r4 + eor r1, r4 + eor r2, r4 + eor r3, r4 + sub r0, r4 + sbc r1, r4 + sbc r2, r4 + sbc r3, r4 + mov r6, r12 + mov r12, r4 //carry + mov r5, r10 + stm r5!, {r0-r3} + mov r11, r5 + mov r8, r0 + mov r9, r1 + ldm r6, {r0-r7} + sub r4, r0 + sbc r5, r1 + sbc r6, r2 + sbc r7, r3 + eor r0, r0 + sbc r0, r0 + eor r4, r0 + eor r5, r0 + eor r6, r0 + eor r7, r0 + sub r4, r0 + sbc r5, r0 + sbc r6, r0 + sbc r7, r0 + mov r1, r12 + eor r0, r1 + mov r1, r11 + stm r1!, {r4-r7} + push {r0} + mov r2, r8 + mov r3, r9 + /////////BEGIN MIDDLE PART//////////////// + /////////MUL128///////////// + //MUL64 + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + push {r0,r1} + mov r1, r10 + mov r10, r2 + ldm r1, {r0, r1, r4, r5} + mov r2, r4 + mov r7, r5 + sub r2, r0 + sbc r7, r1 + sbc r6, r6 + eor r2, r6 + eor r7, r6 + sub r2, r6 + sbc r7, r6 + push {r2, r7} + mov r2, r11 + mov r11, r3 + ldm r2, {r0, r1, r2, r3} + sub r0, r2 + sbc r1, r3 + sbc r7, r7 + eor r0, r7 + eor r1, r7 + sub r0, r7 + sbc r1, r7 + eor r7, r6 + mov r12, r7 + push {r0, r1} + //MUL64 + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + mov r4, r10 + mov r5, r11 + eor r6, r6 + add r0, r4 + adc r1, r5 + adc r2, r6 + adc r3, r6 + mov r10, r2 + mov r11, r3 + pop {r2-r5} + push {r0, r1} + mov r6, r5 + mov r1, r2 + sub r5, r4 + sbc r0, r0 + eor r5, r0 + sub r5, r0 + sub r1, r3 + sbc r7, r7 + eor r1, r7 + sub r1, r7 + eor r7, r0 + mov r9, r1 + mov r8, r5 + lsr r1,r4,#16 + uxth r4,r4 + mov r0,r4 + uxth r5,r2 + lsr r2,#16 + mul r0,r5//00 + mul r5,r1//10 + mul r4,r2//01 + mul r1,r2//11 + lsl r2,r4,#16 + lsr r4,r4,#16 + add r0,r2 + adc r1,r4 + lsl r2,r5,#16 + lsr r4,r5,#16 + add r0,r2 + adc r1,r4 + lsr r4, r6,#16 + uxth r6, r6 + uxth r5, r3 + lsr r3, r3, #16 + mov r2, r6 + mul r2, r5 + mul r5, r4 + mul r6, r3 + mul r3, r4 + lsl r4,r5,#16 + lsr r5,r5,#16 + add r2,r4 + adc r3,r5 + lsl r4,r6,#16 + lsr r5,r6,#16 + add r2,r4 + adc r3,r5 + eor r6, r6 + add r2, r1 + adc r3, r6 + mov r1, r9 + mov r5, r8 + mov r8, r0 + lsr r0, r1,#16 + uxth r1,r1 + mov r4,r1 + lsr r6,r5,#16 + uxth r5,r5 + mul r1,r5 + mul r4,r6 + mul r5,r0 + mul r0,r6 + lsl r6,r4,#16 + lsr r4,#16 + add r1,r6 + adc r0,r4 + lsl r6,r5,#16 + lsr r5,#16 + add r1,r6 + adc r0,r5 + eor r1,r7 + eor r0,r7 + eor r4, r4 + asr r7, r7, #1 + adc r1, r2 + adc r2, r0 + adc r7, r4 + mov r0, r8 + add r1, r0 + adc r2, r3 + adc r3, r7 + pop {r4, r5} + mov r6, r12 + mov r7, r12 + eor r0, r6 + eor r1, r6 + eor r2, r6 + eor r3, r6 + asr r6, r6, #1 + adc r0, r4 + adc r1, r5 + adc r4, r2 + adc r5, r3 + eor r2, r2 + adc r6,r2 //0,1 + adc r7,r2 + pop {r2, r3} + mov r8, r2 + mov r9, r3 + add r2, r0 + adc r3, r1 + mov r0, r10 + mov r1, r11 + adc r4, r0 + adc r5, r1 + adc r6, r0 + adc r7, r1 + //////////END MIDDLE PART//////////////// + pop {r0,r1} //r0,r1 + mov r12, r0 //negative + eor r2, r0 + eor r3, r0 + eor r4, r0 + eor r5, r0 + eor r6, r0 + eor r7, r0 + push {r4-r7} + ldm r1!, {r4-r7} + mov r11, r1 //reference + mov r1, r9 + eor r1, r0 + mov r10, r4 + mov r4, r8 + asr r0, #1 + eor r0, r4 + mov r4, r10 + adc r0, r4 + adc r1, r5 + adc r2, r6 + adc r3, r7 + eor r4, r4 + adc r4, r4 + mov r10, r4 //carry + mov r4, r11 + ldm r4, {r4-r7} + add r0, r4 + adc r1, r5 + adc r2, r6 + adc r3, r7 + mov r9, r4 + mov r4, r11 + stm r4!, {r0-r3} + mov r11, r4 + pop {r0-r3} + mov r4, r9 + adc r4, r0 + adc r5, r1 + adc r6, r2 + adc r7, r3 + mov r1, #0 + adc r1, r1 + mov r0, r10 + mov r10, r1 //carry + asr r0, #1 + pop {r0-r3} + adc r4, r0 + adc r5, r1 + adc r6, r2 + adc r7, r3 + mov r8, r0 + mov r0, r11 + stm r0!, {r4-r7} + mov r11, r0 + mov r0, r8 + mov r6, r12 + mov r5, r10 + eor r4, r4 + adc r5, r6 + adc r6, r4 + add r0, r5 + adc r1, r6 + adc r2, r6 + adc r3, r6 + mov r7, r11 + stm r7!, {r0-r3} + pop {r3-r6} + mov r8, r3 + mov r9, r4 + mov r10, r5 + mov r11, r6 + pop {r4-r7,pc} + bx lr +.size multiply256x256_asm, .-multiply256x256_asm + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/scalarmult.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/scalarmult.c new file mode 100644 index 0000000..488aac7 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/scalarmult.c @@ -0,0 +1,761 @@ +/* ======================= + ============================ C/C++ HEADER FILE ============================= + ======================= + + Collection of all required submodules from naclM0 required for curve25519 + scalar multiplication (not including randomization, etc.) alone. + + Library naclM0 largely bases on work avrNacl of M. Hutter and P. Schwabe. + + Will compile to the two functions + + int + crypto_scalarmult_base_curve25519( + unsigned char* q, + const unsigned char* n + ); + + int + crypto_scalarmult_curve25519 ( + unsigned char* r, + const unsigned char* s, + const unsigned char* p + ); + + Requires inttypes.h header and the four external assembly functions + + extern void + fe25519_reduceTo256Bits_asm ( + fe25519 *res, + const UN_512bitValue *in + ); + + extern void + fe25519_mpyWith121666_asm ( + fe25519* out, + const fe25519* in + ); + + extern void + multiply256x256_asm ( + UN_512bitValue* result, + const UN_256bitValue* x, + const UN_256bitValue* y + ); + + extern void + square256_asm ( + UN_512bitValue* result, + const UN_256bitValue* x + ); + + \file scalarmult.c + + \Author B. Haase, Endress + Hauser Conducta GmbH & Co. KG + + License: CC Common Creative license Attribution 4.0 International (CC BY 4.0) + http://creativecommons.org/licenses/by/4.0/ + ============================================================================*/ + +#include <inttypes.h> + +// comment out this line if implementing conditional swaps by data moves +//#define DH_SWAP_BY_POINTERS + +// Define the symbol to 0 in order to only use ladder steps +//#define DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS 1 + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; +typedef uintptr_t uintptr; + +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; +typedef intptr_t intptr; + +// Note that it's important to define the unit8 as first union member, so that +// an array of uint8 may be used as initializer. +typedef union UN_256bitValue_ +{ + uint8 as_uint8[32]; + uint16 as_uint16[16]; + uint32 as_uint32[8]; + uint64 as_uint64[4]; +} UN_256bitValue; + +// Note that it's important to define the unit8 as first union member, so that +// an array of uint8 may be used as initializer. +typedef union UN_512bitValue_ +{ + uint8 as_uint8[64]; + uint16 as_uint16[32]; + uint32 as_uint32[16]; + uint64 as_uint64[8]; + UN_256bitValue as_256_bitValue[2]; +} UN_512bitValue; + +typedef UN_256bitValue fe25519; + +// **************************************************** +// Assembly functions. +// **************************************************** + +extern void +fe25519_reduceTo256Bits_asm( + fe25519 *res, + const UN_512bitValue *in +); + +#define fe25519_mpyWith121666 fe25519_mpyWith121666_asm +extern void +fe25519_mpyWith121666_asm ( + fe25519* out, + const fe25519* in +); + +#define multiply256x256 multiply256x256_asm +extern void +multiply256x256( + UN_512bitValue* result, + const UN_256bitValue* x, + const UN_256bitValue* y +); + +#define square256 square256_asm +extern void +square256( + UN_512bitValue* result, + const UN_256bitValue* x +); + +// **************************************************** +// C functions for fe25519 +// **************************************************** + +static void +fe25519_cpy( + fe25519* dest, + const fe25519* source +) +{ + uint32 ctr; + + for (ctr = 0; ctr < 8; ctr++) + { + dest->as_uint32[ctr] = source->as_uint32[ctr]; + } +} + +static void +fe25519_unpack( + volatile fe25519* out, + const unsigned char in[32] +) +{ + uint8 ctr; + + for (ctr = 0; ctr < 32; ctr++) + { + out->as_uint8[ctr] = in[ctr]; + } + out->as_uint8[31] &= 0x7f; // make sure that the last bit is cleared. +} + +static void +fe25519_sub( + fe25519* out, + const fe25519* baseValue, + const fe25519* valueToSubstract +) +{ + uint16 ctr; + int64 accu = 0; + + // First subtract the most significant word, so that we may + // reduce the result "on the fly". + accu = baseValue->as_uint32[7]; + accu -= valueToSubstract->as_uint32[7]; + + // We always set bit #31, and compensate this by subtracting 1 from the reduction + // value. + out->as_uint32[7] = ((uint32)accu) | 0x80000000ul; + + accu = 19 * ((int32)(accu >> 31) - 1); + // ^ "-1" is the compensation for the "| 0x80000000ul" above. + // This choice makes sure, that the result will be positive! + + for (ctr = 0; ctr < 7; ctr += 1) + { + accu += baseValue->as_uint32[ctr]; + accu -= valueToSubstract->as_uint32[ctr]; + + out->as_uint32[ctr] = (uint32)accu; + accu >>= 32; + } + accu += out->as_uint32[7]; + out->as_uint32[7] = (uint32)accu; +} + +static void +fe25519_add( + fe25519* out, + const fe25519* baseValue, + const fe25519* valueToAdd +) +{ + uint16 ctr = 0; + uint64 accu = 0; + + // We first add the most significant word, so that we may reduce + // "on the fly". + accu = baseValue->as_uint32[7]; + accu += valueToAdd->as_uint32[7]; + out->as_uint32[7] = ((uint32)accu) & 0x7ffffffful; + + accu = ((uint32)(accu >> 31)) * 19; + + for (ctr = 0; ctr < 7; ctr += 1) + { + accu += baseValue->as_uint32[ctr]; + accu += valueToAdd->as_uint32[ctr]; + + out->as_uint32[ctr] = (uint32)accu; + accu >>= 32; + } + accu += out->as_uint32[7]; + out->as_uint32[7] = (uint32)accu; +} + +static void +fe25519_mul( + fe25519* result, + const fe25519* in1, + const fe25519* in2 +) +{ + UN_512bitValue tmp; + + multiply256x256(&tmp, in1, in2); + fe25519_reduceTo256Bits_asm(result,&tmp); +} + +static void +fe25519_square( + fe25519* result, + const fe25519* in +) +{ + UN_512bitValue tmp; + + square256(&tmp, in); + fe25519_reduceTo256Bits_asm(result,&tmp); +} + +static void +fe25519_reduceCompletely( + volatile fe25519* inout +) +{ + uint32 numberOfTimesToSubstractPrime; + uint32 initialGuessForNumberOfTimesToSubstractPrime = inout->as_uint32[7] >> + 31; + uint64 accu; + uint8 ctr; + + // add one additional 19 to the estimated number of reductions. + // Do the calculation without writing back the results to memory. + // + // The initial guess of required numbers of reductions is based + // on bit #32 of the most significant word. + // This initial guess may be wrong, since we might have a value + // v in the range + // 2^255 - 19 <= v < 2^255 + // . After adding 19 to the value, we will be having the correct + // Number of required subtractions. + accu = initialGuessForNumberOfTimesToSubstractPrime * 19 + 19; + + for (ctr = 0; ctr < 7; ctr++) + { + accu += inout->as_uint32[ctr]; + accu >>= 32; + } + accu += inout->as_uint32[7]; + + numberOfTimesToSubstractPrime = (uint32)(accu >> 31); + + // Do the reduction. + accu = numberOfTimesToSubstractPrime * 19; + + for (ctr = 0; ctr < 7; ctr++) + { + accu += inout->as_uint32[ctr]; + inout->as_uint32[ctr] = (uint32)accu; + accu >>= 32; + } + accu += inout->as_uint32[7]; + inout->as_uint32[7] = accu & 0x7ffffffful; +} + +/// We are already using a packed radix 16 representation for fe25519. The real use for this function +/// is for architectures that use more bits for storing a fe25519 in a representation where multiplication +/// may be calculated more efficiently. +/// Here we simply copy the data. +static void +fe25519_pack( + unsigned char out[32], + volatile fe25519* in +) +{ + uint8 ctr; + + fe25519_reduceCompletely(in); + + for (ctr = 0; ctr < 32; ctr++) + { + out[ctr] = in->as_uint8[ctr]; + } +} + +// Note, that r and x are allowed to overlap! +static void +fe25519_invert_useProvidedScratchBuffers( + fe25519* r, + const fe25519* x, + fe25519* t0, + fe25519* t1, + fe25519* t2 +) +{ + fe25519 *z11 = r; // store z11 in r (in order to save one temporary). + fe25519 *z2_10_0 = t1; + fe25519 *z2_50_0 = t2; + fe25519 *z2_100_0 = z2_10_0; + + uint8 i; + + { + fe25519 *z2 = z2_50_0; + + /* 2 */ fe25519_square(z2, x); + /* 4 */ fe25519_square(t0, z2); + /* 8 */ fe25519_square(t0, t0); + /* 9 */ fe25519_mul(z2_10_0, t0, x); + /* 11 */ fe25519_mul(z11, z2_10_0, z2); + + // z2 is dead. + } + + /* 22 */ fe25519_square(t0, z11); + /* 2^5 - 2^0 = 31 */ fe25519_mul(z2_10_0, t0, z2_10_0); + + /* 2^6 - 2^1 */ fe25519_square(t0, z2_10_0); + /* 2^7 - 2^2 */ fe25519_square(t0, t0); + /* 2^8 - 2^3 */ fe25519_square(t0, t0); + /* 2^9 - 2^4 */ fe25519_square(t0, t0); + /* 2^10 - 2^5 */ fe25519_square(t0, t0); + /* 2^10 - 2^0 */ fe25519_mul(z2_10_0, t0, z2_10_0); + + /* 2^11 - 2^1 */ fe25519_square(t0, z2_10_0); + + /* 2^20 - 2^10 */ for (i = 1; i < 10; i ++) + { + fe25519_square(t0, t0); + } + /* 2^20 - 2^0 */ fe25519_mul(z2_50_0, t0, z2_10_0); + + /* 2^21 - 2^1 */ fe25519_square(t0, z2_50_0); + + /* 2^40 - 2^20 */ for (i = 1; i < 20; i ++) + { + fe25519_square(t0, t0); + } + /* 2^40 - 2^0 */ fe25519_mul(t0, t0, z2_50_0); + + /* 2^41 - 2^1 */ fe25519_square(t0, t0); + + /* 2^50 - 2^10 */ for (i = 1; i < 10; i ++) + { + fe25519_square(t0, t0); + } + /* 2^50 - 2^0 */ fe25519_mul(z2_50_0, t0, z2_10_0); + + /* 2^51 - 2^1 */ fe25519_square(t0, z2_50_0); + + /* 2^100 - 2^50 */ for (i = 1; i < 50; i ++) + { + fe25519_square(t0, t0); + } + /* 2^100 - 2^0 */ fe25519_mul(z2_100_0, t0, z2_50_0); + + /* 2^101 - 2^1 */ fe25519_square(t0, z2_100_0); + + /* 2^200 - 2^100 */ for (i = 1; i < 100; i ++) + { + fe25519_square(t0, t0); + } + /* 2^200 - 2^0 */ fe25519_mul(t0, t0, z2_100_0); + + /* 2^250 - 2^50 */ for (i = 0; i < 50; i ++) + { + fe25519_square(t0, t0); + } + /* 2^250 - 2^0 */ fe25519_mul(t0, t0, z2_50_0); + + /* 2^255 - 2^5 */ for (i = 0; i < 5; i ++) + { + fe25519_square(t0, t0); + } + /* 2^255 - 21 */ fe25519_mul(r, t0, z11); +} + +static void +fe25519_setzero( + fe25519* out +) +{ + uint8 ctr; + + for (ctr = 0; ctr < 8; ctr++) + { + out->as_uint32[ctr] = 0; + } +} + +static void +fe25519_setone( + fe25519* out +) +{ + uint8 ctr; + + out->as_uint32[0] = 1; + + for (ctr = 1; ctr < 8; ctr++) + { + out->as_uint32[ctr] = 0; + } +} + +/* +static void +swapPointersConditionally (void **p1, void **p2, uint8 condition) +{ + // Secure version of this code: + // + // if (condition) + // { + // void *temp; + // temp = *p2; + // *p2 = *p1; + // *p1 = temp; + // } + + uintptr mask = condition; + uintptr val1 = (uintptr) *p1; + uintptr val2 = (uintptr) *p2; + uintptr temp = val2 ^ val1; + + mask = (uintptr)( - (intptr) mask ); + temp ^= mask & (temp ^ val1); + val1 ^= mask & (val1 ^ val2); + val2 ^= mask & (val2 ^ temp); + + *p1 = (void *) val1; + *p2 = (void *) val2; +} +*/ + +static void +fe25519_cswap( + fe25519* in1, + fe25519* in2, + int condition +) +{ + int32 mask = condition; + uint32 ctr; + + mask = -mask; + + for (ctr = 0; ctr < 8; ctr++) + { + uint32 val1 = in1->as_uint32[ctr]; + uint32 val2 = in2->as_uint32[ctr]; + uint32 temp = val1; + + val1 ^= mask & (val2 ^ val1); + val2 ^= mask & (val2 ^ temp); + + + in1->as_uint32[ctr] = val1; + in2->as_uint32[ctr] = val2; + } +} + +// **************************************************** +// Scalarmultiplication implementation. +// **************************************************** + +typedef struct _ST_curve25519ladderstepWorkingState +{ + // The base point in affine coordinates + fe25519 x0; + + // The two working points p, q, in projective coordinates. Possibly randomized. + fe25519 xp; + fe25519 zp; + fe25519 xq; + fe25519 zq; + + volatile UN_256bitValue s; + + int nextScalarBitToProcess; + uint8 previousProcessedBit; + +#ifdef DH_SWAP_BY_POINTERS + fe25519 *pXp; + fe25519 *pZp; + fe25519 *pXq; + fe25519 *pZq; +#endif + +} ST_curve25519ladderstepWorkingState; + +static void +curve25519_ladderstep( + ST_curve25519ladderstepWorkingState* pState +) +{ + // Implements the "ladd-1987-m-3" differential-addition-and-doubling formulas + // Source: 1987 Montgomery "Speeding the Pollard and elliptic curve methods of factorization", page 261, + // fifth and sixth displays, plus common-subexpression elimination. + // + // Notation from the explicit formulas database: + // (X2,Z2) corresponds to (xp,zp), + // (X3,Z3) corresponds to (xq,zq) + // Result (X4,Z4) (X5,Z5) expected in (xp,zp) and (xq,zq) + // + // A = X2+Z2; AA = A^2; B = X2-Z2; BB = B^2; E = AA-BB; C = X3+Z3; D = X3-Z3; + // DA = D*A; CB = C*B; t0 = DA+CB; t1 = t0^2; X5 = Z1*t1; t2 = DA-CB; + // t3 = t2^2; Z5 = X1*t3; X4 = AA*BB; t4 = a24*E; t5 = BB+t4; Z4 = E*t5 ; + // + // Re-Ordered for using less temporaries. + + fe25519 t1, t2; + + #ifdef DH_SWAP_BY_POINTERS + fe25519 *b1=pState->pXp; fe25519 *b2=pState->pZp; + fe25519 *b3=pState->pXq; fe25519 *b4=pState->pZq; + #else + fe25519 *b1=&pState->xp; fe25519 *b2=&pState->zp; + fe25519 *b3=&pState->xq; fe25519 *b4=&pState->zq; + #endif + + fe25519 *b5= &t1; fe25519 *b6=&t2; + + fe25519_add(b5,b1,b2); // A = X2+Z2 + fe25519_sub(b6,b1,b2); // B = X2-Z2 + fe25519_add(b1,b3,b4); // C = X3+Z3 + fe25519_sub(b2,b3,b4); // D = X3-Z3 + fe25519_mul(b3,b2,b5); // DA= D*A + fe25519_mul(b2,b1,b6); // CB= C*B + fe25519_add(b1,b2,b3); // T0= DA+CB + fe25519_sub(b4,b3,b2); // T2= DA-CB + fe25519_square(b3,b1); // X5==T1= T0^2 + fe25519_square(b1,b4); // T3= t2^2 + fe25519_mul(b4,b1,&pState->x0); // Z5=X1*t3 + fe25519_square(b1,b5); // AA=A^2 + fe25519_square(b5,b6); // BB=B^2 + fe25519_sub(b2,b1,b5); // E=AA-BB + fe25519_mul(b1,b5,b1); // X4= AA*BB + fe25519_mpyWith121666 (b6,b2); // T4 = a24*E + fe25519_add(b6,b6,b5); // T5 = BB + t4 + fe25519_mul(b2,b6,b2); // Z4 = E*t5 +} + +static void +curve25519_cswap( + ST_curve25519ladderstepWorkingState* state, + uint8 b +) +{ + #ifdef DH_SWAP_BY_POINTERS + swapPointersConditionally ((void **) &state->pXp,(void **) &state->pXq,b); + swapPointersConditionally ((void **) &state->pZp,(void **) &state->pZq,b); + #else + fe25519_cswap (&state->xp, &state->xq,b); + fe25519_cswap (&state->zp, &state->zq,b); + #endif +} + +#if DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS + +static void +curve25519_doublePointP (ST_curve25519ladderstepWorkingState* pState) +{ + // Implement the doubling formula "dbl-1987-m-3" + // from 1987 Montgomery "Speeding the Pollard and elliptic curve methods of factorization", + // page 261, sixth display, plus common-subexpression elimination. + // + // Three operand code: + // A = X1+Z1 + // AA = A^2 + // B = X1-Z1 + // BB = B^2 + // C = AA-BB + // X3 = AA*BB + // t0 = a24*C + // t1 = BB+t0 + // Z3 = C*t1 + + // Double the point input in the state variable "P". Use the State variable "Q" as temporary + // for storing A, AA and B, BB. Use the same temporary variable for A and AA respectively and + // B, BB respectively. + #ifdef DH_SWAP_BY_POINTERS + fe25519 *pA = pState->pXq; + fe25519 *pB = pState->pZq; + fe25519 *pX = pState->pXp; + fe25519 *pZ = pState->pZp; + #else + fe25519 *pA = &pState->xq; + fe25519 *pB = &pState->zq; + fe25519 *pX = &pState->xp; + fe25519 *pZ = &pState->zp; + #endif + + // A = X1+Z1 + fe25519_add(pA, pX, pZ); + // AA = A^2 + fe25519_square (pA,pA); + // B = X1-Z1 + fe25519_sub(pB, pX, pZ); + // BB = B^2 + fe25519_square (pB,pB); + // X3 = AA*BB + fe25519_mul (pX,pA,pB); + // C = AA-BB + fe25519_sub (pZ,pA,pB); + // t0 = a24*C + fe25519_mpyWith121666 (pA,pZ); + // t1 = BB+t0 + fe25519_add (pB,pA,pB); + // Z3 = C*t1 + fe25519_mul (pZ,pZ,pB); +} + +#endif // #ifdef DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS + +int +crypto_scalarmult_curve25519( + unsigned char* r, + const unsigned char* s, + const unsigned char* p +) +{ + ST_curve25519ladderstepWorkingState state; + unsigned char i; + + + // Prepare the scalar within the working state buffer. + for (i = 0; i < 32; i++) + { + state.s.as_uint8 [i] = s[i]; + } +#if DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS + // Due to explicit final doubling for the last three bits instead of a full ladderstep, + // the following line is no longer necessary. +#else + state.s.as_uint8 [0] &= 248; +#endif + state.s.as_uint8 [31] &= 127; + state.s.as_uint8 [31] |= 64; + + // Copy the affine x-axis of the base point to the state. + fe25519_unpack (&state.x0, p); + + // Prepare the working points within the working state struct. + + fe25519_setone (&state.zq); + fe25519_cpy (&state.xq, &state.x0); + + fe25519_setone(&state.xp); + fe25519_setzero(&state.zp); + + state.nextScalarBitToProcess = 254; + +#ifdef DH_SWAP_BY_POINTERS + // we need to initially assign the pointers correctly. + state.pXp = &state.xp; + state.pZp = &state.zp; + state.pXq = &state.xq; + state.pZq = &state.zq; +#endif + + state.previousProcessedBit = 0; + +#if DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS + // Process all the bits except for the last three where we explicitly double the result. + while (state.nextScalarBitToProcess >= 3) +#else + // Process all the bits except for the last three where we explicitly double the result. + while (state.nextScalarBitToProcess >= 0) +#endif + { + uint8 byteNo = state.nextScalarBitToProcess >> 3; + uint8 bitNo = state.nextScalarBitToProcess & 7; + uint8 bit; + uint8 swap; + + bit = 1 & (state.s.as_uint8 [byteNo] >> bitNo); + swap = bit ^ state.previousProcessedBit; + state.previousProcessedBit = bit; + curve25519_cswap(&state, swap); + curve25519_ladderstep(&state); + state.nextScalarBitToProcess --; + } + + curve25519_cswap(&state,state.previousProcessedBit); + +#if DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS + curve25519_doublePointP (&state); + curve25519_doublePointP (&state); + curve25519_doublePointP (&state); +#endif + +#ifdef DH_SWAP_BY_POINTERS + // optimize for stack usage. + fe25519_invert_useProvidedScratchBuffers (state.pZp, state.pZp, state.pXq,state.pZq,&state.x0); + fe25519_mul(state.pXp, state.pXp, state.pZp); + fe25519_reduceCompletely(state.pXp); + + fe25519_pack (r, state.pXp); +#else + // optimize for stack usage. + fe25519_invert_useProvidedScratchBuffers (&state.zp, &state.zp, &state.xq, &state.zq, &state.x0); + fe25519_mul(&state.xp, &state.xp, &state.zp); + fe25519_reduceCompletely(&state.xp); + + fe25519_pack (r, &state.xp); +#endif + + return 0; +} + +int +crypto_scalarmult_curve25519_base( + unsigned char* q, + const unsigned char* n +) +{ + static const uint8 base[32] = + { + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + return crypto_scalarmult_curve25519(q, n, base); +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/sqr.s b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/sqr.s new file mode 100644 index 0000000..3b190c9 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/arm/unacl/sqr.s @@ -0,0 +1,777 @@ + .align 2 + .global square256_asm + .type square256_asm, %function +square256_asm: + push {r4-r7,lr} + mov r2, r8 + mov r3, r9 + mov r4, r10 + mov r5, r11 + push {r0-r5} + + mov r12, r0 + mov r4, r1 + ldm r4!, {r0-r3} + push {r4} + /////////BEGIN LOW PART ////////////////////// + ///SQR 128, in r0-r3 + mov r8, r2 + mov r9, r3 + eor r4, r4 + sub r2, r0 + sbc r3, r1 + sbc r4, r4 + eor r2, r4 + eor r3, r4 + sub r2, r4 + sbc r3, r4 + mov r10, r2 + mov r11, r3 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r7, r7 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r7, r7 + add r1, r0 + adc r2, r3 + adc r7, r3 + mov r3, r12 + stm r3!, {r0-r1} + push {r3} + + mov r12, r0 + mov r0, r8 + mov r8, r1 + mov r1, r9 + mov r9, r2 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r4, r4 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r4, r4 + add r1, r0 + adc r2, r3 + adc r3, r4 + eor r4, r4 + mov r6, r9 + add r0, r6 + adc r7, r1 + adc r2, r4 + adc r3, r4 + mov r1, r11 + mov r11, r0 + mov r0, r10 + mov r9, r2 + mov r10,r3 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r4, r4 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r4, r4 + add r1, r0 + adc r2, r3 + adc r3, r4 + mov r6, r11 + mov r4, r11 + mov r5, r7 + sub r6, r0 + sbc r7, r1 + sbc r4, r2 + sbc r5, r3 + eor r1, r1 + sbc r1, r1 + mov r2, r12 + mov r3, r8 + add r2, r6 + adc r3, r7 + mov r6, r9 + mov r7, r10 + adc r4, r6 + adc r5, r7 + adc r6, r1 + adc r7, r1 + //results r12, r8, r2-r7 + /////////END LOW PART //////////////////////// + pop {r0,r1} + stm r0!, {r2, r3} + push {r0, r4-r7} + ldm r1, {r0-r3} + /////////BEGIN HIGH PART ////////////////////// + ///SQR 128, in r0-r3 + mov r8, r2 + mov r9, r3 + eor r4, r4 + sub r2, r0 + sbc r3, r1 + sbc r4, r4 + eor r2, r4 + eor r3, r4 + sub r2, r4 + sbc r3, r4 + mov r10, r2 + mov r11, r3 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r7, r7 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r7, r7 + add r1, r0 + adc r2, r3 + adc r7, r3 + mov r12, r0 + mov r0, r8 + mov r8, r1 + mov r1, r9 + mov r9, r2 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r4, r4 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r4, r4 + add r1, r0 + adc r2, r3 + adc r3, r4 + eor r4, r4 + mov r6, r9 + add r0, r6 + adc r7, r1 + adc r2, r4 + adc r3, r4 + mov r1, r11 + mov r11, r0 + mov r0, r10 + mov r9, r2 + mov r10,r3 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r4, r4 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r4, r4 + add r1, r0 + adc r2, r3 + adc r3, r4 + mov r6, r11 + mov r4, r11 + mov r5, r7 + sub r6, r0 + sbc r7, r1 + sbc r4, r2 + sbc r5, r3 + eor r1, r1 + sbc r1, r1 + mov r2, r12 + mov r3, r8 + add r2, r6 + adc r3, r7 + mov r6, r9 + mov r7, r10 + adc r4, r6 + adc r5, r7 + adc r6, r1 + adc r7, r1 + //results r12, r8, r2-r7 + /////////END HIGH PART //////////////////////// + mov r0, r12 + mov r1, r8 + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + pop {r4} + mov r12, r4//str + pop {r4-r7} + add r0, r4 + adc r1, r5 + adc r2, r6 + adc r3, r7 + mov r4, r12 + stm r4!, {r0-r3}//low part + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + eor r0, r0 + adc r4, r0 + adc r5, r0 + adc r6, r0 + adc r7, r0 + pop {r0, r1} //r0->out, r1, in + push {r0,r4-r7} + ldm r1, {r0-r7} + sub r0, r4 + sbc r1, r5 + sbc r2, r6 + sbc r3, r7 + sbc r4, r4 + eor r0, r4 + eor r1, r4 + eor r2, r4 + eor r3, r4 + sub r0, r4 + sbc r1, r4 + sbc r2, r4 + sbc r3, r4 + //////////BEGIN MIDDLE PART//////////////// + ///SQR 128, in r0-r3 + mov r8, r2 + mov r9, r3 + eor r4, r4 + sub r2, r0 + sbc r3, r1 + sbc r4, r4 + eor r2, r4 + eor r3, r4 + sub r2, r4 + sbc r3, r4 + mov r10, r2 + mov r11, r3 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r7, r7 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r7, r7 + add r1, r0 + adc r2, r3 + adc r7, r3 + mov r12, r0 + mov r0, r8 + mov r8, r1 + mov r1, r9 + mov r9, r2 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r4, r4 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r4, r4 + add r1, r0 + adc r2, r3 + adc r3, r4 + eor r4, r4 + mov r6, r9 + add r0, r6 + adc r7, r1 + adc r2, r4 + adc r3, r4 + mov r1, r11 + mov r11, r0 + mov r0, r10 + mov r9, r2 + mov r10,r3 + //SQR64, in: r0, r1, out: r0-r3, used: r0-r6 + mov r2, r0 + eor r3, r3 + sub r2, r1 + sbc r3, r3 + eor r2, r3 + sub r2, r3 + lsr r3, r0, #16 + uxth r0, r0 + mov r4, r0 + mul r4, r3 + mul r0, r0 + mul r3, r3 + lsr r5, r4, #16 + lsl r4, #16 + add r0, r4 + adc r3, r5 + add r0, r4 + adc r3, r5 + lsr r4, r1, #16 + uxth r1, r1 + mov r5, r1 + mul r5, r4 + mul r1, r1 + mul r4, r4 + eor r6, r6 + add r1, r3 + adc r4, r6 + lsr r3, r5, #16 + lsl r5, r5, #16 + add r1, r5 + adc r4, r3 + add r1, r5 + adc r3, r4 + lsr r4, r2, #16 + uxth r2, r2 + mov r5, r2 + mul r5, r4 + mul r2, r2 + mul r4, r4 + lsr r6, r5, #16 + lsl r5, #16 + add r2, r5 + adc r4, r6 + add r5, r2 + adc r6, r4 + eor r4, r4 + mov r2, r1 + sub r1, r5 + sbc r2, r6 + sbc r4, r4 + add r1, r0 + adc r2, r3 + adc r3, r4 + mov r6, r11 + mov r4, r11 + mov r5, r7 + sub r6, r0 + sbc r7, r1 + sbc r4, r2 + sbc r5, r3 + eor r1, r1 + sbc r1, r1 + mov r2, r12 + mov r3, r8 + add r2, r6 + adc r3, r7 + mov r6, r9 + mov r7, r10 + adc r4, r6 + adc r5, r7 + adc r6, r1 + adc r7, r1 + //results r12, r8, r2-r7 + //////////END MIDDLE PART////////////////// + mvn r2, r2 + mvn r3, r3 + mvn r4, r4 + mvn r5, r5 + mvn r6, r6 + mvn r7, r7 + pop {r1} + push {r4-r7} + mov r4, #1 + asr r4, #1 + ldm r1!, {r4-r7} + mov r0, r12 + mov r12, r1 ////////ref + mov r1, r8 + mvn r0, r0 + mvn r1, r1 + adc r0, r4 + adc r1, r5 + adc r2, r6 + adc r3, r7 + eor r4, r4 + adc r4, r4 + mov r8, r4 //carry A --ini + mov r4, r12 + ldm r4, {r4-r7} + add r0, r4 + adc r1, r5 + adc r2, r6 + adc r3, r7 + mov r9, r4 + mov r4, r12 + stm r4!, {r0-r3} + mov r12, r4 + mov r4, r9 + pop {r0-r3} + adc r4, r0 + adc r5, r1 + adc r6, r2 + adc r7, r3 + eor r0, r0 + adc r0, r0 + mov r9, r0 //carry B --ini + mov r0, r8 + asr r0, #1 //carry A --end + pop {r0-r3} + adc r4, r0 + adc r5, r1 + adc r6, r2 + adc r7, r3 + mov r8, r0 + mov r0, r12 + stm r0!, {r4-r7} + mov r11, r0 + mov r0, r8 + eor r4, r4 + mov r5, r9 + adc r5, r4 //carry B --end + mvn r6, r4 + add r5, r6 + adc r6, r4 + add r0, r5 + adc r1, r6 + adc r2, r6 + adc r3, r6 + mov r7, r11 + stm r7!, {r0-r3} + + pop {r3-r6} + mov r8, r3 + mov r9, r4 + mov r10, r5 + mov r11, r6 + pop {r4-r7,pc} + bx lr + .size square256_asm, .-square256_asm diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/bitops.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/bitops.h new file mode 100644 index 0000000..f2ca308 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/bitops.h @@ -0,0 +1,310 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef BITOPS_H +#define BITOPS_H + +#include <stdint.h> +#include <stddef.h> + +#ifdef _WINDOWS +#include <intrin.h> +#endif + +/* Assorted bitwise and common operations used in ciphers. */ + +/** Circularly rotate right x by n bits. + * 0 > n > 32. */ +static inline uint32_t rotr32(uint32_t x, unsigned n) +{ + return (x >> n) | (x << (32 - n)); +} + +/** Circularly rotate left x by n bits. + * 0 > n > 32. */ +static inline uint32_t rotl32(uint32_t x, unsigned n) +{ + return (x << n) | (x >> (32 - n)); +} + +/** Circularly rotate right x by n bits. + * 0 > n > 64. */ +static inline uint64_t rotr64(uint64_t x, unsigned n) +{ + return (x >> n) | (x << (64 - n)); +} + +/** Circularly rotate left x by n bits. + * 0 > n > 64. */ +static inline uint64_t rotl64(uint64_t x, unsigned n) +{ + return (x << n) | (x >> (64 - n)); +} + +/** Read 4 bytes from buf, as a 32-bit big endian quantity. */ +static inline uint32_t read32_be(const uint8_t buf[4]) +{ + return (buf[0] << 24) | + (buf[1] << 16) | + (buf[2] << 8) | + (buf[3]); +} + +/** Read 4 bytes from buf, as a 32-bit little endian quantity. */ +static inline uint32_t read32_le(const uint8_t buf[4]) +{ + return (buf[3] << 24) | + (buf[2] << 16) | + (buf[1] << 8) | + (buf[0]); +} + +/** Read 8 bytes from buf, as a 64-bit big endian quantity. */ +static inline uint64_t read64_be(const uint8_t buf[8]) +{ + uint32_t hi = read32_be(buf), + lo = read32_be(buf + 4); + return ((uint64_t)hi) << 32 | + lo; +} + +/** Read 8 bytes from buf, as a 64-bit little endian quantity. */ +static inline uint64_t read64_le(const uint8_t buf[8]) +{ + uint32_t hi = read32_le(buf + 4), + lo = read32_le(buf); + return ((uint64_t)hi) << 32 | + lo; +} + +/** Encode v as a 32-bit big endian quantity into buf. */ +static inline void write32_be(uint32_t v, uint8_t buf[4]) +{ + *buf++ = (v >> 24) & 0xff; + *buf++ = (v >> 16) & 0xff; + *buf++ = (v >> 8) & 0xff; + *buf = v & 0xff; +} + +/** Encode v as a 32-bit little endian quantity into buf. */ +static inline void write32_le(uint32_t v, uint8_t buf[4]) +{ + *buf++ = v & 0xff; + *buf++ = (v >> 8) & 0xff; + *buf++ = (v >> 16) & 0xff; + *buf = (v >> 24) & 0xff; +} + +/** Encode v as a 64-bit big endian quantity into buf. */ +static inline void write64_be(uint64_t v, uint8_t buf[8]) +{ + *buf++ = (v >> 56) & 0xff; + *buf++ = (v >> 48) & 0xff; + *buf++ = (v >> 40) & 0xff; + *buf++ = (v >> 32) & 0xff; + *buf++ = (v >> 24) & 0xff; + *buf++ = (v >> 16) & 0xff; + *buf++ = (v >> 8) & 0xff; + *buf = v & 0xff; +} + +/** Encode v as a 64-bit little endian quantity into buf. */ +static inline void write64_le(uint64_t v, uint8_t buf[8]) +{ + *buf++ = v & 0xff; + *buf++ = (v >> 8) & 0xff; + *buf++ = (v >> 16) & 0xff; + *buf++ = (v >> 24) & 0xff; + *buf++ = (v >> 32) & 0xff; + *buf++ = (v >> 40) & 0xff; + *buf++ = (v >> 48) & 0xff; + *buf = (v >> 56) & 0xff; +} + +/** out = in ^ b8. + * out and in may alias. */ +static inline void xor_b8(uint8_t *out, const uint8_t *in, uint8_t b8, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) + out[i] = in[i] ^ b8; +} + +/** out = x ^ y. + * out, x and y may alias. */ +static inline void xor_bb(uint8_t *out, const uint8_t *x, const uint8_t *y, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) + out[i] = x[i] ^ y[i]; +} + +/* out ^= x + * out and x may alias. */ +static inline void xor_words(uint32_t *out, const uint32_t *x, size_t nwords) +{ + size_t i; + for (i = 0; i < nwords; i++) + out[i] ^= x[i]; +} + +/** Produce 0xffffffff if x == y, zero otherwise, without branching. */ +static inline uint32_t mask_u32(uint32_t x, uint32_t y) +{ + uint32_t diff = x ^ y; + uint32_t diff_is_zero = ~diff & (diff - 1); + return (uint32_t)(-(int32_t)(diff_is_zero >> 31)); +} + +/** Product 0xff if x == y, zero otherwise, without branching. */ +static inline uint8_t mask_u8(uint32_t x, uint32_t y) +{ + uint32_t diff = x ^ y; + uint8_t diff_is_zero = ~diff & (diff - 1); + return - (diff_is_zero >> 7); +} + +/** Select the ith entry from the given table of n values, in a side channel-silent + * way. */ +static inline uint32_t select_u32(uint32_t i, volatile const uint32_t *tab, uint32_t n) +{ + uint32_t r = 0, ii; + + for (ii = 0; ii < n; ii++) + { + uint32_t mask = mask_u32(i, ii); + r = (r & ~mask) | (tab[ii] & mask); + } + + return r; +} + +/** Select the ith entry from the given table of n values, in a side channel-silent + * way. */ +static inline uint8_t select_u8(uint32_t i, volatile const uint8_t *tab, uint32_t n) +{ + uint8_t r = 0; + uint32_t ii; + + for (ii = 0; ii < n; ii++) + { + uint8_t mask = mask_u8(i, ii); + r = (r & ~mask) | (tab[ii] & mask); + } + + return r; +} + +/** Select the ath, bth, cth and dth entries from the given table of n values, + * placing the results into a, b, c and d. */ +static inline void select_u8x4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d, + volatile const uint8_t *tab, uint32_t n) +{ + uint8_t ra = 0, + rb = 0, + rc = 0, + rd = 0; + uint8_t mask; + uint32_t i; + + for (i = 0; i < n; i++) + { + uint8_t item = tab[i]; + + mask = mask_u8(*a, i); ra = (ra & ~mask) | (item & mask); + mask = mask_u8(*b, i); rb = (rb & ~mask) | (item & mask); + mask = mask_u8(*c, i); rc = (rc & ~mask) | (item & mask); + mask = mask_u8(*d, i); rd = (rd & ~mask) | (item & mask); + } + + *a = ra; + *b = rb; + *c = rc; + *d = rd; +} + +/** out ^= if0 or if1, depending on the value of bit. */ +static inline void select_xor128(uint32_t out[4], + const uint32_t if0[4], + const uint32_t if1[4], + uint8_t bit) +{ + uint32_t mask1 = mask_u32(bit, 1); + uint32_t mask0 = ~mask1; + + out[0] ^= (if0[0] & mask0) | (if1[0] & mask1); + out[1] ^= (if0[1] & mask0) | (if1[1] & mask1); + out[2] ^= (if0[2] & mask0) | (if1[2] & mask1); + out[3] ^= (if0[3] & mask0) | (if1[3] & mask1); +} + +/** Increments the integer stored at v (of non-zero length len) + * with the least significant byte first. */ +static inline void incr_le(uint8_t *v, size_t len) +{ + size_t i = 0; + while (1) + { + if (++v[i] != 0) + return; + i++; + if (i == len) + return; + } +} + +/** Increments the integer stored at v (of non-zero length len) + * with the most significant byte last. */ +static inline void incr_be(uint8_t *v, size_t len) +{ + len--; + while (1) + { + if (++v[len] != 0) + return; + if (len == 0) + return; + len--; + } +} + +/** Copies len bytes from in to out, with in shifted left by offset bits + * to the right. */ +static inline void copy_bytes_unaligned(uint8_t *out, const uint8_t *in, size_t len, uint8_t offset) +{ + uint8_t byte_off = offset / 8; + uint8_t bit_off = offset & 7; + uint8_t rmask = (1 << bit_off) - 1; + uint8_t lmask = ~rmask; + size_t i; + + for (i = 0; i < len; i++) + { + out[i] = (in[i + byte_off] << bit_off) & lmask; + out[i] |= (in[i + byte_off + 1] >> (8 - bit_off)) & rmask; + } +} + +static inline uint32_t count_trailing_zeroes(uint32_t x) +{ +#ifdef _WINDOWS + uint32_t r = 0; + _BitScanReverse(&r, x); + return (31 - r); +#else + return (uint32_t) __builtin_ctzl(x); +#endif +} + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/blockwise.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/blockwise.c new file mode 100644 index 0000000..182c8c5 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/blockwise.c @@ -0,0 +1,195 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "blockwise.h" +#include "bitops.h" +#include "handy.h" +#include "tassert.h" + +#include <string.h> + +void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial, size_t nblock, + const void *inp, size_t nbytes, + cf_blockwise_in_fn process, + void *ctx) +{ + cf_blockwise_accumulate_final(partial, npartial, nblock, + inp, nbytes, + process, process, ctx); +} + +void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial, size_t nblock, + const void *inp, size_t nbytes, + cf_blockwise_in_fn process, + cf_blockwise_in_fn process_final, + void *ctx) +{ + const uint8_t *bufin = inp; + assert(partial && *npartial < nblock); + assert(inp || !nbytes); + assert(process && ctx); + + /* If we have partial data, copy in to buffer. */ + if (*npartial && nbytes) + { + size_t space = nblock - *npartial; + size_t taken = MIN(space, nbytes); + + memcpy(partial + *npartial, bufin, taken); + + bufin += taken; + nbytes -= taken; + *npartial += taken; + + /* If that gives us a full block, process it. */ + if (*npartial == nblock) + { + if (nbytes == 0) + process_final(ctx, partial); + else + process(ctx, partial); + *npartial = 0; + } + } + + /* now nbytes < nblock or *npartial == 0. */ + + /* If we have a full block of data, process it directly. */ + while (nbytes >= nblock) + { + /* Partial buffer must be empty, or we're ignoring extant data */ + assert(*npartial == 0); + + if (nbytes == nblock) + process_final(ctx, bufin); + else + process(ctx, bufin); + bufin += nblock; + nbytes -= nblock; + } + + /* Finally, if we have remaining data, buffer it. */ + while (nbytes) + { + size_t space = nblock - *npartial; + size_t taken = MIN(space, nbytes); + + memcpy(partial + *npartial, bufin, taken); + + bufin += taken; + nbytes -= taken; + *npartial += taken; + + /* If we started with *npartial, we must have copied it + * in first. */ + assert(*npartial < nblock); + } +} + +void cf_blockwise_xor(uint8_t *partial, size_t *npartial, size_t nblock, + const void *inp, void *outp, size_t nbytes, + cf_blockwise_out_fn process, void *ctx) +{ + const uint8_t *inb = inp; + uint8_t *outb = outp; + + assert(partial && *npartial < nblock); + assert(inp || !nbytes); + assert(process && ctx); + + while (nbytes) + { + /* If we're out of material, and need more, produce a block. */ + if (*npartial == 0) + { + process(ctx, partial); + *npartial = nblock; + } + + size_t offset = nblock - *npartial; + size_t taken = MIN(*npartial, nbytes); + xor_bb(outb, inb, partial + offset, taken); + *npartial -= taken; + nbytes -= taken; + outb += taken; + inb += taken; + } +} + +void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial, + size_t nblock, + uint8_t byte, size_t nbytes, + cf_blockwise_in_fn process, + void *ctx) +{ + /* only memset the whole of the block once */ + int filled = 0; + + while (nbytes) + { + size_t start = *npartial; + size_t count = MIN(nbytes, nblock - start); + + if (!filled) + memset(partial + start, byte, count); + + if (start == 0 && count == nblock) + filled = 1; + + if (start + count == nblock) + { + process(ctx, partial); + *npartial = 0; + } else { + *npartial += count; + } + + nbytes -= count; + } +} + +void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial, + size_t nblock, + uint8_t fbyte, uint8_t mbyte, uint8_t lbyte, + size_t nbytes, + cf_blockwise_in_fn process, + void *ctx) +{ + + switch (nbytes) + { + case 0: break; + case 1: fbyte ^= lbyte; + cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx); + break; + case 2: + cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx); + cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx); + break; + default: + cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx); + + /* If the middle and last bytes differ, then process the last byte separately. + * Otherwise, just extend the middle block size. */ + if (lbyte != mbyte) + { + cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 2, process, ctx); + cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx); + } else { + cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 1, process, ctx); + } + + break; + } +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/blockwise.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/blockwise.h new file mode 100644 index 0000000..a20ff95 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/blockwise.h @@ -0,0 +1,147 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef BLOCKWISE_H +#define BLOCKWISE_H + +#include <stdint.h> +#include <stddef.h> + +/* Processing function for cf_blockwise_accumulate. */ +typedef void (*cf_blockwise_in_fn)(void *ctx, const uint8_t *data); + +/* Processing function for cf_blockwise_xor. */ +typedef void (*cf_blockwise_out_fn)(void *ctx, uint8_t *data); + +/* This function manages the common abstraction of accumulating input in + * a buffer, and processing it when a full block is available. + * + * partial is the buffer (maintained by the caller) + * on entry, npartial is the currently valid count of used bytes on + * the front of partial. + * on exit, npartial is updated to reflect the status of partial. + * nblock is the blocksize to accumulate -- partial must be at least + * this long! + * input is the new data to process, of length nbytes. + * process is the processing function, passed ctx and a pointer + * to the data to process (always exactly nblock bytes long!) + * which may not neccessarily be the same as partial. + */ +void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial, + size_t nblock, + const void *input, size_t nbytes, + cf_blockwise_in_fn process, + void *ctx); + +/* This function manages the common abstraction of accumulating input in + * a buffer, and processing it when a full block is available. + * This version supports calling a different processing function for + * the last block. + * + * partial is the buffer (maintained by the caller) + * on entry, npartial is the currently valid count of used bytes on + * the front of partial. + * on exit, npartial is updated to reflect the status of partial. + * nblock is the blocksize to accumulate -- partial must be at least + * this long! + * input is the new data to process, of length nbytes. + * process is the processing function, passed ctx and a pointer + * to the data to process (always exactly nblock bytes long!) + * which may not neccessarily be the same as partial. + * process_final is called last (but may not be called at all if + * all input is buffered). + */ +void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial, + size_t nblock, + const void *input, size_t nbytes, + cf_blockwise_in_fn process, + cf_blockwise_in_fn process_final, + void *ctx); + +/* This function manages XORing an input stream with a keystream + * to produce an output stream. The keystream is produced in blocks + * (ala a block cipher in counter mode). + * + * partial is the keystream buffer (maintained by the caller) + * on entry, *npartial is the currently valid count of bytes in partial: + * unused bytes are at the *end*. So *npartial = 4 means the last four + * bytes of partial are usable as keystream. + * on exit, npartial is updated to reflect the new state of partial. + * nblock is the blocksize to accumulate -- partial must be at least + * this long! + * input is the new data to process, of length nbytes. + * output is where to write input xored with the keystream -- also length + * nbytes. + * process is the processing function, passed ctx and partial which it + * should fill with fresh key stream. + */ +void cf_blockwise_xor(uint8_t *partial, size_t *npartial, + size_t nblock, + const void *input, void *output, size_t nbytes, + cf_blockwise_out_fn newblock, + void *ctx); + +/* This function processes a single byte a number of times. It's useful + * for padding, and more efficient than calling cf_blockwise_accumulate + * a bunch of times. + * + * partial is the buffer (maintained by the caller) + * on entry, npartial is the currently valid count of used bytes on + * the front of partial. + * on exit, npartial is updated to reflect the status of partial. + * nblock is the blocksize to accumulate -- partial must be at least + * this long! + * process is the processing function, passed ctx and a pointer + * to the data to process (always exactly nblock bytes long!) + * which may not neccessarily be the same as partial. + * byte is the byte to process, nbytes times. + */ +void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial, + size_t nblock, + uint8_t byte, size_t nbytes, + cf_blockwise_in_fn process, + void *ctx); + +/* This function attempts to process patterns of bytes common in + * block cipher padding. + * + * This takes three bytes: + * - a first byte, fbyte, + * - a middle byte, mbyte, + * - a last byte, lbyte. + * + * If nbytes is zero, nothing happens. + * If nbytes is one, the byte fbyte ^ lbyte is processed. + * If nbytes is two, the fbyte then lbyte are processed. + * If nbytes is three or more, fbyte, then one or more mbytes, then fbyte + * is processed. + * + * partial is the buffer (maintained by the caller) + * on entry, npartial is the currently valid count of used bytes on + * the front of partial. + * on exit, npartial is updated to reflect the status of partial. + * nblock is the blocksize to accumulate -- partial must be at least + * this long! + * process is the processing function, passed ctx and a pointer + * to the data to process (always exactly nblock bytes long!) + * which may not neccessarily be the same as partial. + */ +void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial, + size_t nblock, + uint8_t fbyte, uint8_t mbyte, uint8_t lbyte, + size_t nbytes, + cf_blockwise_in_fn process, + void *ctx); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/cbcmac.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/cbcmac.c new file mode 100644 index 0000000..f0dfe87 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/cbcmac.c @@ -0,0 +1,79 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "handy.h" +#include "prp.h" +#include "modes.h" +#include "bitops.h" +#include "blockwise.h" +#include "gf128.h" +#include "tassert.h" + +#include <string.h> + +void cf_cbcmac_stream_init(cf_cbcmac_stream *ctx, const cf_prp *prp, void *prpctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->prp = prp; + ctx->prpctx = prpctx; + cf_cbcmac_stream_reset(ctx); +} + +void cf_cbcmac_stream_reset(cf_cbcmac_stream *ctx) +{ + uint8_t iv_zero[CF_MAXBLOCK] = { 0 }; + cf_cbc_init(&ctx->cbc, ctx->prp, ctx->prpctx, iv_zero); + mem_clean(ctx->buffer, sizeof ctx->buffer); + ctx->used = 0; +} + +static void cbcmac_process(void *vctx, const uint8_t *block) +{ + cf_cbcmac_stream *ctx = vctx; + uint8_t output[CF_MAXBLOCK]; + cf_cbc_encrypt(&ctx->cbc, block, output, 1); +} + +void cf_cbcmac_stream_update(cf_cbcmac_stream *ctx, const uint8_t *data, size_t len) +{ + cf_blockwise_accumulate(ctx->buffer, &ctx->used, ctx->prp->blocksz, + data, len, + cbcmac_process, + ctx); +} + +void cf_cbcmac_stream_finish_block_zero(cf_cbcmac_stream *ctx) +{ + if (ctx->used == 0) + return; + + memset(ctx->buffer + ctx->used, 0, ctx->prp->blocksz - ctx->used); + cbcmac_process(ctx, ctx->buffer); + ctx->used = 0; +} + +void cf_cbcmac_stream_nopad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]) +{ + assert(ctx->used == 0); + memcpy(out, ctx->cbc.block, ctx->prp->blocksz); +} + +void cf_cbcmac_stream_pad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]) +{ + uint8_t npad = ctx->prp->blocksz - ctx->used; + cf_blockwise_acc_byte(ctx->buffer, &ctx->used, ctx->prp->blocksz, + npad, npad, + cbcmac_process, ctx); + cf_cbcmac_stream_nopad_final(ctx, out); +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/ccm.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/ccm.c new file mode 100644 index 0000000..7ef87fc --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/ccm.c @@ -0,0 +1,193 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "handy.h" +#include "prp.h" +#include "modes.h" +#include "tassert.h" + +#include <string.h> + +#define CCM_ADATA_PRESENT 0x40 + +static void write_be(uint8_t *out, size_t value, size_t bytes) +{ + while (bytes) + { + out[bytes - 1] = value & 0xff; + value >>= 8; + bytes--; + } + + assert(value == 0); /* or we couldn't encode the value. */ +} + +static void zero_pad(cf_cbcmac_stream *cm) +{ + cf_cbcmac_stream_finish_block_zero(cm); +} + +/* nb. block is general workspace. */ +static void add_aad(cf_cbcmac_stream *cm, uint8_t block[CF_MAXBLOCK], + const uint8_t *header, size_t nheader) +{ + assert(nheader <= 0xffffffff); /* we don't support 64 bit lengths. */ + + /* Add length using stupidly complicated rules. */ + if (nheader < 0xff00) + { + write_be(block, nheader, 2); + cf_cbcmac_stream_update(cm, block, 2); + } else { + write_be(block, 0xfffe, 2); + write_be(block + 2, nheader, 4); + cf_cbcmac_stream_update(cm, block, 6); + } + + cf_cbcmac_stream_update(cm, header, nheader); + zero_pad(cm); +} + +static void add_block0(cf_cbcmac_stream *cm, + uint8_t block[CF_MAXBLOCK], size_t nblock, + const uint8_t *nonce, size_t nnonce, + size_t L, size_t nplain, + size_t nheader, size_t ntag) +{ + /* Construct first block B_0. */ + block[0] = ((nheader == 0) ? 0x00 : CCM_ADATA_PRESENT) | + ((ntag - 2) / 2) << 3 | + (L - 1); + memcpy(block + 1, nonce, nnonce); + write_be(block + 1 + nnonce, nplain, L); + + cf_cbcmac_stream_update(cm, block, nblock); +} + +static void build_ctr_nonce(uint8_t ctr_nonce[CF_MAXBLOCK], + size_t L, + const uint8_t *nonce, size_t nnonce) +{ + ctr_nonce[0] = (L - 1); + memcpy(ctr_nonce + 1, nonce, nnonce); + memset(ctr_nonce + 1 + nnonce, 0, L); +} + +void cf_ccm_encrypt(const cf_prp *prp, void *prpctx, + const uint8_t *plain, size_t nplain, size_t L, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + uint8_t *cipher, + uint8_t *tag, size_t ntag) +{ + uint8_t block[CF_MAXBLOCK]; + + assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0); + assert(L >= 2 && L <= 8); + assert(nnonce == prp->blocksz - L - 1); + + cf_cbcmac_stream cm; + cf_cbcmac_stream_init(&cm, prp, prpctx); + + /* Add first block. */ + add_block0(&cm, block, prp->blocksz, + nonce, nnonce, + L, nplain, nheader, ntag); + + /* Add AAD with length prefix, if present. */ + if (nheader) + add_aad(&cm, block, header, nheader); + + /* Add message. */ + cf_cbcmac_stream_update(&cm, plain, nplain); + zero_pad(&cm); + + /* Finish tag. */ + cf_cbcmac_stream_nopad_final(&cm, block); + + /* Start encryption. */ + /* Construct A_0 */ + uint8_t ctr_nonce[CF_MAXBLOCK]; + build_ctr_nonce(ctr_nonce, L, nonce, nnonce); + + cf_ctr ctr; + cf_ctr_init(&ctr, prp, prpctx, ctr_nonce); + cf_ctr_custom_counter(&ctr, prp->blocksz - L, L); + + /* Encrypt tag first. */ + cf_ctr_cipher(&ctr, block, block, prp->blocksz); + memcpy(tag, block, ntag); + + /* Then encrypt message. */ + cf_ctr_cipher(&ctr, plain, cipher, nplain); +} + +int cf_ccm_decrypt(const cf_prp *prp, void *prpctx, + const uint8_t *cipher, size_t ncipher, size_t L, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + const uint8_t *tag, size_t ntag, + uint8_t *plain) +{ + uint8_t block[CF_MAXBLOCK]; + + assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0); + assert(L >= 2 && L <= 8); + assert(nnonce == prp->blocksz - L - 1); + + uint8_t ctr_nonce[CF_MAXBLOCK]; + build_ctr_nonce(ctr_nonce, L, nonce, nnonce); + + cf_ctr ctr; + cf_ctr_init(&ctr, prp, prpctx, ctr_nonce); + cf_ctr_custom_counter(&ctr, prp->blocksz - L, L); + + /* Decrypt tag. */ + uint8_t plain_tag[CF_MAXBLOCK]; + cf_ctr_cipher(&ctr, tag, plain_tag, ntag); + cf_ctr_discard_block(&ctr); + + /* Decrypt message. */ + cf_ctr_cipher(&ctr, cipher, plain, ncipher); + + cf_cbcmac_stream cm; + cf_cbcmac_stream_init(&cm, prp, prpctx); + + /* Add first block. */ + add_block0(&cm, block, prp->blocksz, + nonce, nnonce, + L, ncipher, nheader, ntag); + + if (nheader) + add_aad(&cm, block, header, nheader); + + cf_cbcmac_stream_update(&cm, plain, ncipher); + zero_pad(&cm); + + /* Finish tag. */ + cf_cbcmac_stream_nopad_final(&cm, block); + + int err = 0; + + if (!mem_eq(block, plain_tag, ntag)) + { + err = 1; + mem_clean(plain, ncipher); + } + + mem_clean(block, sizeof block); + mem_clean(plain_tag, sizeof plain_tag); + return err; +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/cf_config.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/cf_config.h new file mode 100644 index 0000000..ceb7e8d --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/cf_config.h @@ -0,0 +1,59 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef CF_CONFIG_H +#define CF_CONFIG_H + +/** + * Library configuration + * ===================== + */ + +/* .. c:macro:: CF_SIDE_CHANNEL_PROTECTION + * Define this as 1 if you need all available side channel protections. + * **This option may alter the ABI**. + * + * This has a non-trivial performance penalty. Where a + * side-channel free option is cheap or free (like checking + * a MAC) this is always done in a side-channel free way. + * + * The default is **on** for all available protections. + */ +#ifndef CF_SIDE_CHANNEL_PROTECTION +# define CF_SIDE_CHANNEL_PROTECTION 1 +#endif + +/* .. c:macro:: CF_TIME_SIDE_CHANNEL_PROTECTION + * Define this as 1 if you need timing/branch prediction side channel + * protection. + * + * You probably want this. The default is on. */ +#ifndef CF_TIME_SIDE_CHANNEL_PROTECTION +# define CF_TIME_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION +#endif + +/* .. c:macro:: CF_CACHE_SIDE_CHANNEL_PROTECTION + * Define this as 1 if you need cache side channel protection. + * + * If you have a microcontroller with no cache, you can turn this off + * without negative effects. + * + * The default is on. This will have some performance impact, + * especially on AES. + */ +#ifndef CF_CACHE_SIDE_CHANNEL_PROTECTION +# define CF_CACHE_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION +#endif + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20.c new file mode 100644 index 0000000..7a3bf38 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20.c @@ -0,0 +1,161 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "bitops.h" +#include "salsa20.h" +#include "blockwise.h" +#include "tassert.h" + +#include <string.h> +#include <stdlib.h> + +void cf_chacha20_core(const uint8_t key0[16], + const uint8_t key1[16], + const uint8_t nonce[16], + const uint8_t constant[16], + uint8_t out[64]) +{ + uint32_t z0, z1, z2, z3, z4, z5, z6, z7, + z8, z9, za, zb, zc, zd, ze, zf; + + uint32_t x0 = z0 = read32_le(constant + 0), + x1 = z1 = read32_le(constant + 4), + x2 = z2 = read32_le(constant + 8), + x3 = z3 = read32_le(constant + 12), + x4 = z4 = read32_le(key0 + 0), + x5 = z5 = read32_le(key0 + 4), + x6 = z6 = read32_le(key0 + 8), + x7 = z7 = read32_le(key0 + 12), + x8 = z8 = read32_le(key1 + 0), + x9 = z9 = read32_le(key1 + 4), + xa = za = read32_le(key1 + 8), + xb = zb = read32_le(key1 + 12), + xc = zc = read32_le(nonce + 0), + xd = zd = read32_le(nonce + 4), + xe = ze = read32_le(nonce + 8), + xf = zf = read32_le(nonce + 12); + +#define QUARTER(a, b, c, d) \ + a += b; d = rotl32(d ^ a, 16); \ + c += d; b = rotl32(b ^ c, 12); \ + a += b; d = rotl32(d ^ a, 8); \ + c += d; b = rotl32(b ^ c, 7); + + int i; + for (i = 0; i < 10; i++) + { + QUARTER(z0, z4, z8, zc); + QUARTER(z1, z5, z9, zd); + QUARTER(z2, z6, za, ze); + QUARTER(z3, z7, zb, zf); + QUARTER(z0, z5, za, zf); + QUARTER(z1, z6, zb, zc); + QUARTER(z2, z7, z8, zd); + QUARTER(z3, z4, z9, ze); + } + + x0 += z0; + x1 += z1; + x2 += z2; + x3 += z3; + x4 += z4; + x5 += z5; + x6 += z6; + x7 += z7; + x8 += z8; + x9 += z9; + xa += za; + xb += zb; + xc += zc; + xd += zd; + xe += ze; + xf += zf; + + write32_le(x0, out + 0); + write32_le(x1, out + 4); + write32_le(x2, out + 8); + write32_le(x3, out + 12); + write32_le(x4, out + 16); + write32_le(x5, out + 20); + write32_le(x6, out + 24); + write32_le(x7, out + 28); + write32_le(x8, out + 32); + write32_le(x9, out + 36); + write32_le(xa, out + 40); + write32_le(xb, out + 44); + write32_le(xc, out + 48); + write32_le(xd, out + 52); + write32_le(xe, out + 56); + write32_le(xf, out + 60); +} + +static const uint8_t *chacha20_tau = (const uint8_t *) "expand 16-byte k"; +static const uint8_t *chacha20_sigma = (const uint8_t *) "expand 32-byte k"; + +static void set_key(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey) +{ + switch (nkey) + { + case 16: + memcpy(ctx->key0, key, 16); + memcpy(ctx->key1, key, 16); + ctx->constant = chacha20_tau; + break; + case 32: + memcpy(ctx->key0, key, 16); + memcpy(ctx->key1, key + 16, 16); + ctx->constant = chacha20_sigma; + break; + default: + abort(); + } +} + +void cf_chacha20_init(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]) +{ + set_key(ctx, key, nkey); + memset(ctx->nonce, 0, sizeof ctx->nonce); + memcpy(ctx->nonce + 8, nonce, 8); + ctx->nblock = 0; + ctx->ncounter = 8; +} + +void cf_chacha20_init_custom(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, + const uint8_t nonce[16], size_t ncounter) +{ + assert(ncounter > 0); + set_key(ctx, key, nkey); + memcpy(ctx->nonce, nonce, sizeof ctx->nonce); + ctx->nblock = 0; + ctx->ncounter = ncounter; +} + +static void cf_chacha20_next_block(void *vctx, uint8_t *out) +{ + cf_chacha20_ctx *ctx = vctx; + cf_chacha20_core(ctx->key0, + ctx->key1, + ctx->nonce, + ctx->constant, + out); + incr_le(ctx->nonce, ctx->ncounter); +} + +void cf_chacha20_cipher(cf_chacha20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t bytes) +{ + cf_blockwise_xor(ctx->block, &ctx->nblock, 64, + input, output, bytes, + cf_chacha20_next_block, + ctx); +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20poly1305.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20poly1305.c new file mode 100644 index 0000000..0aef725 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20poly1305.c @@ -0,0 +1,148 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "chacha20poly1305.h" +#include "salsa20.h" +#include "poly1305.h" +#include "bitops.h" +#include "handy.h" + +#define ENCRYPT 1 +#define DECRYPT 0 + +#define SUCCESS 0 +#define FAILURE 1 + +static int process(const uint8_t key[32], + const uint8_t nonce[12], + const uint8_t *header, size_t nheader, + const uint8_t *input, size_t nbytes, + uint8_t *output, + int mode, + uint8_t tag[16]) +{ + /* First, generate the Poly1305 key by running ChaCha20 with the + * given key and a zero counter. The first half of the + * 64-byte output is the key. */ + uint8_t fullnonce[16] = { 0 }; + memcpy(fullnonce + 4, nonce, 12); + + uint8_t polykey[32] = { 0 }; + cf_chacha20_ctx chacha; + cf_chacha20_init_custom(&chacha, key, 32, fullnonce, 4); + cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey); + + /* Now initialise Poly1305. */ + cf_poly1305 poly; + cf_poly1305_init(&poly, polykey, polykey + 16); + mem_clean(polykey, sizeof polykey); + + /* Discard next 32 bytes of chacha20 key stream. */ + cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey); + mem_clean(polykey, sizeof polykey); + + /* The input to Poly1305 is: + * AAD || pad(AAD) || cipher || pad(cipher) || len_64(aad) || len_64(cipher) */ + uint8_t padbuf[16] = { 0 }; + +#define PADLEN(x) (16 - ((x) & 0xf)) + + /* AAD || pad(AAD) */ + cf_poly1305_update(&poly, header, nheader); + cf_poly1305_update(&poly, padbuf, PADLEN(nheader)); + + /* || cipher */ + if (mode == ENCRYPT) + { + /* If we're encrypting, we compute the ciphertext + * before inputting it into the MAC. */ + cf_chacha20_cipher(&chacha, input, output, nbytes); + cf_poly1305_update(&poly, output, nbytes); + } else { + /* Otherwise: decryption -- input the ciphertext. + * Delay actual decryption until we checked the MAC. */ + cf_poly1305_update(&poly, input, nbytes); + } + + /* || pad(cipher) */ + cf_poly1305_update(&poly, padbuf, PADLEN(nbytes)); + + /* || len_64(aad) || len_64(cipher) */ + write64_le(nheader, padbuf); + write64_le(nbytes, padbuf + 8); + cf_poly1305_update(&poly, padbuf, sizeof padbuf); + + /* MAC computation is now complete. */ + + if (mode == ENCRYPT) + { + cf_poly1305_finish(&poly, tag); + mem_clean(&chacha, sizeof chacha); + return SUCCESS; + } + + /* Decrypt mode: calculate tag, and check it. + * If it's correct, proceed with decryption. */ + uint8_t checktag[16]; + cf_poly1305_finish(&poly, checktag); + + if (mem_eq(checktag, tag, sizeof checktag)) + { + cf_chacha20_cipher(&chacha, input, output, nbytes); + mem_clean(&chacha, sizeof chacha); + mem_clean(checktag, sizeof checktag); + return SUCCESS; + } else { + mem_clean(output, nbytes); + mem_clean(&chacha, sizeof chacha); + mem_clean(checktag, sizeof checktag); + return FAILURE; + } +} + +void cf_chacha20poly1305_encrypt(const uint8_t key[32], + const uint8_t nonce[12], + const uint8_t *header, size_t nheader, + const uint8_t *plaintext, size_t nbytes, + uint8_t *ciphertext, + uint8_t tag[16]) +{ + process(key, + nonce, + header, nheader, + plaintext, nbytes, + ciphertext, + ENCRYPT, + tag); +} + +int cf_chacha20poly1305_decrypt(const uint8_t key[32], + const uint8_t nonce[12], + const uint8_t *header, size_t nheader, + const uint8_t *ciphertext, size_t nbytes, + const uint8_t tag[16], + uint8_t *plaintext) +{ + uint8_t ourtag[16]; + memcpy(ourtag, tag, sizeof ourtag); + + return process(key, + nonce, + header, nheader, + ciphertext, nbytes, + plaintext, + DECRYPT, + ourtag); +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20poly1305.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20poly1305.h new file mode 100644 index 0000000..1d44156 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chacha20poly1305.h @@ -0,0 +1,73 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef CHACHA20POLY1305_H +#define CHACHA20POLY1305_H + +#include <stdint.h> +#include <stddef.h> + +/** + * The ChaCha20-Poly1305 AEAD construction + * ======================================= + * This is a composition of the ChaCha20 stream cipher and + * the Poly1305 polynomial MAC to form an AEAD. + * It's specified for use in TLS in the form of RFC7539. + * + * It uses a 256-bit key and a 96-bit nonce. + * + * This is a one-shot interface. + */ + +/* .. c:function:: $DECL + * ChaCha20-Poly1305 authenticated encryption. + * + * :param key: key material. + * :param nonce: per-message nonce. + * :param header: header buffer. + * :param nheader: number of header bytes. + * :param plaintext: plaintext bytes to be encrypted. + * :param nbytes: number of plaintext/ciphertext bytes. + * :param ciphertext: ciphertext output buffer, nbytes in length. + * :param tag: authentication tag output buffer. + */ +void cf_chacha20poly1305_encrypt(const uint8_t key[32], + const uint8_t nonce[12], + const uint8_t *header, size_t nheader, + const uint8_t *plaintext, size_t nbytes, + uint8_t *ciphertext, + uint8_t tag[16]); + +/* .. c:function:: $DECL + * ChaCha20-Poly1305 authenticated decryption. + * + * :return: 0 on success, non-zero on error. Plaintext is zeroed on error. + * + * :param key: key material. + * :param nonce: per-message nonce. + * :param header: header buffer. + * :param nheader: number of header bytes. + * :param ciphertext: ciphertext bytes to be decrypted. + * :param nbytes: number of plaintext/ciphertext bytes. + * :param plaintext: plaintext output buffer, nbytes in length. + * :param tag: authentication tag output buffer. + */ +int cf_chacha20poly1305_decrypt(const uint8_t key[32], + const uint8_t nonce[12], + const uint8_t *header, size_t nheader, + const uint8_t *ciphertext, size_t nbytes, + const uint8_t tag[16], + uint8_t *plaintext); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/chash.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chash.c new file mode 100644 index 0000000..4ee5d76 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chash.c @@ -0,0 +1,28 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "chash.h" +#include "handy.h" +#include "tassert.h" + +void cf_hash(const cf_chash *h, const void *m, size_t nm, uint8_t *out) +{ + cf_chash_ctx ctx; + assert(h); + h->init(&ctx); + h->update(&ctx, m, nm); + h->digest(&ctx, out); + mem_clean(&ctx, sizeof ctx); +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/chash.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chash.h new file mode 100644 index 0000000..8f2e201 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/chash.h @@ -0,0 +1,137 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef CHASH_H +#define CHASH_H + +#include <stddef.h> +#include <stdint.h> + +/** + * General hash function description + * ================================= + * This allows us to make use of hash functions without depending + * on a specific one. This is useful in implementing, for example, + * :doc:`HMAC <hmac>`. + */ + +/* .. c:type:: cf_chash_init + * Hashing initialisation function type. + * + * Functions of this type should initialise the context in preparation + * for hashing a message with `cf_chash_update` functions. + * + * :rtype: void + * :param ctx: hash function-specific context structure. + */ +typedef void (*cf_chash_init)(void *ctx); + +/* .. c:type:: cf_chash_update + * Hashing data processing function type. + * + * Functions of this type hash `count` bytes of data at `data`, + * updating the contents of `ctx`. + * + * :rtype: void + * :param ctx: hash function-specific context structure. + * :param data: input data to hash. + * :param count: number of bytes to hash. + */ +typedef void (*cf_chash_update)(void *ctx, const void *data, size_t count); + +/* .. c:type:: cf_chash_digest + * Hashing completion function type. + * + * Functions of this type complete a hashing operation, + * writing :c:member:`cf_chash.hashsz` bytes to `hash`. + * + * This function does not change `ctx` -- any padding which needs doing + * must be done seperately (in a copy of `ctx`, say). + * + * This means you can interlave `_update` and `_digest` calls to + * learn `H(A)` and `H(A || B)` without hashing `A` twice. + * + * :rtype: void + * :param ctx: hash function-specific context structure. + * :param hash: location to write hash result. + */ +typedef void (*cf_chash_digest)(const void *ctx, uint8_t *hash); + +/* .. c:type:: cf_chash + * This type describes an incremental hash function in an abstract way. + * + * .. c:member:: cf_chash.hashsz + * The hash function's output, in bytes. + * + * .. c:member:: cf_chash.blocksz + * The hash function's internal block size, in bytes. + * + * .. c:member:: cf_chash.init + * Context initialisation function. + * + * .. c:member:: cf_chash:update + * Data processing function. + * + * .. c:member:: cf_chash:digest + * Completion function. + * + */ +typedef struct +{ + size_t hashsz; + size_t blocksz; + + cf_chash_init init; + cf_chash_update update; + cf_chash_digest digest; +} cf_chash; + +/* .. c:macro:: CF_CHASH_MAXCTX + * The maximum size of a :c:type:`cf_chash_ctx`. This allows + * use to put a structure in automatic storage that can + * store working data for any supported hash function. */ +#define CF_CHASH_MAXCTX 360 + +/* .. c:macro:: CF_CHASH_MAXBLK + * Maximum hash function block size (in bytes). */ +#define CF_CHASH_MAXBLK 128 + +/* .. c:macro:: CF_MAXHASH + * Maximum hash function output (in bytes). */ +#define CF_MAXHASH 64 + +/* .. c:type:: cf_chash_ctx + * A type usable with any `cf_chash` as a context. */ +typedef union +{ + uint8_t ctx[CF_CHASH_MAXCTX]; + uint16_t u16; + uint32_t u32; + uint64_t u64; +} cf_chash_ctx; + +/* .. c:function:: $DECL + * One shot hashing: `out = h(m)`. + * + * Using the hash function `h`, `nm` bytes at `m` are hashed and `h->hashsz` bytes + * of result is written to the buffer `out`. + * + * :param h: hash function description. + * :param m: message buffer. + * :param nm: message length. + * :param out: hash result buffer (written). + */ +void cf_hash(const cf_chash *h, const void *m, size_t nm, uint8_t *out); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/cmac.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/cmac.c new file mode 100644 index 0000000..51f5843 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/cmac.c @@ -0,0 +1,150 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "handy.h" +#include "prp.h" +#include "modes.h" +#include "bitops.h" +#include "blockwise.h" +#include "gf128.h" +#include "tassert.h" + +#include <string.h> + +void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx) +{ + uint8_t L[CF_MAXBLOCK]; + assert(prp->blocksz == 16); + + mem_clean(ctx, sizeof *ctx); + + /* L = E_K(0^n) */ + mem_clean(L, prp->blocksz); + prp->encrypt(prpctx, L, L); + + /* B = 2L */ + cf_gf128 gf; + cf_gf128_frombytes_be(L, gf); + cf_gf128_double(gf, gf); + cf_gf128_tobytes_be(gf, ctx->B); + + /* P = 4L */ + cf_gf128_double(gf, gf); + cf_gf128_tobytes_be(gf, ctx->P); + + ctx->prp = prp; + ctx->prpctx = prpctx; +} + +void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t len, uint8_t out[CF_MAXBLOCK]) +{ + cf_cmac_stream stream; + stream.cmac = *ctx; + cf_cmac_stream_reset(&stream); + cf_cmac_stream_update(&stream, data, len, 1); + cf_cmac_stream_final(&stream, out); +} + +void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx) +{ + cf_cmac_init(&ctx->cmac, prp, prpctx); + cf_cmac_stream_reset(ctx); +} + +void cf_cmac_stream_reset(cf_cmac_stream *ctx) +{ + uint8_t iv_zero[CF_MAXBLOCK] = { 0 }; + cf_cbc_init(&ctx->cbc, ctx->cmac.prp, ctx->cmac.prpctx, iv_zero); + mem_clean(ctx->buffer, sizeof ctx->buffer); + ctx->used = 0; + ctx->processed = 0; + ctx->finalised = 0; +} + +static void cmac_process(void *vctx, const uint8_t *block) +{ + cf_cmac_stream *ctx = vctx; + uint8_t output[CF_MAXBLOCK]; + cf_cbc_encrypt(&ctx->cbc, block, output, 1); + ctx->processed += ctx->cmac.prp->blocksz; +} + +static void cmac_process_final(cf_cmac_stream *ctx, const uint8_t *block, + const uint8_t *xor) +{ + uint8_t input[CF_MAXBLOCK]; + uint8_t output[CF_MAXBLOCK]; + xor_bb(input, block, xor, ctx->cmac.prp->blocksz); + cf_cbc_encrypt(&ctx->cbc, input, output, 1); + ctx->processed += ctx->cmac.prp->blocksz; + /* signature is in ctx->cbc.block. */ +} + +static void cmac_process_final_nopad(void *vctx, const uint8_t *block) +{ + cf_cmac_stream *ctx = vctx; + cmac_process_final(ctx, block, ctx->cmac.B); + ctx->finalised = 1; +} + +static void cmac_process_final_pad(void *vctx, const uint8_t *block) +{ + cf_cmac_stream *ctx = vctx; + cmac_process_final(ctx, block, ctx->cmac.P); + ctx->finalised = 1; +} + +void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len, int isfinal) +{ + size_t blocksz = ctx->cmac.prp->blocksz; + cf_blockwise_in_fn final_fn = cmac_process; + int needpad = 0; + + if (isfinal) + { + int whole_number_of_blocks = ((len + ctx->used) & 0xf) == 0; + int empty_message = len == 0 && ctx->used == 0 && ctx->processed == 0; + + assert(!ctx->finalised); /* finalised before? */ + assert(len != 0 || empty_message); /* we can't be told we're done after the fact. */ + + /* If we have a whole number of blocks, and at least 1 block, we XOR in B. + * Otherwise, we need to pad and XOR in P. */ + if (whole_number_of_blocks && !empty_message) + final_fn = cmac_process_final_nopad; + else + needpad = 1; + } + + /* Input data */ + cf_blockwise_accumulate_final(ctx->buffer, &ctx->used, blocksz, + data, len, + cmac_process, + final_fn, ctx); + + /* Input padding */ + if (needpad) + { + cf_blockwise_acc_pad(ctx->buffer, &ctx->used, blocksz, + 0x80, 0x00, 0x00, blocksz - ctx->used, + cmac_process_final_pad, ctx); + } +} + +void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK]) +{ + assert(ctx->finalised); + memcpy(out, ctx->cbc.block, ctx->cmac.prp->blocksz); +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.c new file mode 100644 index 0000000..6c4b9c1 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.c @@ -0,0 +1,29 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#if defined(CORTEX_M0) || defined(CORTEX_M3) || defined(CORTEX_M4) +#include "arm/unacl/scalarmult.c" + +void cf_curve25519_mul(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32]) +{ + crypto_scalarmult_curve25519(out, scalar, point); +} + +void cf_curve25519_mul_base(uint8_t out[32], const uint8_t scalar[32]) +{ + crypto_scalarmult_curve25519_base(out, scalar); +} +#else +#include "curve25519.tweetnacl.c" +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.donna.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.donna.c new file mode 100644 index 0000000..3c597d3 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.donna.c @@ -0,0 +1,867 @@ +/* Copyright 2008, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * curve25519-donna: Curve25519 elliptic curve, public key function + * + * http://code.google.com/p/curve25519-donna/ + * + * Adam Langley <agl@imperialviolet.org> + * + * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to> + * + * More information about curve25519 can be found here + * http://cr.yp.to/ecdh.html + * + * djb's sample implementation of curve25519 is written in a special assembly + * language called qhasm and uses the floating point registers. + * + * This is, almost, a clean room reimplementation from the curve25519 paper. It + * uses many of the tricks described therein. Only the crecip function is taken + * from the sample implementation. */ + +#include "curve25519.h" + +#include <string.h> +#include <stdint.h> + +#ifdef _MSC_VER +#define inline __inline +#endif + +typedef uint8_t u8; +typedef int32_t s32; +typedef int64_t limb; + +/* Field element representation: + * + * Field elements are written as an array of signed, 64-bit limbs, least + * significant first. The value of the field element is: + * x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ... + * + * i.e. the limbs are 26, 25, 26, 25, ... bits wide. */ + +/* Sum two numbers: output += in */ +static void fsum(limb *output, const limb *in) { + unsigned i; + for (i = 0; i < 10; i += 2) { + output[0+i] = output[0+i] + in[0+i]; + output[1+i] = output[1+i] + in[1+i]; + } +} + +/* Find the difference of two numbers: output = in - output + * (note the order of the arguments!). */ +static void fdifference(limb *output, const limb *in) { + unsigned i; + for (i = 0; i < 10; ++i) { + output[i] = in[i] - output[i]; + } +} + +/* Multiply a number by a scalar: output = in * scalar */ +static void fscalar_product(limb *output, const limb *in, const limb scalar) { + unsigned i; + for (i = 0; i < 10; ++i) { + output[i] = in[i] * scalar; + } +} + +/* Multiply two numbers: output = in2 * in + * + * output must be distinct to both inputs. The inputs are reduced coefficient + * form, the output is not. + * + * output[x] <= 14 * the largest product of the input limbs. */ +static void fproduct(limb *output, const limb *in2, const limb *in) { + output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]); + output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + + ((limb) ((s32) in2[1])) * ((s32) in[0]); + output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[2]) + + ((limb) ((s32) in2[2])) * ((s32) in[0]); + output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) + + ((limb) ((s32) in2[2])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[0]); + output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) + + 2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[1])) + + ((limb) ((s32) in2[0])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[0]); + output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) + + ((limb) ((s32) in2[3])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[0]); + output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[1])) + + ((limb) ((s32) in2[2])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[2]) + + ((limb) ((s32) in2[0])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[0]); + output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) + + ((limb) ((s32) in2[4])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[0]); + output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) + + 2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[1])) + + ((limb) ((s32) in2[2])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[2]) + + ((limb) ((s32) in2[0])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[0]); + output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) + + ((limb) ((s32) in2[5])) * ((s32) in[4]) + + ((limb) ((s32) in2[3])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[2]) + + ((limb) ((s32) in2[1])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[1]) + + ((limb) ((s32) in2[0])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[0]); + output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) + + ((limb) ((s32) in2[3])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[3]) + + ((limb) ((s32) in2[1])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[1])) + + ((limb) ((s32) in2[4])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[4]) + + ((limb) ((s32) in2[2])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[2]); + output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) + + ((limb) ((s32) in2[6])) * ((s32) in[5]) + + ((limb) ((s32) in2[4])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[4]) + + ((limb) ((s32) in2[3])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[3]) + + ((limb) ((s32) in2[2])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[2]); + output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) + + 2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[5]) + + ((limb) ((s32) in2[3])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[3])) + + ((limb) ((s32) in2[4])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[4]); + output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) + + ((limb) ((s32) in2[7])) * ((s32) in[6]) + + ((limb) ((s32) in2[5])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[5]) + + ((limb) ((s32) in2[4])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[4]); + output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) + + ((limb) ((s32) in2[5])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[5])) + + ((limb) ((s32) in2[6])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[6]); + output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) + + ((limb) ((s32) in2[8])) * ((s32) in[7]) + + ((limb) ((s32) in2[6])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[6]); + output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[7])); + output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) + + ((limb) ((s32) in2[9])) * ((s32) in[8]); + output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]); +} + +/* Reduce a long form to a short form by taking the input mod 2^255 - 19. + * + * On entry: |output[i]| < 14*2^54 + * On exit: |output[0..8]| < 280*2^54 */ +static void freduce_degree(limb *output) { + /* Each of these shifts and adds ends up multiplying the value by 19. + * + * For output[0..8], the absolute entry value is < 14*2^54 and we add, at + * most, 19*14*2^54 thus, on exit, |output[0..8]| < 280*2^54. */ + output[8] += output[18] << 4; + output[8] += output[18] << 1; + output[8] += output[18]; + output[7] += output[17] << 4; + output[7] += output[17] << 1; + output[7] += output[17]; + output[6] += output[16] << 4; + output[6] += output[16] << 1; + output[6] += output[16]; + output[5] += output[15] << 4; + output[5] += output[15] << 1; + output[5] += output[15]; + output[4] += output[14] << 4; + output[4] += output[14] << 1; + output[4] += output[14]; + output[3] += output[13] << 4; + output[3] += output[13] << 1; + output[3] += output[13]; + output[2] += output[12] << 4; + output[2] += output[12] << 1; + output[2] += output[12]; + output[1] += output[11] << 4; + output[1] += output[11] << 1; + output[1] += output[11]; + output[0] += output[10] << 4; + output[0] += output[10] << 1; + output[0] += output[10]; +} + +#if (-1 & 3) != 3 +#error "This code only works on a two's complement system" +#endif + +/* return v / 2^26, using only shifts and adds. + * + * On entry: v can take any value. */ +static inline limb +div_by_2_26(const limb v) +{ + /* High word of v; no shift needed. */ + const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); + /* Set to all 1s if v was negative; else set to 0s. */ + const int32_t sign = ((int32_t) highword) >> 31; + /* Set to 0x3ffffff if v was negative; else set to 0. */ + const int32_t roundoff = ((uint32_t) sign) >> 6; + /* Should return v / (1<<26) */ + return (v + roundoff) >> 26; +} + +/* return v / (2^25), using only shifts and adds. + * + * On entry: v can take any value. */ +static inline limb +div_by_2_25(const limb v) +{ + /* High word of v; no shift needed*/ + const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); + /* Set to all 1s if v was negative; else set to 0s. */ + const int32_t sign = ((int32_t) highword) >> 31; + /* Set to 0x1ffffff if v was negative; else set to 0. */ + const int32_t roundoff = ((uint32_t) sign) >> 7; + /* Should return v / (1<<25) */ + return (v + roundoff) >> 25; +} + +/* Reduce all coefficients of the short form input so that |x| < 2^26. + * + * On entry: |output[i]| < 280*2^54 */ +static void freduce_coefficients(limb *output) { + unsigned i; + + output[10] = 0; + + for (i = 0; i < 10; i += 2) { + limb over = div_by_2_26(output[i]); + /* The entry condition (that |output[i]| < 280*2^54) means that over is, at + * most, 280*2^28 in the first iteration of this loop. This is added to the + * next limb and we can approximate the resulting bound of that limb by + * 281*2^54. */ + output[i] -= over << 26; + output[i+1] += over; + + /* For the first iteration, |output[i+1]| < 281*2^54, thus |over| < + * 281*2^29. When this is added to the next limb, the resulting bound can + * be approximated as 281*2^54. + * + * For subsequent iterations of the loop, 281*2^54 remains a conservative + * bound and no overflow occurs. */ + over = div_by_2_25(output[i+1]); + output[i+1] -= over << 25; + output[i+2] += over; + } + /* Now |output[10]| < 281*2^29 and all other coefficients are reduced. */ + output[0] += output[10] << 4; + output[0] += output[10] << 1; + output[0] += output[10]; + + output[10] = 0; + + /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19*281*2^29 + * So |over| will be no more than 2^16. */ + { + limb over = div_by_2_26(output[0]); + output[0] -= over << 26; + output[1] += over; + } + + /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 2^16 < 2^26. The + * bound on |output[1]| is sufficient to meet our needs. */ +} + +/* A helpful wrapper around fproduct: output = in * in2. + * + * On entry: |in[i]| < 2^27 and |in2[i]| < 2^27. + * + * output must be distinct to both inputs. The output is reduced degree + * (indeed, one need only provide storage for 10 limbs) and |output[i]| < 2^26. */ +static void +fmul(limb *output, const limb *in, const limb *in2) { + limb t[19]; + fproduct(t, in, in2); + /* |t[i]| < 14*2^54 */ + freduce_degree(t); + freduce_coefficients(t); + /* |t[i]| < 2^26 */ + memcpy(output, t, sizeof(limb) * 10); +} + +/* Square a number: output = in**2 + * + * output must be distinct from the input. The inputs are reduced coefficient + * form, the output is not. + * + * output[x] <= 14 * the largest product of the input limbs. */ +static void fsquare_inner(limb *output, const limb *in) { + output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); + output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); + output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + + ((limb) ((s32) in[0])) * ((s32) in[2])); + output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + + ((limb) ((s32) in[0])) * ((s32) in[3])); + output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + + 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + + 2 * ((limb) ((s32) in[0])) * ((s32) in[4]); + output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + + ((limb) ((s32) in[1])) * ((s32) in[4]) + + ((limb) ((s32) in[0])) * ((s32) in[5])); + output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + + ((limb) ((s32) in[2])) * ((s32) in[4]) + + ((limb) ((s32) in[0])) * ((s32) in[6]) + + 2 * ((limb) ((s32) in[1])) * ((s32) in[5])); + output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + + ((limb) ((s32) in[2])) * ((s32) in[5]) + + ((limb) ((s32) in[1])) * ((s32) in[6]) + + ((limb) ((s32) in[0])) * ((s32) in[7])); + output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) + + 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) + + ((limb) ((s32) in[0])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[5]))); + output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) + + ((limb) ((s32) in[3])) * ((s32) in[6]) + + ((limb) ((s32) in[2])) * ((s32) in[7]) + + ((limb) ((s32) in[1])) * ((s32) in[8]) + + ((limb) ((s32) in[0])) * ((s32) in[9])); + output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) + + ((limb) ((s32) in[4])) * ((s32) in[6]) + + ((limb) ((s32) in[2])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) + + ((limb) ((s32) in[1])) * ((s32) in[9]))); + output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) + + ((limb) ((s32) in[4])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[8]) + + ((limb) ((s32) in[2])) * ((s32) in[9])); + output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) + + 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) + + 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) + + ((limb) ((s32) in[3])) * ((s32) in[9]))); + output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) + + ((limb) ((s32) in[5])) * ((s32) in[8]) + + ((limb) ((s32) in[4])) * ((s32) in[9])); + output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) + + ((limb) ((s32) in[6])) * ((s32) in[8]) + + 2 * ((limb) ((s32) in[5])) * ((s32) in[9])); + output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) + + ((limb) ((s32) in[6])) * ((s32) in[9])); + output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) + + 4 * ((limb) ((s32) in[7])) * ((s32) in[9]); + output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]); + output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); +} + +/* fsquare sets output = in^2. + * + * On entry: The |in| argument is in reduced coefficients form and |in[i]| < + * 2^27. + * + * On exit: The |output| argument is in reduced coefficients form (indeed, one + * need only provide storage for 10 limbs) and |out[i]| < 2^26. */ +static void +fsquare(limb *output, const limb *in) { + limb t[19]; + fsquare_inner(t, in); + /* |t[i]| < 14*2^54 because the largest product of two limbs will be < + * 2^(27+27) and fsquare_inner adds together, at most, 14 of those + * products. */ + freduce_degree(t); + freduce_coefficients(t); + /* |t[i]| < 2^26 */ + memcpy(output, t, sizeof(limb) * 10); +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +static void +fexpand(limb *output, const u8 *input) { +#define F(n,start,shift,mask) \ + output[n] = ((((limb) input[start + 0]) | \ + ((limb) input[start + 1]) << 8 | \ + ((limb) input[start + 2]) << 16 | \ + ((limb) input[start + 3]) << 24) >> shift) & mask; + F(0, 0, 0, 0x3ffffff); + F(1, 3, 2, 0x1ffffff); + F(2, 6, 3, 0x3ffffff); + F(3, 9, 5, 0x1ffffff); + F(4, 12, 6, 0x3ffffff); + F(5, 16, 0, 0x1ffffff); + F(6, 19, 1, 0x3ffffff); + F(7, 22, 3, 0x1ffffff); + F(8, 25, 4, 0x3ffffff); + F(9, 28, 6, 0x1ffffff); +#undef F +} + +#if (-32 >> 1) != -16 +#error "This code only works when >> does sign-extension on negative numbers" +#endif + +/* s32_eq returns 0xffffffff iff a == b and zero otherwise. */ +static s32 s32_eq(s32 a, s32 b) { + a = ~(a ^ b); + a &= a << 16; + a &= a << 8; + a &= a << 4; + a &= a << 2; + a &= a << 1; + return a >> 31; +} + +/* s32_gte returns 0xffffffff if a >= b and zero otherwise, where a and b are + * both non-negative. */ +static s32 s32_gte(s32 a, s32 b) { + a -= b; + /* a >= 0 iff a >= b. */ + return ~(a >> 31); +} + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array. + * + * On entry: |input_limbs[i]| < 2^26 */ +static void +fcontract(u8 *output, limb *input_limbs) { + int i; + int j; + s32 input[10]; + s32 mask; + + /* |input_limbs[i]| < 2^26, so it's valid to convert to an s32. */ + for (i = 0; i < 10; i++) { + input[i] = input_limbs[i]; + } + + for (j = 0; j < 2; ++j) { + for (i = 0; i < 9; ++i) { + if ((i & 1) == 1) { + /* This calculation is a time-invariant way to make input[i] + * non-negative by borrowing from the next-larger limb. */ + const s32 mask = input[i] >> 31; + const s32 carry = -((input[i] & mask) >> 25); + input[i] = input[i] + (carry << 25); + input[i+1] = input[i+1] - carry; + } else { + const s32 mask = input[i] >> 31; + const s32 carry = -((input[i] & mask) >> 26); + input[i] = input[i] + (carry << 26); + input[i+1] = input[i+1] - carry; + } + } + + /* There's no greater limb for input[9] to borrow from, but we can multiply + * by 19 and borrow from input[0], which is valid mod 2^255-19. */ + { + const s32 mask = input[9] >> 31; + const s32 carry = -((input[9] & mask) >> 25); + input[9] = input[9] + (carry << 25); + input[0] = input[0] - (carry * 19); + } + + /* After the first iteration, input[1..9] are non-negative and fit within + * 25 or 26 bits, depending on position. However, input[0] may be + * negative. */ + } + + /* The first borrow-propagation pass above ended with every limb + except (possibly) input[0] non-negative. + + If input[0] was negative after the first pass, then it was because of a + carry from input[9]. On entry, input[9] < 2^26 so the carry was, at most, + one, since (2**26-1) >> 25 = 1. Thus input[0] >= -19. + + In the second pass, each limb is decreased by at most one. Thus the second + borrow-propagation pass could only have wrapped around to decrease + input[0] again if the first pass left input[0] negative *and* input[1] + through input[9] were all zero. In that case, input[1] is now 2^25 - 1, + and this last borrow-propagation step will leave input[1] non-negative. */ + { + const s32 mask = input[0] >> 31; + const s32 carry = -((input[0] & mask) >> 26); + input[0] = input[0] + (carry << 26); + input[1] = input[1] - carry; + } + + /* All input[i] are now non-negative. However, there might be values between + * 2^25 and 2^26 in a limb which is, nominally, 25 bits wide. */ + for (j = 0; j < 2; j++) { + for (i = 0; i < 9; i++) { + if ((i & 1) == 1) { + const s32 carry = input[i] >> 25; + input[i] &= 0x1ffffff; + input[i+1] += carry; + } else { + const s32 carry = input[i] >> 26; + input[i] &= 0x3ffffff; + input[i+1] += carry; + } + } + + { + const s32 carry = input[9] >> 25; + input[9] &= 0x1ffffff; + input[0] += 19*carry; + } + } + + /* If the first carry-chain pass, just above, ended up with a carry from + * input[9], and that caused input[0] to be out-of-bounds, then input[0] was + * < 2^26 + 2*19, because the carry was, at most, two. + * + * If the second pass carried from input[9] again then input[0] is < 2*19 and + * the input[9] -> input[0] carry didn't push input[0] out of bounds. */ + + /* It still remains the case that input might be between 2^255-19 and 2^255. + * In this case, input[1..9] must take their maximum value and input[0] must + * be >= (2^255-19) & 0x3ffffff, which is 0x3ffffed. */ + mask = s32_gte(input[0], 0x3ffffed); + for (i = 1; i < 10; i++) { + if ((i & 1) == 1) { + mask &= s32_eq(input[i], 0x1ffffff); + } else { + mask &= s32_eq(input[i], 0x3ffffff); + } + } + + /* mask is either 0xffffffff (if input >= 2^255-19) and zero otherwise. Thus + * this conditionally subtracts 2^255-19. */ + input[0] -= mask & 0x3ffffed; + + for (i = 1; i < 10; i++) { + if ((i & 1) == 1) { + input[i] -= mask & 0x1ffffff; + } else { + input[i] -= mask & 0x3ffffff; + } + } + + input[1] <<= 2; + input[2] <<= 3; + input[3] <<= 5; + input[4] <<= 6; + input[6] <<= 1; + input[7] <<= 3; + input[8] <<= 4; + input[9] <<= 6; +#define F(i, s) \ + output[s+0] |= input[i] & 0xff; \ + output[s+1] = (input[i] >> 8) & 0xff; \ + output[s+2] = (input[i] >> 16) & 0xff; \ + output[s+3] = (input[i] >> 24) & 0xff; + output[0] = 0; + output[16] = 0; + F(0,0); + F(1,3); + F(2,6); + F(3,9); + F(4,12); + F(5,16); + F(6,19); + F(7,22); + F(8,25); + F(9,28); +#undef F +} + +/* Input: Q, Q', Q-Q' + * Output: 2Q, Q+Q' + * + * x2 z3: long form + * x3 z3: long form + * x z: short form, destroyed + * xprime zprime: short form, destroyed + * qmqp: short form, preserved + * + * On entry and exit, the absolute value of the limbs of all inputs and outputs + * are < 2^26. */ +static void fmonty(limb *x2, limb *z2, /* output 2Q */ + limb *x3, limb *z3, /* output Q + Q' */ + limb *x, limb *z, /* input Q */ + limb *xprime, limb *zprime, /* input Q' */ + const limb *qmqp /* input Q - Q' */) { + limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], + zzprime[19], zzzprime[19], xxxprime[19]; + + memcpy(origx, x, 10 * sizeof(limb)); + fsum(x, z); + /* |x[i]| < 2^27 */ + fdifference(z, origx); /* does x - z */ + /* |z[i]| < 2^27 */ + + memcpy(origxprime, xprime, sizeof(limb) * 10); + fsum(xprime, zprime); + /* |xprime[i]| < 2^27 */ + fdifference(zprime, origxprime); + /* |zprime[i]| < 2^27 */ + fproduct(xxprime, xprime, z); + /* |xxprime[i]| < 14*2^54: the largest product of two limbs will be < + * 2^(27+27) and fproduct adds together, at most, 14 of those products. + * (Approximating that to 2^58 doesn't work out.) */ + fproduct(zzprime, x, zprime); + /* |zzprime[i]| < 14*2^54 */ + freduce_degree(xxprime); + freduce_coefficients(xxprime); + /* |xxprime[i]| < 2^26 */ + freduce_degree(zzprime); + freduce_coefficients(zzprime); + /* |zzprime[i]| < 2^26 */ + memcpy(origxprime, xxprime, sizeof(limb) * 10); + fsum(xxprime, zzprime); + /* |xxprime[i]| < 2^27 */ + fdifference(zzprime, origxprime); + /* |zzprime[i]| < 2^27 */ + fsquare(xxxprime, xxprime); + /* |xxxprime[i]| < 2^26 */ + fsquare(zzzprime, zzprime); + /* |zzzprime[i]| < 2^26 */ + fproduct(zzprime, zzzprime, qmqp); + /* |zzprime[i]| < 14*2^52 */ + freduce_degree(zzprime); + freduce_coefficients(zzprime); + /* |zzprime[i]| < 2^26 */ + memcpy(x3, xxxprime, sizeof(limb) * 10); + memcpy(z3, zzprime, sizeof(limb) * 10); + + fsquare(xx, x); + /* |xx[i]| < 2^26 */ + fsquare(zz, z); + /* |zz[i]| < 2^26 */ + fproduct(x2, xx, zz); + /* |x2[i]| < 14*2^52 */ + freduce_degree(x2); + freduce_coefficients(x2); + /* |x2[i]| < 2^26 */ + fdifference(zz, xx); // does zz = xx - zz + /* |zz[i]| < 2^27 */ + memset(zzz + 10, 0, sizeof(limb) * 9); + fscalar_product(zzz, zz, 121665); + /* |zzz[i]| < 2^(27+17) */ + /* No need to call freduce_degree here: + fscalar_product doesn't increase the degree of its input. */ + freduce_coefficients(zzz); + /* |zzz[i]| < 2^26 */ + fsum(zzz, xx); + /* |zzz[i]| < 2^27 */ + fproduct(z2, zz, zzz); + /* |z2[i]| < 14*2^(26+27) */ + freduce_degree(z2); + freduce_coefficients(z2); + /* |z2|i| < 2^26 */ +} + +/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave + * them unchanged if 'iswap' is 0. Runs in data-invariant time to avoid + * side-channel attacks. + * + * NOTE that this function requires that 'iswap' be 1 or 0; other values give + * wrong results. Also, the two limb arrays must be in reduced-coefficient, + * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped, + * and all all values in a[0..9],b[0..9] must have magnitude less than + * INT32_MAX. */ +static void +swap_conditional(limb a[19], limb b[19], limb iswap) { + unsigned i; + const s32 swap = (s32) -iswap; + + for (i = 0; i < 10; ++i) { + const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) ); + a[i] = ((s32)a[i]) ^ x; + b[i] = ((s32)b[i]) ^ x; + } +} + +/* Calculates nQ where Q is the x-coordinate of a point on the curve + * + * resultx/resultz: the x coordinate of the resulting curve point (short form) + * n: a little endian, 32-byte number + * q: a point of the curve (short form) */ +static void +cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { + limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0}; + limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; + limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1}; + limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; + + unsigned i, j; + + memcpy(nqpqx, q, sizeof(limb) * 10); + + for (i = 0; i < 32; ++i) { + u8 byte = n[31 - i]; + for (j = 0; j < 8; ++j) { + const limb bit = byte >> 7; + + swap_conditional(nqx, nqpqx, bit); + swap_conditional(nqz, nqpqz, bit); + fmonty(nqx2, nqz2, + nqpqx2, nqpqz2, + nqx, nqz, + nqpqx, nqpqz, + q); + swap_conditional(nqx2, nqpqx2, bit); + swap_conditional(nqz2, nqpqz2, bit); + + t = nqx; + nqx = nqx2; + nqx2 = t; + t = nqz; + nqz = nqz2; + nqz2 = t; + t = nqpqx; + nqpqx = nqpqx2; + nqpqx2 = t; + t = nqpqz; + nqpqz = nqpqz2; + nqpqz2 = t; + + byte <<= 1; + } + } + + memcpy(resultx, nqx, sizeof(limb) * 10); + memcpy(resultz, nqz, sizeof(limb) * 10); +} + +// ----------------------------------------------------------------------------- +// Shamelessly copied from djb's code +// ----------------------------------------------------------------------------- +static void +crecip(limb *out, const limb *z) { + limb z2[10]; + limb z9[10]; + limb z11[10]; + limb z2_5_0[10]; + limb z2_10_0[10]; + limb z2_20_0[10]; + limb z2_50_0[10]; + limb z2_100_0[10]; + limb t0[10]; + limb t1[10]; + int i; + + /* 2 */ fsquare(z2,z); + /* 4 */ fsquare(t1,z2); + /* 8 */ fsquare(t0,t1); + /* 9 */ fmul(z9,t0,z); + /* 11 */ fmul(z11,z9,z2); + /* 22 */ fsquare(t0,z11); + /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9); + + /* 2^6 - 2^1 */ fsquare(t0,z2_5_0); + /* 2^7 - 2^2 */ fsquare(t1,t0); + /* 2^8 - 2^3 */ fsquare(t0,t1); + /* 2^9 - 2^4 */ fsquare(t1,t0); + /* 2^10 - 2^5 */ fsquare(t0,t1); + /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0); + + /* 2^11 - 2^1 */ fsquare(t0,z2_10_0); + /* 2^12 - 2^2 */ fsquare(t1,t0); + /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0); + + /* 2^21 - 2^1 */ fsquare(t0,z2_20_0); + /* 2^22 - 2^2 */ fsquare(t1,t0); + /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0); + + /* 2^41 - 2^1 */ fsquare(t1,t0); + /* 2^42 - 2^2 */ fsquare(t0,t1); + /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } + /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0); + + /* 2^51 - 2^1 */ fsquare(t0,z2_50_0); + /* 2^52 - 2^2 */ fsquare(t1,t0); + /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0); + + /* 2^101 - 2^1 */ fsquare(t1,z2_100_0); + /* 2^102 - 2^2 */ fsquare(t0,t1); + /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } + /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0); + + /* 2^201 - 2^1 */ fsquare(t0,t1); + /* 2^202 - 2^2 */ fsquare(t1,t0); + /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } + /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0); + + /* 2^251 - 2^1 */ fsquare(t1,t0); + /* 2^252 - 2^2 */ fsquare(t0,t1); + /* 2^253 - 2^3 */ fsquare(t1,t0); + /* 2^254 - 2^4 */ fsquare(t0,t1); + /* 2^255 - 2^5 */ fsquare(t1,t0); + /* 2^255 - 21 */ fmul(out,t1,z11); +} + +void cf_curve25519_mul(u8 out[32], const u8 scalar[32], const u8 point[32]) +{ + limb bp[10], x[10], z[11], zmone[10]; + uint8_t e[32]; + int i; + + for (i = 0; i < 32; ++i) e[i] = scalar[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + fexpand(bp, point); + cmult(x, z, e, bp); + crecip(zmone, z); + fmul(z, x, zmone); + fcontract(out, z); +} + +void cf_curve25519_mul_base(u8 out[32], const u8 scalar[32]) +{ + uint8_t base[32] = { 9 }; + cf_curve25519_mul(out, scalar, base); +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.h new file mode 100644 index 0000000..9b0b7f5 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.h @@ -0,0 +1,42 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef CURVE25519_H +#define CURVE25519_H + +#include <stddef.h> +#include <stdint.h> + +/** + * Curve25519 + * ========== + * This is `curve25519 <http://cr.yp.to/ecdh.html>`_ with switchable + * implementations underneath. + * + * By default tweetnacl is used on hosts, and the implementation + * from μNaCl for Cortex-M0, M3 and M4. + */ + +/* .. c:function:: $DECL + * Multiplies `point` by `scalar`, putting the resulting point into `out`. */ +void cf_curve25519_mul(uint8_t out[32], + const uint8_t scalar[32], + const uint8_t point[32]); + +/* .. c:function:: $DECL + * Multiplies `scalar` by the curve25519 base point, putting the resulting + * point into `out`. */ +void cf_curve25519_mul_base(uint8_t out[32], const uint8_t scalar[32]); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.naclref.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.naclref.c new file mode 100644 index 0000000..9f331d1 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.naclref.c @@ -0,0 +1,273 @@ +/* +version 20081011 +Matthew Dempsky +Public domain. +Derived from public domain code by D. J. Bernstein. +*/ +#include "curve25519.h" + +static void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) +{ + unsigned int j; + unsigned int u; + u = 0; + for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } + u += a[31] + b[31]; out[31] = u; +} + +static void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) +{ + unsigned int j; + unsigned int u; + u = 218; + for (j = 0;j < 31;++j) { + u += a[j] + 65280 - b[j]; + out[j] = u & 255; + u >>= 8; + } + u += a[31] - b[31]; + out[31] = u; +} + +static void squeeze(unsigned int a[32]) +{ + unsigned int j; + unsigned int u; + u = 0; + for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } + u += a[31]; a[31] = u & 127; + u = 19 * (u >> 7); + for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } + u += a[31]; a[31] = u; +} + +static const unsigned int minusp[32] = { + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 +} ; + +static void freeze(unsigned int a[32]) +{ + unsigned int aorig[32]; + unsigned int j; + unsigned int negative; + + for (j = 0;j < 32;++j) aorig[j] = a[j]; + add(a,a,minusp); + negative = -((a[31] >> 7) & 1); + for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]); +} + +static void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) +{ + unsigned int i; + unsigned int j; + unsigned int u; + + for (i = 0;i < 32;++i) { + u = 0; + for (j = 0;j <= i;++j) u += a[j] * b[i - j]; + for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j]; + out[i] = u; + } + squeeze(out); +} + +static void mult121665(unsigned int out[32],const unsigned int a[32]) +{ + unsigned int j; + unsigned int u; + + u = 0; + for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } + u += 121665 * a[31]; out[31] = u & 127; + u = 19 * (u >> 7); + for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; } + u += out[j]; out[j] = u; +} + +static void square(unsigned int out[32],const unsigned int a[32]) +{ + unsigned int i; + unsigned int j; + unsigned int u; + + for (i = 0;i < 32;++i) { + u = 0; + for (j = 0;j < i - j;++j) u += a[j] * a[i - j]; + for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j]; + u *= 2; + if ((i & 1) == 0) { + u += a[i / 2] * a[i / 2]; + u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; + } + out[i] = u; + } + squeeze(out); +} + +static void select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b) +{ + unsigned int j; + unsigned int t; + unsigned int bminus1; + + bminus1 = b - 1; + for (j = 0;j < 64;++j) { + t = bminus1 & (r[j] ^ s[j]); + p[j] = s[j] ^ t; + q[j] = r[j] ^ t; + } +} + +static void mainloop(unsigned int work[64],const unsigned char e[32]) +{ + unsigned int xzm1[64]; + unsigned int xzm[64]; + unsigned int xzmb[64]; + unsigned int xzm1b[64]; + unsigned int xznb[64]; + unsigned int xzn1b[64]; + unsigned int a0[64]; + unsigned int a1[64]; + unsigned int b0[64]; + unsigned int b1[64]; + unsigned int c1[64]; + unsigned int r[32]; + unsigned int s[32]; + unsigned int t[32]; + unsigned int u[32]; + unsigned int j; + unsigned int b; + int pos; + + for (j = 0;j < 32;++j) xzm1[j] = work[j]; + xzm1[32] = 1; + for (j = 33;j < 64;++j) xzm1[j] = 0; + + xzm[0] = 1; + for (j = 1;j < 64;++j) xzm[j] = 0; + + for (pos = 254;pos >= 0;--pos) { + b = e[pos / 8] >> (pos & 7); + b &= 1; + select(xzmb,xzm1b,xzm,xzm1,b); + add(a0,xzmb,xzmb + 32); + sub(a0 + 32,xzmb,xzmb + 32); + add(a1,xzm1b,xzm1b + 32); + sub(a1 + 32,xzm1b,xzm1b + 32); + square(b0,a0); + square(b0 + 32,a0 + 32); + mult(b1,a1,a0 + 32); + mult(b1 + 32,a1 + 32,a0); + add(c1,b1,b1 + 32); + sub(c1 + 32,b1,b1 + 32); + square(r,c1 + 32); + sub(s,b0,b0 + 32); + mult121665(t,s); + add(u,t,b0); + mult(xznb,b0,b0 + 32); + mult(xznb + 32,s,u); + square(xzn1b,c1); + mult(xzn1b + 32,r,work); + select(xzm,xzm1,xznb,xzn1b,b); + } + + for (j = 0;j < 64;++j) work[j] = xzm[j]; +} + +static void recip(unsigned int out[32],const unsigned int z[32]) +{ + unsigned int z2[32]; + unsigned int z9[32]; + unsigned int z11[32]; + unsigned int z2_5_0[32]; + unsigned int z2_10_0[32]; + unsigned int z2_20_0[32]; + unsigned int z2_50_0[32]; + unsigned int z2_100_0[32]; + unsigned int t0[32]; + unsigned int t1[32]; + int i; + + /* 2 */ square(z2,z); + /* 4 */ square(t1,z2); + /* 8 */ square(t0,t1); + /* 9 */ mult(z9,t0,z); + /* 11 */ mult(z11,z9,z2); + /* 22 */ square(t0,z11); + /* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9); + + /* 2^6 - 2^1 */ square(t0,z2_5_0); + /* 2^7 - 2^2 */ square(t1,t0); + /* 2^8 - 2^3 */ square(t0,t1); + /* 2^9 - 2^4 */ square(t1,t0); + /* 2^10 - 2^5 */ square(t0,t1); + /* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0); + + /* 2^11 - 2^1 */ square(t0,z2_10_0); + /* 2^12 - 2^2 */ square(t1,t0); + /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); } + /* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0); + + /* 2^21 - 2^1 */ square(t0,z2_20_0); + /* 2^22 - 2^2 */ square(t1,t0); + /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); } + /* 2^40 - 2^0 */ mult(t0,t1,z2_20_0); + + /* 2^41 - 2^1 */ square(t1,t0); + /* 2^42 - 2^2 */ square(t0,t1); + /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); } + /* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0); + + /* 2^51 - 2^1 */ square(t0,z2_50_0); + /* 2^52 - 2^2 */ square(t1,t0); + /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } + /* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0); + + /* 2^101 - 2^1 */ square(t1,z2_100_0); + /* 2^102 - 2^2 */ square(t0,t1); + /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); } + /* 2^200 - 2^0 */ mult(t1,t0,z2_100_0); + + /* 2^201 - 2^1 */ square(t0,t1); + /* 2^202 - 2^2 */ square(t1,t0); + /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } + /* 2^250 - 2^0 */ mult(t0,t1,z2_50_0); + + /* 2^251 - 2^1 */ square(t1,t0); + /* 2^252 - 2^2 */ square(t0,t1); + /* 2^253 - 2^3 */ square(t1,t0); + /* 2^254 - 2^4 */ square(t0,t1); + /* 2^255 - 2^5 */ square(t1,t0); + /* 2^255 - 21 */ mult(out,t1,z11); +} + +static void crypto_scalarmult(unsigned char *q, + const unsigned char *n, + const unsigned char *p) +{ + unsigned int work[96]; + unsigned char e[32]; + unsigned int i; + for (i = 0;i < 32;++i) e[i] = n[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + for (i = 0;i < 32;++i) work[i] = p[i]; + mainloop(work,e); + recip(work + 32,work + 32); + mult(work + 64,work,work + 32); + freeze(work + 64); + for (i = 0;i < 32;++i) q[i] = work[64 + i]; +} + +void cf_curve25519_mul(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32]) +{ + crypto_scalarmult(out, scalar, point); +} + +void cf_curve25519_mul_base(uint8_t out[32], const uint8_t scalar[32]) +{ + uint8_t base_point[32] = { 9 }; + cf_curve25519_mul(out, scalar, base_point); +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.tweetnacl.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.tweetnacl.c new file mode 100644 index 0000000..c98c107 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/curve25519.tweetnacl.c @@ -0,0 +1,235 @@ +/* This is based on tweetnacl. Some typedefs have been + * replaced with their stdint equivalents. + * + * Original code was public domain. */ + +#include <stdint.h> +#include <stddef.h> + +#include "handy.h" + +typedef int64_t gf[16]; + +static const uint8_t _0[16], + _9[32] = {9}; +static const gf gf0, + gf1 = {1}, + _121665 = {0xDB41, 1}, + D = {0x78a3, 0x1359, 0x4dca, 0x75eb, + 0xd8ab, 0x4141, 0x0a4d, 0x0070, + 0xe898, 0x7779, 0x4079, 0x8cc7, + 0xfe73, 0x2b6f, 0x6cee, 0x5203}, + D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, + 0xb156, 0x8283, 0x149a, 0x00e0, + 0xd130, 0xeef3, 0x80f2, 0x198e, + 0xfce7, 0x56df, 0xd9dc, 0x2406}, + X = {0xd51a, 0x8f25, 0x2d60, 0xc956, + 0xa7b2, 0x9525, 0xc760, 0x692c, + 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, + 0x53fe, 0xcd6e, 0x36d3, 0x2169}, + Y = {0x6658, 0x6666, 0x6666, 0x6666, + 0x6666, 0x6666, 0x6666, 0x6666, + 0x6666, 0x6666, 0x6666, 0x6666, + 0x6666, 0x6666, 0x6666, 0x6666}, + I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, + 0xe478, 0xad2f, 0x1806, 0x2f43, + 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, + 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; + +static void set25519(gf r, const gf a) +{ + size_t i; + for (i = 0; i < 16; i++) + r[i] = a[i]; +} + +static void car25519(gf o) +{ + int64_t c; + size_t i; + + for (i = 0; i < 16; i++) + { + o[i] += (1LL << 16); + c = o[i] >> 16; + o[(i + 1) * (i < 15)] += c - 1 + 37 * (c - 1) * (i == 15); + o[i] -= c << 16; + } +} + +static void sel25519(gf p, gf q, int64_t b) +{ + int64_t tmp, mask = ~(b-1); + size_t i; + for (i = 0; i < 16; i++) + { + tmp = mask & (p[i] ^ q[i]); + p[i] ^= tmp; + q[i] ^= tmp; + } +} + +static void pack25519(uint8_t out[32], const gf n) +{ + size_t i, j; + int b; + gf m, t; + set25519(t, n); + car25519(t); + car25519(t); + car25519(t); + + for(j = 0; j < 2; j++) + { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) + { + m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); + m[i - 1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); + b = (m[15] >> 16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1 - b); + } + + for (i = 0; i < 16; i++) + { + out[2 * i] = t[i] & 0xff; + out[2 * i + 1] = (uint8_t) (t[i] >> 8); + } +} + + + +static void unpack25519(gf o, const uint8_t *n) +{ + size_t i; + for (i = 0; i < 16; i++) + o[i] = n[2 * i] + ((int64_t) n[2 * i + 1] << 8); + o[15] &= 0x7fff; +} + +static void add(gf o, const gf a, const gf b) +{ + size_t i; + for (i = 0; i < 16; i++) + o[i] = a[i] + b[i]; +} + +static void sub(gf o, const gf a, const gf b) +{ + size_t i; + for (i = 0; i < 16; i++) + o[i] = a[i] - b[i]; +} + +static void mul(gf o, const gf a, const gf b) +{ + int64_t t[31]; + size_t i, j; + + for (i = 0; i < 31; i++) + t[i] = 0; + + for (i = 0; i < 16; i++) + for (j = 0; j < 16; j++) + t[i + j] += a[i] * b[j]; + + for (i = 0; i < 15; i++) + t[i] += 38 * t[i + 16]; + + for (i = 0; i < 16; i++) + o[i] = t[i]; + + car25519(o); + car25519(o); +} + +static void sqr(gf o, const gf a) +{ + mul(o, a, a); +} + +static void inv25519(gf o, const gf i) +{ + gf c; + int a; + for (a = 0; a < 16; a++) + c[a] = i[a]; + + for (a = 253; a >= 0; a--) + { + sqr(c, c); + if(a != 2 && a != 4) + mul(c, c, i); + } + + for (a = 0; a < 16; a++) + o[a] = c[a]; +} + + +void cf_curve25519_mul(uint8_t *q, const uint8_t *n, const uint8_t *p) +{ + uint8_t z[32]; + gf x; + gf a, b, c, d, e, f; + + { + size_t i; + for (i = 0; i < 31; i++) + z[i] = n[i]; + z[31] = (n[31] & 127) | 64; + z[0] &= 248; + + unpack25519(x, p); + + for(i = 0; i < 16; i++) + { + b[i] = x[i]; + d[i] = a[i] = c[i] = 0; + } + } + + a[0] = d[0] = 1; + + {int i; + for (i = 254; i >= 0; i--) + { + int64_t r = (z[i >> 3] >> (i & 7)) & 1; + sel25519(a, b, r); + sel25519(c, d, r); + add(e, a, c); + sub(a, a, c); + add(c, b, d); + sub(b, b, d); + sqr(d, e); + sqr(f, a); + mul(a, c, a); + mul(c, b, e); + add(e, a, c); + sub(a, a, c); + sqr(b, a); + sub(c, d, f); + mul(a, c, _121665); + add(a, a, d); + mul(c, c, a); + mul(a, d, f); + mul(d, b, x); + sqr(b, e); + sel25519(a, b, r); + sel25519(c, d, r); + } + } + + inv25519(c, c); + mul(a, a, c); + pack25519(q, a); +} + +void cf_curve25519_mul_base(uint8_t *q, const uint8_t *n) +{ + cf_curve25519_mul(q, n, _9); +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/drbg.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/drbg.c new file mode 100644 index 0000000..ae79067 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/drbg.c @@ -0,0 +1,434 @@ +/* + * cifra - embedded cryptography library + * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "drbg.h" +#include "handy.h" +#include "bitops.h" +#include "sha2.h" +#include "tassert.h" + +#include <string.h> + +#define MAX_DRBG_GENERATE 0x10000ul + +static void hash_df(const cf_chash *H, + const void *in1, size_t nin1, + const void *in2, size_t nin2, + const void *in3, size_t nin3, + const void *in4, size_t nin4, + uint8_t *out, size_t nout) +{ + uint8_t counter = 1; + uint32_t bits_to_return = nout * 8; + uint8_t cbuf[4]; + uint8_t block[CF_MAXHASH]; + + write32_be(bits_to_return, cbuf); + + while (nout) + { + /* Make a block. This is the hash of: + * counter || bits_to_return || in1 || in2 || in3 | in4 + */ + cf_chash_ctx ctx; + H->init(&ctx); + H->update(&ctx, &counter, sizeof counter); + H->update(&ctx, cbuf, sizeof cbuf); + H->update(&ctx, in1, nin1); + H->update(&ctx, in2, nin2); + H->update(&ctx, in3, nin3); + H->update(&ctx, in4, nin4); + H->digest(&ctx, block); + + size_t take = MIN(H->hashsz, nout); + memcpy(out, block, take); + out += take; + nout -= take; + + counter += 1; + } +} + +void cf_hash_drbg_sha256_init(cf_hash_drbg_sha256 *ctx, + const void *entropy, size_t nentropy, + const void *nonce, size_t nnonce, + const void *persn, size_t npersn) +{ + mem_clean(ctx, sizeof *ctx); + + /* 1. seed_material = entropy_input || nonce || personalization_string + * 2. seed = Hash_df(seed_material, seedlen) + * 3. V = seed */ + hash_df(&cf_sha256, + entropy, nentropy, + nonce, nnonce, + persn, npersn, + NULL, 0, + ctx->V, sizeof ctx->V); + + /* 4. C = Hash_df(0x00 || V, seedlen) */ + uint8_t zero = 0; + hash_df(&cf_sha256, + &zero, sizeof zero, + ctx->V, sizeof ctx->V, + NULL, 0, + NULL, 0, + ctx->C, sizeof ctx->C); + + /* 5. reseed_counter = 1 */ + ctx->reseed_counter = 1; +} + +/* Add out += in, mod 2^nout. + * Runs in time dependent on nout and nin, but not the contents of out or in. + */ +static void add(uint8_t *out, size_t nout, const uint8_t *in, size_t nin) +{ + assert(nout >= nin); + + uint16_t carry = 0; + int oi, ii; + + for (oi = nout - 1, ii = nin - 1; + oi >= 0; + ii--, oi--) + { + carry += out[oi]; + if (ii >= 0) + carry += in[ii]; + out[oi] = carry & 0xff; + carry >>= 8; + } +} + +static void hash_process_addnl(const cf_chash *H, + const void *input, size_t ninput, + uint8_t *V, size_t nV) +{ + if (!ninput) + return; + + /* 2.1. w = Hash(0x02 || V || additional_input) */ + uint8_t two = 2; + uint8_t w[CF_MAXHASH]; + cf_chash_ctx ctx; + H->init(&ctx); + H->update(&ctx, &two, sizeof two); + H->update(&ctx, V, nV); + H->update(&ctx, input, ninput); + H->digest(&ctx, w); + + /* 2.2. V = (V + w) mod 2 ^ seedlen */ + add(V, nV, w, H->hashsz); +} + +static void hash_generate(const cf_chash *H, + uint8_t *data, size_t ndata, /* initialised with V */ + void *out, size_t nout) +{ + cf_chash_ctx ctx; + uint8_t w[CF_MAXHASH]; + uint8_t *bout = out; + uint8_t one = 1; + + while (nout) + { + /* 4.1. w = Hash(data) */ + H->init(&ctx); + H->update(&ctx, data, ndata); + H->digest(&ctx, w); + + /* 4.2. W = W || w */ + size_t take = MIN(H->hashsz, nout); + memcpy(bout, w, take); + bout += take; + nout -= take; + + /* 4.3. data = (data + 1) mod 2 ^ seedlen */ + add(data, ndata, &one, sizeof one); + } +} + +static void hash_step(const cf_chash *H, + uint8_t *V, size_t nV, + const uint8_t *C, size_t nC, + uint32_t *reseed_counter) +{ + /* 4. h = Hash(0x03 || V) */ + uint8_t h[CF_MAXHASH]; + uint8_t three = 3; + cf_chash_ctx ctx; + + H->init(&ctx); + H->update(&ctx, &three, sizeof three); + H->update(&ctx, V, nV); + H->digest(&ctx, h); + + /* 5. V = (V + h + C + reseed_counter) mod 2 ^ seedlen */ + uint8_t reseed_counter_buf[4]; + write32_be(*reseed_counter, reseed_counter_buf); + + add(V, nV, h, H->hashsz); + add(V, nV, C, nC); + add(V, nV, reseed_counter_buf, sizeof reseed_counter_buf); + + /* 6. reseed_counter = reseed_counter + 1 */ + *reseed_counter = *reseed_counter + 1; +} + +/* This is Hash_DRBG_Generate_algorithm. + * nout is a maximum of MAX_DRBG_GENERATE */ +static void hash_gen_request(cf_hash_drbg_sha256 *ctx, + const void *addnl, size_t naddnl, + void *out, size_t nout) +{ + uint8_t data[440/8]; /* a temporary copy of V, which gets incremented by generate */ + + assert(!cf_hash_drbg_sha256_needs_reseed(ctx)); + + hash_process_addnl(&cf_sha256, addnl, naddnl, ctx->V, sizeof ctx->V); + assert(sizeof data == sizeof ctx->V); + memcpy(data, ctx->V, sizeof ctx->V); + hash_generate(&cf_sha256, data, sizeof data, out, nout); + hash_step(&cf_sha256, ctx->V, sizeof ctx->V, ctx->C, sizeof ctx->C, &ctx->reseed_counter); +} + +void cf_hash_drbg_sha256_gen_additional(cf_hash_drbg_sha256 *ctx, + const void *addnl, size_t naddnl, + void *out, size_t nout) +{ + uint8_t *bout = out; + + /* Generate output in requests of MAX_DRBG_GENERATE in size. */ + while (nout != 0) + { + size_t take = MIN(MAX_DRBG_GENERATE, nout); + hash_gen_request(ctx, addnl, naddnl, bout, take); + bout += take; + nout -= take; + + /* Add additional data only once. */ + addnl = NULL; + naddnl = 0; + } +} + +void cf_hash_drbg_sha256_gen(cf_hash_drbg_sha256 *ctx, + void *out, size_t nout) +{ + cf_hash_drbg_sha256_gen_additional(ctx, + NULL, 0, + out, nout); +} + +void cf_hash_drbg_sha256_reseed(cf_hash_drbg_sha256 *ctx, + const void *entropy, size_t nentropy, + const void *addnl, size_t naddnl) +{ + /* 1. seed_material = 0x01 || V || entropy_input || additional_input + * 2. seed = Hash_df(seed_material, seedlen) + * 3. V = seed */ + uint8_t one = 1; + /* stash V in C, because it cannot alias output */ + memcpy(ctx->C, ctx->V, sizeof ctx->C); + hash_df(&cf_sha256, + &one, sizeof one, + ctx->C, sizeof ctx->C, + entropy, nentropy, + addnl, naddnl, + ctx->V, sizeof ctx->V); + + /* 4. C = Hash_df(0x00 || V, seedlen) */ + uint8_t zero = 0; + hash_df(&cf_sha256, + &zero, sizeof zero, + ctx->V, sizeof ctx->V, + NULL, 0, + NULL, 0, + ctx->C, sizeof ctx->C); + + /* 5. reseed_counter = 1 */ + ctx->reseed_counter = 1; +} + +uint32_t cf_hash_drbg_sha256_needs_reseed(const cf_hash_drbg_sha256 *ctx) +{ + /* we need reseeding after 2 ^ 32 - 1 requests. */ + return ctx->reseed_counter == 0; +} + +/* --- HMAC_DRBG --- */ + +/* provided_data is in1 || in2 || in3. + * K is already scheduled in ctx->hmac. */ +static void hmac_drbg_update(cf_hmac_drbg *ctx, + const void *in1, size_t nin1, + const void *in2, size_t nin2, + const void *in3, size_t nin3) +{ + cf_hmac_ctx local; + const cf_chash *H = ctx->hmac.hash; + uint8_t new_key[CF_MAXHASH]; + uint8_t zero = 0; + + /* 1. K = HMAC(K, V || 0x00 || provided_data) */ + local = ctx->hmac; + cf_hmac_update(&local, ctx->V, H->hashsz); + cf_hmac_update(&local, &zero, sizeof zero); + cf_hmac_update(&local, in1, nin1); + cf_hmac_update(&local, in2, nin2); + cf_hmac_update(&local, in3, nin3); + cf_hmac_finish(&local, new_key); + cf_hmac_init(&ctx->hmac, H, new_key, H->hashsz); + mem_clean(new_key, sizeof new_key); + + /* 2. V = HMAC(K, V) */ + local = ctx->hmac; + cf_hmac_update(&local, ctx->V, H->hashsz); + cf_hmac_finish(&local, ctx->V); + + /* 3. if (provided_data = null) then return K and V */ + if (nin1 == 0 && nin2 == 0 && nin3 == 0) + return; + + /* 4. K = HMAC(K, V || 0x01 || provided_data) */ + uint8_t one = 1; + local = ctx->hmac; + cf_hmac_update(&local, ctx->V, H->hashsz); + cf_hmac_update(&local, &one, sizeof one); + cf_hmac_update(&local, in1, nin1); + cf_hmac_update(&local, in2, nin2); + cf_hmac_update(&local, in3, nin3); + cf_hmac_finish(&local, new_key); + cf_hmac_init(&ctx->hmac, H, new_key, H->hashsz); + mem_clean(new_key, sizeof new_key); + + /* 5. V = HMAC(K, V) */ + local = ctx->hmac; + cf_hmac_update(&local, ctx->V, H->hashsz); + cf_hmac_finish(&local, ctx->V); +} + +void cf_hmac_drbg_init(cf_hmac_drbg *ctx, + const cf_chash *hash, + const void *entropy, size_t nentropy, + const void *nonce, size_t nnonce, + const void *persn, size_t npersn) +{ + mem_clean(ctx, sizeof *ctx); + + assert(hash->hashsz <= CF_MAXHASH); + + /* 2. Key = 0x00 00 ... 00 + * 3. V = 0x01 01 ... 01 */ + uint8_t initial_key[CF_MAXHASH]; + memset(initial_key, 0x00, hash->hashsz); + memset(ctx->V, 0x01, hash->hashsz); + cf_hmac_init(&ctx->hmac, hash, initial_key, hash->hashsz); + + /* 1. seed_material = entropy_input || nonce || personalization_string + * 4. (Key, V) = HMAC_DRBG_Update(seed_material, Key, V) */ + hmac_drbg_update(ctx, entropy, nentropy, nonce, nnonce, persn, npersn); + + /* 5. reseed_counter = 1 */ + ctx->reseed_counter = 1; +} + +uint32_t cf_hmac_drbg_needs_reseed(const cf_hmac_drbg *ctx) +{ + return ctx->reseed_counter == 0; +} + +static void hmac_drbg_generate(cf_hmac_drbg *ctx, + const void *addnl, size_t naddnl, + void *out, size_t nout) +{ + /* 1. If reseed_counter > reseed_interval, then return an indication + * that a reseed is required */ + assert(!cf_hmac_drbg_needs_reseed(ctx)); + + /* 2. If additional_input != null, then + * (Key, V) = HMAC_DRBG_Update(additional_input, Key, V) + */ + if (naddnl) + hmac_drbg_update(ctx, addnl, naddnl, NULL, 0, NULL, 0); + + /* 3. temp = Null + * 4. While (len(temp) < requested_number_of_bits) do: + * 4.1. V = HMAC(Key, V) + * 4.2. temp = temp || V + * 5. returned_bits = leftmost(temp, requested_number_of_bits) + * + * We write the contents of temp directly into the caller's + * out buffer. + */ + uint8_t *bout = out; + cf_hmac_ctx local; + + while (nout) + { + local = ctx->hmac; + cf_hmac_update(&local, ctx->V, ctx->hmac.hash->hashsz); + cf_hmac_finish(&local, ctx->V); + + size_t take = MIN(ctx->hmac.hash->hashsz, nout); + memcpy(bout, ctx->V, take); + bout += take; + nout -= take; + } + + /* 6. (Key, V) = HMAC_DRBG_Update(additional_input, Key, V) */ + hmac_drbg_update(ctx, addnl, naddnl, NULL, 0, NULL, 0); + + /* 7. reseed_counter = reseed_counter + 1 */ + ctx->reseed_counter++; +} + +void cf_hmac_drbg_gen_additional(cf_hmac_drbg *ctx, + const void *addnl, size_t naddnl, + void *out, size_t nout) +{ + uint8_t *bout = out; + + while (nout != 0) + { + size_t take = MIN(MAX_DRBG_GENERATE, nout); + hmac_drbg_generate(ctx, addnl, naddnl, bout, take); + bout += take; + nout -= take; + + /* Add additional data only once. */ + addnl = NULL; + naddnl = 0; + } +} + +void cf_hmac_drbg_gen(cf_hmac_drbg *ctx, void *out, size_t nout) +{ + cf_hmac_drbg_gen_additional(ctx, + NULL, 0, + out, nout); +} + +void cf_hmac_drbg_reseed(cf_hmac_drbg *ctx, + const void *entropy, size_t nentropy, + const void *addnl, size_t naddnl) +{ + /* 1. seed_material = entropy_input || additional_input + * 2. (Key, V) = HMAC_DRBG_Update(seed_material, Key, V) */ + hmac_drbg_update(ctx, entropy, nentropy, addnl, naddnl, NULL, 0); + + /* 3. reseed_counter = 1 */ + ctx->reseed_counter = 1; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/drbg.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/drbg.h new file mode 100644 index 0000000..18a1070 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/drbg.h @@ -0,0 +1,191 @@ +/* + * cifra - embedded cryptography library + * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef DRBG_H +#define DRBG_H + +#include <stddef.h> +#include <stdint.h> + +#include "chash.h" +#include "hmac.h" + +/** + * Hash_DRBG + * ========= + * This is Hash_DRBG from SP800-90A rev 1, with SHA256 as + * the underlying hash function. + * + * This generator enforces a `reseed_interval` of 2^32-1: + * use :c:func:`cf_hash_drbg_sha256_needs_reseed` to check + * whether you need to reseed before use, and reseed using + * :c:func:`cf_hash_drbg_sha256_reseed`. If you try to use + * the generator when it thinks it needs reseeding, it will + * call `abort`. + * + * Internally it enforces a `max_number_of_bits_per_request` + * of 2^19 bits. It sorts out chunking up multiple requests + * for you though, so feel free to ask for more than 2^16 bytes + * at a time. If you provide additional input when doing that, + * it is added only once, on the first subrequest. + * + * It does not enforce any `max_length` or + * `max_personalization_string_length`. + */ + +/* .. c:type:: cf_hash_drbg_sha256 + * Hash_DRBG with SHA256 context. + * + * .. c:member:: cf_hash_drbg_sha256.V + * Current internal state. + * + * .. c:member:: cf_hash_drbg_sha256.C + * Current update offset. + * + * .. c:member:: cf_hash_drbg_sha256.reseed_counter + * Current number of times entropy has been extracted from + * generator. + */ +typedef struct +{ + uint8_t V[440/8]; + uint8_t C[440/8]; + uint32_t reseed_counter; +} cf_hash_drbg_sha256; + +/* .. c:function:: $DECL + * Initialises the generator state `ctx`, using the provided `entropy`, + * `nonce` and personalisation string `persn`. + */ +extern void cf_hash_drbg_sha256_init(cf_hash_drbg_sha256 *ctx, + const void *entropy, size_t nentropy, + const void *nonce, size_t nnonce, + const void *persn, size_t npersn); + +/* .. c:function:: $DECL + * Returns non-zero if the generator needs reseeding. If + * this function returns non-zero, the next :c:func:`cf_hash_drbg_sha256_gen` + * or :c:func:`cf_hash_drbg_sha256_gen_additional` call will call `abort`. + */ +extern uint32_t cf_hash_drbg_sha256_needs_reseed(const cf_hash_drbg_sha256 *ctx); + +/* .. c:function:: $DECL + * Reseeds the generator with the given `entropy` and additional data `addnl`. + */ +extern void cf_hash_drbg_sha256_reseed(cf_hash_drbg_sha256 *ctx, + const void *entropy, size_t nentropy, + const void *addnl, size_t naddnl); + +/* .. c:function:: $DECL + * Generates pseudo-random output, writing `nout` bytes at `out`. + * This function aborts if the generator needs seeding. + */ +extern void cf_hash_drbg_sha256_gen(cf_hash_drbg_sha256 *ctx, + void *out, size_t nout); + +/* .. c:function:: $DECL + * Generates pseudo-random output, writing `nout` bytes at `out`. + * At the same time, `addnl` is input to the generator as further + * entropy. + * This function aborts if the generator needs seeding. + */ +extern void cf_hash_drbg_sha256_gen_additional(cf_hash_drbg_sha256 *ctx, + const void *addnl, size_t naddnl, + void *out, size_t nout); + +/** + * HMAC_DRBG + * ========= + * This is HMAC_DRBG from SP800-90a r1 with any hash function. + * + * This generator enforces a `reseed_interval` of 2^32-1: + * use :c:func:`cf_hmac_drbg_needs_reseed` to check whether + * you need to reseed before use, and reseed using + * :c:func:`cf_hmac_drbg_reseed`. If you try to use the + * generator when it thinks it needs reseeding, it will + * call `abort`. + * + * Internally it enforces a `max_number_of_bits_per_request` + * of 2^19 bits. It sorts out chunking up multiple requests + * for you though, so feel free to ask for more than 2^16 bytes + * at a time. If you provide additional input when doing that, + * it is added only once, on the first subrequest. + * + * It does not enforce any `max_length` or + * `max_personalization_string_length`. + */ + +/* .. c:type:: cf_hmac_drbg + * HMAC_DRBG context. + * + * .. c:member:: cf_hmac_drbg.V + * Current internal state. + * + * .. c:member:: cf_hmac_drbg.hmac + * Current HMAC context, with key scheduled in it. + * + * .. c:member:: cf_hmac_drbg.reseed_counter + * Current number of times entropy has been extracted from + * generator. + */ +typedef struct +{ + uint8_t V[CF_MAXHASH]; + cf_hmac_ctx hmac; /* pristine context with key scheduled */ + uint32_t reseed_counter; +} cf_hmac_drbg; + +/* .. c:function:: $DECL + * Initialises the generator state `ctx`, using the provided `entropy`, + * `nonce` and personalisation string `persn`. + */ +extern void cf_hmac_drbg_init(cf_hmac_drbg *ctx, + const cf_chash *hash, + const void *entropy, size_t nentropy, + const void *nonce, size_t nnonce, + const void *persn, size_t npersn); + +/* .. c:function:: $DECL + * Returns non-zero if the generator needs reseeding. If + * this function returns non-zero, the next :c:func:`cf_hmac_drbg_gen` + * or :c:func:`cf_hmac_drbg_gen_additional` call will call `abort`. + */ +extern uint32_t cf_hmac_drbg_needs_reseed(const cf_hmac_drbg *ctx); + +/* .. c:function:: $DECL + * Reseeds the generator with the given `entropy` and additional data + * `addnl`. + */ +extern void cf_hmac_drbg_reseed(cf_hmac_drbg *ctx, + const void *entropy, size_t nentropy, + const void *addnl, size_t naddnl); + +/* .. c:function:: $DECL + * Generates pseudo-random output, writing `nout` bytes at `out`. + * This function aborts if the generator needs seeding. + */ +extern void cf_hmac_drbg_gen(cf_hmac_drbg *ctx, + void *out, size_t nout); + +/* .. c:function:: $DECL + * Generates pseudo-random output, writing `nout` bytes at `out`. + * At the same time, `addnl` is input to the generator as further + * entropy. + * This function aborts if the generator needs seeding. + */ +extern void cf_hmac_drbg_gen_additional(cf_hmac_drbg *ctx, + const void *addnl, size_t naddnl, + void *out, size_t nout); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/eax.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/eax.c new file mode 100644 index 0000000..80ba46f --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/eax.c @@ -0,0 +1,116 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "handy.h" +#include "prp.h" +#include "modes.h" +#include "tassert.h" + +#include <string.h> + +static void cmac_compute_n(cf_cmac_stream *ctx, + uint8_t t, + const uint8_t *input, size_t ninput, + uint8_t out[CF_MAXBLOCK]) +{ + size_t blocksz = ctx->cmac.prp->blocksz; + assert(blocksz > 0); + + uint8_t firstblock[CF_MAXBLOCK]; + memset(firstblock, 0, blocksz); + firstblock[blocksz - 1] = t; + + cf_cmac_stream_reset(ctx); + if (ninput) + { + cf_cmac_stream_update(ctx, firstblock, blocksz, 0); + cf_cmac_stream_update(ctx, input, ninput, 1); + } else { + cf_cmac_stream_update(ctx, firstblock, blocksz, 1); + } + + cf_cmac_stream_final(ctx, out); +} + +void cf_eax_encrypt(const cf_prp *prp, void *prpctx, + const uint8_t *plain, size_t nplain, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + uint8_t *cipher, /* the same size as nplain */ + uint8_t *tag, size_t ntag) +{ + uint8_t NN[CF_MAXBLOCK], + HH[CF_MAXBLOCK], + CC[CF_MAXBLOCK]; + + cf_cmac_stream cmac; + cf_cmac_stream_init(&cmac, prp, prpctx); + + /* NN = OMAC_K^0(N) */ + cmac_compute_n(&cmac, 0, nonce, nnonce, NN); + + /* HH = OMAC_K^1(H) */ + cmac_compute_n(&cmac, 1, header, nheader, HH); + + /* C = CTR_K^NN(M) */ + cf_ctr ctr; + cf_ctr_init(&ctr, prp, prpctx, NN); + cf_ctr_cipher(&ctr, plain, cipher, nplain); + + /* CC = OMAC_K^2(C) */ + cmac_compute_n(&cmac, 2, cipher, nplain, CC); + + /* Tag = NN ^ CC ^ HH + * T = Tag [ first tau bits ] */ + assert(ntag <= prp->blocksz); + for (size_t i = 0; i < ntag; i++) + tag[i] = NN[i] ^ CC[i] ^ HH[i]; +} + +int cf_eax_decrypt(const cf_prp *prp, void *prpctx, + const uint8_t *cipher, size_t ncipher, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + const uint8_t *tag, size_t ntag, + uint8_t *plain) /* the same size as ncipher */ +{ + uint8_t NN[CF_MAXBLOCK], + HH[CF_MAXBLOCK], + CC[CF_MAXBLOCK]; + + cf_cmac_stream cmac; + cf_cmac_stream_init(&cmac, prp, prpctx); + + /* NN = OMAC_K^0(N) */ + cmac_compute_n(&cmac, 0, nonce, nnonce, NN); + + /* HH = OMAC_K^1(H) */ + cmac_compute_n(&cmac, 1, header, nheader, HH); + + /* CC = OMAC_K^2(C) */ + cmac_compute_n(&cmac, 2, cipher, ncipher, CC); + + uint8_t tt[CF_MAXBLOCK]; + assert(ntag && ntag <= prp->blocksz); + for (size_t i = 0; i < ntag; i++) + tt[i] = NN[i] ^ CC[i] ^ HH[i]; + + if (!mem_eq(tt, tag, ntag)) + return 1; + + cf_ctr ctr; + cf_ctr_init(&ctr, prp, prpctx, NN); + cf_ctr_cipher(&ctr, cipher, plain, ncipher); + return 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/ext/cutest.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/ext/cutest.h new file mode 100644 index 0000000..c9af425 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/ext/cutest.h @@ -0,0 +1,620 @@ +/* + * CUTest -- C/C++ Unit Test facility + * <http://github.com/mity/cutest> + * + * Copyright (c) 2013-2014 Martin Mitas + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CUTEST_H__ +#define CUTEST_H__ + + +/************************ + *** Public interface *** + ************************/ + +/* By default, <cutest.h> provides the main program entry point (function + * main()). However, if the test suite is composed of multiple source files + * which include <cutest.h>, then this brings a problem of multiple main() + * definitions. To avoid this problem, #define macro TEST_NO_MAIN in all + * compilation units but one. + */ + +/* Macro to specify list of unit tests in the suite. + * The unit test implementation MUST provide list of unit tests it implements + * with this macro: + * + * TEST_LIST = { + * { "test1_name", test1_func_ptr }, + * { "test2_name", test2_func_ptr }, + * ... + * { 0 } + * }; + * + * The list specifies names of each tests (must be unique) and pointer to + * a function implementing it. The function does not take any arguments + * and have no return values, i.e. the test functions should have this + * prototype: + * + * void test_func(void); + */ +#define TEST_LIST const struct test__ test_list__[] + + +/* Macros for testing whether an unit test succeeds or fails. These macros + * can be used arbitrarily in functions implementing the unit tests. + * + * If any condition fails throughout execution of a test, the test fails. + * + * TEST_CHECK takes only one argument (the condition), TEST_CHECK_ allows + * also to specify an error message to print out if the condition fails. + * (It expects printf-like format string and its parameters). The macros + * return non-zero (condition passes) or 0 (condition fails). + * + * That can be useful when more conditions should be checked only if some + * preceding condition passes, as illustrated here: + * + * SomeStruct* ptr = allocate_some_struct(); + * if(TEST_CHECK(ptr != NULL)) { + * TEST_CHECK(ptr->member1 < 100); + * TEST_CHECK(ptr->member2 > 200); + * } + */ +#define TEST_CHECK_(cond,...) test_check__((cond), __FILE__, __LINE__, __VA_ARGS__) +#define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, "%s", #cond) + + +/********************** + *** Implementation *** + **********************/ + +/* The unit test files should not rely on anything below. */ + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) + #define CUTEST_UNIX__ 1 + #include <errno.h> + #include <unistd.h> + #include <sys/types.h> + #include <sys/wait.h> + #include <signal.h> +#endif + +#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) + #define CUTEST_WIN__ 1 + #include <windows.h> + #include <io.h> +#endif + +#ifdef __cplusplus + #include <exception> +#endif + + +/* Note our global private identifiers end with '__' to minimize risk of clash + * with the unit tests implementation. */ + + +#ifdef __cplusplus + extern "C" { +#endif + + +struct test__ { + const char* name; + void (*func)(void); +}; + +extern const struct test__ test_list__[]; +extern int test_verbose_level__; +extern const struct test__* test_current_unit__; +extern int test_current_already_logged__; +extern int test_current_failures__; +extern int test_colorize__; + + +#define CUTEST_COLOR_DEFAULT__ 0 +#define CUTEST_COLOR_GREEN__ 1 +#define CUTEST_COLOR_RED__ 2 +#define CUTEST_COLOR_DEFAULT_INTENSIVE__ 3 +#define CUTEST_COLOR_GREEN_INTENSIVE__ 4 +#define CUTEST_COLOR_RED_INTENSIVE__ 5 + +size_t +test_print_in_color(int color, const char* fmt, ...) +{ + va_list args; + char buffer[256]; + size_t n; + + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + buffer[sizeof(buffer)-1] = '\0'; + + if(!test_colorize__) { + return printf("%s", buffer); + } + +#if defined CUTEST_UNIX__ + const char* col_str; + switch(color) { + case CUTEST_COLOR_GREEN__: col_str = "\e[0;32m"; break; + case CUTEST_COLOR_RED__: col_str = "\e[0;31m"; break; + case CUTEST_COLOR_GREEN_INTENSIVE__: col_str = "\e[1;32m"; break; + case CUTEST_COLOR_RED_INTENSIVE__: col_str = "\e[1;30m"; break; + case CUTEST_COLOR_DEFAULT_INTENSIVE__: col_str = "\e[1m"; break; + default: col_str = "\e[0m"; break; + } + printf("%s", col_str); + n = printf("%s", buffer); + printf("\e[0m"); + return n; +#elif defined CUTEST_WIN__ + HANDLE h; + CONSOLE_SCREEN_BUFFER_INFO info; + WORD attr; + + h = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(h, &info); + + switch(color) { + case CUTEST_COLOR_GREEN__: attr = FOREGROUND_GREEN; break; + case CUTEST_COLOR_RED__: attr = FOREGROUND_RED; break; + case CUTEST_COLOR_GREEN_INTENSIVE__: attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; + case CUTEST_COLOR_RED_INTENSIVE__: attr = FOREGROUND_RED | FOREGROUND_INTENSITY; break; + case CUTEST_COLOR_DEFAULT_INTENSIVE__: attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break; + default: attr = 0; break; + } + if(attr != 0) + SetConsoleTextAttribute(h, attr); + n = printf("%s", buffer); + SetConsoleTextAttribute(h, info.wAttributes); + return n; +#else + n = printf("%s", buffer); + return n; +#endif +} + +int +test_check__(int cond, const char* file, int line, const char* fmt, ...) +{ + const char *result_str; + int result_color; + int verbose_level; + + if(cond) { + result_str = "ok"; + result_color = CUTEST_COLOR_GREEN__; + verbose_level = 3; + } else { + if(!test_current_already_logged__ && test_current_unit__ != NULL) { + printf("[ "); + test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, "FAILED"); + printf(" ]\n"); + } + result_str = "failed"; + result_color = CUTEST_COLOR_RED__; + verbose_level = 2; + test_current_failures__++; + test_current_already_logged__++; + } + + if(test_verbose_level__ >= verbose_level) { + size_t n = 0; + va_list args; + + printf(" "); + + if(file != NULL) + n += printf("%s:%d: Check ", file, line); + + va_start(args, fmt); + n += vprintf(fmt, args); + va_end(args); + + printf("... "); + test_print_in_color(result_color, result_str); + printf("\n"); + test_current_already_logged__++; + } + + return (cond != 0); +} + + +#ifndef TEST_NO_MAIN + +static char* test_argv0__ = NULL; +static int test_count__ = 0; +static int test_no_exec__ = 0; +static int test_no_summary__ = 0; +static int test_skip_mode__ = 0; + +static int test_stat_failed_units__ = 0; +static int test_stat_run_units__ = 0; + +const struct test__* test_current_unit__ = NULL; +int test_current_already_logged__ = 0; +int test_verbose_level__ = 2; +int test_current_failures__ = 0; +int test_colorize__ = 0; + + +static void +test_list_names__(void) +{ + const struct test__* test; + + printf("Unit tests:\n"); + for(test = &test_list__[0]; test->func != NULL; test++) + printf(" %s\n", test->name); +} + +static const struct test__* +test_by_name__(const char* name) +{ + const struct test__* test; + + for(test = &test_list__[0]; test->func != NULL; test++) { + if(strcmp(test->name, name) == 0) + return test; + } + + return NULL; +} + +static int +test_do_run__(const struct test__* test) +{ + test_current_unit__ = test; + test_current_failures__ = 0; + test_current_already_logged__ = 0; + + if(test_verbose_level__ >= 3) { + test_print_in_color(CUTEST_COLOR_DEFAULT_INTENSIVE__, "Test %s:\n", test->name); + test_current_already_logged__++; + } else if(test_verbose_level__ >= 1) { + size_t n; + char spaces[32]; + + n = test_print_in_color(CUTEST_COLOR_DEFAULT_INTENSIVE__, "Test %s... ", test->name); + memset(spaces, ' ', sizeof(spaces)); + if(n < sizeof(spaces)) + printf("%.*s", (int) (sizeof(spaces) - n), spaces); + } else { + test_current_already_logged__ = 1; + } + +#ifdef __cplusplus + try { +#endif + + test->func(); + +#ifdef __cplusplus + } catch(std::exception& e) { + const char* what = e.what(); + if(what != NULL) + test_check__(0, NULL, 0, "Threw std::exception: %s", what); + else + test_check__(0, NULL, 0, "Threw std::exception"); + } catch(...) { + test_check__(0, NULL, 0, "Threw an exception"); + } +#endif + + if(test_verbose_level__ >= 3) { + switch(test_current_failures__) { + case 0: test_print_in_color(CUTEST_COLOR_GREEN_INTENSIVE__, " All conditions have passed.\n\n"); break; + case 1: test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, " One condition has FAILED.\n\n"); break; + default: test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, " %d conditions have FAILED.\n\n", test_current_failures__); break; + } + } else if(test_verbose_level__ >= 1 && test_current_failures__ == 0) { + printf("[ "); + test_print_in_color(CUTEST_COLOR_GREEN_INTENSIVE__, "OK"); + printf(" ]\n"); + } + + test_current_unit__ = NULL; + return (test_current_failures__ == 0) ? 0 : -1; +} + +static void +test_error__(const char* fmt, ...) +{ + va_list args; + + if(!test_current_already_logged__ && test_current_unit__ != NULL) { + printf("[ "); + test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, "FAILED"); + printf(" ]\n"); + } + + if(test_verbose_level__ < 2) + return; + + test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, " Error: "); + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + printf("\n"); +} + +static void +test_run__(const struct test__* test) +{ + int failed = 1; + + test_current_unit__ = test; + test_current_already_logged__ = 0; + + if(!test_no_exec__) { + +#if defined(CUTEST_UNIX__) + + pid_t pid; + int exit_code; + + pid = fork(); + if(pid == (pid_t)-1) { + test_error__("Cannot fork. %s [%d]", strerror(errno), errno); + failed = 1; + } else if(pid == 0) { + failed = (test_do_run__(test) != 0); + exit(failed ? 1 : 0); + } else { + waitpid(pid, &exit_code, 0); + if(WIFEXITED(exit_code)) { + switch(WEXITSTATUS(exit_code)) { + case 0: failed = 0; break; /* test has passed. */ + case 1: /* noop */ break; /* "normal" failure. */ + default: test_error__("Unexpected exit code [%d]", WEXITSTATUS(exit_code)); + } + } else if(WIFSIGNALED(exit_code)) { + char tmp[32]; + const char* signame; + switch(WTERMSIG(exit_code)) { + case SIGINT: signame = "SIGINT"; break; + case SIGHUP: signame = "SIGHUP"; break; + case SIGQUIT: signame = "SIGQUIT"; break; + case SIGABRT: signame = "SIGABRT"; break; + case SIGKILL: signame = "SIGKILL"; break; + case SIGSEGV: signame = "SIGSEGV"; break; + case SIGILL: signame = "SIGILL"; break; + case SIGTERM: signame = "SIGTERM"; break; + default: sprintf(tmp, "signal %d", WTERMSIG(exit_code)); signame = tmp; break; + } + test_error__("Test interrupted by %s", signame); + } else { + test_error__("Test ended in an unexpected way [%d]", exit_code); + } + } + +#elif defined(CUTEST_WIN__) + + char buffer[512] = {0}; + STARTUPINFOA startupInfo = {0}; + PROCESS_INFORMATION processInfo; + DWORD exitCode; + + _snprintf(buffer, sizeof(buffer)-1, + "%s --no-exec --no-summary --verbose=%d --color=%s -- \"%s\"", + test_argv0__, test_verbose_level__, + test_colorize__ ? "always" : "never", test->name); + startupInfo.cb = sizeof(STARTUPINFO); + if(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo)) { + WaitForSingleObject(processInfo.hProcess, INFINITE); + GetExitCodeProcess(processInfo.hProcess, &exitCode); + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + failed = (exitCode != 0); + } else { + test_error__("Cannot create unit test subprocess [%ld].", GetLastError()); + failed = 1; + } + +#else + + failed = (test_do_run__(test) != 0); + +#endif + + } else { + failed = (test_do_run__(test) != 0); + } + + test_current_unit__ = NULL; + + test_stat_run_units__++; + if(failed) + test_stat_failed_units__++; +} + +#if defined(CUTEST_WIN__) +static LONG CALLBACK +test_exception_filter__(EXCEPTION_POINTERS *ptrs) +{ + test_error__("Unhandled SEH exception %08lx at %p.", + ptrs->ExceptionRecord->ExceptionCode, + ptrs->ExceptionRecord->ExceptionAddress); + fflush(stdout); + fflush(stderr); + return EXCEPTION_EXECUTE_HANDLER; +} +#endif + +static void +test_help__(void) +{ + printf("Usage: %s [options] [test...]\n", test_argv0__); + printf("Run the specified unit tests; or if the option '--skip' is used, run all\n"); + printf("tests in the suite but those listed. By default, if no tests are specified\n"); + printf("on the command line, all unit tests in the suite are run.\n"); + printf("\n"); + printf("Options:\n"); + printf(" -s, --skip Execute all unit tests but the listed ones\n"); + printf(" --no-exec Do not execute unit tests as child processes\n"); + printf(" --no-summary Suppress printing of test results summary\n"); + printf(" -l, --list List unit tests in the suite and exit\n"); + printf(" -v, --verbose Enable more verbose output\n"); + printf(" --verbose=LEVEL Set verbose level to LEVEL (small integer)\n"); + printf(" --color=WHEN Enable colorized output (WHEN is one of 'auto', 'always', 'never')\n"); + printf(" -h, --help Display this help and exit\n"); + printf("\n"); + test_list_names__(); +} + +int +main(int argc, char** argv) +{ + const struct test__** tests = NULL; + int i, j, n = 0; + int seen_double_dash = 0; + + test_argv0__ = argv[0]; + +#if defined CUTEST_UNIX__ + test_colorize__ = isatty(fileno(stdout)); +#elif defined CUTEST_WIN__ + test_colorize__ = _isatty(_fileno(stdout)); +#else + test_colorize__ = 0; +#endif + + /* Parse options */ + for(i = 1; i < argc; i++) { + if(seen_double_dash || argv[i][0] != '-') { + tests = (const struct test__**) realloc(tests, (n+1) * sizeof(const struct test__*)); + if(tests == NULL) { + fprintf(stderr, "Out of memory.\n"); + exit(2); + } + tests[n] = test_by_name__(argv[i]); + if(tests[n] == NULL) { + fprintf(stderr, "%s: Unrecognized unit test '%s'\n", argv[0], argv[i]); + fprintf(stderr, "Try '%s --list' for list of unit tests.\n", argv[0]); + exit(2); + } + n++; + } else if(strcmp(argv[i], "--") == 0) { + seen_double_dash = 1; + } else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + test_help__(); + exit(0); + } else if(strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) { + test_verbose_level__++; + } else if(strncmp(argv[i], "--verbose=", 10) == 0) { + test_verbose_level__ = atoi(argv[i] + 10); + } else if(strcmp(argv[i], "--color=auto") == 0) { + /* noop (set from above) */ + } else if(strcmp(argv[i], "--color=always") == 0 || strcmp(argv[i], "--color") == 0) { + test_colorize__ = 1; + } else if(strcmp(argv[i], "--color=never") == 0) { + test_colorize__ = 0; + } else if(strcmp(argv[i], "--skip") == 0 || strcmp(argv[i], "-s") == 0) { + test_skip_mode__ = 1; + } else if(strcmp(argv[i], "--no-exec") == 0) { + test_no_exec__ = 1; + } else if(strcmp(argv[i], "--no-summary") == 0) { + test_no_summary__ = 1; + } else if(strcmp(argv[i], "--list") == 0 || strcmp(argv[i], "-l") == 0) { + test_list_names__(); + exit(0); + } else { + fprintf(stderr, "%s: Unrecognized option '%s'\n", argv[0], argv[i]); + fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); + exit(2); + } + } + +#if defined(CUTEST_WIN__) + SetUnhandledExceptionFilter(test_exception_filter__); +#endif + + /* Count all test units */ + test_count__ = 0; + for(i = 0; test_list__[i].func != NULL; i++) + test_count__++; + + /* Run the tests */ + if(n == 0) { + /* Run all tests */ + for(i = 0; test_list__[i].func != NULL; i++) + test_run__(&test_list__[i]); + } else if(!test_skip_mode__) { + /* Run the listed tests */ + for(i = 0; i < n; i++) + test_run__(tests[i]); + } else { + /* Run all tests except those listed */ + int is_skipped; + + for(i = 0; test_list__[i].func != NULL; i++) { + is_skipped = 0; + for(j = 0; j < n; j++) { + if(tests[j] == &test_list__[i]) { + is_skipped = 1; + break; + } + } + if(!is_skipped) + test_run__(&test_list__[i]); + } + } + + /* Write a summary */ + if(!test_no_summary__ && test_verbose_level__ >= 1) { + test_print_in_color(CUTEST_COLOR_DEFAULT_INTENSIVE__, "\nSummary:\n"); + + if(test_verbose_level__ >= 3) { + printf(" Count of all unit tests: %4d\n", test_count__); + printf(" Count of run unit tests: %4d\n", test_stat_run_units__); + printf(" Count of failed unit tests: %4d\n", test_stat_failed_units__); + printf(" Count of skipped unit tests: %4d\n", test_count__ - test_stat_run_units__); + } + + if(test_stat_failed_units__ == 0) { + test_print_in_color(CUTEST_COLOR_GREEN_INTENSIVE__, + " SUCCESS: All unit tests have passed.\n"); + } else { + test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, + " FAILED: %d of %d unit tests have failed.\n", + test_stat_failed_units__, test_stat_run_units__); + } + } + + if(tests != NULL) + free(tests); + + return (test_stat_failed_units__ == 0) ? 0 : 1; +} + + +#endif /* #ifndef TEST_NO_MAIN */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* #ifndef CUTEST_H__ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/ext/handy.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/ext/handy.h new file mode 100644 index 0000000..936e70f --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/ext/handy.h @@ -0,0 +1,66 @@ +#ifndef HANDY_H +#define HANDY_H + +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +/* + * Handy CPP defines and C inline functions. + */ + +/* Evaluates to the number of items in array-type variable arr. */ +#define ARRAYCOUNT(arr) (sizeof arr / sizeof arr[0]) + +#ifndef MIN +# define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +/** Stringify its argument. */ +#define STRINGIFY(x) STRINGIFY_(x) +#define STRINGIFY_(x) #x + +/* Error handling macros. + * + * These expect a zero = success, non-zero = error convention. + */ + +/** Error: return. + * + * If the expression fails, return the error from this function. */ +#define ER(expr) do { typeof (expr) err_ = (expr); if (err_) return err_; } while (0) + +/** Error: goto. + * + * If the expression fails, goto x_err. Assumes defn of label + * x_err and 'error_type err'. */ +#define EG(expr) do { err = (expr); if (err) goto x_err; } while (0) + +/** Like memset(ptr, 0, len), but not allowed to be removed by + * compilers. */ +static inline void mem_clean(volatile void *v, size_t len) +{ + if (len) + { + memset((void *) v, 0, len); + (void) *((volatile uint8_t *) v); + } +} + +/** Returns 1 if len bytes at va equal len bytes at vb, 0 if they do not. + * Does not leak length of common prefix through timing. */ +static inline unsigned mem_eq(const void *va, const void *vb, size_t len) +{ + const volatile uint8_t *a = va; + const volatile uint8_t *b = vb; + uint8_t diff = 0; + + while (len--) + { + diff |= *a++ ^ *b++; + } + + return !diff; +} + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/gcm.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/gcm.c new file mode 100644 index 0000000..5b37473 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/gcm.c @@ -0,0 +1,249 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "handy.h" +#include "prp.h" +#include "modes.h" +#include "blockwise.h" +#include "bitops.h" +#include "gf128.h" +#include "tassert.h" + +#include <string.h> + +#define STATE_INVALID 0 +#define STATE_AAD 1 +#define STATE_CIPHER 2 + +static void ghash_init(ghash_ctx *ctx, uint8_t H[16]) +{ + memset(ctx, 0, sizeof *ctx); + cf_gf128_frombytes_be(H, ctx->H); + ctx->state = STATE_AAD; +} + +static void ghash_block(void *vctx, const uint8_t *data) +{ + ghash_ctx *ctx = vctx; + cf_gf128 gfdata; + cf_gf128_frombytes_be(data, gfdata); + cf_gf128_add(gfdata, ctx->Y, ctx->Y); + cf_gf128_mul(ctx->Y, ctx->H, ctx->Y); +} + +static void ghash_add(ghash_ctx *ctx, const uint8_t *buf, size_t n) +{ + cf_blockwise_accumulate(ctx->buffer, &ctx->buffer_used, + sizeof ctx->buffer, + buf, n, + ghash_block, + ctx); +} + +static void ghash_add_pad(ghash_ctx *ctx) +{ + if (ctx->buffer_used == 0) + return; + + memset(ctx->buffer + ctx->buffer_used, 0, sizeof(ctx->buffer) - ctx->buffer_used); + ghash_block(ctx, ctx->buffer); + ctx->buffer_used = 0; +} + +static void ghash_add_aad(ghash_ctx *ctx, const uint8_t *buf, size_t n) +{ + assert(ctx->state == STATE_AAD); + ctx->len_aad += n; + ghash_add(ctx, buf, n); +} + +static void ghash_add_cipher(ghash_ctx *ctx, const uint8_t *buf, size_t n) +{ + if (ctx->state == STATE_AAD) + { + ghash_add_pad(ctx); + ctx->state = STATE_CIPHER; + } + + assert(ctx->state == STATE_CIPHER); + ctx->len_cipher += n; + ghash_add(ctx, buf, n); +} + +static void ghash_final(ghash_ctx *ctx, uint8_t out[16]) +{ + uint8_t lenbuf[8]; + + if (ctx->state == STATE_AAD || ctx->state == STATE_CIPHER) + { + ghash_add_pad(ctx); + ctx->state = STATE_INVALID; + } + + /* Add len(A) || len(C) */ + write64_be(ctx->len_aad * 8, lenbuf); + ghash_add(ctx, lenbuf, sizeof lenbuf); + + write64_be(ctx->len_cipher * 8, lenbuf); + ghash_add(ctx, lenbuf, sizeof lenbuf); + + assert(ctx->buffer_used == 0); + cf_gf128_tobytes_be(ctx->Y, out); +} + +void cf_gcm_encrypt_init(const cf_prp *prp, void *prpctx, cf_gcm_ctx *gcmctx, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce) +{ + uint8_t H[16] = { 0 }; + + /* H = E_K(0^128) */ + prp->encrypt(prpctx, H, H); + + /* Produce CTR nonce, Y_0: + * + * if len(IV) == 96 + * Y_0 = IV || 0^31 || 1 + * otherwise + * Y_0 = GHASH(H, {}, IV) + */ + + if (nnonce == 12) + { + memcpy(gcmctx->Y0, nonce, nnonce); + gcmctx->Y0[12] = gcmctx->Y0[13] = gcmctx->Y0[14] = 0x00; + gcmctx->Y0[15] = 0x01; + } else { + ghash_init(&gcmctx->gh, H); + ghash_add_cipher(&gcmctx->gh, nonce, nnonce); + ghash_final(&gcmctx->gh, gcmctx->Y0); + } + + /* Hash AAD */ + ghash_init(&gcmctx->gh, H); + ghash_add_aad(&gcmctx->gh, header, nheader); + + /* Produce ciphertext */ + memset(gcmctx->e_Y0, 0, sizeof(gcmctx->e_Y0)); + cf_ctr_init(&gcmctx->ctr, prp, prpctx, gcmctx->Y0); + cf_ctr_custom_counter(&gcmctx->ctr, 12, 4); /* counter is 2^32 */ + cf_ctr_cipher(&gcmctx->ctr, gcmctx->e_Y0, gcmctx->e_Y0, sizeof gcmctx->e_Y0); /* first block is tag offset */ + + mem_clean(H, sizeof H); +} + +void cf_gcm_encrypt_update(cf_gcm_ctx *gcmctx, const uint8_t *plain, size_t nplain, uint8_t *cipher) +{ + cf_ctr_cipher(&gcmctx->ctr, plain, cipher, nplain); + ghash_add_cipher(&gcmctx->gh, cipher, nplain); +} + +void cf_gcm_encrypt_final(cf_gcm_ctx *gcmctx, uint8_t *tag, size_t ntag) +{ + /* Post-process ghash output */ + uint8_t full_tag[16] = { 0 }; + ghash_final(&gcmctx->gh, full_tag); + + assert(ntag > 1 && ntag <= 16); + xor_bb(tag, full_tag, gcmctx->e_Y0, ntag); + + mem_clean(full_tag, sizeof full_tag); + mem_clean(gcmctx, sizeof *gcmctx); +} + +void cf_gcm_encrypt(const cf_prp *prp, void *prpctx, + const uint8_t *plain, size_t nplain, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + uint8_t *cipher, /* the same size as nplain */ + uint8_t *tag, size_t ntag) +{ + cf_gcm_ctx gcmctx; + + cf_gcm_encrypt_init(prp, prpctx, &gcmctx, header, nheader, nonce, nnonce); + cf_gcm_encrypt_update(&gcmctx, plain, nplain, cipher); + cf_gcm_encrypt_final(&gcmctx, tag, ntag); +} + +int cf_gcm_decrypt(const cf_prp *prp, void *prpctx, + const uint8_t *cipher, size_t ncipher, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + const uint8_t *tag, size_t ntag, + uint8_t *plain) +{ + uint8_t H[16] = { 0 }; + uint8_t Y0[16]; + + /* H = E_K(0^128) */ + prp->encrypt(prpctx, H, H); + + /* Produce CTR nonce, Y_0: + * + * if len(IV) == 96 + * Y_0 = IV || 0^31 || 1 + * otherwise + * Y_0 = GHASH(H, {}, IV) + */ + + if (nnonce == 12) + { + memcpy(Y0, nonce, nnonce); + Y0[12] = Y0[13] = Y0[14] = 0x00; + Y0[15] = 0x01; + } else { + ghash_ctx gh; + ghash_init(&gh, H); + ghash_add_cipher(&gh, nonce, nnonce); + ghash_final(&gh, Y0); + } + + /* Hash AAD. */ + ghash_ctx gh; + ghash_init(&gh, H); + ghash_add_aad(&gh, header, nheader); + + /* Start counter mode, to obtain offset on tag. */ + uint8_t e_Y0[16] = { 0 }; + cf_ctr ctr; + cf_ctr_init(&ctr, prp, prpctx, Y0); + cf_ctr_custom_counter(&ctr, 12, 4); + cf_ctr_cipher(&ctr, e_Y0, e_Y0, sizeof e_Y0); + + /* Hash ciphertext. */ + ghash_add_cipher(&gh, cipher, ncipher); + + /* Produce tag. */ + uint8_t full_tag[16]; + ghash_final(&gh, full_tag); + assert(ntag > 1 && ntag <= 16); + xor_bb(full_tag, full_tag, e_Y0, ntag); + + int err = 1; + if (!mem_eq(full_tag, tag, ntag)) + goto x_err; + + /* Complete decryption. */ + cf_ctr_cipher(&ctr, cipher, plain, ncipher); + err = 0; + +x_err: + mem_clean(H, sizeof H); + mem_clean(Y0, sizeof Y0); + mem_clean(e_Y0, sizeof e_Y0); + mem_clean(full_tag, sizeof full_tag); + mem_clean(&gh, sizeof gh); + mem_clean(&ctr, sizeof ctr); + return err; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/gf128.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/gf128.c new file mode 100644 index 0000000..f7ea834 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/gf128.c @@ -0,0 +1,114 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "cf_config.h" +#include "gf128.h" +#include "bitops.h" + +#include <string.h> + +void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16]) +{ + write32_be(in[0], out + 0); + write32_be(in[1], out + 4); + write32_be(in[2], out + 8); + write32_be(in[3], out + 12); +} + +void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out) +{ + out[0] = read32_be(in + 0); + out[1] = read32_be(in + 4); + out[2] = read32_be(in + 8); + out[3] = read32_be(in + 12); +} + +/* out = 2 * in. Arguments may alias. */ +void cf_gf128_double(const cf_gf128 in, cf_gf128 out) +{ + uint8_t table[2] = { 0x00, 0x87 }; + uint32_t borrow = 0; + uint32_t inword; + + inword = in[3]; out[3] = (inword << 1) | borrow; borrow = inword >> 31; + inword = in[2]; out[2] = (inword << 1) | borrow; borrow = inword >> 31; + inword = in[1]; out[1] = (inword << 1) | borrow; borrow = inword >> 31; + inword = in[0]; out[0] = (inword << 1) | borrow; borrow = inword >> 31; + +#if CF_CACHE_SIDE_CHANNEL_PROTECTION + out[3] ^= select_u8(borrow, table, 2); +#else + out[3] ^= table[borrow]; +#endif +} + +/* out = 2 * in. Arguments may alias. */ +void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out) +{ + uint8_t table[2] = { 0x00, 0xe1 }; + uint32_t borrow = 0; + uint32_t inword; + + inword = in[0]; out[0] = (inword >> 1) | (borrow << 31); borrow = inword & 1; + inword = in[1]; out[1] = (inword >> 1) | (borrow << 31); borrow = inword & 1; + inword = in[2]; out[2] = (inword >> 1) | (borrow << 31); borrow = inword & 1; + inword = in[3]; out[3] = (inword >> 1) | (borrow << 31); borrow = inword & 1; + +#if CF_CACHE_SIDE_CHANNEL_PROTECTION + out[0] ^= select_u8(borrow, table, 2) << 24; +#else + out[0] ^= table[borrow] << 24; +#endif +} + +/* out = x + y. Arguments may alias. */ +void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out) +{ + out[0] = x[0] ^ y[0]; + out[1] = x[1] ^ y[1]; + out[2] = x[2] ^ y[2]; + out[3] = x[3] ^ y[3]; +} + +/* out = xy. Arguments may alias. */ +void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out) +{ +#if CF_TIME_SIDE_CHANNEL_PROTECTION + cf_gf128 zero = { 0 }; +#endif + + /* Z_0 = 0^128 + * V_0 = Y */ + cf_gf128 Z, V; + memset(Z, 0, sizeof Z); + memcpy(V, y, sizeof V); + + int i; + for (i = 0; i < 128; i++) + { + uint32_t word = x[i >> 5]; + uint8_t bit = (word >> (31 - (i & 31))) & 1; + +#if CF_TIME_SIDE_CHANNEL_PROTECTION + select_xor128(Z, zero, V, bit); +#else + if (bit) + xor_words(Z, V, 4); +#endif + + cf_gf128_double_le(V, V); + } + + memcpy(out, Z, sizeof Z); +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/gf128.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/gf128.h new file mode 100644 index 0000000..7560862 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/gf128.h @@ -0,0 +1,55 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef GF128_H +#define GF128_H + +#include <stddef.h> +#include <stdint.h> + +/** + * @brief Operations in GF(2^128). + * + * These implementations are constant time, but relatively slow. + */ + +typedef uint32_t cf_gf128[4]; + +/* Unpack from big-endian bytes into out. */ +void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out); + +/* Pack in big-endian order into out. */ +void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16]); + +/* out = 2 * in. Arguments may not alias. */ +void cf_gf128_double(const cf_gf128 in, cf_gf128 out); + +/* out = 2 * in. Arguments may not alias. + * This differs from cf_gf128_double because it interprets the + * block in little endian: the lsb is the msb of the + * first element, the msb is the lsb of the last element. + * + * GCM uses this convention. */ +void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out); + +/* out = x + y. Arguments may alias. */ +void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out); + +/* out = xy. Arguments may alias. + * + * This uses cf_gf128_double_le internally, and is suitable for + * GCM. */ +void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/hmac.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/hmac.c new file mode 100644 index 0000000..98646d7 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/hmac.c @@ -0,0 +1,106 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "hmac.h" +#include "chash.h" +#include "bitops.h" +#include "handy.h" +#include "tassert.h" + +#include <string.h> + +void cf_hmac_init(cf_hmac_ctx *ctx, + const cf_chash *hash, + const uint8_t *key, size_t nkey) +{ + assert(ctx); + assert(hash); + + mem_clean(ctx, sizeof *ctx); + ctx->hash = hash; + + /* Prepare key: */ + uint8_t k[CF_CHASH_MAXBLK]; + + /* Shorten long keys. */ + if (nkey > hash->blocksz) + { + /* Standard doesn't cover case where blocksz < hashsz. + * FIPS186-1 seems to want to append a negative number of zero bytes. + * In any case, we only have a k buffer of CF_CHASH_MAXBLK! */ + assert(hash->hashsz <= hash->blocksz); + + cf_hash(hash, key, nkey, k); + key = k; + nkey = hash->hashsz; + } + + /* Right zero-pad short keys. */ + if (k != key) + memcpy(k, key, nkey); + if (hash->blocksz > nkey) + memset(k + nkey, 0, hash->blocksz - nkey); + + /* Start inner hash computation */ + uint8_t blk[CF_CHASH_MAXBLK]; + + xor_b8(blk, k, 0x36, hash->blocksz); + hash->init(&ctx->inner); + hash->update(&ctx->inner, blk, hash->blocksz); + + /* And outer. */ + xor_b8(blk, k, 0x5c, hash->blocksz); + hash->init(&ctx->outer); + hash->update(&ctx->outer, blk, hash->blocksz); + + mem_clean(blk, sizeof blk); + mem_clean(k, sizeof k); +} + +void cf_hmac_update(cf_hmac_ctx *ctx, const void *data, size_t ndata) +{ + assert(ctx && ctx->hash); + + ctx->hash->update(&ctx->inner, data, ndata); +} + +void cf_hmac_finish(cf_hmac_ctx *ctx, uint8_t *out) +{ + assert(ctx && ctx->hash); + assert(out); + + uint8_t innerh[CF_MAXHASH]; + ctx->hash->digest(&ctx->inner, innerh); + + ctx->hash->update(&ctx->outer, innerh, ctx->hash->hashsz); + ctx->hash->digest(&ctx->outer, out); + + mem_clean(ctx, sizeof *ctx); +} + +void cf_hmac(const uint8_t *key, size_t nkey, + const uint8_t *msg, size_t nmsg, + uint8_t *out, + const cf_chash *hash) +{ + cf_hmac_ctx ctx; + + assert(out); + assert(hash); + + cf_hmac_init(&ctx, hash, key, nkey); + cf_hmac_update(&ctx, msg, nmsg); + cf_hmac_finish(&ctx, out); +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/hmac.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/hmac.h new file mode 100644 index 0000000..2f9ea7b --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/hmac.h @@ -0,0 +1,78 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef HMAC_H +#define HMAC_H + +#include <stddef.h> +#include <stdint.h> + +#include "chash.h" + +/** + * HMAC + * ==== + * This is a one-shot and incremental interface to computing + * HMAC with any hash function. + * + * (Note: HMAC with SHA3 is possible, but is probably not a + * sensible thing to want.) + */ + +/* .. c:type:: cf_hmac_ctx + * HMAC incremental interface context. + * + * .. c:member:: cf_hmac_ctx.hash + * Hash function description. + * + * .. c:member:: cf_hmac_ctx.inner + * Inner hash computation. + * + * .. c:member:: cf_hmac_ctx.outer + * Outer hash computation. + */ +typedef struct +{ + const cf_chash *hash; + cf_chash_ctx inner; + cf_chash_ctx outer; +} cf_hmac_ctx; + +/* .. c:function:: $DECL + * Set up ctx for computing a HMAC using the given hash and key. */ +void cf_hmac_init(cf_hmac_ctx *ctx, + const cf_chash *hash, + const uint8_t *key, size_t nkey); + +/* .. c:function:: $DECL + * Input data. */ +void cf_hmac_update(cf_hmac_ctx *ctx, + const void *data, size_t ndata); + +/* .. c:function:: $DECL + * Finish and compute HMAC. + * `ctx->hash->hashsz` bytes are written to `out`. */ +void cf_hmac_finish(cf_hmac_ctx *ctx, uint8_t *out); + +/* .. c:function:: $DECL + * One shot interface: compute `HMAC_hash(key, msg)`, writing the + * answer (which is `hash->hashsz` long) to `out`. + * + * This function does not fail. */ +void cf_hmac(const uint8_t *key, size_t nkey, + const uint8_t *msg, size_t nmsg, + uint8_t *out, + const cf_chash *hash); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/modes.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/modes.c new file mode 100644 index 0000000..1e44af1 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/modes.c @@ -0,0 +1,99 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "prp.h" +#include "modes.h" +#include "bitops.h" +#include "blockwise.h" + +#include <string.h> +#include "tassert.h" + +/* CBC */ +void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK]) +{ + ctx->prp = prp; + ctx->prpctx = prpctx; + memcpy(ctx->block, iv, prp->blocksz); +} + +void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks) +{ + uint8_t buf[CF_MAXBLOCK]; + size_t nblk = ctx->prp->blocksz; + + while (blocks--) + { + xor_bb(buf, input, ctx->block, nblk); + ctx->prp->encrypt(ctx->prpctx, buf, ctx->block); + memcpy(output, ctx->block, nblk); + input += nblk; + output += nblk; + } +} + +void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks) +{ + uint8_t buf[CF_MAXBLOCK]; + size_t nblk = ctx->prp->blocksz; + + while (blocks--) + { + ctx->prp->decrypt(ctx->prpctx, input, buf); + xor_bb(output, buf, ctx->block, nblk); + memcpy(ctx->block, input, nblk); + input += nblk; + output += nblk; + } +} + +/* CTR */ +void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK]) +{ + memset(ctx, 0, sizeof *ctx); + ctx->counter_offset = 0; + ctx->counter_width = prp->blocksz; + ctx->prp = prp; + ctx->prpctx = prpctx; + ctx->nkeymat = 0; + memcpy(ctx->nonce, nonce, prp->blocksz); +} + +void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width) +{ + assert(ctx->prp->blocksz <= offset + width); + ctx->counter_offset = offset; + ctx->counter_width = width; +} + +static void ctr_next_block(void *vctx, uint8_t *out) +{ + cf_ctr *ctx = vctx; + ctx->prp->encrypt(ctx->prpctx, ctx->nonce, out); + incr_be(ctx->nonce + ctx->counter_offset, ctx->counter_width); +} + +void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes) +{ + cf_blockwise_xor(ctx->keymat, &ctx->nkeymat, + ctx->prp->blocksz, + input, output, bytes, + ctr_next_block, + ctx); +} + +void cf_ctr_discard_block(cf_ctr *ctx) +{ + ctx->nkeymat = 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/modes.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/modes.h new file mode 100644 index 0000000..20940a3 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/modes.h @@ -0,0 +1,587 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef MODES_H +#define MODES_H + +#include <stddef.h> +#include <stdint.h> + +#include "gf128.h" +#include "prp.h" + +/** + * Block cipher modes + * ================== + */ + +/** + * CBC mode + * -------- + * This implementation allows encryption or decryption of whole + * blocks in CBC mode. It does not offer a byte-wise incremental + * interface, or do any padding. + * + * This mode provides no useful integrity and should not be used + * directly. + */ + +/* .. c:type:: cf_cbc + * This structure binds together the things needed to encrypt/decrypt whole + * blocks in CBC mode. + * + * .. c:member:: cf_cbc.prp + * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`. + * + * .. c:member:: cf_cbc.prpctx + * Private data for prp functions. For a `prp` of `cf_aes`, this would be a + * pointer to a :c:type:`cf_aes_context` instance. + * + * .. c:member:: cf_cbc.block + * The IV or last ciphertext block. + */ +typedef struct +{ + const cf_prp *prp; + void *prpctx; + uint8_t block[CF_MAXBLOCK]; +} cf_cbc; + +/* .. c:function:: $DECL + * Initialise CBC encryption/decryption context using selected prp, prp context and IV. */ +void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK]); + +/* .. c:function:: $DECL + * Encrypt blocks in CBC mode. input and output + * must point to blocks * ctx->prp->blocksz bytes of storage (and may alias). */ +void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks); + +/* .. c:function:: $DECL + * Decrypt blocks in CBC mode. input and output + * must point to blocks * ctx->prp->blocksz bytes of storage (and may alias). */ +void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks); + +/** + * Counter mode + * ------------ + * This implementation allows incremental encryption/decryption of + * messages. Encryption and decryption are the same operation. + * + * The counter is always big-endian, but has configurable location + * and size within the nonce block. The counter wraps, so you + * should make sure the length of a message with a given nonce + * doesn't cause nonce reuse. + * + * This mode provides no integrity and should not be used directly. + */ + +/* .. c:type:: cf_ctr + * + * .. c:member:: cf_ctr.prp + * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`. + * + * .. c:member:: cf_ctr.prpctx + * Private data for prp functions. For a `prp` of `cf_aes`, this would be a + * pointer to a :c:type:`cf_aes_context` instance. + * + * .. c:member:: cf_ctr.nonce + * The next block to encrypt to get another block of key stream. + * + * .. c:member:: cf_ctr.keymat + * The current block of key stream. + * + * .. c:member:: cf_ctr.nkeymat + * The number of bytes at the end of :c:member:`keymat` that are so-far unused. + * If this is zero, all the bytes are used up and/or of undefined value. + * + * .. c:member:: cf_ctr.counter_offset + * The offset (in bytes) of the counter block within the nonce. + * + * .. c:member:: cf_ctr.counter_width + * The width (in bytes) of the counter block in the nonce. + */ +typedef struct +{ + const cf_prp *prp; + void *prpctx; + uint8_t nonce[CF_MAXBLOCK]; + uint8_t keymat[CF_MAXBLOCK]; + size_t nkeymat; + size_t counter_offset; + size_t counter_width; +} cf_ctr; + +/* .. c:function:: $DECL + * Initialise CTR encryption/decryption context using selected prp and nonce. + * (nb, this only increments the whole nonce as a big endian block) */ +void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK]); + +/* .. c:function:: $DECL + * Set the location and width of the nonce counter. + * + * eg. offset = 12, width = 4 means the counter is mod 2^32 and placed + * at the end of the nonce. */ +void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width); + +/* .. c:function:: $DECL + * Encrypt or decrypt bytes in CTR mode. + * input and output may alias and must point to specified number of bytes. */ +void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes); + +/* .. c:function:: $DECL + * Discards the rest of this block of key stream. */ +void cf_ctr_discard_block(cf_ctr *ctx); + +/** + * CBC-MAC + * ------- + * This is a incremental interface to computing a CBC-MAC tag over a message. + * + * It optionally pads the message with PKCS#5/PKCS#7 padding -- if you don't + * do this, messages must be an exact number of blocks long. + * + * You shouldn't use this directly because it isn't secure for variable-length + * messages. Use CMAC instead. + */ + +/* .. c:type:: cf_cbcmac_stream + * Stream interface to CBC-MAC signing. + * + * .. c:member:: cf_cbcmac.prp + * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`. + * + * .. c:member:: cf_cbcmac.prpctx + * Private data for prp functions. For a `prp` of `cf_aes`, this would be a + * pointer to a :c:type:`cf_aes_context` instance. + * + * .. c:member:: cf_cbcmac.cbc + * CBC data. + * + * .. c:member:: cf_cbcmac.buffer + * Buffer for data which can't be processed until we have a full block. + * + * .. c:member:: cf_cbcmac.used + * How many bytes at the front of :c:member:`buffer` are valid. + */ +typedef struct +{ + const cf_prp *prp; + void *prpctx; + cf_cbc cbc; + uint8_t buffer[CF_MAXBLOCK]; + size_t used; +} cf_cbcmac_stream; + +/* .. c:function:: $DECL + * Initialise CBC-MAC signing context using selected prp. */ +void cf_cbcmac_stream_init(cf_cbcmac_stream *ctx, const cf_prp *prp, void *prpctx); + +/* .. c:function:: $DECL + * Reset the streaming signing context, to sign a new message. */ +void cf_cbcmac_stream_reset(cf_cbcmac_stream *ctx); + +/* .. c:function:: $DECL + * Process ndata bytes at data. */ +void cf_cbcmac_stream_update(cf_cbcmac_stream *ctx, const uint8_t *data, size_t ndata); + +/* .. c:function:: $DECL + * Finish the current block of data by adding zeroes. Does nothing if there + * are no bytes awaiting processing. */ +void cf_cbcmac_stream_finish_block_zero(cf_cbcmac_stream *ctx); + +/* .. c:function:: $DECL + * Output the MAC to ctx->prp->blocksz bytes at out. + * ctx->used must be zero: the inputed message must be an exact number of + * blocks. */ +void cf_cbcmac_stream_nopad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]); + +/* .. c:function:: $DECL + * Output the MAC to ctx->prp->blocksz bytes at out. + * + * The message is padded with PKCS#5 padding. */ +void cf_cbcmac_stream_pad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]); + +/** + * CMAC + * ---- + * This is both a one-shot and incremental interface to + * computing a CMAC tag over a message. + * + * The one-shot interface separates out the per-key computation, + * so if you need to compute lots of MACs with one key you don't + * pay that cost more than once. + * + * CMAC is a good choice for a symmetric MAC. + */ + +/* .. c:type:: cf_cmac + * One-shot interface to CMAC signing. + * + * .. c:member:: cf_cmac.prp + * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`. + * + * .. c:member:: cf_cmac.prpctx + * Private data for prp functions. For a `prp` of `cf_aes`, this would be a + * pointer to a :c:type:`cf_aes_context` instance. + * + * .. c:member:: cf_cmac.B + * The XOR offset for the last message block if it is a complete block + * (also known as K\ :sub:`1`). + * + * .. c:member:: cf_cmac.P + * The XOR offset for the last message block if it is a partial block + * (also known as K\ :sub:`2`). + */ +typedef struct +{ + const cf_prp *prp; + void *prpctx; + uint8_t B[CF_MAXBLOCK]; + uint8_t P[CF_MAXBLOCK]; +} cf_cmac; + +/* .. c:function:: $DECL + * Initialise CMAC signing context using selected prp. */ +void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx); + +/* .. c:function:: $DECL + * CMAC sign the given data. The MAC is written to ctx->prp->blocksz + * bytes at out. This is a one-shot function. */ +void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t bytes, + uint8_t out[CF_MAXBLOCK]); + +/* .. c:type:: cf_cmac_stream + * Stream interface to CMAC signing. + * + * Input data in arbitrary chunks using :c:func:`cf_cmac_stream_update`. + * The last bit of data must be signalled with the `isfinal` flag to + * that function, and the data cannot be zero length unless the whole + * message is empty. + * + * .. c:member:: cf_cmac_stream.cmac + * CMAC one-shot data. + * + * .. c:member:: cf_cmac_stream.cbc + * CBC block encryption data. + * + * .. c:member:: cf_cmac_stream.buffer + * Buffer for data which can't be processed until we have a full block. + * + * .. c:member:: cf_cmac_stream.used + * How many bytes at the front of :c:member:`buffer` are valid. + * + * .. c:member:: cf_cmac_stream.processed + * How many bytes in total we've processed. This is used to correctly + * process empty messages. + * + * .. c:member:: cf_cmac_stream.finalised + * A flag set when the final chunk of the message has been processed. + * Only when this flag is set can you get the MAC out. + */ +typedef struct +{ + cf_cmac cmac; + cf_cbc cbc; + uint8_t buffer[CF_MAXBLOCK]; + size_t used; + size_t processed; + int finalised; +} cf_cmac_stream; + +/* .. c:function:: $DECL + * Initialise CMAC streaming signing context using selected prp. */ +void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx); + +/* .. c:function:: $DECL + * Reset the streaming signing context, to sign a new message. */ +void cf_cmac_stream_reset(cf_cmac_stream *ctx); + +/* .. c:function:: $DECL + * Process ndata bytes at data. isfinal is non-zero if this is the last piece + * of data. */ +void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t ndata, + int isfinal); + +/* .. c:function:: $DECL + * Output the MAC to ctx->cmac->prp->blocksz bytes at out. + * cf_cmac_stream_update with isfinal non-zero must have been called + * since the last _init/_reset. */ +void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK]); + +/** + * EAX + * --- + * + * The EAX authenticated encryption mode. This is a one-shot + * interface. + * + * EAX is a pretty respectable and fast AEAD mode. + */ + +/* .. c:function:: $DECL + * EAX authenticated encryption. + * + * This function does not fail. + * + * :param prp/prpctx: describe the block cipher to use. + * :param plain: message plaintext. + * :param nplain: length of message. May be zero. + * :param header: additionally authenticated data (AAD). + * :param nheader: length of AAD. May be zero. + * :param nonce: nonce. This must not repeat for a given key. + * :param nnonce: length of nonce. The nonce can be any length. + * :param cipher: ciphertext output. `nplain` bytes are written here. + * :param tag: authentication tag. `ntag` bytes are written here. + * :param ntag: authentication tag length. This must be non-zero and no greater than `prp->blocksz`. + */ +void cf_eax_encrypt(const cf_prp *prp, void *prpctx, + const uint8_t *plain, size_t nplain, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + uint8_t *cipher, + uint8_t *tag, size_t ntag); + +/* .. c:function:: $DECL + * EAX authenticated decryption. + * + * :return: 0 on success, non-zero on error. Nothing is written to plain on error. + * + * :param prp/prpctx: describe the block cipher to use. + * :param cipher: message ciphertext. + * :param ncipher: message length. + * :param header: additionally authenticated data (AAD). + * :param nheader: length of AAD. + * :param nonce: nonce. + * :param nnonce: length of nonce. + * :param tag: authentication tag. `ntag` bytes are read from here. + * :param ntag: authentication tag length. + * :param plain: plaintext output. `ncipher` bytes are written here. + */ +int cf_eax_decrypt(const cf_prp *prp, void *prpctx, + const uint8_t *cipher, size_t ncipher, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + const uint8_t *tag, size_t ntag, + uint8_t *plain); + +/** + * GCM + * --- + * The GCM ('Galois counter mode') authenticated encryption mode. + * This is a one-shot interface. + * + * GCM is a reasonably respectable AEAD mode. It's somewhat more + * complex than EAX, and side channel-free implementations can + * be quite slow. + */ + +/* .. c:function:: $DECL + * GCM authenticated encryption. + * + * This function does not fail. + * + * :param prp/prpctx: describe the block cipher to use. + * :param plain: message plaintext. + * :param nplain: length of message. May be zero. + * :param header: additionally authenticated data (AAD). + * :param nheader: length of AAD. May be zero. + * :param nonce: nonce. This must not repeat for a given key. + * :param nnonce: length of nonce. The nonce can be any length, but 12 bytes is strongly recommended. + * :param cipher: ciphertext output. `nplain` bytes are written here. + * :param tag: authentication tag. `ntag` bytes are written here. + * :param ntag: authentication tag length. This must be non-zero and no greater than `prp->blocksz`. + * + * This function does not fail. + */ +void cf_gcm_encrypt(const cf_prp *prp, void *prpctx, + const uint8_t *plain, size_t nplain, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + uint8_t *cipher, + uint8_t *tag, size_t ntag); + +/* Incremental GHASH computation. */ +typedef struct +{ + cf_gf128 H; + cf_gf128 Y; + uint8_t buffer[16]; + size_t buffer_used; + uint64_t len_aad; + uint64_t len_cipher; + unsigned state; +} ghash_ctx; + +typedef struct +{ + cf_ctr ctr; + ghash_ctx gh; + uint8_t Y0[16]; + uint8_t e_Y0[16]; +} cf_gcm_ctx; + +void cf_gcm_encrypt_init(const cf_prp *prp, void *prpctx, cf_gcm_ctx *gcmctx, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce); +void cf_gcm_encrypt_update(cf_gcm_ctx *gcmctx, const uint8_t *plain, size_t nplain, uint8_t *cipher); +void cf_gcm_encrypt_final(cf_gcm_ctx *gcmctx, uint8_t *tag, size_t ntag); + +/* .. c:function:: $DECL + * GCM authenticated decryption. + * + * :return: 0 on success, non-zero on error. Nothing is written to plain on error. + * + * :param prp: describe the block cipher to use. + * :param prpctx: describe the block cipher to use. + * :param cipher: message ciphertext. + * :param ncipher: message length. + * :param header: additionally authenticated data (AAD). + * :param nheader: length of AAD. + * :param nonce: nonce. + * :param nnonce: length of nonce. + * :param tag: authentication tag. `ntag` bytes are read from here. + * :param ntag: authentication tag length. + * :param plain: plaintext output. `ncipher` bytes are written here. + */ +int cf_gcm_decrypt(const cf_prp *prp, void *prpctx, + const uint8_t *cipher, size_t ncipher, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + const uint8_t *tag, size_t ntag, + uint8_t *plain); + +/** + * CCM + * --- + * + * The CCM ('Counter with CBC-MAC') authenticated encryption mode. + * CCM is a widely used AEAD mode (in IPSec, WPA2, Bluetooth, etc.) + * + * It works (at a high level) by just gluing together CTR and CBC-MAC + * modes (in MAC-then-encrypt mode) and then fixing the problems inherent + * with CBC-MAC in over-complicated ways. + * + * This is a one-shot interface, which is good because the underlying + * mechanism isn't actually online: you need to know the message length + * before you start, or do everything in two passes. + */ + +/* .. c:function:: $DECL + * CCM authenticated encryption. + * + * This function does not fail. + * + * :param prp/prpctx: describe the block cipher to use. + * :param plain: message plaintext. + * :param nplain: length of message. May be zero. Must meet the constraints placed on it by `L`. + * :param L: length of the message length encoding. This must be in the interval `[2,8]` and gives a maximum message size of 2\ :sup:`8L` bytes. + * :param header: additionally authenticated data (AAD). + * :param nheader: length of AAD. May be zero. + * :param nonce: nonce. This must not repeat for a given key. + * :param nnonce: length of nonce. Must be exactly `15 - L` bytes for a 128-bit block cipher. + * :param cipher: ciphertext output. `nplain` bytes are written here. + * :param tag: authentication tag. `ntag` bytes are written here. + * :param ntag: authentication tag length. This must be 4, 6, 8, 10, 12, 14 or 16. + */ +void cf_ccm_encrypt(const cf_prp *prp, void *prpctx, + const uint8_t *plain, size_t nplain, size_t L, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + uint8_t *cipher, + uint8_t *tag, size_t ntag); + +/* .. c:function:: $DECL + * CCM authenticated decryption. + * + * :return: 0 on success, non-zero on error. Plain is cleared on error. + * + * :param prp: describe the block cipher to use. + * :param prpctx: describe the block cipher to use. + * :param cipher: message ciphertext. + * :param ncipher: length of message. + * :param L: length of the message length encoding. See :c:func:`cf_ccm_encrypt`. + * :param header: additionally authenticated data (AAD). + * :param nheader: length of AAD. + * :param nonce: nonce. + * :param nnonce: length of nonce. + * :param tag: authentication tag. `ntag` bytes are read from here. + * :param ntag: authentication tag length. This must be 4, 6, 8, 10, 12, 14 or 16. + * :param plain: plaintext output. `ncipher` bytes are written here. + */ +int cf_ccm_decrypt(const cf_prp *prp, void *prpctx, + const uint8_t *cipher, size_t ncipher, size_t L, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + const uint8_t *tag, size_t ntag, + uint8_t *plain); + +/** + * OCB + * --- + * + * OCB is an authenticated encryption mode by Phil Rogaway. + * + * This is version 3, as standardised in RFC7253. It's defined + * only for block ciphers with a 128-bit block size. + * + * This is a one-shot interface. + */ + +/* .. c:function:: $DECL + * OCB authenticated encryption. + * + * This function does not fail. + * + * :param prp/prpctx: describe the block cipher to use. + * :param plain: message plaintext. + * :param nplain: length of message. May be zero. + * :param header: additionally authenticated data (AAD). + * :param nheader: length of AAD. May be zero. + * :param nonce: nonce. This must not repeat for a given key. + * :param nnonce: length of nonce. Must be 15 or fewer bytes. + * :param cipher: ciphertext output. `nplain` bytes are written here. + * :param tag: authentication tag. `ntag` bytes are written here. + * :param ntag: authentication tag length. Must be 16 or fewer bytes. + */ +void cf_ocb_encrypt(const cf_prp *prp, void *prpctx, + const uint8_t *plain, size_t nplain, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + uint8_t *cipher, + uint8_t *tag, size_t ntag); + +/* .. c:function:: $DECL + * OCB authenticated decryption. + * + * :return: 0 on success, non-zero on error. `plain` is cleared on error. + * + * :param prp: describe the block cipher to use. + * :param prpctx: describe the block cipher to use. + * :param cipher: message ciphertext. + * :param ncipher: length of message. + * :param header: additionally authenticated data (AAD). + * :param nheader: length of AAD. + * :param nonce: nonce. + * :param nnonce: length of nonce. + * :param tag: authentication tag. `ntag` bytes are read from here. + * :param ntag: authentication tag length. + * :param plain: plaintext output. `ncipher` bytes are written here. + */ +int cf_ocb_decrypt(const cf_prp *prp, void *prpctx, + const uint8_t *cipher, size_t ncipher, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + const uint8_t *tag, size_t ntag, + uint8_t *plain); +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/norx.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/norx.c new file mode 100644 index 0000000..8f0aba6 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/norx.c @@ -0,0 +1,410 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + + +#include "norx.h" +#include "bitops.h" +#include "handy.h" +#include "blockwise.h" +#include "tassert.h" + +#include <string.h> + +typedef struct +{ + uint32_t s[16]; +} norx32_ctx; + +/* Domain separation constants */ +#define DOMAIN_HEADER 0x01 +#define DOMAIN_PAYLOAD 0x02 +#define DOMAIN_TRAILER 0x04 +#define DOMAIN_TAG 0x08 + +#define WORD_BYTES 4 +#define WORD_BITS 32 +#define ROUNDS 4 +#define DEGREE 1 +#define TAG_BITS 128 +#define RATE_BYTES 48 +#define RATE_WORDS 12 + +static void permute(norx32_ctx *ctx) +{ +#ifdef CORTEX_M0 + /* Register usage: A-D r2, r3, r4, r5. + * Temps: r6 */ + +#define in(xx) "%[" #xx "]" + + /* Load numbered slots of S into r2-r5 */ +#define LOAD(u, v, w, x) \ + " ldr r2, [%[S], " in(u) "]\n" \ + " ldr r3, [%[S], " in(v) "]\n" \ + " ldr r4, [%[S], " in(w) "]\n" \ + " ldr r5, [%[S], " in(x) "]\n" + + /* Store r2-r5 into numbered slots of S */ +#define STORE(u, v, w, x) \ + " str r2, [%[S], " in(u) "]\n" \ + " str r3, [%[S], " in(v) "]\n" \ + " str r4, [%[S], " in(w) "]\n" \ + " str r5, [%[S], " in(x) "]\n" + + /* This is H() plus the xor and rotate in one step of G. + * rx is the register containing x (read/write) + * ry is the register containing y (read) + * rw is the register containing d (read/write) + * rot is the rotation constant r_n */ +#define P(rx, ry, rw, rot) \ + " mov r6, " #rx "\n" \ + " and " #rx ", " #ry "\n" \ + " lsl " #rx ", #1\n" \ + " eor " #rx ", r6\n" \ + " eor " #rx ", " #ry "\n" \ + " mov r6, #" #rot "\n" \ + " eor " #rw ", " #rx "\n" \ + " ror " #rw ", r6\n" + + /* The function G. s is the state array, a-d are indices + * into it. */ +#define G(s, a, b, c, d) \ + __asm__ ( \ + LOAD(A, B, C, D) \ + P(r2, r3, r5, 8) \ + P(r4, r5, r3, 11) \ + P(r2, r3, r5, 16) \ + P(r4, r5, r3, 31) \ + STORE(A, B, C, D) \ + : \ + : [S] "r" (s), \ + [A] "i" (a << 2), \ + [B] "i" (b << 2), \ + [C] "i" (c << 2), \ + [D] "i" (d << 2) \ + : "memory", "cc", "r2", "r3", "r4", "r5", "r6"); +#else + + /* This is one quarter of G; the function H plus xor/rotate. */ +#define P(u, v, w, rr) \ + (u) = ((u) ^ (v)) ^ (((u) & (v)) << 1); \ + (w) = rotr32((u) ^ (w), rr); + +#define G(s, a, b, c, d) \ + P(s[a], s[b], s[d], 8) \ + P(s[c], s[d], s[b], 11) \ + P(s[a], s[b], s[d], 16) \ + P(s[c], s[d], s[b], 31) +#endif + + for (int i = 0; i < ROUNDS; i++) + { + /* columns */ + G(ctx->s, 0, 4, 8, 12); + G(ctx->s, 1, 5, 9, 13); + G(ctx->s, 2, 6, 10, 14); + G(ctx->s, 3, 7, 11, 15); + + /* diagonals */ + G(ctx->s, 0, 5, 10, 15); + G(ctx->s, 1, 6, 11, 12); + G(ctx->s, 2, 7, 8, 13); + G(ctx->s, 3, 4, 9, 14); + } + +#undef G +#undef P +} + +static void init(norx32_ctx *ctx, + const uint8_t key[16], + const uint8_t nonce[8]) +{ + /* 1. Basic setup */ + ctx->s[0] = read32_le(nonce + 0); + ctx->s[1] = read32_le(nonce + 4); + ctx->s[2] = 0xb707322f; + ctx->s[3] = 0xa0c7c90d; + + ctx->s[4] = read32_le(key + 0); + ctx->s[5] = read32_le(key + 4); + ctx->s[6] = read32_le(key + 8); + ctx->s[7] = read32_le(key + 12); + + ctx->s[8] = 0xa3d8d930; + ctx->s[9] = 0x3fa8b72c; + ctx->s[10] = 0xed84eb49; + ctx->s[11] = 0xedca4787; + + ctx->s[12] = 0x335463eb; + ctx->s[13] = 0xf994220b; + ctx->s[14] = 0xbe0bf5c9; + ctx->s[15] = 0xd7c49104; + + /* 2. Parameter integration + * w = 32 + * l = 4 + * p = 1 + * t = 128 + */ + ctx->s[12] ^= WORD_BITS; + ctx->s[13] ^= ROUNDS; + ctx->s[14] ^= DEGREE; + ctx->s[15] ^= TAG_BITS; + + permute(ctx); +} + +/* Input domain separation constant for next step, and final permutation of + * preceeding step. */ +static void switch_domain(norx32_ctx *ctx, uint32_t constant) +{ + ctx->s[15] ^= constant; + permute(ctx); +} + +typedef struct +{ + norx32_ctx *ctx; + uint32_t type; +} blockctx; + +static void input_block_final(void *vctx, const uint8_t *data) +{ + blockctx *bctx = vctx; + norx32_ctx *ctx = bctx->ctx; + + /* just xor-in data. */ + for (int i = 0; i < RATE_WORDS; i++) + { + ctx->s[i] ^= read32_le(data); + data += WORD_BYTES; + } +} + +static void input_block(void *vctx, const uint8_t *data) +{ + /* Process block, then prepare for the next one. */ + blockctx *bctx = vctx; + input_block_final(vctx, data); + switch_domain(bctx->ctx, bctx->type); +} + +static void input(norx32_ctx *ctx, uint32_t type, + const uint8_t *buf, size_t nbuf) +{ + uint8_t partial[RATE_BYTES]; + size_t npartial = 0; + blockctx bctx = { ctx, type }; + + /* Process input. */ + cf_blockwise_accumulate(partial, &npartial, sizeof partial, + buf, nbuf, + input_block, + &bctx); + + /* Now pad partial. This contains the trailing portion of buf. */ + memset(partial + npartial, 0, sizeof(partial) - npartial); + partial[npartial] = 0x01; + partial[sizeof(partial) - 1] ^= 0x80; + + input_block_final(&bctx, partial); +} + +static void do_header(norx32_ctx *ctx, const uint8_t *buf, size_t nbuf) +{ + if (nbuf) + { + switch_domain(ctx, DOMAIN_HEADER); + input(ctx, DOMAIN_HEADER, buf, nbuf); + } +} + +static void do_trailer(norx32_ctx *ctx, const uint8_t *buf, size_t nbuf) +{ + if (nbuf) + { + switch_domain(ctx, DOMAIN_TRAILER); + input(ctx, DOMAIN_TRAILER, buf, nbuf); + } +} + +static void body_block_encrypt(norx32_ctx *ctx, + const uint8_t plain[RATE_BYTES], + uint8_t cipher[RATE_BYTES]) +{ + for (int i = 0; i < RATE_WORDS; i++) + { + ctx->s[i] ^= read32_le(plain); + write32_le(ctx->s[i], cipher); + plain += WORD_BYTES; + cipher += WORD_BYTES; + } +} + +static void encrypt_body(norx32_ctx *ctx, + const uint8_t *plain, uint8_t *cipher, size_t nbytes) +{ + if (nbytes == 0) + return; + + /* Process full blocks: easy */ + while (nbytes >= RATE_BYTES) + { + switch_domain(ctx, DOMAIN_PAYLOAD); + body_block_encrypt(ctx, plain, cipher); + plain += RATE_BYTES; + cipher += RATE_BYTES; + nbytes -= RATE_BYTES; + } + + /* Final padded block. */ + uint8_t partial[RATE_BYTES]; + memset(partial, 0, sizeof partial); + memcpy(partial, plain, nbytes); + partial[nbytes] ^= 0x01; + partial[sizeof(partial) - 1] ^= 0x80; + + switch_domain(ctx, DOMAIN_PAYLOAD); + body_block_encrypt(ctx, partial, partial); + + memcpy(cipher, partial, nbytes); +} + +static void body_block_decrypt(norx32_ctx *ctx, + const uint8_t cipher[RATE_BYTES], + uint8_t plain[RATE_BYTES], + size_t start, size_t end) +{ + for (size_t i = start; i < end; i++) + { + uint32_t ct = read32_le(cipher); + write32_le(ctx->s[i] ^ ct, plain); + ctx->s[i] = ct; + plain += WORD_BYTES; + cipher += WORD_BYTES; + } +} + +static void undo_padding(norx32_ctx *ctx, size_t bytes) +{ + assert(bytes < RATE_BYTES); + ctx->s[bytes / WORD_BYTES] ^= 0x01 << ((bytes % WORD_BYTES) * 8); + ctx->s[RATE_WORDS - 1] ^= 0x80000000; +} + +static void decrypt_body(norx32_ctx *ctx, + const uint8_t *cipher, uint8_t *plain, size_t nbytes) +{ + if (nbytes == 0) + return; + + /* Process full blocks. */ + while (nbytes >= RATE_BYTES) + { + switch_domain(ctx, DOMAIN_PAYLOAD); + body_block_decrypt(ctx, cipher, plain, 0, RATE_WORDS); + plain += RATE_BYTES; + cipher += RATE_BYTES; + nbytes -= RATE_BYTES; + } + + /* Then partial blocks. */ + size_t offset = 0; + switch_domain(ctx, DOMAIN_PAYLOAD); + + undo_padding(ctx, nbytes); + + /* In units of whole words. */ + while (nbytes >= WORD_BYTES) + { + body_block_decrypt(ctx, cipher, plain, offset, offset + 1); + plain += WORD_BYTES; + cipher += WORD_BYTES; + nbytes -= WORD_BYTES; + offset += 1; + } + + /* And then, finally, bytewise. */ + uint8_t tmp[WORD_BYTES]; + write32_le(ctx->s[offset], tmp); + + for (size_t i = 0; i < nbytes; i++) + { + uint8_t c = cipher[i]; + plain[i] = tmp[i] ^ c; + tmp[i] = c; + } + + ctx->s[offset] = read32_le(tmp); +} + +static void get_tag(norx32_ctx *ctx, uint8_t tag[16]) +{ + switch_domain(ctx, DOMAIN_TAG); + permute(ctx); + write32_le(ctx->s[0], tag + 0); + write32_le(ctx->s[1], tag + 4); + write32_le(ctx->s[2], tag + 8); + write32_le(ctx->s[3], tag + 12); +} + +void cf_norx32_encrypt(const uint8_t key[16], + const uint8_t nonce[8], + const uint8_t *header, size_t nheader, + const uint8_t *plaintext, size_t nbytes, + const uint8_t *trailer, size_t ntrailer, + uint8_t *ciphertext, + uint8_t tag[16]) +{ + norx32_ctx ctx; + + init(&ctx, key, nonce); + do_header(&ctx, header, nheader); + encrypt_body(&ctx, plaintext, ciphertext, nbytes); + do_trailer(&ctx, trailer, ntrailer); + get_tag(&ctx, tag); + + mem_clean(&ctx, sizeof ctx); +} + +int cf_norx32_decrypt(const uint8_t key[16], + const uint8_t nonce[8], + const uint8_t *header, size_t nheader, + const uint8_t *ciphertext, size_t nbytes, + const uint8_t *trailer, size_t ntrailer, + const uint8_t tag[16], + uint8_t *plaintext) +{ + norx32_ctx ctx; + uint8_t ourtag[16]; + + init(&ctx, key, nonce); + do_header(&ctx, header, nheader); + decrypt_body(&ctx, ciphertext, plaintext, nbytes); + do_trailer(&ctx, trailer, ntrailer); + get_tag(&ctx, ourtag); + + int err = 0; + + if (!mem_eq(ourtag, tag, sizeof ourtag)) + { + err = 1; + mem_clean(plaintext, nbytes); + mem_clean(ourtag, sizeof ourtag); + } + + mem_clean(&ctx, sizeof ctx); + return err; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/norx.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/norx.h new file mode 100644 index 0000000..aee7bfe --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/norx.h @@ -0,0 +1,84 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef NORX_H +#define NORX_H + +#include <stdint.h> +#include <stddef.h> + +/** + * The NORX AEAD cipher + * ==================== + * This is an implementation of NORX32-4-1 with a one-shot + * interface. NORX is a CAESAR candidate with a core similar + * to ChaCha20 and a sponge structure like Keccak. + * + * This is NORX v2.0. It is not compatible with earlier + * versions. + * + * NORX32 uses a 128-bit key. Each encryption requires a + * 64-bit nonce. An encryption processes one sequence of + * additional data ('header'), followed by encryption of + * the plaintext, followed by processing a second sequence + * of additional data ('trailer'). It outputs a 128-bit + * tag. + */ + +/* .. c:function:: $DECL + * NORX32-4-1 one-shot encryption interface. + * + * :param key: key material. + * :param nonce: per-message nonce. + * :param header: header buffer. + * :param nheader: number of header bytes. + * :param plaintext: plaintext bytes to be encrypted. + * :param nbytes: number of plaintext/ciphertext bytes. + * :param trailer: trailer buffer. + * :param ntrailer: number of trailer bytes. + * :param ciphertext: ciphertext output buffer, nbytes in length. + * :param tag: authentication tag output buffer. + */ +void cf_norx32_encrypt(const uint8_t key[16], + const uint8_t nonce[8], + const uint8_t *header, size_t nheader, + const uint8_t *plaintext, size_t nbytes, + const uint8_t *trailer, size_t ntrailer, + uint8_t *ciphertext, + uint8_t tag[16]); +/* .. c:function:: $DECL + * NORX32-4-1 one-shot decryption interface. + * + * :return: 0 on success, non-zero on error. Plaintext is zeroed on error. + * + * :param key: key material. + * :param nonce: per-message nonce. + * :param header: header buffer. + * :param nheader: number of header bytes. + * :param ciphertext: ciphertext bytes to be decrypted. + * :param nbytes: number of plaintext/ciphertext bytes. + * :param trailer: trailer buffer. + * :param ntrailer: number of trailer bytes. + * :param plaintext: plaintext output buffer, nbytes in length. + * :param tag: authentication tag output buffer. + */ +int cf_norx32_decrypt(const uint8_t key[16], + const uint8_t nonce[8], + const uint8_t *header, size_t nheader, + const uint8_t *ciphertext, size_t nbytes, + const uint8_t *trailer, size_t ntrailer, + const uint8_t tag[16], + uint8_t *plaintext); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/ocb.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/ocb.c new file mode 100644 index 0000000..3d244d4 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/ocb.c @@ -0,0 +1,404 @@ +/* + * cifra - embedded cryptography library + * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "handy.h" +#include "prp.h" +#include "modes.h" +#include "blockwise.h" +#include "bitops.h" +#include "gf128.h" +#include "tassert.h" + +#include <string.h> + +/* How many L_n values to compute at schedule time. */ +#define MAX_L 4 + +/* We and RFC7253 assume 128-bit blocks. */ +#define BLOCK 16 + +typedef struct +{ + const cf_prp *prp; + void *prpctx; /* Our PRP */ + uint8_t *out; /* Output pointer for block processing */ + cf_gf128 L_star; /* Zero block ciphertext */ + cf_gf128 L_dollar; /* L_$ is double of L_* */ + cf_gf128 L[MAX_L]; /* L[0] is double of L_$, L[1] is double of L[0], etc. */ + cf_gf128 offset; /* Offset_i */ + cf_gf128 checksum; /* Checksum_i */ + uint32_t i; /* Block index, 1-based */ +} ocb; + +typedef struct +{ + ocb *o; /* OCB context (contains PRP, etc.) */ + cf_gf128 sum; /* Current Sum_i */ + cf_gf128 offset; /* Current Offset_i */ + uint32_t i; /* Block index, 1-based */ +} ocb_hash; + +static void ocb_init(ocb *o, const cf_prp *prp, void *prpctx, + const uint8_t *nonce, size_t nnonce, + size_t ntag) +{ + o->prp = prp; + o->prpctx = prpctx; + + assert(o->prp->blocksz == BLOCK); + + /* L_* = ENCIPHER(K, zeros(128)) */ + uint8_t L_star_bytes[BLOCK] = { 0 }; + prp->encrypt(prpctx, L_star_bytes, L_star_bytes); + cf_gf128_frombytes_be(L_star_bytes, o->L_star); + + /* L_$ = double(L_*) */ + cf_gf128_double(o->L_star, o->L_dollar); + + /* L_0 = double(L_$) etc. */ + cf_gf128_double(o->L_dollar, o->L[0]); + + for (int i = 1; i < MAX_L; i++) + cf_gf128_double(o->L[i - 1], o->L[i]); + + /* Compute nonce-dependent and per-encryption vars */ + assert(nnonce > 0 && nnonce < BLOCK); + uint8_t full_nonce[BLOCK] = { 0 }; + full_nonce[0] = ((ntag * 8) & 0x7f) << 1; + full_nonce[BLOCK - 1 - nnonce] |= 0x01; + memcpy(full_nonce + BLOCK - nnonce, nonce, nnonce); + uint8_t bottom = full_nonce[BLOCK - 1] & 0x3f; + + /* Make Ktop */ + full_nonce[BLOCK - 1] &= 0xc0; + uint8_t Ktop[BLOCK + 8]; + prp->encrypt(prpctx, full_nonce, Ktop); + + /* Stretch Ktop */ + for (int i = 0; i < 8; i++) + Ktop[i + BLOCK] = Ktop[i] ^ Ktop[i + 1]; + + /* Outputs */ + uint8_t offset[BLOCK]; + copy_bytes_unaligned(offset, Ktop, BLOCK, bottom); + cf_gf128_frombytes_be(offset, o->offset); + memset(o->checksum, 0, sizeof o->checksum); +} + +static void ocb_start_cipher(ocb *o, uint8_t *output) +{ + o->i = 1; + o->out = output; +} + +static void ocb_add_Ln(ocb *o, uint32_t n, cf_gf128 out) +{ + /* Do we have a precomputed L term? */ + if (n < MAX_L) + { + cf_gf128_add(o->L[n], out, out); + return; + } + + /* Compute more terms of L. */ + cf_gf128 accum; + memcpy(accum, o->L[MAX_L - 1], sizeof accum); + + for (uint32_t i = MAX_L - 1; i < n; i++) + { + cf_gf128 next; + cf_gf128_double(accum, next); + memcpy(accum, next, sizeof accum); + } + + cf_gf128_add(accum, out, out); +} + +static void ocb_hash_init(ocb_hash *h) +{ + memset(h->offset, 0, sizeof h->offset); + memset(h->sum, 0, sizeof h->sum); + h->i = 1; +} + +static void ocb_hash_sum(ocb *o, const uint8_t *block, + cf_gf128 sum, const cf_gf128 offset) +{ + uint8_t offset_bytes[BLOCK]; + cf_gf128_tobytes_be(offset, offset_bytes); + + uint8_t block_tmp[BLOCK]; + xor_bb(block_tmp, block, offset_bytes, sizeof block_tmp); + o->prp->encrypt(o->prpctx, block_tmp, block_tmp); + + cf_gf128 tmp; + cf_gf128_frombytes_be(block_tmp, tmp); + cf_gf128_add(sum, tmp, sum); +} + +static void ocb_hash_block(void *vctx, const uint8_t *block) +{ + ocb_hash *h = vctx; + + /* Offset_i = Offset_{i - 1} xor L{ntz(i)} */ + ocb_add_Ln(h->o, count_trailing_zeroes(h->i), h->offset); + + /* Sum_i = Sum_{i - 1} xor ENCIPHER(K, A_i xor Offset_i) */ + ocb_hash_sum(h->o, block, h->sum, h->offset); + + h->i++; +} + +static void ocb_process_header(ocb *o, const uint8_t *header, size_t nheader, + uint8_t out[BLOCK]) +{ + ocb_hash ctx = { o }; + ocb_hash_init(&ctx); + + uint8_t partial[BLOCK]; + size_t npartial = 0; + + cf_blockwise_accumulate(partial, &npartial, + o->prp->blocksz, + header, nheader, + ocb_hash_block, + &ctx); + + if (npartial) + { + /* Offset_* = Offset_m xor L_* */ + cf_gf128_add(ctx.offset, o->L_star, ctx.offset); + + /* CipherInput = (A_* || 1 || zeros(127 - bitlen(A_*))) xor Offset_* */ + memset(partial + npartial, 0, sizeof(partial) - npartial); + partial[npartial] = 0x80; + + /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ + ocb_hash_sum(ctx.o, partial, ctx.sum, ctx.offset); + } + + cf_gf128_tobytes_be(ctx.sum, out); + mem_clean(&ctx, sizeof ctx); +} + +static void ocb_encrypt_block(void *vctx, const uint8_t *block) +{ + ocb *o = vctx; + + /* Offset_i = Offset_{i - 1} xor L{ntz(i)} */ + ocb_add_Ln(o, count_trailing_zeroes(o->i), o->offset); + + /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ + uint8_t offset_bytes[BLOCK]; + cf_gf128_tobytes_be(o->offset, offset_bytes); + + uint8_t block_tmp[BLOCK]; + xor_bb(block_tmp, block, offset_bytes, sizeof block_tmp); + o->prp->encrypt(o->prpctx, block_tmp, block_tmp); + xor_bb(o->out, block_tmp, offset_bytes, sizeof block_tmp); + o->out += sizeof block_tmp; + + /* Checksum_i = Checksum_{i - 1} xor P_i */ + cf_gf128 P; + cf_gf128_frombytes_be(block, P); + cf_gf128_add(o->checksum, P, o->checksum); + + o->i++; +} + +void cf_ocb_encrypt(const cf_prp *prp, void *prpctx, + const uint8_t *plain, size_t nplain, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + uint8_t *cipher, /* the same size as nplain */ + uint8_t *tag, size_t ntag) +{ + ocb o; + ocb_init(&o, prp, prpctx, nonce, nnonce, ntag); + + /* Process blocks. The blockwise machinery takes care of + * splitting the input into 128-bit blocks, and calling + * a function on each one. */ + uint8_t partial[BLOCK]; + size_t npartial = 0; + + ocb_start_cipher(&o, cipher); + cf_blockwise_accumulate(partial, &npartial, + prp->blocksz, + plain, nplain, + ocb_encrypt_block, + &o); + + /* Move along plain and cipher. */ + plain += (o.out - cipher); + cipher = o.out; + + /* If we have remaining data to pad and process, + * it's in partial. */ + if (npartial) + { + /* Offset_* = Offset_m xor L_* */ + cf_gf128_add(o.offset, o.L_star, o.offset); + + /* Pad = ENCIPHER(K, Offset_*) */ + uint8_t pad[BLOCK]; + cf_gf128_tobytes_be(o.offset, pad); + o.prp->encrypt(o.prpctx, pad, pad); + + /* C_* = P_* xor Pad[1..bitlen(P_*)] */ + xor_bb(cipher, partial, pad, npartial); + mem_clean(pad, sizeof pad); + + /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127 - bitlen(P_*))) */ + memset(partial + npartial, 0, sizeof(partial) - npartial); + partial[npartial] = 0x80; + + cf_gf128 last_block; + cf_gf128_frombytes_be(partial, last_block); + cf_gf128_add(o.checksum, last_block, o.checksum); + mem_clean(last_block, sizeof last_block); + } + + /* Compute: Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K, A) */ + cf_gf128 full_tag; + for (size_t i = 0; i < 4; i++) + full_tag[i] = o.checksum[i] ^ o.offset[i] ^ o.L_dollar[i]; + + /* Convert tag to bytes for encryption */ + uint8_t tag_bytes[BLOCK]; + cf_gf128_tobytes_be(full_tag, tag_bytes); + + /* ENCIPHER(...) */ + o.prp->encrypt(o.prpctx, tag_bytes, tag_bytes); + + /* Compute HASH(K, A). */ + uint8_t hash_a[BLOCK]; + ocb_process_header(&o, header, nheader, hash_a); + + /* ... xor HASH(K, A) */ + xor_bb(tag_bytes, tag_bytes, hash_a, sizeof tag_bytes); + + /* Copy out tag to caller. */ + memcpy(tag, tag_bytes, ntag); + + mem_clean(&o, sizeof o); +} + +static void ocb_decrypt_block(void *vctx, const uint8_t *block) +{ + ocb *o = vctx; + + /* Offset_i = Offset_{i - 1} xor L{ntz(i)} */ + ocb_add_Ln(o, count_trailing_zeroes(o->i), o->offset); + + /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */ + uint8_t offset_bytes[BLOCK]; + cf_gf128_tobytes_be(o->offset, offset_bytes); + + uint8_t block_tmp[BLOCK]; + xor_bb(block_tmp, block, offset_bytes, sizeof block_tmp); + o->prp->decrypt(o->prpctx, block_tmp, block_tmp); + xor_bb(o->out, block_tmp, offset_bytes, sizeof block_tmp); + + /* Checksum_i = Checksum_{i - 1} xor P_i */ + cf_gf128 P; + cf_gf128_frombytes_be(o->out, P); + o->out += sizeof block_tmp; + cf_gf128_add(o->checksum, P, o->checksum); + + o->i++; +} + +int cf_ocb_decrypt(const cf_prp *prp, void *prpctx, + const uint8_t *cipher, size_t ncipher, + const uint8_t *header, size_t nheader, + const uint8_t *nonce, size_t nnonce, + const uint8_t *tag, size_t ntag, + uint8_t *plain) +{ + ocb o; + ocb_init(&o, prp, prpctx, nonce, nnonce, ntag); + + /* Do blockwise decryption */ + uint8_t partial[BLOCK]; + size_t npartial = 0; + + ocb_start_cipher(&o, plain); + cf_blockwise_accumulate(partial, &npartial, + prp->blocksz, + cipher, ncipher, + ocb_decrypt_block, + &o); + + if (npartial) + { + /* Offset_* = Offset_m xor L_* */ + cf_gf128_add(o.offset, o.L_star, o.offset); + + /* Pad = ENCIPHER(K, Offset_*) */ + uint8_t pad[BLOCK]; + cf_gf128_tobytes_be(o.offset, pad); + o.prp->encrypt(o.prpctx, pad, pad); + + /* P_* = C_* xor Pad[1..bitlen(C_*)] */ + xor_bb(partial, partial, pad, npartial); + mem_clean(pad, sizeof pad); + + memcpy(o.out, partial, npartial); + + /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127 - bitlen(P_*))) */ + memset(partial + npartial, 0, sizeof(partial) - npartial); + partial[npartial] = 0x80; + + cf_gf128 last_block; + cf_gf128_frombytes_be(partial, last_block); + cf_gf128_add(o.checksum, last_block, o.checksum); + mem_clean(last_block, sizeof last_block); + } + + /* Compute: Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K, A) */ + cf_gf128 full_tag; + for (size_t i = 0; i < 4; i++) + full_tag[i] = o.checksum[i] ^ o.offset[i] ^ o.L_dollar[i]; + + /* Convert tag to bytes for encryption */ + uint8_t tag_bytes[BLOCK]; + cf_gf128_tobytes_be(full_tag, tag_bytes); + + /* ENCIPHER(...) */ + o.prp->encrypt(o.prpctx, tag_bytes, tag_bytes); + + /* Compute HASH(K, A). */ + uint8_t hash_a[BLOCK]; + ocb_process_header(&o, header, nheader, hash_a); + + /* ... xor HASH(K, A) */ + xor_bb(tag_bytes, tag_bytes, hash_a, sizeof tag_bytes); + + /* Check against caller's tag. */ + int err; + + if (mem_eq(tag, tag_bytes, ntag)) + { + err = 0; + } else { + err = 1; + mem_clean(plain, ncipher); + } + + mem_clean(&o, sizeof o); + mem_clean(tag_bytes, sizeof tag_bytes); + mem_clean(full_tag, sizeof full_tag); + return err; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/pbkdf2.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/pbkdf2.c new file mode 100644 index 0000000..fce6a22 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/pbkdf2.c @@ -0,0 +1,84 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "pbkdf2.h" +#include "hmac.h" +#include "bitops.h" +#include "handy.h" +#include "tassert.h" + +#include <string.h> + +static void F(const cf_hmac_ctx *startctx, + uint32_t counter, + const uint8_t *salt, size_t nsalt, + uint32_t iterations, + uint8_t *out) +{ + uint8_t U[CF_MAXHASH]; + size_t hashsz = startctx->hash->hashsz; + + uint8_t countbuf[4]; + write32_be(counter, countbuf); + + /* First iteration: + * U_1 = PRF(P, S || INT_32_BE(i)) + */ + cf_hmac_ctx ctx = *startctx; + cf_hmac_update(&ctx, salt, nsalt); + cf_hmac_update(&ctx, countbuf, sizeof countbuf); + cf_hmac_finish(&ctx, U); + memcpy(out, U, hashsz); + + /* Subsequent iterations: + * U_c = PRF(P, U_{c-1}) + */ + for (uint32_t i = 1; i < iterations; i++) + { + ctx = *startctx; + cf_hmac_update(&ctx, U, hashsz); + cf_hmac_finish(&ctx, U); + xor_bb(out, out, U, hashsz); + } +} + +void cf_pbkdf2_hmac(const uint8_t *pw, size_t npw, + const uint8_t *salt, size_t nsalt, + uint32_t iterations, + uint8_t *out, size_t nout, + const cf_chash *hash) +{ + uint32_t counter = 1; + uint8_t block[CF_MAXHASH]; + + assert(iterations); + assert(out && nout); + assert(hash); + + /* Starting point for inner loop. */ + cf_hmac_ctx ctx; + cf_hmac_init(&ctx, hash, pw, npw); + + while (nout) + { + F(&ctx, counter, salt, nsalt, iterations, block); + + size_t taken = MIN(nout, hash->hashsz); + memcpy(out, block, taken); + out += taken; + nout -= taken; + counter++; + } +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/pbkdf2.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/pbkdf2.h new file mode 100644 index 0000000..2f30484 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/pbkdf2.h @@ -0,0 +1,47 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef PBKDF2_H +#define PBKDF2_H + +#include <stddef.h> +#include <stdint.h> + +#include "chash.h" + +/** + * PBKDF2-HMAC + * =========== + * This is PBKDF2 as described by PKCS#5/RFC2898 with HMAC as the PRF. + */ + +/* .. c:function:: $DECL + * This computes PBKDF2-HMAC with the given hash functon. + * + * :param pw: password input buffer. + * :param npw: password length. + * :param salt: salt input buffer. + * :param nsalt: salt length. + * :param iterations: non-zero iteration count. Tune this for performance/security tradeoff. + * :param out: key material output buffer. `nout` bytes are written here. + * :param nout: key material length. + * :param hash: hash function description. + */ +void cf_pbkdf2_hmac(const uint8_t *pw, size_t npw, + const uint8_t *salt, size_t nsalt, + uint32_t iterations, + uint8_t *out, size_t nout, + const cf_chash *hash); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.c new file mode 100644 index 0000000..6c3f13d --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.c @@ -0,0 +1,221 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "poly1305.h" +#include "bitops.h" +#include "handy.h" +#include "blockwise.h" + +#include <string.h> +#include <stdio.h> + +void cf_poly1305_init(cf_poly1305 *ctx, + const uint8_t r[16], + const uint8_t s[16]) +{ + memset(ctx, 0, sizeof *ctx); + + ctx->r[0] = r[0]; + ctx->r[1] = r[1]; + ctx->r[2] = r[2]; + ctx->r[3] = r[3] & 0x0f; + ctx->r[4] = r[4] & 0xfc; + ctx->r[5] = r[5]; + ctx->r[6] = r[6]; + ctx->r[7] = r[7] & 0x0f; + ctx->r[8] = r[8] & 0xfc; + ctx->r[9] = r[9]; + ctx->r[10] = r[10]; + ctx->r[11] = r[11] & 0x0f; + ctx->r[12] = r[12] & 0xfc; + ctx->r[13] = r[13]; + ctx->r[14] = r[14]; + ctx->r[15] = r[15] & 0x0f; + ctx->r[16] = 0; + + memcpy(ctx->s, s, 16); +} + +static void poly1305_add(uint32_t h[17], + const uint32_t x[17]) +{ + uint32_t carry = 0; + int i; + + for (i = 0; i < 17; i++) + { + carry += h[i] + x[i]; + h[i] = carry & 0xff; + carry >>= 8; + } +} + +/* Minimal reduction/carry chain. */ +static void poly1305_min_reduce(uint32_t x[17]) +{ + uint32_t carry = 0; + int i; + for (i = 0; i < 16; i++) + { + carry += x[i]; + x[i] = carry & 0xff; + carry >>= 8; + } + + /* 2 ** 130 - 5 = 0x3fffffffffffffffffffffffffffffffb + * ^ + * So 2 bits of carry are put into top word. + * Remaining bits get multiplied by 5 and carried back + * into bottom */ + carry += x[16]; + x[16] = carry & 0x03; + carry = 5 * (carry >> 2); + + for (i = 0; i < 16; i++) + { + carry += x[i]; + x[i] = carry & 0xff; + carry >>= 8; + } + + x[16] += carry; +} + +/* This is - 2 ** 130 - 5 in twos complement. */ +static const uint32_t negative_1305[17] = { + 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0xfc +}; + +static void poly1305_full_reduce(uint32_t x[17]) +{ + uint32_t xsub[17]; + size_t i; + + for (i = 0; i < 17; i++) + xsub[i] = x[i]; + + poly1305_add(xsub, negative_1305); + + /* If x - (2 ** 130 - 5) is negative, then + * x didn't need reduction: we discard the results. + * Do this in a side-channel silent way. */ + uint32_t negative_mask = mask_u32(xsub[16] & 0x80, 0x80); + uint32_t positive_mask = negative_mask ^ 0xffffffff; + + for (i = 0; i < 17; i++) + x[i] = (x[i] & negative_mask) | (xsub[i] & positive_mask); +} + +static void poly1305_mul(uint32_t x[17], + const uint32_t y[17]) +{ + uint32_t r[17]; + int i; + + for (i = 0; i < 17; i++) + { + uint32_t accum = 0; + int j; + + for (j = 0; j <= i; j++) + accum += x[j] * y[i - j]; + + /* Add in carries. These get shifted 130 bits + * to the right, with a combination of byte indexing + * and shifting (136 bits right, then 6 bits left). + * + * nb. 5 << 6 is made up of two parts: + * 5: reduction of 2 ** 130 leaves a multiple 5 + * shift 6 places left + * 17 * 8: byte indexing shift (136 bits) + * 130: desired shift + */ + for (j = i + 1; j < 17; j++) + accum += (5 << 6) * x[j] * y[i + 17 - j]; + + r[i] = accum; + } + + poly1305_min_reduce(r); + + for (i = 0; i < 17; i++) + x[i] = r[i]; +} + +static void poly1305_block(cf_poly1305 *ctx, + const uint32_t c[17]) +{ + poly1305_add(ctx->h, c); + poly1305_mul(ctx->h, ctx->r); +} + +static void poly1305_whole_block(void *vctx, + const uint8_t *buf) +{ + cf_poly1305 *ctx = vctx; + uint32_t c[17]; + int i; + + for (i = 0; i < 16; i++) + c[i] = buf[i]; + + c[16] = 1; + poly1305_block(ctx, c); +} + +static void poly1305_last_block(cf_poly1305 *ctx) +{ + uint32_t c[17] = { 0 }; + size_t i; + + for (i = 0; i < ctx->npartial; i++) + c[i] = ctx->partial[i]; + + c[ctx->npartial] = 1; + poly1305_block(ctx, c); +} + +void cf_poly1305_update(cf_poly1305 *ctx, + const uint8_t *buf, + size_t nbytes) +{ + cf_blockwise_accumulate(ctx->partial, &ctx->npartial, + sizeof ctx->partial, + buf, nbytes, + poly1305_whole_block, + ctx); +} + +void cf_poly1305_finish(cf_poly1305 *ctx, + uint8_t out[16]) +{ + if (ctx->npartial) + poly1305_last_block(ctx); + + uint32_t s[17]; + size_t i; + for (i = 0; i < 16; i++) + s[i] = ctx->s[i]; + s[16] = 0; + + poly1305_full_reduce(ctx->h); + poly1305_add(ctx->h, s); + + for (i = 0; i < 16; i++) + out[i] = ctx->h[i]; + + mem_clean(ctx, sizeof *ctx); +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.h new file mode 100644 index 0000000..b318e28 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.h @@ -0,0 +1,91 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef POLY1305_H +#define POLY1305_H + +#include <stddef.h> +#include <stdint.h> + +/** + * Poly1305 + * ======== + * This is an incremental interface to computing the poly1305 + * single shot MAC. + * + * Note: construct Poly1305-AES with this by taking a 16 byte + * nonce and encrypting it, and then using the result as an + * input to this function. + */ + +/* .. c:type:: cf_poly1305 + * Poly1305 incremental interface context. + * + * .. c:member:: cf_poly1305.h + * Current accumulator. + * + * .. c:member:: cf_poly1305.r + * Block multiplier. + * + * .. c:member:: cf_poly1305.s + * Final XOR offset. + * + * .. c:member:: cf_poly1305.partial + * Unprocessed input. + * + * .. c:member:: cf_poly1305.npartial + * Number of bytes of unprocessed input. + * + */ +typedef struct +{ + uint32_t h[17]; + uint32_t r[17]; + uint8_t s[16]; + uint8_t partial[16]; + size_t npartial; +} cf_poly1305; + +/* .. c:function:: $DECL + * Sets up `ctx` ready to compute a new MAC. + * + * In Poly1305-AES, `r` is the second half of the 32-byte key. + * `s` is a nonce encrypted under the first half of the key. + * + * :param ctx: context (written) + * :param r: MAC key. + * :param s: preprocessed nonce. + * + */ +void cf_poly1305_init(cf_poly1305 *ctx, + const uint8_t r[16], + const uint8_t s[16]); + +/* .. c:function:: $DECL + * Processes `nbytes` at `data`. Copies the data if there isn't enough to make + * a full block. + */ +void cf_poly1305_update(cf_poly1305 *ctx, + const uint8_t *data, + size_t nbytes); + +/* .. c:function:: $DECL + * Finishes the operation, writing 16 bytes to `out`. + * + * This destroys `ctx`. + */ +void cf_poly1305_finish(cf_poly1305 *ctx, + uint8_t out[16]); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.py b/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.py new file mode 100644 index 0000000..41a1b9d --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/poly1305.py @@ -0,0 +1,127 @@ +rs = (0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91 +,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25 +,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65 +,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80) + +msg = (0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73 + ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce + ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4 + ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a + ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b + ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72 + ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2 + ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38 + ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a + ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae + ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea + ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda + ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde + ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3 + ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6 + ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74 + ,0xe3,0x55,0xa5) + +tag = (0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5 +,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9) + +print len(msg) + +WORD = 0xffffffff + +def add(x, y): + u = 0 + r = [0] * 17 + for i in range(17): + u += (x[i] + y[i]) & WORD + r[i] = u & 0xff + u >>= 8 + return r + +def reduce(x): + r = list(x) + u = 0 + + for i in range(16): + u += r[i] + r[i] = u & 0xff + u >>= 8 + u += r[16] + r[16] = u & 3 + u = 5 * (u >> 2) + + for i in range(16): + u += r[i] + r[i] = u & 0xff + u >>= 8 + u += r[16] + r[16] = u + + return r + +def modmul(x, y): + r = [0] * 17 + for i in range(17): + u = 0 + for j in range(i + 1): + u += (x[j] * y[i - j]) & WORD + for j in range(i + 1, 17): + u += (320 * x[j] * y[i + 17 - j]) & WORD + r[i] = u + return reduce(r) + +def dump(why, v): + print '%s = %s' % (why, ' '.join('%08x' % x for x in v)) + +def freeze(x): + # -2^130 - 5 in twos complement + negative_130_5 = (5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252) + + r = add(x, negative_130_5) + dump('minusp', r) + negative = bool(x[16] >> 7) + if negative: + return r + else: + return x + +def poly1305(msg, rs): + r, s = list(rs[:16]), list(rs[16:]) + + r[3] &= 15 + r[4] &= 252 + r[7] &= 15 + r[8] &= 252 + r[11] &= 15 + r[12] &= 252 + r[15] &= 15 + r.append(0) + + h = [0] * 17 + dump('r-init', r) + dump('h-init', h) + + block = 0 + + for offs in range(0, len(msg), 16): + print '--- block %d ---' % block + block += 1 + c = list(msg[offs:offs+16]) + c.append(1) + while len(c) != 17: c.append(0) + dump('c', c) + + h = add(h, c) + dump('after-add', h) + h = modmul(h, r) + dump('after-mul', h) + + dump('end-block', h) + h = freeze(h) + dump('h', h) + s.append(0) + h = add(h, s) + dump('final', h) + return h[:16] + +r = poly1305(msg, rs) +print repr([hex(x) for x in r]) diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/prp.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/prp.h new file mode 100644 index 0000000..1aa7258 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/prp.h @@ -0,0 +1,64 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef PRP_H +#define PRP_H + +#include <stddef.h> +#include <stdint.h> + +/** + * General block cipher description + * ================================ + * This allows us to implement block cipher modes which can work + * with different block ciphers. + */ + +/* .. c:type:: cf_prp_block + * Block processing function type. + * + * The `in` and `out` blocks may alias. + * + * :rtype: void + * :param ctx: block cipher-specific context object. + * :param in: input block. + * :param out: output block. + */ +typedef void (*cf_prp_block)(void *ctx, const uint8_t *in, uint8_t *out); + +/* .. c:type:: cf_prp + * Describes an PRP in a general way. + * + * .. c:member:: cf_prp.blocksz + * Block size in bytes. Must be no more than :c:macro:`CF_MAXBLOCK`. + * + * .. c:member:: cf_prp.encrypt + * Block encryption function. + * + * .. c:member:: cf_prp.decrypt + * Block decryption function. + */ +typedef struct +{ + size_t blocksz; + cf_prp_block encrypt; + cf_prp_block decrypt; +} cf_prp; + +/* .. c:macro:: CF_MAXBLOCK + * The maximum block cipher blocksize we support, in bytes. + */ +#define CF_MAXBLOCK 16 + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/salsa20.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/salsa20.c new file mode 100644 index 0000000..34bd156 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/salsa20.c @@ -0,0 +1,164 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "salsa20.h" +#include "bitops.h" +#include "blockwise.h" + +#include <string.h> +#include <stdlib.h> + +void cf_salsa20_core(const uint8_t key0[16], + const uint8_t key1[16], + const uint8_t nonce[16], + const uint8_t constant[16], + uint8_t out[64]) +{ + /* unpack sequence is: + * + * c0 + * key0 + * c1 + * nonce + * c2 + * key1 + * c3 + * + * where c0, c1, c2, c3 = constant + */ + + uint32_t z0, z1, z2, z3, z4, z5, z6, z7, + z8, z9, za, zb, zc, zd, ze, zf; + + uint32_t x0 = z0 = read32_le(constant + 0), + x1 = z1 = read32_le(key0 + 0), + x2 = z2 = read32_le(key0 + 4), + x3 = z3 = read32_le(key0 + 8), + x4 = z4 = read32_le(key0 + 12), + x5 = z5 = read32_le(constant + 4), + x6 = z6 = read32_le(nonce + 0), + x7 = z7 = read32_le(nonce + 4), + x8 = z8 = read32_le(nonce + 8), + x9 = z9 = read32_le(nonce + 12), + xa = za = read32_le(constant + 8), + xb = zb = read32_le(key1 + 0), + xc = zc = read32_le(key1 + 4), + xd = zd = read32_le(key1 + 8), + xe = ze = read32_le(key1 + 12), + xf = zf = read32_le(constant + 12); + +#define QUARTER(v0, v1, v2, v3) \ + v1 ^= rotl32(v0 + v3, 7); \ + v2 ^= rotl32(v1 + v0, 9); \ + v3 ^= rotl32(v2 + v1, 13);\ + v0 ^= rotl32(v3 + v2, 18) + +#define ROW \ + QUARTER(z0, z1, z2, z3); \ + QUARTER(z5, z6, z7, z4); \ + QUARTER(za, zb, z8, z9); \ + QUARTER(zf, zc, zd, ze) + +#define COLUMN\ + QUARTER(z0, z4, z8, zc); \ + QUARTER(z5, z9, zd, z1); \ + QUARTER(za, ze, z2, z6); \ + QUARTER(zf, z3, z7, zb) + + for (int i = 0; i < 10; i++) + { + COLUMN; + ROW; + } + + x0 += z0; + x1 += z1; + x2 += z2; + x3 += z3; + x4 += z4; + x5 += z5; + x6 += z6; + x7 += z7; + x8 += z8; + x9 += z9; + xa += za; + xb += zb; + xc += zc; + xd += zd; + xe += ze; + xf += zf; + + write32_le(x0, out + 0); + write32_le(x1, out + 4); + write32_le(x2, out + 8); + write32_le(x3, out + 12); + write32_le(x4, out + 16); + write32_le(x5, out + 20); + write32_le(x6, out + 24); + write32_le(x7, out + 28); + write32_le(x8, out + 32); + write32_le(x9, out + 36); + write32_le(xa, out + 40); + write32_le(xb, out + 44); + write32_le(xc, out + 48); + write32_le(xd, out + 52); + write32_le(xe, out + 56); + write32_le(xf, out + 60); +} + +static const uint8_t *salsa20_tau = (const uint8_t *) "expand 16-byte k"; +static const uint8_t *salsa20_sigma = (const uint8_t *) "expand 32-byte k"; + +void cf_salsa20_init(cf_salsa20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]) +{ + switch (nkey) + { + case 16: + memcpy(ctx->key0, key, 16); + memcpy(ctx->key1, key, 16); + ctx->constant = salsa20_tau; + break; + case 32: + memcpy(ctx->key0, key, 16); + memcpy(ctx->key1, key + 16, 16); + ctx->constant = salsa20_sigma; + break; + default: + abort(); + } + + memset(ctx->nonce, 0, sizeof ctx->nonce); + memcpy(ctx->nonce + 8, nonce, 8); + ctx->nblock = 0; + ctx->ncounter = 8; +} + +static void cf_salsa20_next_block(void *vctx, uint8_t *out) +{ + cf_salsa20_ctx *ctx = vctx; + cf_salsa20_core(ctx->key0, + ctx->key1, + ctx->nonce, + ctx->constant, + out); + incr_le(ctx->nonce, ctx->ncounter); +} + +void cf_salsa20_cipher(cf_salsa20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t bytes) +{ + cf_blockwise_xor(ctx->block, &ctx->nblock, 64, + input, output, bytes, + cf_salsa20_next_block, + ctx); +} diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/salsa20.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/salsa20.h new file mode 100644 index 0000000..462d019 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/salsa20.h @@ -0,0 +1,140 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef SALSA20_H +#define SALSA20_H + +#include <stdint.h> +#include <stddef.h> + +/** + * The Salsa20/Chacha20 stream ciphers + * =================================== + * + * These are similar stream ciphers by djb. + * + * A reduced round variant of Salsa20 (Salsa20/12) + * was selected as a finalist of the eSTREAM stream + * cipher competition. This implementation does + * the full 20 rounds. + * + * ChaCha20 is fundamentally like Salsa20, but + * has a tweaked round function to improve security + * margin without damaging performance. + */ + +/* Salsa20 core transform. */ +void cf_salsa20_core(const uint8_t key0[16], + const uint8_t key1[16], + const uint8_t nonce[16], + const uint8_t constant[16], + uint8_t out[64]); + +/* Chacha20 core transform. */ +void cf_chacha20_core(const uint8_t key0[16], + const uint8_t key1[16], + const uint8_t nonce[16], + const uint8_t constant[16], + uint8_t out[64]); + +/* .. c:type:: cf_salsa20_ctx + * Incremental interface to Salsa20. + * + * .. c:member:: cf_salsa20_ctx.key0 + * Half of key material. + * + * .. c:member:: cf_salsa20_ctx.key1 + * Half of key material. + * + * .. c:member:: cf_salsa20_ctx.nonce + * Nonce and counter block. + * + * .. c:member:: cf_salsa20_ctx.constant + * Per-key-length constants. + * + * .. c:member:: cf_salsa20_ctx.block + * Buffer for unused key stream material. + * + * .. c:member:: cf_salsa20_ctx.nblock + * Number of bytes at end of `block` that can be used as key stream. + * + */ +typedef struct +{ + uint8_t key0[16], key1[16]; + uint8_t nonce[16]; + const uint8_t *constant; + uint8_t block[64]; + size_t nblock; + size_t ncounter; +} cf_salsa20_ctx, cf_chacha20_ctx; + +/* .. c:type:: cf_chacha20_ctx + * Incremental interface to Chacha20. This structure + * is identical to :c:type:`cf_salsa20_ctx`. + */ + +/* .. c:function:: $DECL + * Salsa20 initialisation function. + * + * :param ctx: salsa20 context. + * :param key: key material. + * :param nkey: length of key in bytes, either 16 or 32. + * :param nonce: per-message nonce. + */ +void cf_salsa20_init(cf_salsa20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]); + +/* .. c:function:: $DECL + * Chacha20 initialisation function. + * + * :param ctx: chacha20 context (written). + * :param key: key material. + * :param nkey: length of key in bytes, either 16 or 32. + * :param nonce: per-message nonce. + */ +void cf_chacha20_init(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]); + +/* .. c:function:: $DECL + * Chacha20 initialisation function. This version gives full control over the whole + * initial nonce value, and the size of the counter. The counter is always at the front + * of the nonce. + * + * :param ctx: chacha20 context (written). + * :param key: key material. + * :param nkey: length of key in bytes, either 16 or 32. + * :param nonce: per-message nonce. `ncounter` bytes at the start are the block counter. + * :param ncounter: length, in bytes, of the counter portion of the nonce. + */ +void cf_chacha20_init_custom(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, + const uint8_t nonce[16], size_t ncounter); + +/* .. c:function:: $DECL + * Salsa20 encryption/decryption function. + * + * :param ctx: salsa20 context. + * :param input: input data buffer (read), `count` bytes long. + * :param output: output data buffer (written), `count` bytes long. + */ +void cf_salsa20_cipher(cf_salsa20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t count); + +/* .. c:function:: $DECL + * Chacha20 encryption/decryption function. + * + * :param ctx: chacha20 context. + * :param input: input data buffer (read), `count` bytes long. + * :param output: output data buffer (written), `count` bytes long. + */ +void cf_chacha20_cipher(cf_chacha20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t count); + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha1.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha1.c new file mode 100644 index 0000000..8b7d02f --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha1.c @@ -0,0 +1,150 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include <string.h> + +#include "sha1.h" +#include "blockwise.h" +#include "bitops.h" +#include "handy.h" +#include "tassert.h" + +void cf_sha1_init(cf_sha1_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->H[0] = 0x67452301; + ctx->H[1] = 0xefcdab89; + ctx->H[2] = 0x98badcfe; + ctx->H[3] = 0x10325476; + ctx->H[4] = 0xc3d2e1f0; +} + +static void sha1_update_block(void *vctx, const uint8_t *inp) +{ + cf_sha1_context *ctx = vctx; + + /* This is a 16-word window into the whole W array. */ + uint32_t W[16]; + + uint32_t a = ctx->H[0], + b = ctx->H[1], + c = ctx->H[2], + d = ctx->H[3], + e = ctx->H[4], + Wt; + + for (size_t t = 0; t < 80; t++) + { + /* For W[0..16] we process the input into W. + * For W[16..79] we compute the next W value: + * + * W[t] = (W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]) <<< 1 + * + * But all W indices are reduced mod 16 into our window. + */ + if (t < 16) + { + W[t] = Wt = read32_be(inp); + inp += 4; + } else { + Wt = W[(t - 3) % 16] ^ W[(t - 8) % 16] ^ W[(t - 14) % 16] ^ W[(t - 16) % 16]; + Wt = rotl32(Wt, 1); + W[t % 16] = Wt; + } + + uint32_t f, k; + + if (t <= 19) + { + f = (b & c) | (~b & d); + k = 0x5a827999; + } else if (t <= 39) { + f = b ^ c ^ d; + k = 0x6ed9eba1; + } else if (t <= 59) { + f = (b & c) | (b & d) | (c & d); + k = 0x8f1bbcdc; + } else { + f = b ^ c ^ d; + k = 0xca62c1d6; + } + + uint32_t temp = rotl32(a, 5) + f + e + k + Wt; + e = d; + d = c; + c = rotl32(b, 30); + b = a; + a = temp; + } + + ctx->H[0] += a; + ctx->H[1] += b; + ctx->H[2] += c; + ctx->H[3] += d; + ctx->H[4] += e; + + ctx->blocks++; +} + +void cf_sha1_update(cf_sha1_context *ctx, const void *data, size_t nbytes) +{ + cf_blockwise_accumulate(ctx->partial, &ctx->npartial, sizeof ctx->partial, + data, nbytes, + sha1_update_block, ctx); +} + +void cf_sha1_digest(const cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]) +{ + cf_sha1_context ours = *ctx; + cf_sha1_digest_final(&ours, hash); +} + +void cf_sha1_digest_final(cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]) +{ + uint64_t digested_bytes = ctx->blocks; + digested_bytes = digested_bytes * CF_SHA1_BLOCKSZ + ctx->npartial; + uint64_t digested_bits = digested_bytes * 8; + + size_t padbytes = CF_SHA1_BLOCKSZ - ((digested_bytes + 8) % CF_SHA1_BLOCKSZ); + + /* Hash 0x80 00 ... block first. */ + cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, sizeof ctx->partial, + 0x80, 0x00, 0x00, padbytes, + sha1_update_block, ctx); + + /* Now hash length. */ + uint8_t buf[8]; + write64_be(digested_bits, buf); + cf_sha1_update(ctx, buf, 8); + + /* We ought to have got our padding calculation right! */ + assert(ctx->npartial == 0); + + write32_be(ctx->H[0], hash + 0); + write32_be(ctx->H[1], hash + 4); + write32_be(ctx->H[2], hash + 8); + write32_be(ctx->H[3], hash + 12); + write32_be(ctx->H[4], hash + 16); + + memset(ctx, 0, sizeof *ctx); +} + +const cf_chash cf_sha1 = { + .hashsz = CF_SHA1_HASHSZ, + .blocksz = CF_SHA1_BLOCKSZ, + .init = (cf_chash_init) cf_sha1_init, + .update = (cf_chash_update) cf_sha1_update, + .digest = (cf_chash_digest) cf_sha1_digest +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha1.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha1.h new file mode 100644 index 0000000..4ca0e91 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha1.h @@ -0,0 +1,91 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef SHA1_H +#define SHA1_H + +#include <stddef.h> +#include <stdint.h> + +#include "chash.h" + +/** + * SHA1 + * ==== + * + * You shouldn't use this for anything new. + */ + +/* .. c:macro:: CF_SHA1_HASHSZ + * The output size of SHA1: 20 bytes. */ +#define CF_SHA1_HASHSZ 20 + +/* .. c:macro:: CF_SHA1_BLOCKSZ + * The block size of SHA1: 64 bytes. */ +#define CF_SHA1_BLOCKSZ 64 + +/* .. c:type:: cf_sha1_context + * Incremental SHA1 hashing context. + * + * .. c:member:: cf_sha1_context.H + * Intermediate values. + * + * .. c:member:: cf_sha1_context.partial + * Unprocessed input. + * + * .. c:member:: cf_sha1_context.npartial + * Number of bytes of unprocessed input. + * + * .. c:member:: cf_sha1_context.blocks + * Number of full blocks processed. + */ +typedef struct +{ + uint32_t H[5]; /* State. */ + uint8_t partial[CF_SHA1_BLOCKSZ]; /* Partial block of input. */ + uint32_t blocks; /* Number of full blocks processed into H. */ + size_t npartial; /* Number of bytes in prefix of partial. */ +} cf_sha1_context; + +/* .. c:function:: $DECL + * Sets up `ctx` ready to hash a new message. + */ +extern void cf_sha1_init(cf_sha1_context *ctx); + +/* .. c:function:: $DECL + * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make + * a full block. + */ +extern void cf_sha1_update(cf_sha1_context *ctx, const void *data, size_t nbytes); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA1_HASHSZ` bytes to `hash`. + * + * This leaves `ctx` unchanged. + */ +extern void cf_sha1_digest(const cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA1_HASHSZ` bytes to `hash`. + * + * This destroys `ctx`, but uses less stack than :c:func:`cf_sha1_digest`. + */ +extern void cf_sha1_digest_final(cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]); + +/* .. c:var:: cf_sha1 + * Abstract interface to SHA1. See :c:type:`cf_chash` for more information. + */ +extern const cf_chash cf_sha1; + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha2.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha2.h new file mode 100644 index 0000000..c4ed24b --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha2.h @@ -0,0 +1,235 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef SHA2_H +#define SHA2_H + +#include <stddef.h> +#include <stdint.h> + +#include "chash.h" + +/** + * SHA224/SHA256 + * ============= + */ + +/* .. c:macro:: CF_SHA224_HASHSZ + * The output size of SHA224: 28 bytes. */ +#define CF_SHA224_HASHSZ 28 + +/* .. c:macro:: CF_SHA224_BLOCKSZ + * The block size of SHA224: 64 bytes. */ +#define CF_SHA224_BLOCKSZ 64 + +/* .. c:macro:: CF_SHA256_HASHSZ + * The output size of SHA256: 32 bytes. */ +#define CF_SHA256_HASHSZ 32 + +/* .. c:macro:: CF_SHA256_BLOCKSZ + * The block size of SHA256: 64 bytes. */ +#define CF_SHA256_BLOCKSZ 64 + +/* .. c:type:: cf_sha256_context + * Incremental SHA256 hashing context. + * + * .. c:member:: cf_sha256_context.H + * Intermediate values. + * + * .. c:member:: cf_sha256_context.partial + * Unprocessed input. + * + * .. c:member:: cf_sha256_context.npartial + * Number of bytes of unprocessed input. + * + * .. c:member:: cf_sha256_context.blocks + * Number of full blocks processed. + */ +typedef struct +{ + uint32_t H[8]; /* State. */ + uint8_t partial[CF_SHA256_BLOCKSZ]; /* Partial block of input. */ + uint32_t blocks; /* Number of full blocks processed into H. */ + size_t npartial; /* Number of bytes in prefix of partial. */ +} cf_sha256_context; + +/* .. c:function:: $DECL + * Sets up `ctx` ready to hash a new message. + */ +extern void cf_sha256_init(cf_sha256_context *ctx); + +/* .. c:function:: $DECL + * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make + * a full block. + */ +extern void cf_sha256_update(cf_sha256_context *ctx, const void *data, size_t nbytes); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA256_HASHSZ` bytes to `hash`. + * + * This leaves `ctx` unchanged. + */ +extern void cf_sha256_digest(const cf_sha256_context *ctx, uint8_t hash[CF_SHA256_HASHSZ]); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA256_HASHSZ` bytes to `hash`. + * + * This destroys `ctx`, but uses less stack than :c:func:`cf_sha256_digest`. + */ +extern void cf_sha256_digest_final(cf_sha256_context *ctx, uint8_t hash[CF_SHA256_HASHSZ]); + +/* .. c:function:: $DECL + * Sets up `ctx` ready to hash a new message. + * + * nb. SHA224 uses SHA256's underlying types. + */ +extern void cf_sha224_init(cf_sha256_context *ctx); + +/* .. c:function:: $DECL + * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make + * a full block. + */ +extern void cf_sha224_update(cf_sha256_context *ctx, const void *data, size_t nbytes); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA224_HASHSZ` bytes to `hash`. + * + * This leaves `ctx` unchanged. + */ +extern void cf_sha224_digest(const cf_sha256_context *ctx, uint8_t hash[CF_SHA224_HASHSZ]); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA224_HASHSZ` bytes to `hash`. + * + * This destroys `ctx`, but uses less stack than :c:func:`cf_sha224_digest`. + */ +extern void cf_sha224_digest_final(cf_sha256_context *ctx, uint8_t hash[CF_SHA224_HASHSZ]); + +/* .. c:var:: cf_sha224 + * Abstract interface to SHA224. See :c:type:`cf_chash` for more information. + */ +extern const cf_chash cf_sha224; + +/* .. c:var:: cf_sha256 + * Abstract interface to SHA256. See :c:type:`cf_chash` for more information. + */ +extern const cf_chash cf_sha256; + +/** + * SHA384/SHA512 + * ============= + */ + +/* .. c:macro:: CF_SHA384_HASHSZ + * The output size of SHA384: 48 bytes. */ +#define CF_SHA384_HASHSZ 48 + +/* .. c:macro:: CF_SHA384_BLOCKSZ + * The block size of SHA384: 128 bytes. */ +#define CF_SHA384_BLOCKSZ 128 + +/* .. c:macro:: CF_SHA512_HASHSZ + * The output size of SHA512: 64 bytes. */ +#define CF_SHA512_HASHSZ 64 + +/* .. c:macro:: CF_SHA512_BLOCKSZ + * The block size of SHA512: 128 bytes. */ +#define CF_SHA512_BLOCKSZ 128 + +/* .. c:type:: cf_sha512_context + * Incremental SHA512 hashing context. + * + * .. c:member:: cf_sha512_context.H + * Intermediate values. + * + * .. c:member:: cf_sha512_context.partial + * Unprocessed input. + * + * .. c:member:: cf_sha512_context.npartial + * Number of bytes of unprocessed input. + * + * .. c:member:: cf_sha512_context.blocks + * Number of full blocks processed. + */ +typedef struct +{ + uint64_t H[8]; + uint8_t partial[CF_SHA512_BLOCKSZ]; + uint32_t blocks; + size_t npartial; +} cf_sha512_context; + +/* .. c:function:: $DECL + * Sets up `ctx` ready to hash a new message. + */ +extern void cf_sha512_init(cf_sha512_context *ctx); + +/* .. c:function:: $DECL + * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make + * a full block. + */ +extern void cf_sha512_update(cf_sha512_context *ctx, const void *data, size_t nbytes); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA512_HASHSZ` bytes to `hash`. + * + * This leaves `ctx` unchanged. + */ +extern void cf_sha512_digest(const cf_sha512_context *ctx, uint8_t hash[CF_SHA512_HASHSZ]); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA512_HASHSZ` bytes to `hash`. + * + * This destroys `ctx`, but uses less stack than :c:func:`cf_sha512_digest`. + */ +extern void cf_sha512_digest_final(cf_sha512_context *ctx, uint8_t hash[CF_SHA512_HASHSZ]); + +/* .. c:function:: $DECL + * Sets up `ctx` ready to hash a new message. + * + * nb. SHA384 uses SHA512's underlying types. + */ +extern void cf_sha384_init(cf_sha512_context *ctx); + +/* .. c:function:: $DECL + * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make + * a full block. + */ +extern void cf_sha384_update(cf_sha512_context *ctx, const void *data, size_t nbytes); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA384_HASHSZ` bytes to `hash`. + * + * This leaves `ctx` unchanged. + */ +extern void cf_sha384_digest(const cf_sha512_context *ctx, uint8_t hash[CF_SHA384_HASHSZ]); + +/* .. c:function:: $DECL + * Finishes the hash operation, writing `CF_SHA384_HASHSZ` bytes to `hash`. + * + * This destroys `ctx`, but uses less stack than :c:func:`cf_sha384_digest`. + */ +extern void cf_sha384_digest_final(cf_sha512_context *ctx, uint8_t hash[CF_SHA384_HASHSZ]); + +/* .. c:var:: cf_sha384 + * Abstract interface to SHA384. See :c:type:`cf_chash` for more information. + */ +extern const cf_chash cf_sha384; + +/* .. c:var:: cf_sha512 + * Abstract interface to SHA512. See :c:type:`cf_chash` for more information. + */ +extern const cf_chash cf_sha512; + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha256.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha256.c new file mode 100644 index 0000000..8ecef16 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha256.c @@ -0,0 +1,232 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include <string.h> + +#include "sha2.h" +#include "blockwise.h" +#include "bitops.h" +#include "handy.h" +#include "tassert.h" + +static const uint32_t K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +# define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +# define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +# define BSIG0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22)) +# define BSIG1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25)) +# define SSIG0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3)) +# define SSIG1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10)) + +void cf_sha256_init(cf_sha256_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->H[0] = 0x6a09e667; + ctx->H[1] = 0xbb67ae85; + ctx->H[2] = 0x3c6ef372; + ctx->H[3] = 0xa54ff53a; + ctx->H[4] = 0x510e527f; + ctx->H[5] = 0x9b05688c; + ctx->H[6] = 0x1f83d9ab; + ctx->H[7] = 0x5be0cd19; +} + +void cf_sha224_init(cf_sha256_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->H[0] = 0xc1059ed8; + ctx->H[1] = 0x367cd507; + ctx->H[2] = 0x3070dd17; + ctx->H[3] = 0xf70e5939; + ctx->H[4] = 0xffc00b31; + ctx->H[5] = 0x68581511; + ctx->H[6] = 0x64f98fa7; + ctx->H[7] = 0xbefa4fa4; +} + +static void sha256_update_block(void *vctx, const uint8_t *inp) +{ + cf_sha256_context *ctx = vctx; + + /* This is a 16-word window into the whole W array. */ + uint32_t W[16]; + + uint32_t a = ctx->H[0], + b = ctx->H[1], + c = ctx->H[2], + d = ctx->H[3], + e = ctx->H[4], + f = ctx->H[5], + g = ctx->H[6], + h = ctx->H[7], + Wt; + + size_t t; + for (t = 0; t < 64; t++) + { + /* For W[0..16] we process the input into W. + * For W[16..64] we compute the next W value: + * + * W[t] = SSIG1(W[t - 2]) + W[t - 7] + SSIG0(W[t - 15]) + W[t - 16]; + * + * But all W indices are reduced mod 16 into our window. + */ + if (t < 16) + { + W[t] = Wt = read32_be(inp); + inp += 4; + } else { + Wt = SSIG1(W[(t - 2) % 16]) + + W[(t - 7) % 16] + + SSIG0(W[(t - 15) % 16]) + + W[(t - 16) % 16]; + W[t % 16] = Wt; + } + + uint32_t T1 = h + BSIG1(e) + CH(e, f, g) + K[t] + Wt; + uint32_t T2 = BSIG0(a) + MAJ(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + ctx->H[0] += a; + ctx->H[1] += b; + ctx->H[2] += c; + ctx->H[3] += d; + ctx->H[4] += e; + ctx->H[5] += f; + ctx->H[6] += g; + ctx->H[7] += h; + + ctx->blocks++; +} + +void cf_sha256_update(cf_sha256_context *ctx, const void *data, size_t nbytes) +{ + cf_blockwise_accumulate(ctx->partial, &ctx->npartial, sizeof ctx->partial, + data, nbytes, + sha256_update_block, ctx); +} + +void cf_sha224_update(cf_sha256_context *ctx, const void *data, size_t nbytes) +{ + cf_sha256_update(ctx, data, nbytes); +} + +void cf_sha256_digest(const cf_sha256_context *ctx, uint8_t hash[CF_SHA256_HASHSZ]) +{ + /* We copy the context, so the finalisation doesn't effect the caller's + * context. This means the caller can do: + * + * x = init() + * x.update('hello') + * h1 = x.digest() + * x.update(' world') + * h2 = x.digest() + * + * to get h1 = H('hello') and h2 = H('hello world') + * + * This wouldn't work if we applied MD-padding to *ctx. + */ + + cf_sha256_context ours = *ctx; + cf_sha256_digest_final(&ours, hash); +} + +void cf_sha256_digest_final(cf_sha256_context *ctx, uint8_t hash[CF_SHA256_HASHSZ]) +{ + uint64_t digested_bytes = ctx->blocks; + digested_bytes = digested_bytes * CF_SHA256_BLOCKSZ + ctx->npartial; + uint64_t digested_bits = digested_bytes * 8; + + size_t padbytes = CF_SHA256_BLOCKSZ - ((digested_bytes + 8) % CF_SHA256_BLOCKSZ); + + /* Hash 0x80 00 ... block first. */ + cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, sizeof ctx->partial, + 0x80, 0x00, 0x00, padbytes, + sha256_update_block, ctx); + + /* Now hash length. */ + uint8_t buf[8]; + write64_be(digested_bits, buf); + cf_sha256_update(ctx, buf, 8); + + /* We ought to have got our padding calculation right! */ + assert(ctx->npartial == 0); + + write32_be(ctx->H[0], hash + 0); + write32_be(ctx->H[1], hash + 4); + write32_be(ctx->H[2], hash + 8); + write32_be(ctx->H[3], hash + 12); + write32_be(ctx->H[4], hash + 16); + write32_be(ctx->H[5], hash + 20); + write32_be(ctx->H[6], hash + 24); + write32_be(ctx->H[7], hash + 28); + + memset(ctx, 0, sizeof *ctx); +} + +void cf_sha224_digest(const cf_sha256_context *ctx, uint8_t hash[CF_SHA224_HASHSZ]) +{ + uint8_t full[CF_SHA256_HASHSZ]; + cf_sha256_digest(ctx, full); + memcpy(hash, full, CF_SHA224_HASHSZ); +} + +void cf_sha224_digest_final(cf_sha256_context *ctx, uint8_t hash[CF_SHA224_HASHSZ]) +{ + uint8_t full[CF_SHA256_HASHSZ]; + cf_sha256_digest_final(ctx, full); + memcpy(hash, full, CF_SHA224_HASHSZ); +} + +const cf_chash cf_sha224 = { + .hashsz = CF_SHA224_HASHSZ, + .blocksz = CF_SHA256_BLOCKSZ, + .init = (cf_chash_init) cf_sha224_init, + .update = (cf_chash_update) cf_sha224_update, + .digest = (cf_chash_digest) cf_sha224_digest +}; + +const cf_chash cf_sha256 = { + .hashsz = CF_SHA256_HASHSZ, + .blocksz = CF_SHA256_BLOCKSZ, + .init = (cf_chash_init) cf_sha256_init, + .update = (cf_chash_update) cf_sha256_update, + .digest = (cf_chash_digest) cf_sha256_digest +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha3.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha3.c new file mode 100644 index 0000000..f130747 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha3.c @@ -0,0 +1,444 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include <string.h> + +#include "sha3.h" +#include "blockwise.h" +#include "handy.h" +#include "bitops.h" +#include "tassert.h" + +/* The round constants, pre-interleaved. See bitinter.py */ +static const cf_sha3_bi round_constants[24] = { + { 0x00000001, 0x00000000 }, { 0x00000000, 0x00000089 }, + { 0x00000000, 0x8000008b }, { 0x00000000, 0x80008080 }, + { 0x00000001, 0x0000008b }, { 0x00000001, 0x00008000 }, + { 0x00000001, 0x80008088 }, { 0x00000001, 0x80000082 }, + { 0x00000000, 0x0000000b }, { 0x00000000, 0x0000000a }, + { 0x00000001, 0x00008082 }, { 0x00000000, 0x00008003 }, + { 0x00000001, 0x0000808b }, { 0x00000001, 0x8000000b }, + { 0x00000001, 0x8000008a }, { 0x00000001, 0x80000081 }, + { 0x00000000, 0x80000081 }, { 0x00000000, 0x80000008 }, + { 0x00000000, 0x00000083 }, { 0x00000000, 0x80008003 }, + { 0x00000001, 0x80008088 }, { 0x00000000, 0x80000088 }, + { 0x00000001, 0x00008000 }, { 0x00000000, 0x80008082 } +}; + +static const uint8_t rotation_constants[5][5] = { + { 0, 1, 62, 28, 27, }, + { 36, 44, 6, 55, 20, }, + { 3, 10, 43, 25, 39, }, + { 41, 45, 15, 21, 8, }, + { 18, 2, 61, 56, 14, } +}; + +/* --- Bit interleaving and uninterleaving --- */ +/* See bitinter.py for models of these bit twiddles. The originals + * come from "Hacker's Delight" by Henry Warren, where they are named + * shuffle2 and unshuffle. + * See: + * http://www.hackersdelight.org/hdcodetxt/shuffle.c.txt + * + * The overriding aim is to change bit ordering: + * AaBbCcDd -> ABCDabcd + * and back. Once they're in the shuffled form, we can extract + * odd/even bits by taking the half words from each pair. + */ + +static inline uint32_t shuffle_out(uint32_t x) +{ + uint32_t t; + t = (x ^ (x >> 1)) & 0x22222222; x = x ^ t ^ (t << 1); + t = (x ^ (x >> 2)) & 0x0c0c0c0c; x = x ^ t ^ (t << 2); + t = (x ^ (x >> 4)) & 0x00f000f0; x = x ^ t ^ (t << 4); + t = (x ^ (x >> 8)) & 0x0000ff00; x = x ^ t ^ (t << 8); + return x; +} + +/* Convert ABCDabcd -> AaBbCcDd. */ +static inline uint32_t shuffle_in(uint32_t x) +{ + uint32_t t; + t = (x ^ (x >> 8)) & 0x0000ff00; x = x ^ t ^ (t << 8); + t = (x ^ (x >> 4)) & 0x00f000f0; x = x ^ t ^ (t << 4); + t = (x ^ (x >> 2)) & 0x0c0c0c0c; x = x ^ t ^ (t << 2); + t = (x ^ (x >> 1)) & 0x22222222; x = x ^ t ^ (t << 1); + return x; +} + +static inline void read64_bi(cf_sha3_bi *out, const uint8_t data[8]) +{ + uint32_t lo = read32_le(data + 0), + hi = read32_le(data + 4); + + lo = shuffle_out(lo); + hi = shuffle_out(hi); + + out->odd = (lo & 0x0000ffff) | (hi << 16); + out->evn = (lo >> 16) | (hi & 0xffff0000); +} + +static inline void write64_bi(const cf_sha3_bi *bi, uint8_t data[8]) +{ + uint32_t lo = (bi->odd & 0x0000ffff) | (bi->evn << 16), + hi = (bi->odd >> 16) | (bi->evn & 0xffff0000); + + lo = shuffle_in(lo); + hi = shuffle_in(hi); + + write32_le(lo, data + 0); + write32_le(hi, data + 4); +} + +static inline void rotl_bi_1(cf_sha3_bi *out, const cf_sha3_bi *in) +{ + /* in bit-interleaved representation, a rotation of 1 + * is a swap plus a single rotation of the odd word. */ + out->odd = rotl32(in->evn, 1); + out->evn = in->odd; +} + +static inline void rotl_bi_n(cf_sha3_bi *out, const cf_sha3_bi *in, uint8_t rot) +{ + uint8_t half = rot >> 1; + + /* nb. rot is a constant, so this isn't a branch leak. */ + if (rot & 1) + { + out->odd = rotl32(in->evn, half + 1); + out->evn = rotl32(in->odd, half); + } else { + out->evn = rotl32(in->evn, half); + out->odd = rotl32(in->odd, half); + } +} + +/* --- */ + +static void sha3_init(cf_sha3_context *ctx, uint16_t rate_bits, uint16_t capacity_bits) +{ + mem_clean(ctx, sizeof *ctx); + ctx->rate = rate_bits / 8; + ctx->capacity = capacity_bits / 8; +} + +static void absorb(cf_sha3_context *ctx, const uint8_t *data, uint16_t sz) +{ + uint16_t lanes = sz / 8; + + for (uint16_t x = 0, y = 0, i = 0; i < lanes; i++) + { + cf_sha3_bi bi; + read64_bi(&bi, data); + ctx->A[x][y].odd ^= bi.odd; + ctx->A[x][y].evn ^= bi.evn; + data += 8; + + x++; + if (x == 5) + { + y++; + x = 0; + } + } +} + +/* Integers [-1,20] mod 5. To avoid a divmod. Indices + * are constants; not data-dependant. */ +static const uint8_t mod5_table[] = { + 4, + 0, + 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, + 1, 2, 3, 4, 0, 1, 2, 3, 4, 0 +}; + +#define MOD5(x) (mod5_table[(x) + 1]) + +static void theta(cf_sha3_context *ctx) +{ + cf_sha3_bi C[5], D[5]; + + for (int x = 0; x < 5; x++) + { + C[x].odd = ctx->A[x][0].odd ^ ctx->A[x][1].odd ^ ctx->A[x][2].odd ^ ctx->A[x][3].odd ^ ctx->A[x][4].odd; + C[x].evn = ctx->A[x][0].evn ^ ctx->A[x][1].evn ^ ctx->A[x][2].evn ^ ctx->A[x][3].evn ^ ctx->A[x][4].evn; + } + + for (int x = 0; x < 5; x++) + { + cf_sha3_bi r; + rotl_bi_1(&r, &C[MOD5(x + 1)]); + D[x].odd = C[MOD5(x - 1)].odd ^ r.odd; + D[x].evn = C[MOD5(x - 1)].evn ^ r.evn; + + for (int y = 0; y < 5; y++) + { + ctx->A[x][y].odd ^= D[x].odd; + ctx->A[x][y].evn ^= D[x].evn; + } + } +} + +static void rho_pi_chi(cf_sha3_context *ctx) +{ + cf_sha3_bi B[5][5] = { { { 0 } } }; + + for (int x = 0; x < 5; x++) + for (int y = 0; y < 5; y++) + rotl_bi_n(&B[y][MOD5(2 * x + 3 * y)], &ctx->A[x][y], rotation_constants[y][x]); + + for (int x = 0; x < 5; x++) + { + unsigned x1 = MOD5(x + 1); + unsigned x2 = MOD5(x + 2); + + for (int y = 0; y < 5; y++) + { + ctx->A[x][y].odd = B[x][y].odd ^ ((~ B[x1][y].odd) & B[x2][y].odd); + ctx->A[x][y].evn = B[x][y].evn ^ ((~ B[x1][y].evn) & B[x2][y].evn); + } + } +} + +static void permute(cf_sha3_context *ctx) +{ + for (int r = 0; r < 24; r++) + { + theta(ctx); + rho_pi_chi(ctx); + + /* iota */ + ctx->A[0][0].odd ^= round_constants[r].odd; + ctx->A[0][0].evn ^= round_constants[r].evn; + } +} + +static void extract(cf_sha3_context *ctx, uint8_t *out, size_t nbytes) +{ + uint16_t lanes = (nbytes + 7) / 8; + + for (uint16_t x = 0, y = 0, i = 0; i < lanes; i++) + { + if (nbytes >= 8) + { + write64_bi(&ctx->A[x][y], out); + out += 8; + nbytes -= 8; + } else { + uint8_t buf[8]; + write64_bi(&ctx->A[x][y], buf); + memcpy(out, buf, nbytes); + out += nbytes; + nbytes = 0; + } + + x++; + if (x == 5) + { + y++; + x = 0; + } + } +} + +static void squeeze(cf_sha3_context *ctx, uint8_t *out, size_t nbytes) +{ + while (nbytes) + { + size_t take = MIN(nbytes, ctx->rate); + extract(ctx, out, take); + out += take; + nbytes -= take; + + assert(nbytes == 0); +#if 0 + /* Note: if we ever have |H| >= rate, we need to permute + * after each rate-length block. + * + * This cannot currently happen. */ + if (nbytes) + permute(ctx); +#endif + } +} + +static void sha3_block(void *vctx, const uint8_t *data) +{ + cf_sha3_context *ctx = vctx; + + absorb(ctx, data, ctx->rate); + permute(ctx); +} + +static void sha3_update(cf_sha3_context *ctx, const void *data, size_t nbytes) +{ + cf_blockwise_accumulate(ctx->partial, &ctx->npartial, ctx->rate, + data, nbytes, + sha3_block, ctx); +} + +/* Padding and domain separation constants. + * + * FIPS 202 specifies that 0b01 is appended to hash function + * input, and 0b1111 is appended to SHAKE input. + * + * This is done in internal (little endian) bit ordering, and + * we convolve it with the leftmost (first) padding bit, so: + * + * Hash: 0b110 + * SHAKE: 0b11111 + */ + +#define DOMAIN_HASH_PAD 0x06 +#define DOMAIN_SHAKE_PAD 0x1f + +static void pad(cf_sha3_context *ctx, uint8_t domain, size_t npad) +{ + assert(npad >= 1); + + cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, ctx->rate, + domain, 0x00, 0x80, + npad, + sha3_block, ctx); +} + +static void pad_and_squeeze(cf_sha3_context *ctx, uint8_t *out, size_t nout) +{ + pad(ctx, DOMAIN_HASH_PAD, ctx->rate - ctx->npartial); + assert(ctx->npartial == 0); + + squeeze(ctx, out, nout); + mem_clean(ctx, sizeof *ctx); +} + +/* SHA3-224 */ +void cf_sha3_224_init(cf_sha3_context *ctx) +{ + sha3_init(ctx, 1152, 448); +} + +void cf_sha3_224_update(cf_sha3_context *ctx, const void *data, size_t nbytes) +{ + sha3_update(ctx, data, nbytes); +} + +void cf_sha3_224_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ]) +{ + cf_sha3_context ours = *ctx; + cf_sha3_224_digest_final(&ours, hash); +} + +void cf_sha3_224_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ]) +{ + pad_and_squeeze(ctx, hash, CF_SHA3_224_HASHSZ); +} + +const cf_chash cf_sha3_224 = { + .hashsz = CF_SHA3_224_HASHSZ, + .blocksz = CF_SHA3_224_BLOCKSZ, + .init = (cf_chash_init) cf_sha3_224_init, + .update = (cf_chash_update) cf_sha3_224_update, + .digest = (cf_chash_digest) cf_sha3_224_digest +}; + +/* SHA3-256 */ +void cf_sha3_256_init(cf_sha3_context *ctx) +{ + sha3_init(ctx, 1088, 512); +} + +void cf_sha3_256_update(cf_sha3_context *ctx, const void *data, size_t nbytes) +{ + sha3_update(ctx, data, nbytes); +} + +void cf_sha3_256_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ]) +{ + cf_sha3_context ours = *ctx; + cf_sha3_256_digest_final(&ours, hash); +} + +void cf_sha3_256_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ]) +{ + pad_and_squeeze(ctx, hash, CF_SHA3_256_HASHSZ); +} + +const cf_chash cf_sha3_256 = { + .hashsz = CF_SHA3_256_HASHSZ, + .blocksz = CF_SHA3_256_BLOCKSZ, + .init = (cf_chash_init) cf_sha3_256_init, + .update = (cf_chash_update) cf_sha3_256_update, + .digest = (cf_chash_digest) cf_sha3_256_digest +}; + +/* SHA3-384 */ +void cf_sha3_384_init(cf_sha3_context *ctx) +{ + sha3_init(ctx, 832, 768); +} + +void cf_sha3_384_update(cf_sha3_context *ctx, const void *data, size_t nbytes) +{ + sha3_update(ctx, data, nbytes); +} + +void cf_sha3_384_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ]) +{ + cf_sha3_context ours = *ctx; + cf_sha3_384_digest_final(&ours, hash); +} + +void cf_sha3_384_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ]) +{ + pad_and_squeeze(ctx, hash, CF_SHA3_384_HASHSZ); +} + +const cf_chash cf_sha3_384 = { + .hashsz = CF_SHA3_384_HASHSZ, + .blocksz = CF_SHA3_384_BLOCKSZ, + .init = (cf_chash_init) cf_sha3_384_init, + .update = (cf_chash_update) cf_sha3_384_update, + .digest = (cf_chash_digest) cf_sha3_384_digest +}; + +/* SHA3-512 */ +void cf_sha3_512_init(cf_sha3_context *ctx) +{ + sha3_init(ctx, 576, 1024); +} + +void cf_sha3_512_update(cf_sha3_context *ctx, const void *data, size_t nbytes) +{ + sha3_update(ctx, data, nbytes); +} + +void cf_sha3_512_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ]) +{ + cf_sha3_context ours = *ctx; + cf_sha3_512_digest_final(&ours, hash); +} + +void cf_sha3_512_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ]) +{ + pad_and_squeeze(ctx, hash, CF_SHA3_512_HASHSZ); +} + +const cf_chash cf_sha3_512 = { + .hashsz = CF_SHA3_512_HASHSZ, + .blocksz = CF_SHA3_512_BLOCKSZ, + .init = (cf_chash_init) cf_sha3_512_init, + .update = (cf_chash_update) cf_sha3_512_update, + .digest = (cf_chash_digest) cf_sha3_512_digest +}; diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha3.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha3.h new file mode 100644 index 0000000..44895dc --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha3.h @@ -0,0 +1,180 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef SHA3_H +#define SHA3_H + +#include <stddef.h> +#include <stdint.h> + +#include "chash.h" + +/** + * SHA3/Keccak + * =========== + * This implementation is compatible with FIPS 202, + * rather than the original Keccak submission. + * + */ + +/* .. c:macro:: CF_SHA3_224_HASHSZ + * The output size of SHA3-224: 28 bytes. */ +#define CF_SHA3_224_HASHSZ 28 + +/* .. c:macro:: CF_SHA3_256_HASHSZ + * The output size of SHA3-256: 32 bytes. */ +#define CF_SHA3_256_HASHSZ 32 + +/* .. c:macro:: CF_SHA3_384_HASHSZ + * The output size of SHA3-384: 48 bytes. */ +#define CF_SHA3_384_HASHSZ 48 + +/* .. c:macro:: CF_SHA3_512_HASHSZ + * The output size of SHA3-512: 64 bytes. */ +#define CF_SHA3_512_HASHSZ 64 + +/* .. c:macro:: CF_SHA3_224_BLOCKSZ + * The block size of SHA3-224. */ +#define CF_SHA3_224_BLOCKSZ 144 + +/* .. c:macro:: CF_SHA3_256_BLOCKSZ + * The block size of SHA3-256. */ +#define CF_SHA3_256_BLOCKSZ 136 + +/* .. c:macro:: CF_SHA3_384_BLOCKSZ + * The block size of SHA3-384. */ +#define CF_SHA3_384_BLOCKSZ 104 + +/* .. c:macro:: CF_SHA3_512_BLOCKSZ + * The block size of SHA3-512. */ +#define CF_SHA3_512_BLOCKSZ 72 + +/* We use bit-interleaved internal representation. This + * stores a 64 bit quantity in two 32 bit words: one word + * contains odd bits, the other even. This means 64-bit rotations + * are cheaper to compute. */ +typedef struct +{ + uint32_t odd, evn; +} cf_sha3_bi; + +/* .. c:type:: cf_sha3_context + * Incremental SHA3 hashing context. + * + * .. c:member:: cf_sha3_context.A + * Intermediate state. + * + * .. c:member:: cf_sha3_context.partial + * Unprocessed input. + * + * .. c:member:: cf_sha3_context.npartial + * Number of bytes of unprocessed input. + * + * .. c:member:: cf_sha3_context.rate + * Sponge absorption rate. + * + * .. c:member:: cf_sha3_context.rate + * Sponge capacity. + */ +typedef struct +{ + /* State is a 5x5 block of 64-bit values, for Keccak-f[1600]. */ + cf_sha3_bi A[5][5]; + uint8_t partial[CF_SHA3_224_BLOCKSZ]; + size_t npartial; + uint16_t rate, capacity; /* rate and capacity, in bytes. */ +} cf_sha3_context; + + +/* -- _init functions -- */ + +/* .. c:function:: $DECL */ +extern void cf_sha3_224_init(cf_sha3_context *ctx); + +/* .. c:function:: $DECL */ +extern void cf_sha3_256_init(cf_sha3_context *ctx); + +/* .. c:function:: $DECL */ +extern void cf_sha3_384_init(cf_sha3_context *ctx); + +/* .. c:function:: $DECL + * Sets up `ctx` ready to hash a new message. + */ +extern void cf_sha3_512_init(cf_sha3_context *ctx); + +/* -- _update functions -- */ + +/* .. c:function:: $DECL */ +extern void cf_sha3_224_update(cf_sha3_context *ctx, const void *data, size_t nbytes); + +/* .. c:function:: $DECL */ +extern void cf_sha3_256_update(cf_sha3_context *ctx, const void *data, size_t nbytes); + +/* .. c:function:: $DECL */ +extern void cf_sha3_384_update(cf_sha3_context *ctx, const void *data, size_t nbytes); + +/* .. c:function:: $DECL + * Hashes `nbytes` at `data`. Copies the data for processing later if there + * isn't enough to make a full block. + */ +extern void cf_sha3_512_update(cf_sha3_context *ctx, const void *data, size_t nbytes); + +/* -- _digest functions -- */ + +/* .. c:function:: $DECL */ +extern void cf_sha3_224_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ]); + +/* .. c:function:: $DECL */ +extern void cf_sha3_256_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ]); + +/* .. c:function:: $DECL */ +extern void cf_sha3_384_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ]); + +/* .. c:function:: $DECL + * Finishes the hashing operation, writing result to `hash`. + * + * This leaves `ctx` unchanged. + */ +extern void cf_sha3_512_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ]); + +/* -- _digest_final functions -- */ + +/* .. c:function:: $DECL */ +extern void cf_sha3_224_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ]); + +/* .. c:function:: $DECL */ +extern void cf_sha3_256_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ]); + +/* .. c:function:: $DECL */ +extern void cf_sha3_384_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ]); + +/* .. c:function:: $DECL + * Finishes the hashing operation, writing result to `hash`. + * + * This destroys the contents of `ctx`. + */ +extern void cf_sha3_512_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ]); + +/* .. c:var:: cf_sha3_224 + * .. c:var:: cf_sha3_256 + * .. c:var:: cf_sha3_384 + * .. c:var:: cf_sha3_512 + * Abstract interface to SHA3 functions. See :c:type:`cf_chash` for more information. + */ +extern const cf_chash cf_sha3_224; +extern const cf_chash cf_sha3_256; +extern const cf_chash cf_sha3_384; +extern const cf_chash cf_sha3_512; + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha512.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha512.c new file mode 100644 index 0000000..2d1c896 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/sha512.c @@ -0,0 +1,248 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include <string.h> + +#include "sha2.h" +#include "blockwise.h" +#include "bitops.h" +#include "handy.h" +#include "tassert.h" + +static const uint64_t K[80] = { + UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), + UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), + UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), + UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), + UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), + UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), + UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), + UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), + UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), + UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), + UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), + UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), + UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), + UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), + UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), + UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), + UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), + UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), + UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), + UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), + UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), + UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), + UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), + UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), + UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), + UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), + UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), + UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), + UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), + UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), + UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), + UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), + UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), + UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), + UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), + UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), + UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), + UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), + UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), + UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817) +}; + +# define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +# define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +# define BSIG0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39)) +# define BSIG1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41)) +# define SSIG0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7)) +# define SSIG1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6)) + +void cf_sha512_init(cf_sha512_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->H[0] = UINT64_C(0x6a09e667f3bcc908); + ctx->H[1] = UINT64_C(0xbb67ae8584caa73b); + ctx->H[2] = UINT64_C(0x3c6ef372fe94f82b); + ctx->H[3] = UINT64_C(0xa54ff53a5f1d36f1); + ctx->H[4] = UINT64_C(0x510e527fade682d1); + ctx->H[5] = UINT64_C(0x9b05688c2b3e6c1f); + ctx->H[6] = UINT64_C(0x1f83d9abfb41bd6b); + ctx->H[7] = UINT64_C(0x5be0cd19137e2179); +} + +void cf_sha384_init(cf_sha512_context *ctx) +{ + memset(ctx, 0, sizeof *ctx); + ctx->H[0] = UINT64_C(0xcbbb9d5dc1059ed8); + ctx->H[1] = UINT64_C(0x629a292a367cd507); + ctx->H[2] = UINT64_C(0x9159015a3070dd17); + ctx->H[3] = UINT64_C(0x152fecd8f70e5939); + ctx->H[4] = UINT64_C(0x67332667ffc00b31); + ctx->H[5] = UINT64_C(0x8eb44a8768581511); + ctx->H[6] = UINT64_C(0xdb0c2e0d64f98fa7); + ctx->H[7] = UINT64_C(0x47b5481dbefa4fa4); +} + +static void sha512_update_block(void *vctx, const uint8_t *inp) +{ + cf_sha512_context *ctx = vctx; + + uint64_t W[16]; + + uint64_t a = ctx->H[0], + b = ctx->H[1], + c = ctx->H[2], + d = ctx->H[3], + e = ctx->H[4], + f = ctx->H[5], + g = ctx->H[6], + h = ctx->H[7], + Wt; + + for (size_t t = 0; t < 80; t++) + { + if (t < 16) + { + W[t] = Wt = read64_be(inp); + inp += 8; + } else { + Wt = SSIG1(W[(t - 2) % 16]) + + W[(t - 7) % 16] + + SSIG0(W[(t - 15) % 16]) + + W[(t - 16) % 16]; + W[t % 16] = Wt; + } + + uint64_t T1 = h + BSIG1(e) + CH(e, f, g) + K[t] + Wt; + uint64_t T2 = BSIG0(a) + MAJ(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + ctx->H[0] += a; + ctx->H[1] += b; + ctx->H[2] += c; + ctx->H[3] += d; + ctx->H[4] += e; + ctx->H[5] += f; + ctx->H[6] += g; + ctx->H[7] += h; + + ctx->blocks++; +} + +void cf_sha512_update(cf_sha512_context *ctx, const void *data, size_t nbytes) +{ + cf_blockwise_accumulate(ctx->partial, &ctx->npartial, sizeof ctx->partial, + data, nbytes, + sha512_update_block, ctx); +} + +void cf_sha384_update(cf_sha512_context *ctx, const void *data, size_t nbytes) +{ + cf_sha512_update(ctx, data, nbytes); +} + +void cf_sha512_digest(const cf_sha512_context *ctx, uint8_t hash[CF_SHA512_HASHSZ]) +{ + /* We copy the context, so the finalisation doesn't effect the caller's + * context. This means the caller can do: + * + * x = init() + * x.update('hello') + * h1 = x.digest() + * x.update(' world') + * h2 = x.digest() + * + * to get h1 = H('hello') and h2 = H('hello world') + * + * This wouldn't work if we applied MD-padding to *ctx. + */ + + cf_sha512_context ours = *ctx; + cf_sha512_digest_final(&ours, hash); +} + +void cf_sha512_digest_final(cf_sha512_context *ctx, uint8_t hash[CF_SHA512_HASHSZ]) +{ + uint64_t digested_bytes = ctx->blocks; + digested_bytes = digested_bytes * CF_SHA512_BLOCKSZ + ctx->npartial; + uint64_t digested_bits = digested_bytes * 8; + + size_t padbytes = CF_SHA512_BLOCKSZ - ((digested_bytes + 16) % CF_SHA512_BLOCKSZ); + + /* Hash 0x80 00 ... block first. */ + cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, sizeof ctx->partial, + 0x80, 0x00, 0x00, padbytes, + sha512_update_block, ctx); + + /* Now hash length (this is 128 bits long). */ + uint8_t buf[8]; + write64_be(0, buf); + cf_sha512_update(ctx, buf, 8); + write64_be(digested_bits, buf); + cf_sha512_update(ctx, buf, 8); + + /* We ought to have got our padding calculation right! */ + assert(ctx->npartial == 0); + + write64_be(ctx->H[0], hash + 0); + write64_be(ctx->H[1], hash + 8); + write64_be(ctx->H[2], hash + 16); + write64_be(ctx->H[3], hash + 24); + write64_be(ctx->H[4], hash + 32); + write64_be(ctx->H[5], hash + 40); + write64_be(ctx->H[6], hash + 48); + write64_be(ctx->H[7], hash + 56); + memset(ctx, 0, sizeof *ctx); +} + +void cf_sha384_digest(const cf_sha512_context *ctx, uint8_t hash[CF_SHA384_HASHSZ]) +{ + uint8_t full[CF_SHA512_HASHSZ]; + cf_sha512_digest(ctx, full); + memcpy(hash, full, CF_SHA384_HASHSZ); +} + +void cf_sha384_digest_final(cf_sha512_context *ctx, uint8_t hash[CF_SHA384_HASHSZ]) +{ + uint8_t full[CF_SHA512_HASHSZ]; + cf_sha512_digest_final(ctx, full); + memcpy(hash, full, CF_SHA384_HASHSZ); +} + +const cf_chash cf_sha384 = { + .hashsz = CF_SHA384_HASHSZ, + .blocksz = CF_SHA384_BLOCKSZ, + .init = (cf_chash_init) cf_sha384_init, + .update = (cf_chash_update) cf_sha384_update, + .digest = (cf_chash_digest) cf_sha384_digest +}; + +const cf_chash cf_sha512 = { + .hashsz = CF_SHA512_HASHSZ, + .blocksz = CF_SHA512_BLOCKSZ, + .init = (cf_chash_init) cf_sha512_init, + .update = (cf_chash_update) cf_sha512_update, + .digest = (cf_chash_digest) cf_sha512_digest +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/tassert.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/tassert.h new file mode 100644 index 0000000..58ebb4c --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/tassert.h @@ -0,0 +1,32 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef TASSERT_H +#define TASSERT_H + +/* Tiny assert + * ----------- + * + * This is an assert(3) definition which doesn't include any + * strings, but just branches to abort(3) on failure. + */ + +#ifndef FULL_FAT_ASSERT +# include <stdlib.h> +# define assert(expr) do { if (!(expr)) abort(); } while (0) +#else +# include <assert.h> +#endif + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testaes.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testaes.c new file mode 100644 index 0000000..12543bb --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testaes.c @@ -0,0 +1,258 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "aes.h" +#include "modes.h" +#include "bitops.h" +#include "gf128.h" + +#include "handy.h" +#include "cutest.h" +#include "testutil.h" + +static void test_memclean(void) +{ + uint8_t buf[32], buf2[32]; + memset(buf, 0xff, sizeof buf); + mem_clean(buf + 1, sizeof buf - 2); + TEST_CHECK(buf[0] == 0xff); + TEST_CHECK(buf[1] == 0x00); + TEST_CHECK(buf[16] == 0x00); + TEST_CHECK(buf[30] == 0x00); + TEST_CHECK(buf[31] == 0xff); + + memcpy(buf2, buf, sizeof buf); + TEST_CHECK(buf2[0] == 0xff); + TEST_CHECK(buf2[1] == 0x00); + TEST_CHECK(buf2[16] == 0x00); + TEST_CHECK(buf2[30] == 0x00); + TEST_CHECK(buf2[31] == 0xff); + + memset(buf2, 0xee, sizeof buf); + TEST_CHECK(buf2[0] == 0xee); + TEST_CHECK(buf2[1] == 0xee); + TEST_CHECK(buf2[2] == 0xee); + TEST_CHECK(buf2[3] == 0xee); + TEST_CHECK(buf2[30] == 0xee); + TEST_CHECK(buf2[31] == 0xee); +} + +static void test_bitops_select(void) +{ + uint8_t tab8[8]; + uint32_t tab32[32]; + + for (size_t i = 0; i < 8; i++) + tab8[i] = 1 << i; + for (size_t i = 0; i < 32; i++) + tab32[i] = 1 << i; + + for (size_t i = 0; i < 8; i++) + { + TEST_CHECK(select_u8(i, tab8, 8) == tab8[i]); + } + + for (size_t i = 0; i < 32; i++) + { + TEST_CHECK(select_u32(i, tab32, 32) == tab32[i]); + } +} + +static void test_bitops_incr(void) +{ + uint8_t buf[4]; + +#define CHECK_BE(start, add, end) \ + { \ + write32_be((start), buf); \ + for (size_t i = 0; i < (add); i++) \ + incr_be(buf, sizeof buf); \ + TEST_CHECK(read32_be(buf) == (end)); \ + } + +#define CHECK_LE(start, add, end) \ + { \ + write32_le((start), buf); \ + for (size_t i = 0; i < (add); i++) \ + incr_le(buf, sizeof buf); \ + TEST_CHECK(read32_le(buf) == (end)); \ + } + + CHECK_BE(0, 1, 1); + CHECK_BE(0, 256, 256); + CHECK_BE(256, 256, 512); + CHECK_BE(0xffffffff, 1, 0); + + CHECK_LE(0, 1, 1); + CHECK_LE(0, 256, 256); + CHECK_LE(0x7fffffff, 1, 0x80000000); + CHECK_LE(0xffffffff, 1, 0); + +#undef CHECK_BE +#undef CHECK_LE +} + +static void test_bitops_unaligned(void) +{ + uint8_t in[4], out[4]; + +#define CHECK(outw, len, offs) \ + { \ + memset(out, 0, sizeof out); \ + copy_bytes_unaligned(out, in, len, offs); \ + TEST_CHECK(read32_be(out) == (outw)); \ + } + + write32_be(0x11223344, in); + + CHECK(0x11223344, 4, 0); + CHECK(0x22446600, 3, 1); + CHECK(0x4488cd00, 3, 2); + CHECK(0x89119a00, 3, 3); + CHECK(0x12233400, 3, 4); + CHECK(0x24466800, 3, 5); + CHECK(0x488cd100, 3, 6); + CHECK(0x9119a200, 3, 7); + CHECK(0x22334400, 3, 8); + CHECK(0x44660000, 2, 9); + CHECK(0x33440000, 2, 16); + +#undef CHECK +} + +static void test_expand(const uint8_t *key, size_t nkey, + const uint32_t *answer, size_t roundkeys) +{ + cf_aes_context ctx; + + cf_aes_init(&ctx, key, nkey); + + for (size_t i = 0; i < roundkeys; i++) + { + TEST_CHECK(ctx.ks[i] == answer[i]); + } +} + +static void test_expand_128(void) +{ + /* This is FIPS-197 appendix A.1. */ + const uint8_t key[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + + const uint32_t answer[] = { + 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c, 0xa0fafe17, 0x88542cb1, + 0x23a33939, 0x2a6c7605, 0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f, + 0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b, 0xef44a541, 0xa8525b7f, + 0xb671253b, 0xdb0bad00, 0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc, + 0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd, 0x4e54f70e, 0x5f5fc9f3, + 0x84a64fb2, 0x4ea6dc4f, 0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f, + 0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e, 0xd014f9a8, 0xc9ee2589, + 0xe13f0cc8, 0xb6630ca6 + }; + + test_expand(key, sizeof key, answer, ARRAYCOUNT(answer)); +} + +static void test_expand_192(void) +{ + /* This is FIPS-197 appendix A.2. */ + const uint8_t key[] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, + 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b + }; + + const uint32_t answer[] = { + 0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5, 0x62f8ead2, 0x522c6b7b, + 0xfe0c91f7, 0x2402f5a5, 0xec12068e, 0x6c827f6b, 0x0e7a95b9, 0x5c56fec2, + 0x4db7b4bd, 0x69b54118, 0x85a74796, 0xe92538fd, 0xe75fad44, 0xbb095386, + 0x485af057, 0x21efb14f, 0xa448f6d9, 0x4d6dce24, 0xaa326360, 0x113b30e6, + 0xa25e7ed5, 0x83b1cf9a, 0x27f93943, 0x6a94f767, 0xc0a69407, 0xd19da4e1, + 0xec1786eb, 0x6fa64971, 0x485f7032, 0x22cb8755, 0xe26d1352, 0x33f0b7b3, + 0x40beeb28, 0x2f18a259, 0x6747d26b, 0x458c553e, 0xa7e1466c, 0x9411f1df, + 0x821f750a, 0xad07d753, 0xca400538, 0x8fcc5006, 0x282d166a, 0xbc3ce7b5, + 0xe98ba06f, 0x448c773c, 0x8ecc7204, 0x01002202 + }; + + test_expand(key, sizeof key, answer, ARRAYCOUNT(answer)); +} + +static void test_expand_256(void) +{ + /* And this is A.3. */ + const uint8_t key[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, + 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 + }; + + const uint32_t answer[] = { + 0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781, 0x1f352c07, 0x3b6108d7, + 0x2d9810a3, 0x0914dff4, 0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde, + 0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a, 0xd59aecb8, 0x5bf3c917, + 0xfee94248, 0xde8ebe96, 0xb5a9328a, 0x2678a647, 0x98312229, 0x2f6c79b3, + 0x812c81ad, 0xdadf48ba, 0x24360af2, 0xfab8b464, 0x98c5bfc9, 0xbebd198e, + 0x268c3ba7, 0x09e04214, 0x68007bac, 0xb2df3316, 0x96e939e4, 0x6c518d80, + 0xc814e204, 0x76a9fb8a, 0x5025c02d, 0x59c58239, 0xde136967, 0x6ccc5a71, + 0xfa256395, 0x9674ee15, 0x5886ca5d, 0x2e2f31d7, 0x7e0af1fa, 0x27cf73c3, + 0x749c47ab, 0x18501dda, 0xe2757e4f, 0x7401905a, 0xcafaaae3, 0xe4d59b34, + 0x9adf6ace, 0xbd10190d, 0xfe4890d1, 0xe6188d0b, 0x046df344, 0x706c631e + }; + + test_expand(key, sizeof key, answer, ARRAYCOUNT(answer)); +} + +static void vector(const char *input, const char *output, + const char *key) +{ + uint8_t keybuf[32], inbuf[16], outbuf[16], tmp[16]; + size_t nkey = sizeof keybuf; + cf_aes_context ctx; + + nkey = unhex(keybuf, 32, key); + unhex(inbuf, 16, input); + unhex(outbuf, 16, output); + + cf_aes_init(&ctx, keybuf, nkey); + cf_aes_encrypt(&ctx, inbuf, tmp); + TEST_CHECK(memcmp(tmp, outbuf, 16) == 0); + + cf_aes_decrypt(&ctx, outbuf, tmp); + TEST_CHECK(memcmp(tmp, inbuf, 16) == 0); + cf_aes_finish(&ctx); +} + +static void test_vectors(void) +{ + vector("00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a", + "000102030405060708090a0b0c0d0e0f"); + vector("00112233445566778899aabbccddeeff", "dda97ca4864cdfe06eaf70a0ec0d7191", + "000102030405060708090a0b0c0d0e0f1011121314151617"); + vector("00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); +} + +TEST_LIST = { + { "handy-memclean", test_memclean }, + { "bitops-select", test_bitops_select }, + { "bitops-incr", test_bitops_incr }, + { "bitops-unaligned", test_bitops_unaligned }, + { "key-expansion-128", test_expand_128 }, + { "key-expansion-192", test_expand_192 }, + { "key-expansion-256", test_expand_256 }, + { "vectors", test_vectors }, + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testchacha20poly1305.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testchacha20poly1305.c new file mode 100644 index 0000000..f1b53e6 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testchacha20poly1305.c @@ -0,0 +1,91 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "chacha20poly1305.h" +#include "handy.h" +#include "cutest.h" +#include "testutil.h" + +static void vector(const char *keystr, + const char *noncestr, + const char *headerstr, + const char *plainstr, + const char *cipherstr, + const char *tagstr) +{ + /* inputs */ + uint8_t K[32], N[12], H[12], A[16]; + uint8_t C[265], P[265]; + + unhex(K, sizeof K, keystr); + unhex(N, sizeof N, noncestr); + size_t headerlen = unhex(H, sizeof H, headerstr); + size_t plainlen = unhex(P, sizeof P, plainstr); + size_t cipherlen = unhex(C, sizeof C, cipherstr); + unhex(A, sizeof A, tagstr); + + assert(cipherlen == plainlen); + + /* working data */ + uint8_t out[265], ourtag[16]; + + /* check encryption works. */ + cf_chacha20poly1305_encrypt(K, N, + H, headerlen, + P, plainlen, + out, ourtag); + + TEST_CHECK(memcmp(out, C, cipherlen) == 0); + TEST_CHECK(memcmp(ourtag, A, sizeof A) == 0); + + /* proper decryption */ + TEST_CHECK(0 == cf_chacha20poly1305_decrypt(K, N, + H, headerlen, + C, cipherlen, + A, out)); + TEST_CHECK(0 == memcmp(out, P, plainlen)); + + /* failure decryption */ + C[0] ^= 0xff; + + TEST_CHECK(1 == cf_chacha20poly1305_decrypt(K, N, + H, headerlen, + C, cipherlen, + A, out)); +} + +static void test_vectors(void) +{ + /* Test vector from section 2.8.2. */ + vector("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "070000004041424344454647", + "50515253c0c1c2c3c4c5c6c7", + "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", + "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116", + "1ae10b594f09e26a7e902ecbd0600691"); + + /* Test vector from A.5. */ + vector("1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", + "000000000102030405060708", + "f33388860000000000004e91", + "496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d", + "64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b", + "eead9d67890cbb22392336fea1851f38"); +} + +TEST_LIST = { + { "vectors", test_vectors }, + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testcurve25519.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testcurve25519.c new file mode 100644 index 0000000..a0ab8db --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testcurve25519.c @@ -0,0 +1,56 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "curve25519.h" +#include "handy.h" +#include "cutest.h" +#include "testutil.h" + +static void test_base_mul(void) +{ + uint8_t secret[32]; + uint8_t public[32]; + uint8_t expect[32]; + + unhex(secret, 32, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"); + unhex(expect, 32, "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"); + cf_curve25519_mul_base(public, secret); + TEST_CHECK(memcmp(expect, public, 32) == 0); + + unhex(secret, 32, "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"); + unhex(expect, 32, "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"); + cf_curve25519_mul_base(public, secret); + TEST_CHECK(memcmp(expect, public, 32) == 0); +} + +static void test_mul(void) +{ + uint8_t scalar[32]; + uint8_t public[32]; + uint8_t shared[32]; + uint8_t expect[32]; + + unhex(scalar, 32, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"); + unhex(public, 32, "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"); + unhex(expect, 32, "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); + cf_curve25519_mul(shared, scalar, public); + TEST_CHECK(memcmp(expect, shared, 32) == 0); +} + +TEST_LIST = { + { "base-mul", test_base_mul }, + { "mul", test_mul }, + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testdrbg.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testdrbg.c new file mode 100644 index 0000000..253c8c0 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testdrbg.c @@ -0,0 +1,206 @@ +/* + * cifra - embedded cryptography library + * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "drbg.h" +#include "sha1.h" +#include "sha2.h" + +#include "handy.h" +#include "cutest.h" +#include "testutil.h" + +static void test_hashdrbg_sha256_vector(void) +{ + uint8_t entropy[32], nonce[16], persn[32], reseed[32], got[128], expect[128]; + + /* This is the first KAT from NIST's CAVP example + * file for SHA-256 with all inputs used; line 4360. */ + unhex(entropy, sizeof entropy, "b87bb4de5c148d964fc0cb612d69295671780b4270fe32bf389b6f49488efe13"); + unhex(nonce, sizeof nonce, "27eb37a0c695c4ee3c9b70b7f6b33492"); + unhex(persn, sizeof persn, "52321406ac8a9c266b1f8d811bb871269e5824b59a0234f01d358193523bbb7c"); + unhex(reseed, sizeof reseed, "7638267f534c4e6ee22cc6ca6ed824fd5d3d387c00b89dd791eb5ac9766385b8"); + + unhex(expect, sizeof expect, "de01c061651bab3cef2fc4ea89a56b6e86e74b2e9fd11ed671c97c813778a06a2c1f41b41e754a5257750c6bde9601da9d67d8d9564f4a8538b92516a2dacc496dee257b85393f2a01ad59aa3257f1b6da9566e3706d2d6d4a26e511b0c64d7dc223acb24827178afa43ca8d5a66f983d6929dc61564c4c14fc32d85765a23f7"); + + cf_hash_drbg_sha256 ctx; + cf_hash_drbg_sha256_init(&ctx, entropy, sizeof entropy, nonce, sizeof nonce, persn, sizeof persn); + cf_hash_drbg_sha256_reseed(&ctx, reseed, sizeof reseed, NULL, 0); + cf_hash_drbg_sha256_gen(&ctx, got, sizeof got); + cf_hash_drbg_sha256_gen(&ctx, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); + + /* This is line 5064 from Hash_DRBG.rsp */ + unhex(entropy, sizeof entropy, "63363377e41e86468deb0ab4a8ed683f6a134e47e014c700454e81e95358a569"); + unhex(nonce, sizeof nonce, "808aa38f2a72a62359915a9f8a04ca68"); + /* no persn */ + unhex(reseed, sizeof reseed, "e62b8a8ee8f141b6980566e3bfe3c04903dad4ac2cdf9f2280010a6739bc83d3"); + unhex(expect, sizeof expect, "04eec63bb231df2c630a1afbe724949d005a587851e1aa795e477347c8b056621c18bddcdd8d99fc5fc2b92053d8cfacfb0bb8831205fad1ddd6c071318a6018f03b73f5ede4d4d071f9de03fd7aea105d9299b8af99aa075bdb4db9aa28c18d174b56ee2a014d098896ff2282c955a81969e069fa8ce007a180183a07dfae17"); + + cf_hash_drbg_sha256_init(&ctx, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0); + cf_hash_drbg_sha256_reseed(&ctx, reseed, sizeof reseed, NULL, 0); + cf_hash_drbg_sha256_gen(&ctx, got, sizeof got); + cf_hash_drbg_sha256_gen(&ctx, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); +} + +static void test_hashdrbg_sha256_vector_addnl(void) +{ + uint8_t entropy[32], nonce[16], reseed[32], got[128], expect[128], addnl[32]; + + /* Hash_DRBG.rsp, line 5230. No personlisation string, but with additional data. */ + unhex(entropy, sizeof entropy, "9cfb7ad03be487a3b42be06e9ae44f283c2b1458cec801da2ae6532fcb56cc4c"); + unhex(nonce, sizeof nonce, "a20765538e8db31295747ec922c13a69"); + unhex(reseed, sizeof reseed, "96bc8014f90ebdf690db0e171b59cc46c75e2e9b8e1dc699c65c03ceb2f4d7dc"); + unhex(expect, sizeof expect, "71c1154a2a7a3552413970bf698aa02f14f8ea95e861f801f463be27868b1b14b1b4babd9eba5915a6414ab1104c8979b1918f3094925aeab0d07d2037e613b63cbd4f79d9f95c84b47ed9b77230a57515c211f48f4af6f5edb2c308b33905db308cf88f552c8912c49b34e66c026e67b302ca65b187928a1aba9a49edbfe190"); + + cf_hash_drbg_sha256 ctx; + cf_hash_drbg_sha256_init(&ctx, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0); + unhex(addnl, sizeof addnl, "6fea0894052dab3c44d503950c7c72bd7b87de87cb81d3bb51c32a62f742286d"); + cf_hash_drbg_sha256_reseed(&ctx, reseed, sizeof reseed, addnl, sizeof addnl); + unhex(addnl, sizeof addnl, "d3467c78563b74c13db7af36c2a964820f2a9b1b167474906508fdac9b2049a6"); + cf_hash_drbg_sha256_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got); + unhex(addnl, sizeof addnl, "5840a11cc9ebf77b963854726a826370ffdb2fc2b3d8479e1df5dcfa3dddd10b"); + cf_hash_drbg_sha256_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); +} + +static void test_hmacdrbg_sha1_vector(void) +{ + uint8_t entropy[16], nonce[8], reseed[16], got[80], expect[80]; + + /* HMAC_DRBG.rsp, line 8. */ + unhex(entropy, sizeof entropy, "79349bbf7cdda5799557866621c91383"); + unhex(nonce, sizeof nonce, "1146733abf8c35c8"); + unhex(reseed, sizeof reseed, "c7215b5b96c48e9b338c74e3e99dfedf"); + unhex(expect, sizeof expect, "c6a16ab8d420706f0f34ab7fec5adca9d8ca3a133e159ca6ac43c6f8a2be22834a4c0a0affb10d7194f1c1a5cf7322ec1ae0964ed4bf122746e087fdb5b3e91b3493d5bb98faed49e85f130fc8a459b7"); + + cf_hmac_drbg ctx; + cf_hmac_drbg_init(&ctx, &cf_sha1, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0); + cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, NULL, 0); + cf_hmac_drbg_gen(&ctx, got, sizeof got); + cf_hmac_drbg_gen(&ctx, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); +} + +static void test_hmacdrbg_sha1_vector_addnl(void) +{ + uint8_t entropy[16], nonce[8], reseed[16], got[80], expect[80], addnl[16]; + + /* HMAC_DRBG.rsp, line 174. */ + unhex(entropy, sizeof entropy, "7d7052a776fd2fb3d7191f733304ee8b"); + unhex(nonce, sizeof nonce, "be4a0ceedca80207"); + unhex(reseed, sizeof reseed, "49047e879d610955eed916e4060e00c9"); + unhex(expect, sizeof expect, "a736343844fc92511391db0addd9064dbee24c8976aa259a9e3b6368aa6de4c9bf3a0effcda9cb0e9dc33652ab58ecb7650ed80467f76a849fb1cfc1ed0a09f7155086064db324b1e124f3fc9e614fcb"); + + cf_hmac_drbg ctx; + cf_hmac_drbg_init(&ctx, &cf_sha1, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0); + unhex(addnl, sizeof addnl, "fd8bb33aab2f6cdfbc541811861d518d"); + cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, addnl, sizeof addnl); + unhex(addnl, sizeof addnl, "99afe347540461ddf6abeb491e0715b4"); + cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got); + unhex(addnl, sizeof addnl, "02f773482dd7ae66f76e381598a64ef0"); + cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); +} + +static void test_hmacdrbg_sha256_vector(void) +{ + uint8_t entropy[32], nonce[16], reseed[32], got[128], expect[128]; + + /* HMAC_DRBG.rsp, line 5064. */ + unhex(entropy, sizeof entropy, "06032cd5eed33f39265f49ecb142c511da9aff2af71203bffaf34a9ca5bd9c0d"); + unhex(nonce, sizeof nonce, "0e66f71edc43e42a45ad3c6fc6cdc4df"); + unhex(reseed, sizeof reseed, "01920a4e669ed3a85ae8a33b35a74ad7fb2a6bb4cf395ce00334a9c9a5a5d552"); + unhex(expect, sizeof expect, "76fc79fe9b50beccc991a11b5635783a83536add03c157fb30645e611c2898bb2b1bc215000209208cd506cb28da2a51bdb03826aaf2bd2335d576d519160842e7158ad0949d1a9ec3e66ea1b1a064b005de914eac2e9d4f2d72a8616a80225422918250ff66a41bd2f864a6a38cc5b6499dc43f7f2bd09e1e0f8f5885935124"); + + cf_hmac_drbg ctx; + cf_hmac_drbg_init(&ctx, &cf_sha256, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0); + cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, NULL, 0); + cf_hmac_drbg_gen(&ctx, got, sizeof got); + cf_hmac_drbg_gen(&ctx, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); +} + +static void test_hmacdrbg_sha256_vector_addnl(void) +{ + uint8_t entropy[32], nonce[16], reseed[32], got[128], expect[128], addnl[32]; + + /* HMAC_DRBG.rsp, line 5230. */ + unhex(entropy, sizeof entropy, "05ac9fc4c62a02e3f90840da5616218c6de5743d66b8e0fbf833759c5928b53d"); + unhex(nonce, sizeof nonce, "2b89a17904922ed8f017a63044848545"); + unhex(reseed, sizeof reseed, "2791126b8b52ee1fd9392a0a13e0083bed4186dc649b739607ac70ec8dcecf9b"); + unhex(expect, sizeof expect, "02ddff5173da2fcffa10215b030d660d61179e61ecc22609b1151a75f1cbcbb4363c3a89299b4b63aca5e581e73c860491010aa35de3337cc6c09ebec8c91a6287586f3a74d9694b462d2720ea2e11bbd02af33adefb4a16e6b370fa0effd57d607547bdcfbb7831f54de7073ad2a7da987a0016a82fa958779a168674b56524"); + + cf_hmac_drbg ctx; + cf_hmac_drbg_init(&ctx, &cf_sha256, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0); + unhex(addnl, sizeof addnl, "43bac13bae715092cf7eb280a2e10a962faf7233c41412f69bc74a35a584e54c"); + cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, addnl, sizeof addnl); + unhex(addnl, sizeof addnl, "3f2fed4b68d506ecefa21f3f5bb907beb0f17dbc30f6ffbba5e5861408c53a1e"); + cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got); + unhex(addnl, sizeof addnl, "529030df50f410985fde068df82b935ec23d839cb4b269414c0ede6cffea5b68"); + cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); +} + +static void test_hmacdrbg_sha512_vector(void) +{ + uint8_t entropy[32], nonce[16], reseed[32], got[256], expect[256]; + + /* HMAC_DRBG.rsp, line 10120. */ + unhex(entropy, sizeof entropy, "48c121b18733af15c27e1dd9ba66a9a81a5579cdba0f5b657ec53c2b9e90bbf6"); + unhex(nonce, sizeof nonce, "bbb7c777428068fad9970891f879b1af"); + unhex(reseed, sizeof reseed, "e0ffefdadb9ccf990504d568bdb4d862cbe17ccce6e22dfcab8b4804fd21421a"); + unhex(expect, sizeof expect, "05da6aac7d980da038f65f392841476d37fe70fbd3e369d1f80196e66e54b8fadb1d60e1a0f3d4dc173769d75fc3410549d7a843270a54a068b4fe767d7d9a59604510a875ad1e9731c8afd0fd50b825e2c50d062576175106a9981be37e02ec7c5cd0a69aa0ca65bddaee1b0de532e10cfa1f5bf6a026e47379736a099d6750ab121dbe3622b841baf8bdcbe875c85ba4b586b8b5b57b0fecbec08c12ff2a9453c47c6e32a52103d972c62ab9affb8e728a31fcefbbccc556c0f0a35f4b10ace2d96b906e36cbb72233201e536d3e13b045187b417d2449cad1edd192e061f12d22147b0a176ea8d9c4c35404395b6502ef333a813b6586037479e0fa3c6a23"); + + cf_hmac_drbg ctx; + cf_hmac_drbg_init(&ctx, &cf_sha512, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0); + cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, NULL, 0); + cf_hmac_drbg_gen(&ctx, got, sizeof got); + cf_hmac_drbg_gen(&ctx, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); +} + +static void test_hmacdrbg_sha512_vector_addnl(void) +{ + uint8_t entropy[32], nonce[16], reseed[32], got[256], expect[256], addnl[32]; + + /* HMAC_DRBG.rsp, line 10286. */ + unhex(entropy, sizeof entropy, "4686a959e17dfb96c294b09c0f7a60efb386416cfb4c8972bcc55e44a151607a"); + unhex(nonce, sizeof nonce, "5226543b4c89321bbfb0f11f18ee3462"); + unhex(reseed, sizeof reseed, "5ef50daaf29929047870235c17762f5df5d9ab1af656e0e215fcc6fd9fc0d85d"); + unhex(expect, sizeof expect, "b60d8803531b2b8583d17bdf3ac7c01f3c65cf9b069862b2d39b9024b34c172b712db0704acb078a1ab1aec0390dbaee2dec9be7b234e63da481fd469a92c77bc7bb2cfca586855520e0f9e9d47dcb9bdf2a2fdfa9f2b4342ef0ea582616b55477717cfd516d46d6383257743656f7cf8b38402ba795a8c9d35a4aa88bec623313dad6ead689d152b54074f183b2fee556f554db343626cea853718f18d386bc8bebb0c07b3c5e96ceb391ffceece88864dbd3be83a613562c5c417a24807d5f9332974f045e79a9ade36994af6cf9bbeeb71d0025fcb4ad50f121cbc2df7cd12ff5a50cddfd9a4bbc6d942d743c8b8fbebe00eeccea3d14e07ff8454fa715da"); + + cf_hmac_drbg ctx; + cf_hmac_drbg_init(&ctx, &cf_sha512, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0); + unhex(addnl, sizeof addnl, "d2383c3e528492269e6c3b3aaa2b54fbf48731f5aa52150ce7fc644679a5e7c6"); + cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, addnl, sizeof addnl); + unhex(addnl, sizeof addnl, "c841e7a2d9d13bdb8644cd7f5d91d241a369e12dc6c9c2be50d1ed29484bff98"); + cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got); + unhex(addnl, sizeof addnl, "9054cf9216af66a788d3bf6757b8987e42d4e49b325e728dc645d5e107048245"); + cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got); + TEST_CHECK(memcmp(got, expect, sizeof got) == 0); +} + +TEST_LIST = { + { "hashdrbg-sha256", test_hashdrbg_sha256_vector }, + { "hashdrbg-sha256-addnl", test_hashdrbg_sha256_vector_addnl }, + { "hmacdrbg-sha1", test_hmacdrbg_sha1_vector }, + { "hmacdrbg-sha1-addnl", test_hmacdrbg_sha1_vector_addnl }, + { "hmacdrbg-sha256", test_hmacdrbg_sha256_vector }, + { "hmacdrbg-sha256-addnl", test_hmacdrbg_sha256_vector_addnl }, + { "hmacdrbg-sha512", test_hmacdrbg_sha512_vector }, + { "hmacdrbg-sha512-addnl", test_hmacdrbg_sha512_vector_addnl }, + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testmodes.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testmodes.c new file mode 100644 index 0000000..ed96dde --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testmodes.c @@ -0,0 +1,890 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "aes.h" +#include "modes.h" +#include "bitops.h" +#include "gf128.h" + +#include "handy.h" +#include "cutest.h" +#include "testutil.h" + +/* Some tests are too big for microcontrollers. */ +#if defined(CORTEX_M0) || defined(CORTEX_M3) || defined(CORTEX_M4) +# define MCU_TARGET 1 +#else +# define MCU_TARGET 0 +#endif + +static void test_cbc(void) +{ + uint8_t out[16]; + + const void *iv = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"; + const void *key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c"; + const void *inp = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"; + const void *expect = "\x76\x49\xab\xac\x81\x19\xb2\x46\xce\xe9\x8e\x9b\x12\xe9\x19\x7d"; + + cf_aes_context aes; + cf_aes_init(&aes, key, 16); + + cf_cbc cbc; + cf_cbc_init(&cbc, &cf_aes, &aes, iv); + cf_cbc_encrypt(&cbc, inp, out, 1); + TEST_CHECK(memcmp(out, expect, 16) == 0); + + uint8_t decrypt[16]; + cf_cbc_init(&cbc, &cf_aes, &aes, iv); + cf_cbc_decrypt(&cbc, out, decrypt, 1); + TEST_CHECK(memcmp(decrypt, inp, 16) == 0); +} + +static void cbcmac_vector(const void *tag_expect, size_t ntag, + const void *key, size_t nkey, + const void *msg, size_t nmsg) +{ + uint8_t tag[16]; + + cf_aes_context aes; + cf_aes_init(&aes, key, nkey); + + cf_cbcmac_stream cm; + cf_cbcmac_stream_init(&cm, &cf_aes, &aes); + cf_cbcmac_stream_update(&cm, msg, nmsg); + cf_cbcmac_stream_pad_final(&cm, tag); + + TEST_CHECK(sizeof tag == ntag); + TEST_CHECK(memcmp(tag, tag_expect, sizeof tag) == 0); +} + +static void test_cbcmac(void) +{ + cbcmac_vector("\xf0\xf1\x89\x75\xa0\x85\x9d\x13\xa4\x9d\x3d\xbf\xc6\xcd\x65\xd9", 16, "\x04\xf7\xf7\x78\x62\x1d\x1e\x2c\x86\x47\x82\x2a\x50\xd9\x8a\x83", 16, "\x83\x1b\xe7\x4b\x9b\xe6\x85\xc8\x38\xe2\x2a\x25\xa3\x11\xcb\x14\x79\x62\x35\xf5\x28\x98\xd0", 23); + cbcmac_vector("\x0d\x6a\x13\x8f\x75\xb7\x56\x94\xd5\x15\xc5\x55\x5e\xee\xdd\x92", 16, "\xff\x84\x5a\xfc\x51\xf2\x06\x35\xa4\x8f\x6c\xec\x9f\x78\x1f\x2e", 16, "\xc5\x85\x3e\x6b\x3f\x7e\xf5\x10\x93\x6e\x30\xd5\x54\x13\x5f\x0d\x55\x43\x92\x8c\x53\xfc\x2f\x81\xa3", 25); + cbcmac_vector("\x96\x81\x3d\xb1\x7e\xac\x06\xb9\x79\x42\xa7\x3a\x7c\x5a\x0a\xad", 16, "\x10\x77\x16\x47\x23\x2e\xda\x40\x23\xd7\xc5\xc9\xbb\x51\x2e\x93", 16, "\x06\x53\x5f\x70\xd9\x6c\x80\x50\x85\x6b\x02\x4f\x67\xae\x87\xde\xc8\xd2\x9d\xab\xb7\x1f\x55\x93\x51\x00\x0a\x3c\x8f\xfc\x63\x60", 32); + cbcmac_vector("\x20\xdd\xa5\xb1\xc1\x14\x00\x90\x97\x41\xef\x3b\xc6\xac\xe8\xec", 16, "\x5b\x39\xdb\x4b\xa4\x53\x1f\x97\xf9\xca\x4b\xdd\xed\x9b\x28\x53", 16, "\x49\x91\xb3\x35\x40\xda\x4d\x8a\xdf\xe9\x37\x4b\xb4\xe1\xc5", 15); + cbcmac_vector("\xc0\x2f\x8f\x0a\xba\x13\x4b\x6b\x16\x69\xfb\x58\x2f\xc1\xc8\x76", 16, "\xd0\x22\xc7\xe7\x85\xd2\xfc\xa4\xd6\x7f\xaa\x18\xb1\xa9\xfd\x9d\x7a\x47\x37\x09\x33\x43\x06\x32", 24, "\x2b\xa2\x8e\xa5\x62\xdd\x9c\x5e\x80\xcc\xaf\x80\x16\x77", 14); + cbcmac_vector("\x05\x79\x4b\x5f\xc8\xf2\xee\x87\x74\xcd\x88\x9f\x7c\x29\xeb\xa0", 16, "\xe4\x51\xdb\x26\x8e\x2a\x26\xd1\xbf\x78\x3e\xab\x5d\xc6\xf9\x3f\xb2\xc5\xe2\x5c\xe8\x61\x28\x3c", 24, "\xea\x14\xfa\xaa\x95\x48\x12\xcb", 8); + cbcmac_vector("\x6a\x14\x4b\xaa\x39\xf6\x19\x71\x62\x65\xd3\x4e\x53\xb4\xc6\x7c", 16, "\xff\x46\x38\x0f\x62\xa9\x37\x7f\xb2\x41\x88\x44\x39\x2a\x97\xf5\xb9\x9a\xc0\x37\xf9\xc6\x75\x3f", 24, "\x64\x04\x53\x4c\xa8\x0a\x60\xf6\x5e\x22\xb6\xc4\xd7\xf3\xa9\x33\xf9\x3e", 18); + cbcmac_vector("\xf7\x1d\x16\x5c\xba\xac\x0f\xf0\x1a\x12\x75\xf8\x5b\x6a\x8e\x15", 16, "\x67\xce\x47\x6c\x11\x0e\xa1\xbc\xf0\x81\x30\x2b\x5f\xe2\x3b\xbc\x34\xc5\x4d\x46\x01\xed\x49\x04", 24, "\x94\xb1\x25\x63\x49\x49\x46\x7e\x7a\xa0\x0e\xa1\x10\x25\x21\x9a\xc9\x1f\x0d\xed\xa1\x10\x30\x7e\x08\x84\xee\x09\xe8\x31\x53\x81", 32); + cbcmac_vector("\x22\xfb\x7e\x4c\x77\x12\x7c\xed\x2c\xaa\xf9\x8d\x9f\x35\x15\x60", 16, "\x1c\x50\xc0\x79\x7c\xd6\x7f\x89\x26\xd1\xc9\xb9\x85\xf9\xee\xaf\x18\x3f\x07\x0b\x3a\xd2\x5f\x7e\xfa\x08\x95\xfe\x98\xe3\x43\x91", 32, "\x7d\x1e\x7e\x19\x9a\xd4\xf4\x3f\xcf\xff\x55\xf7\xc9\x81\xe6\x13\xc0\x22\xab\x7f\x83\x92\x21\x72\x65\x79\x78\xcd\xf0\x8b\x36", 31); + cbcmac_vector("\x40\xc1\xef\xf3\xf4\x71\x54\x58\x77\x3c\xd3\x07\x96\xdf\xfd\x54", 16, "\x3c\x1e\xae\xa7\x4a\xf6\xee\x43\x9b\xd7\xa3\x76\x38\xd6\x08\x21\x60\xe6\x1b\x23\x2b\xf8\xa4\x5d\x05\xd5\xf4\x89\x04\x3e\x2d\x19", 32, "\xd2\xa3\x38\x1a\x82\xd6\xb6\xc2\x52\x93\x43\x1d\xdc\x1d\x73\xb5\x14\x82\x40\xfe\x00\xc3\x24\x52\x8d\x69\xc6\x11\x4e\x4c\xa9\x40\xcd\xfb\x29\x17", 36); + cbcmac_vector("\x69\x7c\x65\x95\xa2\x1f\xa2\xfa\x3a\xd3\x60\x68\x7a\xed\x68\x37", 16, "\xc2\xda\x01\xb4\x12\xa5\xcd\x1c\x75\xb5\x08\x5f\xd2\xee\x79\xc3\x47\xd9\xf9\x12\x86\x3d\x81\xd0\x42\x89\x75\x96\x58\x70\x47\x05", 32, "\x65\x22\x9b\x77\x15\xe5\x02\x54\x04\x90\xfb\xe2\xbf\x5a\x8e\xb0\xbf\x64\xff\x7f\xb7\xab\x7f\x18\x69\x7b", 26); + cbcmac_vector("\xf5\x2d\x65\x16\x84\x43\x0d\xe8\x1f\x29\x51\x06\xec\xf0\xa5\xd2", 16, "\x76\xff\xb3\x38\x5b\xca\x7c\x93\xc0\x12\xd7\xbc\xb3\xa3\xd0\xf2\x87\xa7\x0a\x91\x36\x76\xa7\x8d\x28\x47\x05\x8e\x75\xae\x5e\x3c", 32, "\x12\x90\x91\x65\x32\x37\xd0\x35\xf6\x40\x42\xa7\x4f\x61\xa9\x9c\x8f\xd6\x84\x9a\x86\x0e\x57\xe7\xe4", 25); +} + +static void test_ctr(void) +{ + uint8_t out[16]; + + const void *nonce = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; + const void *key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c"; + const void *inp = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"; + const void *expect = "\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce"; + + cf_aes_context aes; + cf_aes_init(&aes, key, 16); + + cf_ctr ctr; + cf_ctr_init(&ctr, &cf_aes, &aes, nonce); + cf_ctr_cipher(&ctr, inp, out, 16); /* one piece */ + TEST_CHECK(memcmp(expect, out, 16) == 0); + + cf_ctr_init(&ctr, &cf_aes, &aes, nonce); + cf_ctr_cipher(&ctr, inp, out, 1); /* incremental (2 blocks) */ + cf_ctr_cipher(&ctr, inp, out, 16); + cf_ctr_cipher(&ctr, inp, out, 16); + + cf_ctr_init(&ctr, &cf_aes, &aes, nonce); + cf_ctr_cipher(&ctr, inp, out, 1); /* incremental */ + cf_ctr_cipher(&ctr, ((uint8_t *)inp) + 1, out + 1, 15); + TEST_CHECK(memcmp(expect, out, 16) == 0); + + uint8_t decrypt[16]; + cf_ctr_init(&ctr, &cf_aes, &aes, nonce); + cf_ctr_cipher(&ctr, out, decrypt, 16); + TEST_CHECK(memcmp(decrypt, inp, 16) == 0); + + /* Test we use the right number of blocks up. */ + uint8_t test_nonce[16], test_inp[16]; + memset(test_nonce, 0xff, 16); + memset(test_inp, 0x00, 16); + cf_ctr_init(&ctr, &cf_aes, &aes, test_nonce); + + /* Exercise cf_blockwise_xor code paths. */ + for (int i = 0; i < 1024; i++) + { + cf_ctr_cipher(&ctr, test_inp, out, i % 16); + } + + /* expected counter value is 1024 * 7.5 / 16 - 1: + * 479 = 0x1df + */ + + memset(test_nonce, 0, sizeof test_nonce); + test_nonce[15] = 0xdf; + test_nonce[14] = 0x01; + + TEST_CHECK(memcmp(test_nonce, ctr.nonce, 16) == 0); +} + +static void check_eax(const void *key, size_t nkey, + const void *msg, size_t nmsg, + const void *nonce, size_t nnonce, + const void *header, size_t nheader, + const void *expect_cipher, + const void *expect_tag, size_t ntag) +{ + uint8_t cipher[32]; + uint8_t tag[16]; + + assert(nmsg <= sizeof cipher); + assert(ntag <= ntag); + + cf_aes_context aes; + cf_aes_init(&aes, key, nkey); + + cf_eax_encrypt(&cf_aes, &aes, + msg, nmsg, + header, nheader, + nonce, nnonce, + cipher, + tag, ntag); + + TEST_CHECK(memcmp(expect_cipher, cipher, nmsg) == 0); + TEST_CHECK(memcmp(expect_tag, tag, ntag) == 0); + + int rc; + uint8_t tmp[sizeof cipher]; + rc = cf_eax_decrypt(&cf_aes, &aes, + cipher, nmsg, + header, nheader, + nonce, nnonce, + tag, ntag, + tmp); + TEST_CHECK(rc == 0); + TEST_CHECK(memcmp(tmp, msg, nmsg) == 0); + + tag[0] ^= 0xff; + rc = cf_eax_decrypt(&cf_aes, &aes, + cipher, nmsg, + header, nheader, + nonce, nnonce, + tag, ntag, + tmp); + TEST_CHECK(rc == 1); +} + +static void test_eax(void) +{ + /* Test vectors from paper. */ + check_eax("\x23\x39\x52\xDE\xE4\xD5\xED\x5F\x9B\x9C\x6D\x6F\xF8\x0F\xF4\x78", 16, + "", 0, + "\x62\xEC\x67\xF9\xC3\xA4\xA4\x07\xFC\xB2\xA8\xC4\x90\x31\xA8\xB3", 16, + "\x6B\xFB\x91\x4F\xD0\x7E\xAE\x6B", 8, + "", + "\xE0\x37\x83\x0E\x83\x89\xF2\x7B\x02\x5A\x2D\x65\x27\xE7\x9D\x01", 16); + + check_eax("\x91\x94\x5D\x3F\x4D\xCB\xEE\x0B\xF4\x5E\xF5\x22\x55\xF0\x95\xA4", 16, + "\xF7\xFB", 2, + "\xBE\xCA\xF0\x43\xB0\xA2\x3D\x84\x31\x94\xBA\x97\x2C\x66\xDE\xBD", 16, + "\xFA\x3B\xFD\x48\x06\xEB\x53\xFA", 8, + "\x19\xDD", + "\x5C\x4C\x93\x31\x04\x9D\x0B\xDA\xB0\x27\x74\x08\xF6\x79\x67\xE5", 16); + + check_eax("\x01\xF7\x4A\xD6\x40\x77\xF2\xE7\x04\xC0\xF6\x0A\xDA\x3D\xD5\x23", 16, + "\x1A\x47\xCB\x49\x33", 5, + "\x70\xC3\xDB\x4F\x0D\x26\x36\x84\x00\xA1\x0E\xD0\x5D\x2B\xFF\x5E", 16, + "\x23\x4A\x34\x63\xC1\x26\x4A\xC6", 8, + "\xD8\x51\xD5\xBA\xE0", + "\x3A\x59\xF2\x38\xA2\x3E\x39\x19\x9D\xC9\x26\x66\x26\xC4\x0F\x80", 16); + + check_eax("\xD0\x7C\xF6\xCB\xB7\xF3\x13\xBD\xDE\x66\xB7\x27\xAF\xD3\xC5\xE8", 16, + "\x48\x1C\x9E\x39\xB1", 5, + "\x84\x08\xDF\xFF\x3C\x1A\x2B\x12\x92\xDC\x19\x9E\x46\xB7\xD6\x17", 16, + "\x33\xCC\xE2\xEA\xBF\xF5\xA7\x9D", 8, + "\x63\x2A\x9D\x13\x1A", + "\xD4\xC1\x68\xA4\x22\x5D\x8E\x1F\xF7\x55\x93\x99\x74\xA7\xBE\xDE", 16); + + check_eax("\x35\xB6\xD0\x58\x00\x05\xBB\xC1\x2B\x05\x87\x12\x45\x57\xD2\xC2", 16, + "\x40\xD0\xC0\x7D\xA5\xE4", 6, + "\xFD\xB6\xB0\x66\x76\xEE\xDC\x5C\x61\xD7\x42\x76\xE1\xF8\xE8\x16", 16, + "\xAE\xB9\x6E\xAE\xBE\x29\x70\xE9", 8, + "\x07\x1D\xFE\x16\xC6\x75", + "\xCB\x06\x77\xE5\x36\xF7\x3A\xFE\x6A\x14\xB7\x4E\xE4\x98\x44\xDD", 16); + + check_eax("\xBD\x8E\x6E\x11\x47\x5E\x60\xB2\x68\x78\x4C\x38\xC6\x2F\xEB\x22", 16, + "\x4D\xE3\xB3\x5C\x3F\xC0\x39\x24\x5B\xD1\xFB\x7D", 12, + "\x6E\xAC\x5C\x93\x07\x2D\x8E\x85\x13\xF7\x50\x93\x5E\x46\xDA\x1B", 16, + "\xD4\x48\x2D\x1C\xA7\x8D\xCE\x0F", 8, + "\x83\x5B\xB4\xF1\x5D\x74\x3E\x35\x0E\x72\x84\x14", + "\xAB\xB8\x64\x4F\xD6\xCC\xB8\x69\x47\xC5\xE1\x05\x90\x21\x0A\x4F", 16); + + check_eax("\x7C\x77\xD6\xE8\x13\xBE\xD5\xAC\x98\xBA\xA4\x17\x47\x7A\x2E\x7D", 16, + "\x8B\x0A\x79\x30\x6C\x9C\xE7\xED\x99\xDA\xE4\xF8\x7F\x8D\xD6\x16\x36", 17, + "\x1A\x8C\x98\xDC\xD7\x3D\x38\x39\x3B\x2B\xF1\x56\x9D\xEE\xFC\x19", 16, + "\x65\xD2\x01\x79\x90\xD6\x25\x28", 8, + "\x02\x08\x3E\x39\x79\xDA\x01\x48\x12\xF5\x9F\x11\xD5\x26\x30\xDA\x30", + "\x13\x73\x27\xD1\x06\x49\xB0\xAA\x6E\x1C\x18\x1D\xB6\x17\xD7\xF2", 16); + + check_eax("\x5F\xFF\x20\xCA\xFA\xB1\x19\xCA\x2F\xC7\x35\x49\xE2\x0F\x5B\x0D", 16, + "\x1B\xDA\x12\x2B\xCE\x8A\x8D\xBA\xF1\x87\x7D\x96\x2B\x85\x92\xDD\x2D\x56", 18, + "\xDD\xE5\x9B\x97\xD7\x22\x15\x6D\x4D\x9A\xFF\x2B\xC7\x55\x98\x26", 16, + "\x54\xB9\xF0\x4E\x6A\x09\x18\x9A", 8, + "\x2E\xC4\x7B\x2C\x49\x54\xA4\x89\xAF\xC7\xBA\x48\x97\xED\xCD\xAE\x8C\xC3", + "\x3B\x60\x45\x05\x99\xBD\x02\xC9\x63\x82\x90\x2A\xEF\x7F\x83\x2A", 16); + + check_eax("\xA4\xA4\x78\x2B\xCF\xFD\x3E\xC5\xE7\xEF\x6D\x8C\x34\xA5\x61\x23", 16, + "\x6C\xF3\x67\x20\x87\x2B\x85\x13\xF6\xEA\xB1\xA8\xA4\x44\x38\xD5\xEF\x11", 18, + "\xB7\x81\xFC\xF2\xF7\x5F\xA5\xA8\xDE\x97\xA9\xCA\x48\xE5\x22\xEC", 16, + "\x89\x9A\x17\x58\x97\x56\x1D\x7E", 8, + "\x0D\xE1\x8F\xD0\xFD\xD9\x1E\x7A\xF1\x9F\x1D\x8E\xE8\x73\x39\x38\xB1\xE8", + "\xE7\xF6\xD2\x23\x16\x18\x10\x2F\xDB\x7F\xE5\x5F\xF1\x99\x17\x00", 16); + + check_eax("\x83\x95\xFC\xF1\xE9\x5B\xEB\xD6\x97\xBD\x01\x0B\xC7\x66\xAA\xC3", 16, + "\xCA\x40\xD7\x44\x6E\x54\x5F\xFA\xED\x3B\xD1\x2A\x74\x0A\x65\x9F\xFB\xBB\x3C\xEA\xB7", 21, + "\x22\xE7\xAD\xD9\x3C\xFC\x63\x93\xC5\x7E\xC0\xB3\xC1\x7D\x6B\x44", 16, + "\x12\x67\x35\xFC\xC3\x20\xD2\x5A", 8, + "\xCB\x89\x20\xF8\x7A\x6C\x75\xCF\xF3\x96\x27\xB5\x6E\x3E\xD1\x97\xC5\x52\xD2\x95\xA7", + "\xCF\xC4\x6A\xFC\x25\x3B\x46\x52\xB1\xAF\x37\x95\xB1\x24\xAB\x6E", 16); + + /* Test vector from bug #3 */ + check_eax("\x58\x94\x17\xB0\x32\x4B\x1B\x71\xD7\xA6\x75\x18\x52\x86\x7A\xE8", 16, + "\x00\x00\x1C\x40\x00\x00\x00\x48\x00\x00\x00\x73", 12, + "\x00\x01\x00\x00\xF6\x83", 6, + "", 0, + "\xD5\xD8\x99\x79\xAE\x79\xEB\xEE\x4E\x38\x5F\xA5", + "\x0E\xFB\x21\xFA\xD7\x14\xA2\x5B\x44\x14\x5F\x79\x22\x1A\x2C\x9A", 16); + +} + +static void check_cmac(const void *key, size_t nkey, + const void *msg, size_t nmsg, + const void *wanttag, size_t ntag) +{ + uint8_t gottag[16]; + + TEST_CHECK(cf_aes.blocksz == ntag); + + cf_aes_context aes; + cf_aes_init(&aes, key, nkey); + + cf_cmac cmac; + cf_cmac_init(&cmac, &cf_aes, &aes); + cf_cmac_sign(&cmac, msg, nmsg, gottag); + + TEST_CHECK(memcmp(gottag, wanttag, cf_aes.blocksz) == 0); +} + +static void test_cmac(void) +{ + /* These from SP800-38B */ + check_cmac("\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16, + "", 0, + "\xbb\x1d\x69\x29\xe9\x59\x37\x28\x7f\xa3\x7d\x12\x9b\x75\x67\x46", 16); + check_cmac("\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16, + "\x07\x0a\x16\xb4\x6b\x4d\x41\x44\xf7\x9b\xdd\x9d\xd0\x4a\x28\x7c", 16); + check_cmac("\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", 40, + "\xdf\xa6\x67\x47\xde\x9a\xe6\x30\x30\xca\x32\x61\x14\x97\xc8\x27", 16); + check_cmac("\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64, + "\x51\xf0\xbe\xbf\x7e\x3b\x9d\x92\xfc\x49\x74\x17\x79\x36\x3c\xfe", 16); + + check_cmac("\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24, + "", 0, + "\xd1\x7d\xdf\x46\xad\xaa\xcd\xe5\x31\xca\xc4\x83\xde\x7a\x93\x67", 16); + check_cmac("\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16, + "\x9e\x99\xa7\xbf\x31\xe7\x10\x90\x06\x62\xf6\x5e\x61\x7c\x51\x84", 16); + check_cmac("\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", 40, + "\x8a\x1d\xe5\xbe\x2e\xb3\x1a\xad\x08\x9a\x82\xe6\xee\x90\x8b\x0e", 16); + check_cmac("\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64, + "\xa1\xd5\xdf\x0e\xed\x79\x0f\x79\x4d\x77\x58\x96\x59\xf3\x9a\x11", 16); + + check_cmac("\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32, + "", 0, + "\x02\x89\x62\xf6\x1b\x7b\xf8\x9e\xfc\x6b\x55\x1f\x46\x67\xd9\x83", 16); + check_cmac("\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16, + "\x28\xa7\x02\x3f\x45\x2e\x8f\x82\xbd\x4b\xf2\x8d\x8c\x37\xc3\x5c", 16); + check_cmac("\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", 40, + "\xaa\xf3\xd8\xf1\xde\x56\x40\xc2\x32\xf5\xb1\x69\xb9\xc9\x11\xe6", 16); + check_cmac("\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64, + "\xe1\x99\x21\x90\x54\x9f\x6e\xd5\x69\x6a\x2c\x05\x6c\x31\x54\x10", 16); +} + +static void test_gf128_mul(void) +{ + uint8_t bout[16]; + + const void *bx = "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78"; + const void *by = "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e"; + const void *bexpect = "\x5e\x2e\xc7\x46\x91\x70\x62\x88\x2c\x85\xb0\x68\x53\x53\xde\xb7"; + + cf_gf128 x, y, out; + cf_gf128_frombytes_be(bx, x); + cf_gf128_frombytes_be(by, y); + cf_gf128_mul(x, y, out); + cf_gf128_tobytes_be(out, bout); + TEST_CHECK(memcmp(bexpect, bout, 16) == 0); +} + +static void check_gcm(const void *key, size_t nkey, + const void *plain, size_t nplain, + const void *aad, size_t naad, + const void *iv, size_t niv, + const void *cipher_expect, size_t ncipher, + const void *tag_expect, size_t ntag) +{ + uint8_t plain_decrypt[64], + cipher[64], + tag[16]; + + assert(ncipher == nplain); + + cf_aes_context ctx; + cf_aes_init(&ctx, key, nkey); + + cf_gcm_encrypt(&cf_aes, &ctx, + plain, nplain, + aad, naad, + iv, niv, + cipher, + tag, ntag); + + TEST_CHECK(memcmp(tag, tag_expect, ntag) == 0); + TEST_CHECK(memcmp(cipher, cipher_expect, ncipher) == 0); + + int err = cf_gcm_decrypt(&cf_aes, &ctx, + cipher, ncipher, + aad, naad, + iv, niv, + tag, ntag, + plain_decrypt); + TEST_CHECK(err == 0); + TEST_CHECK(memcmp(plain_decrypt, plain, ncipher) == 0); + + tag[0] ^= 0xff; + err = cf_gcm_decrypt(&cf_aes, &ctx, + cipher, ncipher, + aad, naad, + iv, niv, + tag, ntag, + plain_decrypt); + TEST_CHECK(err == 1); +} + +static void test_gcm(void) +{ + check_gcm("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, + "", 0, + "", 0, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45\x5a", 16); + check_gcm("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, + "", 0, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78", 16, + "\xab\x6e\x47\xd4\x2c\xec\x13\xbd\xf5\x3a\x67\xb2\x12\x57\xbd\xdf", 16); + check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55", 64, + "", 0, + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12, + "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85", 64, + "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", 16); + check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12, + "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91", 60, + "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb\x94\xfa\xe9\x5a\xe7\x12\x1a\x47", 16); + check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad", 8, + "\x61\x35\x3b\x4c\x28\x06\x93\x4a\x77\x7f\xf5\x1f\xa2\x2a\x47\x55" + "\x69\x9b\x2a\x71\x4f\xcd\xc6\xf8\x37\x66\xe5\xf9\x7b\x6c\x74\x23" + "\x73\x80\x69\x00\xe4\x9f\x24\xb2\x2b\x09\x75\x44\xd4\x89\x6b\x42" + "\x49\x89\xb5\xe1\xeb\xac\x0f\x07\xc2\x3f\x45\x98", 60, + "\x36\x12\xd2\xe7\x9e\x3b\x07\x85\x56\x1b\xe1\x4a\xac\xa2\xfc\xcb", 16); + check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa" + "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28" + "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54" + "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60, + "\x8c\xe2\x49\x98\x62\x56\x15\xb6\x03\xa0\x33\xac\xa1\x3f\xb8\x94" + "\xbe\x91\x12\xa5\xc3\xa2\x11\xa8\xba\x26\x2a\x3c\xca\x7e\x2c\xa7" + "\x01\xe4\xa9\xa4\xfb\xa4\x3c\x90\xcc\xdc\xb2\x81\xd4\x8c\x7c\x6f" + "\xd6\x28\x75\xd2\xac\xa4\x17\x03\x4c\x34\xae\xe5", 60, + "\x61\x9c\xc5\xae\xff\xfe\x0b\xfa\x46\x2a\xf4\x3c\x16\x99\xd0\x50", 16); + + check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa" + "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28" + "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54" + "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60, + "\x8c\xe2\x49\x98\x62\x56\x15\xb6\x03\xa0\x33\xac\xa1\x3f\xb8\x94" + "\xbe\x91\x12\xa5\xc3\xa2\x11\xa8\xba\x26\x2a\x3c\xca\x7e\x2c\xa7" + "\x01\xe4\xa9\xa4\xfb\xa4\x3c\x90\xcc\xdc\xb2\x81\xd4\x8c\x7c\x6f" + "\xd6\x28\x75\xd2\xac\xa4\x17\x03\x4c\x34\xae\xe5", 60, + "\x61\x9c\xc5\xae\xff\xfe\x0b\xfa\x46\x2a\xf4\x3c\x16\x99\xd0\x50", 16); + check_gcm("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 24, + "", 0, + "", 0, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b\xa0\x0e\xd1\xf3\x12\x57\x24\x35", 16); + check_gcm("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 24, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, + "", 0, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "\x98\xe7\x24\x7c\x07\xf0\xfe\x41\x1c\x26\x7e\x43\x84\xb0\xf6\x00", 16, + "\x2f\xf5\x8d\x80\x03\x39\x27\xab\x8e\xf4\xd4\x58\x75\x14\xf0\xfb", 16); + check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", 24, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55", 64, + "", 0, + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12, + "\x39\x80\xca\x0b\x3c\x00\xe8\x41\xeb\x06\xfa\xc4\x87\x2a\x27\x57" + "\x85\x9e\x1c\xea\xa6\xef\xd9\x84\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" + "\x7d\x77\x3d\x00\xc1\x44\xc5\x25\xac\x61\x9d\x18\xc8\x4a\x3f\x47" + "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9\xcc\xda\x27\x10\xac\xad\xe2\x56", 64, + "\x99\x24\xa7\xc8\x58\x73\x36\xbf\xb1\x18\x02\x4d\xb8\x67\x4a\x14", 16); +} + +static void check_ccm(const void *key, size_t nkey, + const void *header, size_t nheader, + const void *plain, size_t nplain, + const void *nonce, size_t nnonce, + const void *expect_cipher, size_t ncipher, + const void *expect_tag, size_t ntag) +{ + uint8_t cipher[32], tag[16], decrypted[32]; + + assert(ncipher == nplain); + + cf_aes_context ctx; + cf_aes_init(&ctx, key, nkey); + + cf_ccm_encrypt(&cf_aes, &ctx, + plain, nplain, 15 - nnonce, + header, nheader, + nonce, nnonce, + cipher, + tag, ntag); + + TEST_CHECK(memcmp(tag, expect_tag, ntag) == 0); + TEST_CHECK(memcmp(cipher, expect_cipher, ncipher) == 0); + + int err; + err = cf_ccm_decrypt(&cf_aes, &ctx, + expect_cipher, ncipher, 15 - nnonce, + header, nheader, + nonce, nnonce, + tag, ntag, + decrypted); + TEST_CHECK(err == 0); + TEST_CHECK(memcmp(decrypted, plain, nplain) == 0); + + tag[0] ^= 0xff; + + err = cf_ccm_decrypt(&cf_aes, &ctx, + expect_cipher, ncipher, 15 - nnonce, + header, nheader, + nonce, nnonce, + tag, ntag, + decrypted); + TEST_CHECK(err == 1); +} + +#if !MCU_TARGET +static void fill(uint8_t *buf, size_t len, uint8_t b) +{ + for (size_t i = 0; i < len; i++) + buf[i] = b++; +} + +static void test_ccm_long(void) +{ + /* This is example 4 from SP800-38C, to test the long AAD code path. */ + uint8_t header[0x10000]; + uint8_t key[16]; + uint8_t tag[14]; + uint8_t nonce[13]; + uint8_t plain[32], cipher[32]; + + fill(header, sizeof header, 0x00); + fill(key, sizeof key, 0x40); + fill(nonce, sizeof nonce, 0x10); + fill(plain, sizeof plain, 0x20); + + const void *expect_tag = "\xb4\xac\x6b\xec\x93\xe8\x59\x8e\x7f\x0d\xad\xbc\xea\x5b"; + const void *expect_cipher = "\x69\x91\x5d\xad\x1e\x84\xc6\x37\x6a\x68\xc2\x96\x7e\x4d\xab\x61\x5a\xe0\xfd\x1f\xae\xc4\x4c\xc4\x84\x82\x85\x29\x46\x3c\xcf\x72"; + + cf_aes_context ctx; + cf_aes_init(&ctx, key, sizeof key); + + cf_ccm_encrypt(&cf_aes, &ctx, + plain, sizeof plain, 15 - sizeof nonce, + header, sizeof header, + nonce, sizeof nonce, + cipher, + tag, sizeof tag); + + TEST_CHECK(memcmp(expect_tag, tag, sizeof tag) == 0); + TEST_CHECK(memcmp(expect_cipher, cipher, sizeof cipher) == 0); +} +#endif + +static void test_ccm(void) +{ + check_ccm("\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07", 8, + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e", 23, + "\x00\x00\x00\x03\x02\x01\x00\xa0\xa1\xa2\xa3\xa4\xa5", 13, + "\x58\x8c\x97\x9a\x61\xc6\x63\xd2\xf0\x66\xd0\xc2\xc0\xf9\x89\x80\x6d\x5f\x6b\x61\xda\xc3\x84", 23, + "\x17\xe8\xd1\x2c\xfd\xf9\x26\xe0", 8); + + check_ccm("\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07", 8, + "\x20\x21\x22\x23", 4, + "\x10\x11\x12\x13\x14\x15\x16", 7, + "\x71\x62\x01\x5b", 4, + "\x4d\xac\x25\x5d", 4); + + check_ccm("\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13", 20, + "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37", 24, + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b", 12, + "\xe3\xb2\x01\xa9\xf5\xb7\x1a\x7a\x9b\x1c\xea\xec\xcd\x97\xe7\x0b\x61\x76\xaa\xd9\xa4\x42\x8a\xa5", 24, + "\x48\x43\x92\xfb\xc1\xb0\x99\x51", 8); +} + +static void check_ocb(const void *key, size_t nkey, + const void *header, size_t nheader, + const void *plain, size_t nplain, + const void *nonce, size_t nnonce, + const void *expect_cipher, size_t ncipher, + const void *expect_tag, size_t ntag) +{ + uint8_t cipher[40], tag[16]; + + assert(ncipher == nplain); + assert(ncipher <= sizeof cipher); + assert(ntag <= sizeof tag); + + cf_aes_context ctx; + cf_aes_init(&ctx, key, nkey); + + cf_ocb_encrypt(&cf_aes, &ctx, + plain, nplain, + header, nheader, + nonce, nnonce, + cipher, + tag, ntag); + + TEST_CHECK(memcmp(tag, expect_tag, ntag) == 0); + TEST_CHECK(memcmp(cipher, expect_cipher, ncipher) == 0); + + uint8_t decrypted[40]; + int err; + err = cf_ocb_decrypt(&cf_aes, &ctx, + expect_cipher, ncipher, + header, nheader, + nonce, nnonce, + tag, ntag, + decrypted); + TEST_CHECK(err == 0); + TEST_CHECK(memcmp(decrypted, plain, nplain) == 0); + + tag[0] ^= 0xff; + + err = cf_ocb_decrypt(&cf_aes, &ctx, + expect_cipher, ncipher, + header, nheader, + nonce, nnonce, + tag, ntag, + decrypted); + TEST_CHECK(err == 1); +} + +static void test_ocb(void) +{ + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "", 0, + "", 0, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00", 12, + "", 0, + "\x78\x54\x07\xBF\xFF\xC8\xAD\x9E\xDC\xC5\x52\x0A\xC9\x11\x1E\xE6", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07", 8, + "\x00\x01\x02\x03\x04\x05\x06\x07", 8, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x01", 12, + "\x68\x20\xB3\x65\x7B\x6F\x61\x5A", 8, + "\x57\x25\xBD\xA0\xD3\xB4\xEB\x3A\x25\x7C\x9A\xF1\xF8\xF0\x30\x09", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07", 8, + "", 0, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x02", 12, + "", 0, + "\x81\x01\x7F\x82\x03\xF0\x81\x27\x71\x52\xFA\xDE\x69\x4A\x0A\x00", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "", 0, + "\x00\x01\x02\x03\x04\x05\x06\x07", 8, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x03", 12, + "\x45\xDD\x69\xF8\xF5\xAA\xE7\x24", 8, + "\x14\x05\x4C\xD1\xF3\x5D\x82\x76\x0B\x2C\xD0\x0D\x2F\x99\xBF\xA9", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x04", 12, + "\x57\x1D\x53\x5B\x60\xB2\x77\x18\x8B\xE5\x14\x71\x70\xA9\xA2\x2C", 16, + "\x3A\xD7\xA4\xFF\x38\x35\xB8\xC5\x70\x1C\x1C\xCE\xC8\xFC\x33\x58", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "", 0, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x05", 12, + "", 0, + "\x8C\xF7\x61\xB6\x90\x2E\xF7\x64\x46\x2A\xD8\x64\x98\xCA\x6B\x97", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "", 0, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x06", 12, + "\x5C\xE8\x8E\xC2\xE0\x69\x27\x06\xA9\x15\xC0\x0A\xEB\x8B\x23\x96", 16, + "\xF4\x0E\x1C\x74\x3F\x52\x43\x6B\xDF\x06\xD8\xFA\x1E\xCA\x34\x3D", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", 24, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", 24, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x07", 12, + "\x1C\xA2\x20\x73\x08\xC8\x7C\x01\x07\x56\x10\x4D\x88\x40\xCE\x19\x52\xF0\x96\x73\xA4\x48\xA1\x22", 24, + "\xC9\x2C\x62\x24\x10\x51\xF5\x73\x56\xD7\xF3\xC9\x0B\xB0\xE0\x7F", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", 24, + "", 0, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x08", 12, + "", 0, + "\x6D\xC2\x25\xA0\x71\xFC\x1B\x9F\x7C\x69\xF9\x3B\x0F\x1E\x10\xDE", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "", 0, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", 24, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x09", 12, + "\x22\x1B\xD0\xDE\x7F\xA6\xFE\x99\x3E\xCC\xD7\x69\x46\x0A\x0A\xF2\xD6\xCD\xED\x0C\x39\x5B\x1C\x3C", 24, + "\xE7\x25\xF3\x24\x94\xB9\xF9\x14\xD8\x5C\x0B\x1E\xB3\x83\x57\xFF", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 32, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 32, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0A", 12, + "\xBD\x6F\x6C\x49\x62\x01\xC6\x92\x96\xC1\x1E\xFD\x13\x8A\x46\x7A\xBD\x3C\x70\x79\x24\xB9\x64\xDE\xAF\xFC\x40\x31\x9A\xF5\xA4\x85", 32, + "\x40\xFB\xBA\x18\x6C\x55\x53\xC6\x8A\xD9\xF5\x92\xA7\x9A\x42\x40", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 32, + "", 0, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0B", 12, + "", 0, + "\xFE\x80\x69\x0B\xEE\x8A\x48\x5D\x11\xF3\x29\x65\xBC\x9D\x2A\x32", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "", 0, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 32, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0C", 12, + "\x29\x42\xBF\xC7\x73\xBD\xA2\x3C\xAB\xC6\xAC\xFD\x9B\xFD\x58\x35\xBD\x30\x0F\x09\x73\x79\x2E\xF4\x60\x40\xC5\x3F\x14\x32\xBC\xDF", 32, + "\xB5\xE1\xDD\xE3\xBC\x18\xA5\xF8\x40\xB5\x2E\x65\x34\x44\xD5\xDF", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27", 40, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27", 40, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0D", 12, + "\xD5\xCA\x91\x74\x84\x10\xC1\x75\x1F\xF8\xA2\xF6\x18\x25\x5B\x68\xA0\xA1\x2E\x09\x3F\xF4\x54\x60\x6E\x59\xF9\xC1\xD0\xDD\xC5\x4B\x65\xE8\x62\x8E\x56\x8B\xAD\x7A", 40, + "\xED\x07\xBA\x06\xA4\xA6\x94\x83\xA7\x03\x54\x90\xC5\x76\x9E\x60", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27", 40, + "", 0, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0E", 12, + "", 0, + "\xC5\xCD\x9D\x18\x50\xC1\x41\xE3\x58\x64\x99\x94\xEE\x70\x1B\x68", 16); + + check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16, + "", 0, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27", 40, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0F", 12, + "\x44\x12\x92\x34\x93\xC5\x7D\x5D\xE0\xD7\x00\xF7\x53\xCC\xE0\xD1\xD2\xD9\x50\x60\x12\x2E\x9F\x15\xA5\xDD\xBF\xC5\x78\x7E\x50\xB5\xCC\x55\xEE\x50\x7B\xCB\x08\x4E", 40, + "\x47\x9A\xD3\x63\xAC\x36\x6B\x95\xA9\x8C\xA5\xF3\x00\x0B\x14\x79", 16); + + check_ocb("\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00", 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27", 40, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27", 40, + "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0D", 12, + "\x17\x92\xA4\xE3\x1E\x07\x55\xFB\x03\xE3\x1B\x22\x11\x6E\x6C\x2D\xDF\x9E\xFD\x6E\x33\xD5\x36\xF1\xA0\x12\x4B\x0A\x55\xBA\xE8\x84\xED\x93\x48\x15\x29\xC7\x6B\x6A", 40, + "\xD0\xC5\x15\xF4\xD1\xCD\xD4\xFD\xAC\x4F\x02\xAA", 12); +} + +#if !MCU_TARGET +static void check_ocb_long(size_t nkey, const void *expect_tag, size_t ntag) +{ + uint8_t C[22400]; + uint8_t K[32]; + uint8_t S[128] = { 0 }; + uint8_t N[12] = { 0 }; + size_t nC = 0; + + memset(K, 0, sizeof K); + K[nkey - 1] = ntag * 8; + + cf_aes_context aes; + cf_aes_init(&aes, K, nkey); + + for (size_t i = 0; i < 128; i++) + { + /* N = num2str(3i+1, 96) */ + memset(N, 0, sizeof N); + write32_be(3 * i + 1, N + 8); + + /* C = C || OCB-ENCRYPT(K, N, S, S) + * nb. OCB-ENCRYPT(Key, Nonce, AAD, Plain) */ + cf_ocb_encrypt(&cf_aes, &aes, + S, i, /* plain */ + S, i, /* aad */ + N, sizeof N, /* nonce */ + C + nC, /* cipher out */ + C + nC + i, /* tag out */ + ntag); + nC += i + ntag; + + /* N = num2str(3i+2,96) */ + write32_be(3 * i + 2, N + 8); + + /* C = C || OCB-ENCRYPT(K, N, <empty string>, S) */ + cf_ocb_encrypt(&cf_aes, &aes, + S, i, + NULL, 0, + N, sizeof N, + C + nC, + C + nC + i, + ntag); + nC += i + ntag; + + /* N = num2str(3i+3,96) */ + write32_be(3 * i + 3, N + 8); + + /* C = C || OCB-ENCRYPT(K, N, S, <empty string>) */ + cf_ocb_encrypt(&cf_aes, &aes, + NULL, 0, + S, i, + N, sizeof N, + NULL, + C + nC, + ntag); + nC += ntag; + } + + /* N = num2str(385, 96) */ + write32_be(385, N + 8); + + /* Output : OCB-ENCRYPT(K, N, C, <empty string>) */ + uint8_t result[16]; + cf_ocb_encrypt(&cf_aes, &aes, + NULL, 0, + C, nC, + N, sizeof N, + NULL, + result, ntag); + + TEST_CHECK(memcmp(result, expect_tag, ntag) == 0); +} + +static void test_ocb_long(void) +{ + check_ocb_long(16, "\x67\xE9\x44\xD2\x32\x56\xC5\xE0\xB6\xC6\x1F\xA2\x2F\xDF\x1E\xA2", 16); + check_ocb_long(24, "\xF6\x73\xF2\xC3\xE7\x17\x4A\xAE\x7B\xAE\x98\x6C\xA9\xF2\x9E\x17", 16); + check_ocb_long(32, "\xD9\x0E\xB8\xE9\xC9\x77\xC8\x8B\x79\xDD\x79\x3D\x7F\xFA\x16\x1C", 16); + check_ocb_long(16, "\x77\xA3\xD8\xE7\x35\x89\x15\x8D\x25\xD0\x12\x09", 12); + check_ocb_long(24, "\x05\xD5\x6E\xAD\x27\x52\xC8\x6B\xE6\x93\x2C\x5E", 12); + check_ocb_long(32, "\x54\x58\x35\x9A\xC2\x3B\x0C\xBA\x9E\x63\x30\xDD", 12); + check_ocb_long(16, "\x19\x2C\x9B\x7B\xD9\x0B\xA0\x6A", 8); + check_ocb_long(24, "\x00\x66\xBC\x6E\x0E\xF3\x4E\x24", 8); + check_ocb_long(32, "\x7D\x4E\xA5\xD4\x45\x50\x1C\xBE", 8); +} +#endif + +TEST_LIST = { + { "cbc", test_cbc }, + { "cbcmac", test_cbcmac }, + { "ctr", test_ctr }, + { "eax", test_eax }, + { "cmac", test_cmac }, + { "gf128-mul", test_gf128_mul }, + { "gcm", test_gcm }, + { "ccm", test_ccm }, + { "ocb", test_ocb }, + /* These remaining tests are too big for microcontroller targets. */ +#if !MCU_TARGET + { "ccm-long", test_ccm_long }, + { "ocb-long", test_ocb_long }, +#endif + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testnorx.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testnorx.c new file mode 100644 index 0000000..b18393f --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testnorx.c @@ -0,0 +1,118 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "norx.h" +#include "handy.h" +#include "cutest.h" +#include "testutil.h" + +static void test_vector(void) +{ + uint8_t K[16], N[8], A[128], M[128], Z[128], C[128], T[16]; + + /* This is from the v2.0 paper, section A.2. */ + + unhex(K, sizeof K, "000102030405060708090a0b0c0d0e0f"); + unhex(N, sizeof N, "f0e0d0c0b0a09080"); + + for (unsigned i = 0; i < 128; i++) + { + A[i] = M[i] = Z[i] = i; + } + + cf_norx32_encrypt(K, N, + A, sizeof A, + M, sizeof M, + Z, sizeof Z, + C, T); + + uint8_t expect_C[128], expect_T[16]; + + unhex(expect_C, sizeof expect_C, "f4afc8e66d2d80de0a7f719c899624c9ad896ec7c61739d5376d0648c7bcb204e57db05c6f83b3ff4315e8a4ef2f2c855f21ea4c51ac6de575773ba548f36e636a13b979d953bb91298ea4a6e2aa27402991e0da541997825407b2f12441de3ae6c5dbfe41b12f1480d234832765111e4c09deef9fe3971618d2217c4b77921e"); + unhex(expect_T, sizeof expect_T, "7810131eea2eab1e5da05d23d4e3cb99"); + + TEST_CHECK(memcmp(C, expect_C, sizeof C) == 0); + TEST_CHECK(memcmp(T, expect_T, sizeof T) == 0); + + uint8_t M2[128]; + TEST_CHECK(0 == + cf_norx32_decrypt(K, N, + A, sizeof A, + C, sizeof C, + Z, sizeof Z, + T, + M2)); + + TEST_CHECK(memcmp(M, M2, sizeof M) == 0); + T[0] ^= 0xff; + + TEST_CHECK(cf_norx32_decrypt(K, N, + A, sizeof A, + C, sizeof C, + Z, sizeof Z, + T, + M2)); +} + +#include "testnorx.katdata.inc" + +static void test_kat(void) +{ + uint8_t K[16], N[16], H[256], W[256]; + const uint8_t *kats = kat_data; + +#define FILL(arr, c) \ + do { \ + for (size_t i = 0; i < sizeof arr; i++) \ + arr[i] = (i * c + 123) & 0xff; \ + } while (0) + FILL(N, 181); + FILL(K, 191); + FILL(H, 193); + FILL(W, 197); +#undef FILL + + for (size_t i = 0; i < sizeof W; i++) + { + uint8_t C[256]; + uint8_t A[16]; + + cf_norx32_encrypt(K, N, + H, i, + W, i, + NULL, 0, + C, A); + + TEST_CHECK(memcmp(kats, C, i) == 0); + kats += i; + TEST_CHECK(memcmp(kats, A, sizeof A) == 0); + kats += sizeof A; + + uint8_t M[256] = { 0 }; + TEST_CHECK(0 == cf_norx32_decrypt(K, N, + H, i, + C, i, + NULL, 0, + A, M)); + + TEST_CHECK(0 == memcmp(M, W, i)); + } +} + +TEST_LIST = { + { "vector", test_vector }, + { "kat", test_kat }, + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testnorx.katdata.inc b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testnorx.katdata.inc new file mode 100644 index 0000000..13dd746 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testnorx.katdata.inc @@ -0,0 +1,4961 @@ +static const uint8_t kat_data[] = { + 0xAF, 0x7C, 0xEF, 0x63, 0x5D, 0xEE, 0x94, 0x74, + 0x9B, 0xC2, 0x03, 0x9E, 0xC0, 0x49, 0xE0, 0x81, + + 0x69, 0x63, 0x57, 0x72, 0xEC, 0x0B, 0x66, 0xF2, + 0xE4, 0xB0, 0x1D, 0x30, 0x34, 0x29, 0x84, 0xE9, + 0xA8, + + 0x02, 0x46, 0x13, 0xCC, 0x6B, 0x19, 0x96, 0xB3, + 0x7E, 0x1C, 0xA6, 0x79, 0x00, 0x28, 0x19, 0x09, + 0x9F, 0x86, + + 0x99, 0xAC, 0xEA, 0x8C, 0x2B, 0x70, 0x02, 0xBA, + 0x86, 0xE9, 0xEB, 0x22, 0xEC, 0x23, 0xAF, 0x9A, + 0x95, 0xD0, 0xE5, + + 0xFE, 0xFB, 0xA0, 0xBA, 0x20, 0x28, 0x50, 0xDC, + 0xE5, 0xD6, 0x70, 0x26, 0x7A, 0x9E, 0x2A, 0xC3, + 0x3F, 0xCB, 0xD7, 0x0C, + + 0xB9, 0x67, 0x98, 0x4F, 0xDF, 0x1B, 0x19, 0x66, + 0x9C, 0xDE, 0xAE, 0x96, 0x76, 0xDB, 0xDE, 0x55, + 0x95, 0x50, 0xD9, 0xC2, 0xBA, + + 0x62, 0x28, 0x9A, 0x03, 0xF3, 0xF2, 0xFB, 0x0E, + 0xCF, 0xD4, 0x11, 0x74, 0x1D, 0x8E, 0x8B, 0xCD, + 0x92, 0x52, 0x96, 0x5B, 0x64, 0x99, + + 0x2F, 0xCE, 0xB4, 0x86, 0x4C, 0x0A, 0x47, 0xEB, + 0x98, 0x2A, 0xD2, 0xA1, 0x59, 0x9A, 0x5A, 0xB9, + 0x0C, 0xA7, 0x7D, 0xB0, 0xA6, 0xFF, 0x05, + + 0xE0, 0x22, 0x71, 0xE2, 0xCD, 0xF8, 0x3C, 0x12, + 0x8B, 0x4E, 0x28, 0x14, 0x6F, 0x0E, 0x18, 0xAE, + 0x23, 0xDF, 0xD0, 0x59, 0x70, 0x9E, 0x54, 0x49, + + 0xF6, 0xB6, 0x9E, 0x08, 0xB8, 0x27, 0x54, 0x94, + 0xD1, 0x0B, 0x93, 0x25, 0xEF, 0xD5, 0xE2, 0x19, + 0xEF, 0xEA, 0x0C, 0xFC, 0x01, 0x75, 0xC2, 0x90, + 0x00, + + 0x54, 0xBE, 0x7D, 0xFB, 0xF5, 0xCC, 0x52, 0xC6, + 0x9A, 0x0F, 0x65, 0xBD, 0xF1, 0x53, 0x5D, 0x01, + 0x07, 0xCC, 0xAB, 0xB9, 0xA5, 0x53, 0xFD, 0xE7, + 0xE4, 0x74, + + 0xD7, 0x6E, 0x5B, 0x87, 0xD0, 0xC1, 0x68, 0x92, + 0xD0, 0x80, 0x7D, 0x36, 0x8D, 0xE7, 0x36, 0xC5, + 0x97, 0xE7, 0x46, 0xDA, 0xC9, 0x19, 0xD9, 0x98, + 0xD9, 0xBD, 0x7B, + + 0x7E, 0xEB, 0x69, 0xAB, 0x77, 0x97, 0xDA, 0xE8, + 0x47, 0xA4, 0x6E, 0x4A, 0x1D, 0xC9, 0x00, 0xF3, + 0x4B, 0x2E, 0xCD, 0x56, 0xDF, 0xE1, 0xAF, 0x9E, + 0xE8, 0xAD, 0x94, 0x48, + + 0xDF, 0xAB, 0x2B, 0xE7, 0x84, 0x9C, 0xBB, 0x96, + 0x3F, 0x02, 0x99, 0x65, 0x42, 0x1A, 0x0D, 0x33, + 0x97, 0xA8, 0x23, 0x7C, 0x59, 0x4E, 0xCC, 0x64, + 0x54, 0x11, 0x6F, 0x09, 0x80, + + 0xB5, 0x4B, 0x1A, 0x8C, 0x05, 0x62, 0x60, 0x7A, + 0xCC, 0xA8, 0x63, 0x7F, 0xCC, 0xC6, 0x13, 0x70, + 0xF8, 0xC6, 0x09, 0x5C, 0x45, 0x93, 0x3E, 0x7C, + 0x9E, 0x27, 0x23, 0x42, 0xAE, 0x52, + + 0x56, 0x3E, 0x38, 0xC7, 0x66, 0xCE, 0xB5, 0x8F, + 0x77, 0xA1, 0x20, 0xE2, 0x69, 0x08, 0x92, 0x1E, + 0x32, 0x01, 0x75, 0xD2, 0x05, 0x92, 0x1B, 0x60, + 0x60, 0x9F, 0xD2, 0xA3, 0x89, 0x49, 0x6E, + + 0x01, 0x91, 0x5D, 0xDC, 0xC7, 0xB1, 0x4F, 0x6D, + 0x73, 0x4D, 0x3B, 0x68, 0xA0, 0xA5, 0x1D, 0xA5, + 0x22, 0x3C, 0xFE, 0xDC, 0x86, 0xB1, 0x64, 0x54, + 0x92, 0xE1, 0x0F, 0x32, 0xD5, 0xA6, 0x4B, 0xAC, + + 0x13, 0xF8, 0xFC, 0xDB, 0x41, 0x62, 0x9F, 0x6E, + 0xE6, 0x9B, 0xAB, 0xE5, 0x27, 0x3B, 0x8C, 0x15, + 0x8C, 0xC8, 0x03, 0x38, 0xE3, 0x7E, 0x83, 0xDA, + 0xA2, 0x5B, 0xA8, 0x44, 0xE2, 0x41, 0x47, 0x53, + 0x2A, + + 0xD2, 0x73, 0x87, 0xC2, 0xF0, 0x28, 0x2A, 0x0F, + 0xE6, 0x37, 0xC9, 0xAF, 0xF3, 0x02, 0xAC, 0xEA, + 0x37, 0xB6, 0x8C, 0xA6, 0x37, 0x5F, 0x79, 0x89, + 0xCD, 0x90, 0x6B, 0xCC, 0xF6, 0x7C, 0xEC, 0xD9, + 0x75, 0xE6, + + 0x0B, 0x76, 0x2F, 0xAC, 0x9F, 0x20, 0xA1, 0x56, + 0x5F, 0xF9, 0x67, 0xB8, 0xDC, 0xAC, 0x48, 0xA0, + 0x00, 0xD3, 0xFE, 0x87, 0xAE, 0x13, 0x07, 0x26, + 0xD9, 0xC2, 0x6D, 0xF9, 0xEC, 0xB4, 0xA2, 0x41, + 0x17, 0xB6, 0x4C, + + 0xA2, 0xE6, 0x67, 0xBC, 0x65, 0x03, 0x88, 0xDC, + 0xAD, 0x8B, 0x3C, 0x28, 0x83, 0x5F, 0xE3, 0x47, + 0x95, 0xDA, 0xF9, 0x6A, 0x09, 0xE9, 0xF9, 0xD5, + 0x58, 0xE4, 0xC3, 0x64, 0x3E, 0xE2, 0x82, 0x22, + 0xC3, 0xF7, 0x50, 0x40, + + 0x73, 0xA2, 0xA1, 0xB7, 0xC4, 0xCC, 0x5F, 0xA6, + 0x86, 0x7A, 0xFB, 0xF9, 0x2D, 0xB0, 0x92, 0x90, + 0xDB, 0xD1, 0xD0, 0xD4, 0x7E, 0x83, 0xD8, 0xF7, + 0x39, 0x38, 0xFA, 0xD4, 0x24, 0x56, 0x96, 0x1D, + 0xF5, 0xB9, 0x35, 0x7A, 0x7B, + + 0xCB, 0xA1, 0x1C, 0x70, 0x7E, 0x42, 0xF7, 0x32, + 0x68, 0x56, 0x27, 0xC7, 0xFD, 0x13, 0xCE, 0xC2, + 0xD3, 0xEE, 0x3E, 0x33, 0xF3, 0xC3, 0xB4, 0x87, + 0x31, 0x6E, 0xDA, 0xA1, 0x09, 0x77, 0x9E, 0xBE, + 0x43, 0x8D, 0x11, 0xF9, 0x0B, 0x5B, + + 0x31, 0xD7, 0x0C, 0xE3, 0xD3, 0x37, 0xCA, 0xF9, + 0x9E, 0x7E, 0x57, 0xF1, 0x45, 0x02, 0x7D, 0xDC, + 0xA9, 0xBF, 0x73, 0x6B, 0x04, 0x16, 0x44, 0x6D, + 0x62, 0x65, 0x2E, 0x5D, 0xBE, 0x75, 0xD0, 0xA2, + 0x88, 0xF2, 0x60, 0xFE, 0x7B, 0xED, 0x74, + + 0x42, 0xD4, 0xAD, 0xFF, 0xDB, 0x5D, 0xBF, 0x2F, + 0xA9, 0xE1, 0x7B, 0x60, 0xB8, 0xE8, 0x4D, 0x6F, + 0xF9, 0x70, 0xE4, 0x26, 0x40, 0xFA, 0x19, 0x36, + 0x07, 0x5C, 0xEA, 0x0F, 0x47, 0x89, 0xE0, 0x91, + 0xD2, 0xF7, 0x75, 0xB7, 0x27, 0x3A, 0xCC, 0xEB, + + 0xCB, 0x20, 0xDD, 0xCD, 0x30, 0x13, 0xD8, 0x84, + 0xD8, 0x57, 0xAA, 0xFA, 0x74, 0xDA, 0x46, 0x49, + 0x35, 0x60, 0x93, 0x20, 0xAB, 0x32, 0x19, 0x02, + 0x3C, 0x8F, 0x9F, 0x1E, 0xAD, 0x4B, 0x8F, 0x5A, + 0xE5, 0x1F, 0xEA, 0x8B, 0x5C, 0x53, 0x81, 0x68, + 0x0D, + + 0xF9, 0x00, 0x75, 0x76, 0x0E, 0x8B, 0x33, 0xAF, + 0x83, 0xD4, 0xB4, 0x0D, 0xF1, 0x48, 0xD5, 0x02, + 0x08, 0x6F, 0xEC, 0x1B, 0xB0, 0x40, 0x82, 0xF2, + 0xF4, 0x52, 0xCB, 0x43, 0xE6, 0x0F, 0x1F, 0xBE, + 0x15, 0xCE, 0x9D, 0xB8, 0xED, 0x3F, 0x7B, 0xD0, + 0x94, 0xFF, + + 0x6C, 0x78, 0x7D, 0x34, 0x07, 0xA5, 0xB2, 0xA9, + 0xF8, 0x8F, 0xB6, 0x4E, 0x0D, 0x31, 0x23, 0xD2, + 0x71, 0xB5, 0x7D, 0x10, 0xBA, 0xA7, 0x35, 0x1F, + 0xDE, 0x10, 0xE7, 0x21, 0x56, 0x50, 0xB1, 0xAD, + 0x76, 0x03, 0x7C, 0x8C, 0x88, 0x12, 0x09, 0x46, + 0xF4, 0x5F, 0x57, + + 0xFC, 0xAC, 0x41, 0xB1, 0x66, 0xBD, 0xFE, 0x96, + 0x4D, 0xDA, 0x18, 0x9C, 0xDA, 0xA8, 0xC7, 0x6A, + 0x94, 0x5D, 0x2B, 0x44, 0xB0, 0xF6, 0x89, 0x58, + 0x9C, 0x30, 0xD3, 0xC8, 0x48, 0x2F, 0xE8, 0x9F, + 0xB5, 0x33, 0x4C, 0x2A, 0x89, 0x15, 0x71, 0xDF, + 0xDB, 0xA0, 0x4B, 0x00, + + 0x1F, 0x85, 0x54, 0x96, 0x15, 0x04, 0x80, 0x09, + 0xDB, 0x13, 0xA7, 0x52, 0x03, 0x5F, 0x8C, 0x6E, + 0x66, 0x9D, 0x65, 0x64, 0xB0, 0x73, 0xC0, 0x61, + 0xCD, 0xF1, 0xEF, 0xE6, 0x01, 0x5B, 0x3B, 0x85, + 0xB8, 0x9E, 0x54, 0xC8, 0x47, 0x9C, 0x8A, 0x9C, + 0x27, 0x43, 0x4D, 0xB3, 0x33, + + 0x96, 0xEA, 0xF6, 0x72, 0xED, 0x28, 0x75, 0x42, + 0x06, 0x81, 0xEA, 0x29, 0xDF, 0xE4, 0x06, 0x51, + 0xD2, 0x3F, 0x42, 0xF5, 0x9C, 0xDD, 0x4C, 0xCD, + 0xA3, 0xEC, 0x46, 0x65, 0xD8, 0xA2, 0x5D, 0x05, + 0x6D, 0x5B, 0x46, 0x18, 0x44, 0xB0, 0x34, 0x02, + 0x7A, 0xEF, 0x24, 0x2A, 0x73, 0x69, + + 0x41, 0xC9, 0xA4, 0x8C, 0xE0, 0x92, 0xB4, 0xAB, + 0xCB, 0xFA, 0x94, 0xDF, 0xF5, 0x29, 0xFA, 0x23, + 0x43, 0x0F, 0xF0, 0x96, 0x01, 0x58, 0xAC, 0x6E, + 0x16, 0x5B, 0x59, 0xAA, 0x46, 0x10, 0xA5, 0x27, + 0xF3, 0xD0, 0x6D, 0x7B, 0xA8, 0x44, 0x2E, 0x9D, + 0xF9, 0x62, 0x87, 0xA4, 0xA2, 0xDC, 0x69, + + 0xA6, 0xBB, 0x70, 0x33, 0x8E, 0x2E, 0xBD, 0xF7, + 0x24, 0xAF, 0x04, 0xAF, 0x33, 0x3C, 0x58, 0x6A, + 0xB0, 0x83, 0xC6, 0x4B, 0xE6, 0xB6, 0x90, 0xDA, + 0x29, 0xFC, 0x34, 0xDE, 0x50, 0x4E, 0x4F, 0x77, + 0xD6, 0x31, 0x41, 0x80, 0x52, 0x06, 0x39, 0x11, + 0x83, 0xA9, 0x34, 0x69, 0x87, 0xAC, 0x54, 0x28, + + 0x5E, 0x8D, 0x7B, 0xAE, 0xCD, 0x3B, 0x76, 0xBC, + 0xD6, 0x0A, 0x5D, 0x7A, 0x91, 0x4C, 0x51, 0x5D, + 0x54, 0xA6, 0x9D, 0xB8, 0xAD, 0xE9, 0xA3, 0xCB, + 0x80, 0xAD, 0xE8, 0x72, 0x99, 0xFE, 0x31, 0xFA, + 0x9F, 0x5E, 0xB4, 0x7A, 0x8A, 0x33, 0x19, 0x42, + 0xF4, 0x7E, 0xB1, 0x68, 0x28, 0x72, 0xFD, 0xCB, + 0x39, + + 0x4E, 0x1D, 0xFC, 0x0C, 0x9C, 0x55, 0x80, 0x6A, + 0x05, 0x1B, 0x55, 0x77, 0x9D, 0x42, 0x98, 0x4A, + 0x70, 0x70, 0x1E, 0x06, 0x48, 0xD3, 0x76, 0x72, + 0x6A, 0x14, 0x71, 0xA2, 0xF9, 0xB1, 0xB2, 0xE9, + 0x17, 0x08, 0x95, 0x20, 0x2A, 0x00, 0xDF, 0x29, + 0x3B, 0xFA, 0x3C, 0xD2, 0x63, 0xAF, 0x24, 0xF9, + 0x08, 0x09, + + 0xCB, 0x1E, 0x1E, 0x95, 0xE6, 0x40, 0xDF, 0x3F, + 0x0C, 0x7B, 0x5B, 0x76, 0xFD, 0x13, 0xC4, 0x95, + 0xBE, 0xCC, 0x66, 0xD9, 0x1D, 0x4F, 0xBD, 0x29, + 0xBB, 0x3F, 0x5C, 0x3B, 0xA4, 0x0E, 0x4E, 0x76, + 0xD4, 0x42, 0x6F, 0x64, 0xCA, 0x26, 0xAB, 0x7B, + 0xA6, 0x9C, 0x54, 0x7B, 0x2A, 0x71, 0xBA, 0xC2, + 0xF0, 0xF2, 0x6F, + + 0x63, 0xF4, 0x8B, 0x62, 0x4F, 0xE7, 0x46, 0xCC, + 0x4F, 0x60, 0x20, 0x8B, 0x00, 0x57, 0xD0, 0xA7, + 0xDF, 0x6F, 0x08, 0x5C, 0x6F, 0x00, 0x78, 0xA8, + 0x5A, 0x77, 0x71, 0x65, 0x6E, 0x01, 0x71, 0x8D, + 0x2B, 0x15, 0x90, 0x7E, 0x59, 0xA4, 0xF6, 0x23, + 0xF3, 0x12, 0xBC, 0x3C, 0xFD, 0x21, 0x7D, 0x2E, + 0x7E, 0x4F, 0x83, 0xD7, + + 0x76, 0xC1, 0x46, 0xC5, 0x86, 0x11, 0xE9, 0x28, + 0x6A, 0x97, 0x26, 0xC7, 0x89, 0xA7, 0xCD, 0x01, + 0x40, 0x53, 0xD6, 0x42, 0xB3, 0xF1, 0x48, 0x51, + 0x11, 0xC6, 0x9E, 0xDF, 0x91, 0x5C, 0xD9, 0x4C, + 0xB9, 0x68, 0x63, 0x6D, 0xBC, 0xCE, 0x6F, 0x5E, + 0xE3, 0xFC, 0xAB, 0xCE, 0x24, 0x94, 0x5C, 0x43, + 0x51, 0xB6, 0xE7, 0x99, 0x45, + + 0xC9, 0xC7, 0xCD, 0x1F, 0x2E, 0x48, 0x25, 0xC3, + 0x1C, 0xF8, 0x85, 0x32, 0x15, 0x56, 0x82, 0x17, + 0xF4, 0xDC, 0x5F, 0xAE, 0xEF, 0x94, 0xDD, 0xFA, + 0xEA, 0xEE, 0xFC, 0x9B, 0x8C, 0xE1, 0x2E, 0xCF, + 0xE3, 0x40, 0x03, 0xF7, 0xBD, 0x7B, 0x12, 0x56, + 0x42, 0xCA, 0x1A, 0x68, 0xEF, 0xC3, 0xEF, 0xAC, + 0xEB, 0xA8, 0xD8, 0x91, 0x8C, 0x42, + + 0x78, 0xF9, 0x51, 0x9E, 0x84, 0x32, 0xFC, 0xBA, + 0x46, 0xA0, 0xF1, 0x04, 0x77, 0xF6, 0x93, 0xAD, + 0xB3, 0x95, 0xA3, 0x69, 0xA4, 0xAD, 0x45, 0x89, + 0x39, 0xFC, 0x08, 0x35, 0x45, 0xA9, 0xDC, 0x26, + 0x55, 0xA2, 0x8E, 0x3E, 0xF5, 0xE3, 0x86, 0xD1, + 0x1A, 0x37, 0x4C, 0x96, 0x16, 0x68, 0x06, 0x01, + 0xF0, 0x0D, 0x02, 0x4F, 0x17, 0x34, 0x9C, + + 0xD8, 0xFF, 0x53, 0x2C, 0xEE, 0xA5, 0xEB, 0x21, + 0xD8, 0x4C, 0x89, 0xCF, 0x7F, 0x15, 0x59, 0x5D, + 0xDD, 0x45, 0x01, 0x6A, 0x71, 0x0B, 0x47, 0x2C, + 0x72, 0x08, 0xC4, 0x5D, 0x71, 0x6A, 0x59, 0xDB, + 0x46, 0x0E, 0xDF, 0xD7, 0x2B, 0xDA, 0xE1, 0x69, + 0x0A, 0xE7, 0xD7, 0x5F, 0x18, 0x49, 0xC6, 0xA2, + 0xA7, 0x1A, 0x2E, 0x94, 0xCD, 0x45, 0xD9, 0x5A, + + 0x51, 0x54, 0x80, 0x8F, 0x07, 0xDA, 0xCC, 0x7B, + 0xB8, 0xE1, 0xE0, 0xEE, 0xF2, 0x7D, 0x8D, 0x2D, + 0xF0, 0x50, 0x5A, 0xB6, 0xF5, 0xBC, 0x62, 0xBC, + 0xA6, 0x75, 0xB7, 0x80, 0xBA, 0x6E, 0x1D, 0x7C, + 0xD5, 0xC7, 0x42, 0x31, 0xA3, 0x98, 0x08, 0xFE, + 0x13, 0xA2, 0xA6, 0x74, 0x4D, 0xF3, 0x20, 0x9E, + 0xEB, 0x83, 0x64, 0x27, 0xE4, 0x9C, 0x3C, 0x1F, + 0xC2, + + 0xF1, 0x24, 0xBC, 0xD3, 0x95, 0x66, 0x65, 0x69, + 0xA7, 0x6E, 0x61, 0x08, 0x9C, 0xBF, 0xC3, 0x9B, + 0x9B, 0x09, 0x05, 0x0B, 0x94, 0xB4, 0x64, 0xB2, + 0x0E, 0x0F, 0x19, 0x0C, 0x6D, 0x92, 0xF5, 0xC3, + 0xB8, 0x9B, 0xBF, 0x59, 0x00, 0x6D, 0x8D, 0x48, + 0xE0, 0xB1, 0x06, 0xC2, 0x3E, 0x33, 0x26, 0x24, + 0x6F, 0x53, 0xBE, 0x86, 0xD7, 0xEA, 0xCD, 0x18, + 0x18, 0x24, + + 0xE8, 0xE1, 0xC4, 0x50, 0xEF, 0xB6, 0xF0, 0xCA, + 0x78, 0xEF, 0x9C, 0x51, 0x61, 0x58, 0x18, 0xB7, + 0x90, 0x09, 0x48, 0x73, 0xA1, 0x13, 0x6D, 0x16, + 0x8D, 0x97, 0x84, 0x92, 0x25, 0x44, 0xBF, 0xF5, + 0x3C, 0x9D, 0xCE, 0x68, 0x7E, 0x4B, 0x0A, 0x49, + 0xE1, 0xAE, 0xA7, 0xB3, 0xC8, 0xE0, 0x7B, 0x54, + 0xF9, 0xAB, 0x22, 0x0A, 0x19, 0x4F, 0x86, 0x1F, + 0xB7, 0x0F, 0x3A, + + 0x23, 0xD4, 0x95, 0xC7, 0xF9, 0xB7, 0x17, 0x4B, + 0xE8, 0x10, 0xF9, 0xB4, 0xCA, 0x9F, 0xBA, 0xBE, + 0x66, 0xAA, 0x83, 0x98, 0x7D, 0x2B, 0xF4, 0x84, + 0x18, 0x13, 0xCE, 0xBE, 0x10, 0x7D, 0x1B, 0x76, + 0x89, 0xBC, 0x9C, 0xF4, 0xE6, 0x71, 0x62, 0xA7, + 0x39, 0x89, 0xEF, 0x0D, 0xE9, 0x63, 0xD9, 0xB1, + 0x96, 0x63, 0xAC, 0xBC, 0xC7, 0x85, 0x77, 0xE3, + 0xD4, 0x40, 0x41, 0x5C, + + 0x0F, 0x8F, 0x47, 0xF8, 0xEA, 0x17, 0x30, 0x7E, + 0x67, 0xE2, 0x69, 0xF5, 0x20, 0xD9, 0xE0, 0x87, + 0xAB, 0xF6, 0x70, 0xBE, 0xF1, 0x26, 0x25, 0x01, + 0x14, 0x69, 0xE8, 0x8E, 0xA9, 0x8E, 0xB2, 0xAE, + 0xA5, 0x2C, 0x5F, 0x9D, 0x0C, 0x50, 0xC6, 0x95, + 0xC1, 0xDE, 0xEC, 0x7D, 0xEA, 0x87, 0xCA, 0x02, + 0xD7, 0x3F, 0x5E, 0x8A, 0xB3, 0x3A, 0xDA, 0x6A, + 0x33, 0xAD, 0x06, 0xD4, 0x6D, + + 0xAB, 0x89, 0xF3, 0x78, 0x67, 0x63, 0xD5, 0xFC, + 0xF2, 0x19, 0xD5, 0x91, 0x5C, 0x10, 0x86, 0x9F, + 0xD2, 0xDC, 0x46, 0xD9, 0xC7, 0xAA, 0x4E, 0x44, + 0xFF, 0x79, 0x5B, 0x8A, 0xE3, 0x47, 0x92, 0x20, + 0xA8, 0xA3, 0x5C, 0x95, 0xEF, 0xD2, 0x21, 0x49, + 0x8C, 0x66, 0x0D, 0xCD, 0xD2, 0x1D, 0x11, 0x22, + 0x31, 0x62, 0x47, 0xC9, 0xD4, 0xC1, 0xBC, 0xB3, + 0x80, 0x84, 0xB4, 0x71, 0xC1, 0xAB, + + 0x85, 0x76, 0x7F, 0x0D, 0x73, 0xE2, 0x6C, 0xB5, + 0x98, 0x1F, 0x7E, 0x09, 0xFC, 0x2D, 0xD6, 0xA4, + 0xE7, 0x57, 0xDC, 0x14, 0xCB, 0xD9, 0x7D, 0x46, + 0xC9, 0x6E, 0xE7, 0x61, 0x0A, 0x5F, 0x3D, 0xAB, + 0x4D, 0x39, 0x77, 0x96, 0xF5, 0xB0, 0x0C, 0x53, + 0x21, 0xBB, 0xA2, 0xAC, 0xA9, 0xC6, 0x91, 0xB9, + 0xF8, 0x03, 0xE2, 0xDD, 0xEE, 0x3B, 0xB7, 0xEB, + 0xD8, 0xB7, 0xCE, 0xAC, 0x02, 0xA1, 0xA8, + + 0xAA, 0xBE, 0xDD, 0x59, 0x61, 0xF8, 0xD1, 0x11, + 0x7A, 0xC2, 0x81, 0x7E, 0x61, 0x58, 0xAF, 0xA2, + 0x67, 0xC1, 0xA2, 0x8F, 0xE1, 0xC7, 0x0D, 0x27, + 0x2B, 0x4A, 0x9A, 0x6A, 0x77, 0x68, 0xFD, 0x68, + 0x18, 0xF1, 0xDB, 0x55, 0xBA, 0xEC, 0x2A, 0x37, + 0x7F, 0xD2, 0x68, 0xA7, 0xEF, 0x31, 0x77, 0x97, + 0xDE, 0x6B, 0x56, 0xB1, 0x5E, 0xBE, 0xBD, 0x51, + 0x07, 0x3E, 0xD6, 0xD9, 0x01, 0x64, 0xB8, 0x65, + + 0x52, 0x67, 0x5D, 0x5E, 0x11, 0xDA, 0x06, 0xC2, + 0xA6, 0x8E, 0x41, 0xE4, 0x30, 0x59, 0x2F, 0x73, + 0x40, 0x03, 0x88, 0x85, 0xE6, 0x91, 0x29, 0xCB, + 0xA6, 0x68, 0x56, 0xCF, 0x05, 0xE4, 0xD7, 0xA2, + 0x46, 0xC6, 0xC1, 0x06, 0x50, 0x0E, 0x1F, 0xAA, + 0xC2, 0xB2, 0x6E, 0x2F, 0xB9, 0x1A, 0x9F, 0xC3, + 0xC0, 0xD8, 0xD7, 0xF6, 0xCD, 0xD8, 0x92, 0xFB, + 0x6A, 0x4F, 0xFA, 0x2D, 0x0E, 0x13, 0x01, 0xD8, + 0x9A, + + 0x6B, 0xA5, 0xF2, 0x8D, 0x73, 0x10, 0x6F, 0x06, + 0x2B, 0x8B, 0x10, 0x56, 0xF6, 0x5F, 0xC0, 0x94, + 0x1C, 0x70, 0xB3, 0xBE, 0xEE, 0x00, 0x4D, 0x50, + 0x94, 0x88, 0xC5, 0x51, 0x01, 0x8B, 0xE8, 0xA5, + 0xF8, 0x89, 0x0F, 0x97, 0x7F, 0x0C, 0x67, 0x6F, + 0xC7, 0x1F, 0x91, 0x20, 0xD7, 0x32, 0x9C, 0x63, + 0xFF, 0xE7, 0xB8, 0x63, 0x0F, 0xE1, 0xCE, 0xC7, + 0xEA, 0x82, 0x1D, 0x57, 0xEC, 0xB9, 0xF9, 0x05, + 0x8D, 0x94, + + 0xFE, 0x5B, 0xB2, 0x66, 0xD8, 0xDF, 0x19, 0x49, + 0x59, 0x8E, 0xBC, 0xC5, 0xC7, 0xD1, 0x6F, 0x0A, + 0x8A, 0x5B, 0x0C, 0xF4, 0xC2, 0x35, 0x62, 0x61, + 0x89, 0x2E, 0x43, 0x70, 0x7D, 0x5A, 0xE7, 0xF1, + 0x63, 0x92, 0xDD, 0xD4, 0xBD, 0x61, 0x93, 0x8C, + 0x21, 0x13, 0x96, 0xBA, 0xDB, 0x7A, 0x1B, 0x81, + 0x43, 0x6B, 0x3F, 0x2C, 0x2E, 0x6B, 0xB2, 0x49, + 0x2E, 0x28, 0xB2, 0x79, 0x52, 0x66, 0x89, 0x48, + 0xE7, 0x97, 0x44, + + 0x4C, 0xAD, 0x82, 0xE3, 0x09, 0xEA, 0x08, 0x73, + 0xF4, 0x16, 0x4D, 0x67, 0x33, 0x17, 0xB0, 0x47, + 0x16, 0xA2, 0xAF, 0x99, 0xFE, 0x5A, 0x45, 0x70, + 0x5C, 0xB2, 0xF2, 0x7A, 0x64, 0xC9, 0x65, 0xE3, + 0x07, 0xAD, 0x8D, 0x77, 0x3F, 0x10, 0x9E, 0xCE, + 0xC5, 0x63, 0xA2, 0x67, 0xE3, 0xFE, 0x48, 0xAC, + 0x9A, 0x8F, 0x9E, 0xB9, 0x63, 0xB2, 0x2B, 0x59, + 0xF1, 0x53, 0x18, 0x95, 0xA8, 0x12, 0x28, 0xAF, + 0xCF, 0x97, 0x9A, 0xC9, + + 0x5C, 0x23, 0xC9, 0xB0, 0x2F, 0x8E, 0x8B, 0x75, + 0xBC, 0xD3, 0x76, 0x22, 0xD0, 0x83, 0x85, 0x0A, + 0xA8, 0xC1, 0xF6, 0x06, 0xD5, 0x80, 0x59, 0xEB, + 0xF5, 0xD2, 0xBF, 0x35, 0x76, 0x64, 0xF6, 0x40, + 0x2B, 0xC4, 0x59, 0xA4, 0x8A, 0x21, 0x78, 0x77, + 0xBD, 0x4C, 0x2D, 0x11, 0x24, 0x31, 0x33, 0xF4, + 0x8D, 0x89, 0x61, 0xA4, 0xD9, 0x74, 0xEC, 0xEA, + 0xC9, 0x90, 0x9C, 0x79, 0x5D, 0x4B, 0x9E, 0x92, + 0xB5, 0x0D, 0x94, 0xE4, 0xCE, + + 0xAC, 0xE3, 0xD3, 0xD0, 0x7C, 0x51, 0x6F, 0xD7, + 0x73, 0xC9, 0x82, 0x6B, 0x9A, 0x6C, 0x8D, 0x56, + 0xB4, 0x17, 0xB7, 0xD8, 0xAD, 0x80, 0xA7, 0xFC, + 0xCA, 0xD5, 0x5B, 0x8E, 0x3A, 0xE3, 0x4B, 0x6B, + 0xFD, 0x75, 0x1B, 0xD1, 0xE5, 0xBA, 0x64, 0xD8, + 0xC4, 0x29, 0x83, 0xF8, 0x18, 0x98, 0xA2, 0x96, + 0x10, 0xB2, 0x3E, 0x60, 0x04, 0xE9, 0x9A, 0x68, + 0x2D, 0xFD, 0x41, 0x6A, 0xB7, 0xB4, 0xB8, 0x81, + 0x08, 0x54, 0x7A, 0xBF, 0xD1, 0x91, + + 0xA9, 0xB0, 0xF9, 0x25, 0x66, 0xC3, 0xF5, 0x4D, + 0x9A, 0x9A, 0x18, 0x15, 0x8E, 0x06, 0x8E, 0xC3, + 0x75, 0x7B, 0x99, 0xE2, 0x07, 0x49, 0x41, 0x19, + 0xA1, 0x7E, 0x3E, 0x13, 0xED, 0x3E, 0xB9, 0x66, + 0x89, 0x37, 0x37, 0xE3, 0xBC, 0xC4, 0xA7, 0xA5, + 0xB4, 0x5A, 0x57, 0x1B, 0xF7, 0xAD, 0x54, 0x13, + 0xF5, 0x4F, 0x80, 0x3F, 0xF9, 0x02, 0x89, 0xCA, + 0xFE, 0x2F, 0xE3, 0xC5, 0x63, 0xB6, 0x4D, 0x72, + 0x95, 0x25, 0x51, 0xFE, 0xD7, 0x4C, 0x7B, + + 0xB9, 0x14, 0xD1, 0xAD, 0x98, 0x4B, 0x37, 0x28, + 0x4B, 0x73, 0xFE, 0x28, 0x3F, 0x0B, 0x83, 0xC4, + 0xB6, 0xED, 0x8D, 0x4E, 0x25, 0x12, 0xB5, 0x41, + 0xB3, 0xAC, 0x2C, 0x2A, 0x8B, 0x5C, 0x3D, 0xE6, + 0x69, 0xE1, 0x99, 0x18, 0x31, 0x78, 0xCB, 0xAC, + 0xA8, 0xE7, 0x7F, 0x44, 0xFF, 0x87, 0xBB, 0x92, + 0xBD, 0x98, 0xEF, 0xD3, 0x86, 0x1B, 0xD3, 0xB5, + 0xB2, 0x78, 0x56, 0x1D, 0x7A, 0x0C, 0x4D, 0xC7, + 0x15, 0xA1, 0x68, 0x10, 0x85, 0x19, 0x39, 0x9A, + + 0x4B, 0x01, 0x86, 0x3D, 0x0D, 0xB2, 0x31, 0x1F, + 0xA1, 0xCA, 0x12, 0x0C, 0x59, 0x69, 0xEC, 0x14, + 0x62, 0xC9, 0x17, 0xC2, 0x61, 0xF1, 0x60, 0x2B, + 0x8C, 0x46, 0x80, 0x62, 0x9E, 0x7E, 0xE4, 0x21, + 0xC3, 0x3F, 0xF7, 0x4C, 0x31, 0xCE, 0x8B, 0x4C, + 0x87, 0x48, 0xD9, 0x60, 0x39, 0xFD, 0xFC, 0x12, + 0x15, 0x2F, 0x35, 0x74, 0x79, 0xEB, 0x87, 0x20, + 0x72, 0x23, 0xE6, 0x66, 0x5A, 0xD4, 0xFB, 0x72, + 0xA9, 0x6B, 0xDB, 0xB4, 0x30, 0xFD, 0x80, 0xF5, + 0xBB, + + 0xBC, 0xD6, 0x2A, 0xC2, 0x2E, 0x81, 0x71, 0xF7, + 0xF9, 0x29, 0x5B, 0xBB, 0x8C, 0x84, 0xB3, 0xB2, + 0x47, 0xF4, 0xBB, 0x9C, 0x82, 0xC0, 0x35, 0xA2, + 0xEA, 0xA7, 0x4E, 0xA5, 0x5E, 0xD5, 0x0D, 0xDF, + 0x89, 0x3E, 0xC1, 0x3F, 0x8B, 0x82, 0xE5, 0xEB, + 0x4D, 0x87, 0xD9, 0x73, 0xAC, 0x06, 0x8A, 0xB4, + 0xF3, 0x2C, 0x83, 0xCB, 0x08, 0xB5, 0xB2, 0x74, + 0x16, 0xD0, 0x97, 0x87, 0x53, 0x6C, 0x73, 0x7B, + 0x20, 0x0D, 0x18, 0x7F, 0x3A, 0xD6, 0x3D, 0xF0, + 0x9E, 0x00, + + 0xE9, 0x20, 0xCF, 0x62, 0x26, 0x4F, 0xA8, 0xA2, + 0x8C, 0xCC, 0x32, 0xDE, 0x6B, 0xA5, 0x44, 0xB7, + 0xD0, 0x25, 0x48, 0x4B, 0xB7, 0x10, 0x61, 0x3B, + 0x93, 0xFB, 0xFB, 0x57, 0x02, 0xBC, 0x02, 0xD2, + 0x8E, 0x33, 0x08, 0xBF, 0xA2, 0x02, 0xB4, 0xDF, + 0x86, 0x33, 0xCD, 0xCD, 0x7C, 0x3B, 0x8D, 0xDB, + 0x90, 0x3A, 0xF3, 0x55, 0x82, 0x73, 0x5F, 0x27, + 0x8D, 0xED, 0x06, 0x08, 0x18, 0x27, 0xAF, 0xF8, + 0x7B, 0x01, 0x4E, 0xB0, 0xF2, 0xE8, 0xD9, 0x73, + 0x43, 0x59, 0xB0, + + 0x92, 0x47, 0x3D, 0x62, 0x6D, 0x82, 0xB4, 0x89, + 0x35, 0xCB, 0x4A, 0x66, 0x24, 0xF1, 0x14, 0x40, + 0xA6, 0xAD, 0xE1, 0xD4, 0xC8, 0xFB, 0x08, 0x90, + 0xFC, 0x33, 0xA8, 0x2E, 0xCF, 0x38, 0x4C, 0x45, + 0xF8, 0x8D, 0x4B, 0x11, 0xF8, 0x7F, 0xD8, 0x4F, + 0x22, 0x2D, 0x7B, 0x38, 0x8C, 0x8F, 0xDF, 0x8B, + 0xF1, 0x4B, 0xCF, 0x46, 0xE5, 0xCC, 0x8D, 0x0A, + 0x7A, 0x0E, 0xF8, 0xDE, 0xCE, 0x10, 0xCA, 0xCD, + 0xA8, 0x30, 0x0A, 0x63, 0x0E, 0xA0, 0x32, 0x54, + 0x5C, 0x77, 0x49, 0xDC, + + 0xED, 0xA1, 0x20, 0xA9, 0x5E, 0x2A, 0xBC, 0xBC, + 0x1A, 0x8D, 0x48, 0x71, 0x4E, 0x3A, 0xFA, 0xEA, + 0x8F, 0x78, 0x3F, 0xA6, 0x61, 0x28, 0xC3, 0xC9, + 0x01, 0xCF, 0xD4, 0x2E, 0x36, 0x40, 0x90, 0xA8, + 0xCA, 0x45, 0x40, 0xFE, 0x9E, 0xB6, 0x40, 0x28, + 0xFB, 0x28, 0x3E, 0x07, 0xFC, 0xA1, 0x1A, 0x8D, + 0xA8, 0x5B, 0xB1, 0x1A, 0xE3, 0x18, 0xDC, 0xB3, + 0x19, 0x14, 0xF9, 0xB9, 0x9C, 0xF2, 0x15, 0xE2, + 0x70, 0xD5, 0x74, 0xFF, 0x1E, 0xED, 0x92, 0x0C, + 0xC9, 0xE7, 0x57, 0x55, 0x8B, + + 0xD5, 0x15, 0x63, 0x0A, 0x41, 0xF9, 0x2B, 0x15, + 0x55, 0x1E, 0x63, 0x96, 0xC3, 0xF0, 0x21, 0x90, + 0xFB, 0xB9, 0xC7, 0xFE, 0xEE, 0x15, 0x2C, 0x28, + 0xBB, 0x2C, 0x9D, 0x6F, 0x8E, 0xAB, 0x73, 0xD3, + 0x03, 0x39, 0xE9, 0xB4, 0xEC, 0xED, 0x48, 0x1F, + 0xDA, 0x87, 0x29, 0xA1, 0x4B, 0xD7, 0xC8, 0xCD, + 0xDB, 0xF0, 0xCF, 0x82, 0x54, 0x27, 0xBF, 0x20, + 0xF4, 0xD4, 0x52, 0xED, 0x64, 0xA2, 0x4A, 0x6D, + 0xC8, 0x78, 0x1E, 0x83, 0x03, 0xBA, 0x22, 0x9C, + 0xFC, 0xB1, 0xE0, 0x67, 0xC7, 0x23, + + 0x62, 0xB2, 0xA4, 0xD4, 0xCD, 0xAE, 0xD3, 0xF1, + 0xFB, 0x71, 0x5C, 0xDD, 0xD6, 0x51, 0x91, 0x9D, + 0x48, 0xBD, 0x3C, 0xF9, 0x0C, 0x05, 0xEB, 0xF8, + 0x55, 0x48, 0x03, 0xE6, 0x9C, 0x13, 0x9E, 0xB8, + 0x6B, 0xB5, 0x09, 0xB3, 0x89, 0x04, 0x96, 0xFD, + 0x1C, 0xE8, 0x0F, 0xC9, 0x19, 0x85, 0xE4, 0xCC, + 0xBB, 0xDB, 0xC3, 0x15, 0x69, 0xD9, 0xA1, 0x91, + 0x9B, 0x16, 0xE0, 0xD0, 0x74, 0x3F, 0xF4, 0x2D, + 0x33, 0x74, 0x02, 0x1D, 0xE3, 0xDB, 0xF8, 0xD3, + 0x33, 0xD9, 0x2F, 0x77, 0x94, 0x6B, 0x20, + + 0x86, 0x99, 0xFC, 0xEF, 0x12, 0x8E, 0x6E, 0x84, + 0x7A, 0x25, 0xD3, 0xB6, 0x37, 0xEE, 0x42, 0x0D, + 0x88, 0xE2, 0x53, 0xD7, 0x59, 0x4A, 0x73, 0x67, + 0xA6, 0x20, 0xA3, 0x91, 0x7C, 0x1F, 0xCA, 0x18, + 0xC9, 0xEF, 0xD1, 0xD0, 0xE0, 0xC7, 0x23, 0x14, + 0x03, 0x05, 0x7F, 0x84, 0xCD, 0xDB, 0xDB, 0x2D, + 0x31, 0x33, 0xBE, 0xD5, 0x1A, 0xDC, 0xC2, 0xBE, + 0x6C, 0x9B, 0x35, 0xFB, 0xAD, 0xC1, 0xDE, 0xDC, + 0xDC, 0xB9, 0xDE, 0xF5, 0x38, 0xCF, 0x06, 0x95, + 0x53, 0x24, 0x47, 0x9F, 0xB8, 0x41, 0x84, 0x9B, + + 0x13, 0x83, 0x54, 0x9F, 0x66, 0xE7, 0x40, 0x2D, + 0xD9, 0xB5, 0xB9, 0xAC, 0xB0, 0x08, 0x06, 0x54, + 0x50, 0x34, 0x07, 0x8A, 0x2E, 0x0B, 0xF2, 0x06, + 0x85, 0xF2, 0x8C, 0xC1, 0x24, 0x2D, 0x9F, 0x66, + 0x9A, 0x94, 0x93, 0x0E, 0xFA, 0x5E, 0xCC, 0x1D, + 0x74, 0xAE, 0x8F, 0xAA, 0x51, 0x0E, 0x7F, 0xD4, + 0x61, 0xA2, 0x29, 0xAB, 0xE9, 0x70, 0x8F, 0x99, + 0xFF, 0x11, 0x38, 0x84, 0x63, 0x6D, 0x91, 0xB8, + 0xF8, 0x08, 0x01, 0x08, 0x65, 0x39, 0xCF, 0x42, + 0x34, 0x29, 0x36, 0xDE, 0x29, 0xE9, 0x44, 0xFE, + 0x7E, + + 0x13, 0x26, 0xF8, 0xB2, 0xD9, 0x68, 0xE5, 0x81, + 0x20, 0xE6, 0xA3, 0xC8, 0x34, 0x43, 0x4D, 0xCE, + 0xA7, 0x87, 0x10, 0x98, 0x35, 0x91, 0x70, 0xF0, + 0x1D, 0xA4, 0xFB, 0x73, 0x00, 0x8E, 0x15, 0x49, + 0x14, 0xF8, 0xE8, 0x11, 0xA6, 0xBD, 0xEE, 0x7D, + 0x51, 0x49, 0x52, 0x5F, 0x0D, 0x63, 0x8D, 0x52, + 0x40, 0x4D, 0xF5, 0x40, 0x15, 0x04, 0x7C, 0xE2, + 0x23, 0xCE, 0x1F, 0x37, 0x15, 0x2C, 0xDF, 0x92, + 0xDC, 0xF7, 0xAB, 0xA5, 0x2B, 0xE8, 0x8C, 0xF9, + 0xF1, 0xBC, 0x42, 0x79, 0xE0, 0x6B, 0xBF, 0xEA, + 0x74, 0xBA, + + 0xB4, 0x5B, 0x74, 0xCE, 0x30, 0x5A, 0x8C, 0x7B, + 0xCE, 0x65, 0x3E, 0x64, 0xEE, 0x0D, 0xC8, 0x91, + 0x2E, 0x57, 0x6B, 0xE6, 0xD1, 0x95, 0xCC, 0x64, + 0xB6, 0x0E, 0x67, 0xD2, 0xB3, 0x52, 0x78, 0x18, + 0x1E, 0xE6, 0x49, 0x32, 0x61, 0x68, 0x94, 0x19, + 0x98, 0x54, 0xDB, 0x92, 0x8B, 0x9B, 0x4E, 0x75, + 0x93, 0x72, 0x59, 0x63, 0x8D, 0x3F, 0x2F, 0x9C, + 0x4D, 0xC6, 0x94, 0x60, 0xDD, 0xD9, 0xB3, 0xB4, + 0x04, 0xC0, 0xBC, 0x49, 0x94, 0x01, 0x61, 0x1B, + 0xF0, 0xB6, 0x94, 0xCF, 0x21, 0xE6, 0x96, 0x77, + 0xDF, 0xB9, 0x13, + + 0xB2, 0xEB, 0xE5, 0x13, 0x22, 0xCD, 0x5F, 0x6C, + 0x28, 0xB3, 0xCD, 0x37, 0x6A, 0xCC, 0xC8, 0x59, + 0xBC, 0x0A, 0x44, 0xC0, 0x53, 0xB7, 0xD9, 0x1F, + 0x6A, 0xD2, 0x7D, 0x34, 0xB8, 0x9F, 0xBF, 0xA7, + 0xF2, 0x87, 0x09, 0xF7, 0xE0, 0xDE, 0x43, 0x66, + 0xD8, 0xAF, 0x04, 0x03, 0x2A, 0x48, 0xBC, 0x70, + 0x49, 0x34, 0x05, 0x03, 0x85, 0xFC, 0x30, 0x78, + 0xE5, 0x2A, 0x30, 0x65, 0x95, 0x62, 0xD6, 0x0B, + 0x5C, 0xD6, 0x97, 0x4C, 0x65, 0x0A, 0x94, 0xB5, + 0x2E, 0xF7, 0x86, 0x30, 0x63, 0x4F, 0xA8, 0x72, + 0xAD, 0xF4, 0x19, 0xFB, + + 0x9B, 0x61, 0xE9, 0xE9, 0x8D, 0xB0, 0x02, 0x06, + 0x4D, 0x1C, 0x28, 0x5C, 0x65, 0x7E, 0x89, 0x02, + 0x47, 0x76, 0x1A, 0x1E, 0xEC, 0x64, 0xBA, 0x8D, + 0x59, 0xF0, 0xC5, 0xCE, 0x89, 0xCF, 0x11, 0x5E, + 0x3A, 0xBF, 0x8A, 0x32, 0x63, 0xFB, 0xD8, 0xC7, + 0x56, 0xA8, 0x6F, 0xF3, 0x2B, 0xC8, 0x5B, 0x8F, + 0xEC, 0x2C, 0x91, 0x35, 0x60, 0xE4, 0x84, 0x09, + 0x2F, 0x36, 0x8E, 0x4F, 0xFB, 0x06, 0xBD, 0x53, + 0xC4, 0x8A, 0x6B, 0x3B, 0xFA, 0x04, 0x50, 0x15, + 0x17, 0x63, 0x46, 0x9C, 0x54, 0xF6, 0xB6, 0xA9, + 0xEA, 0xE5, 0x60, 0x5E, 0x75, + + 0xC6, 0x4D, 0xA8, 0x7B, 0xC5, 0xC5, 0xDA, 0x2B, + 0xBB, 0x19, 0xA2, 0x36, 0xBE, 0x76, 0xA7, 0x34, + 0x92, 0xD4, 0xE2, 0xA5, 0xF3, 0xF1, 0xF8, 0xBE, + 0xA0, 0xA3, 0xB8, 0xE2, 0x3C, 0x39, 0x34, 0x84, + 0xE5, 0xF7, 0x48, 0xF3, 0xD1, 0x4F, 0x4E, 0xC2, + 0x4E, 0xB3, 0xC2, 0xBB, 0xE0, 0x1E, 0xAA, 0xBF, + 0x42, 0x62, 0x90, 0x4D, 0x62, 0xF5, 0x79, 0xE5, + 0x50, 0x25, 0x03, 0x37, 0x90, 0xAA, 0xF7, 0xFC, + 0xEB, 0xC0, 0x32, 0xDA, 0x1C, 0xD7, 0x1E, 0xA5, + 0x1C, 0x49, 0xF4, 0xE4, 0x94, 0x2D, 0x88, 0xA8, + 0x24, 0x7C, 0x0D, 0x1F, 0xB1, 0xA7, + + 0xE5, 0x1F, 0xCF, 0xE1, 0x7A, 0x7C, 0xF5, 0x66, + 0x6E, 0x92, 0x41, 0x68, 0x89, 0x5C, 0xD7, 0xB4, + 0x24, 0x06, 0xEE, 0x3D, 0x0D, 0xC7, 0xDF, 0xA9, + 0x48, 0x39, 0xCB, 0x8E, 0x79, 0xE9, 0xA8, 0x3D, + 0xB9, 0xFC, 0x97, 0xF1, 0x03, 0x06, 0xEB, 0xFB, + 0x14, 0x97, 0x96, 0xA1, 0xFB, 0x25, 0x12, 0x6D, + 0xA9, 0x2B, 0x0C, 0xC1, 0x27, 0x87, 0x4D, 0x17, + 0xDE, 0xEA, 0xD3, 0xEE, 0x3A, 0xA9, 0xD5, 0x80, + 0x52, 0x0E, 0xBB, 0x15, 0xA8, 0x16, 0x58, 0x25, + 0x7A, 0x6C, 0x55, 0x30, 0x80, 0xCE, 0x9B, 0x1E, + 0x97, 0x21, 0xD7, 0xEE, 0x5D, 0x4C, 0xE6, + + 0xEE, 0x3C, 0x03, 0x94, 0x28, 0xD8, 0xED, 0x96, + 0x2E, 0x67, 0x08, 0xEE, 0xDB, 0x31, 0xD9, 0x42, + 0x10, 0x51, 0x99, 0x56, 0x68, 0x60, 0xA6, 0x79, + 0x19, 0x7A, 0x54, 0xC3, 0xBD, 0x2A, 0x2D, 0x69, + 0xF1, 0xE2, 0xEF, 0xA7, 0x26, 0x3D, 0x9A, 0x6F, + 0x26, 0x8D, 0xE3, 0x0E, 0x3B, 0xFB, 0xCC, 0xFF, + 0x65, 0x09, 0xAD, 0x24, 0xEE, 0xA8, 0xD8, 0x55, + 0x83, 0xF5, 0xEA, 0x61, 0x07, 0x6F, 0x90, 0x54, + 0x3C, 0x1A, 0x8E, 0xB0, 0x89, 0x79, 0x8A, 0xA7, + 0x35, 0x05, 0x7B, 0xAF, 0xF0, 0xBC, 0x94, 0xB1, + 0x59, 0xF2, 0xB8, 0xAA, 0xC9, 0x92, 0x9B, 0x4A, + + 0xF6, 0xF8, 0x0F, 0x47, 0xEF, 0xEB, 0x09, 0xB2, + 0xB3, 0xC6, 0x0E, 0xE1, 0xA5, 0xA2, 0x62, 0x6D, + 0x44, 0x25, 0xEE, 0xEE, 0x35, 0xD0, 0x18, 0xBE, + 0x07, 0xC3, 0xAD, 0x9E, 0x8E, 0x93, 0xBB, 0x78, + 0xD7, 0x8F, 0x47, 0x6A, 0x27, 0x4C, 0x39, 0x18, + 0xD1, 0xC5, 0xA9, 0x9F, 0x31, 0x7F, 0x47, 0x6A, + 0x95, 0x35, 0x74, 0x6B, 0x1C, 0xD5, 0x33, 0x51, + 0x68, 0x58, 0x67, 0x89, 0xA8, 0x43, 0x9B, 0xE5, + 0xB4, 0x94, 0x5E, 0x62, 0xD5, 0x1C, 0xCB, 0x31, + 0x1E, 0x5C, 0xA8, 0x10, 0xA4, 0xC0, 0x62, 0xDE, + 0x19, 0xCC, 0x17, 0x09, 0x4A, 0x5B, 0x88, 0xC3, + 0xE4, + + 0xFB, 0xD9, 0x1D, 0x95, 0x93, 0x0F, 0xBA, 0xDB, + 0x70, 0x42, 0x47, 0x89, 0xB4, 0xF2, 0xCB, 0xF9, + 0x65, 0x5F, 0x8D, 0xC7, 0x44, 0x51, 0x39, 0x7F, + 0xCC, 0xD2, 0x8A, 0xA7, 0x14, 0xFE, 0xFC, 0x4A, + 0x36, 0x50, 0x6E, 0x18, 0xF9, 0xAF, 0x0E, 0xB5, + 0xEC, 0x1B, 0xCB, 0x66, 0xE0, 0x1A, 0x41, 0xC2, + 0xA8, 0x5F, 0x62, 0x35, 0xE5, 0x9C, 0xCB, 0x35, + 0x40, 0x51, 0x54, 0x25, 0xA6, 0xAB, 0x3D, 0x87, + 0x13, 0x58, 0x6C, 0x39, 0xEA, 0x09, 0xDE, 0xF4, + 0xD9, 0x8D, 0x55, 0xF3, 0xBF, 0x18, 0xDC, 0xD5, + 0x9E, 0xD2, 0xCE, 0x9D, 0x38, 0x99, 0x16, 0xB3, + 0x67, 0xAB, + + 0xFF, 0x15, 0x86, 0xD2, 0x9C, 0x6E, 0xBB, 0xC6, + 0x3F, 0xB4, 0x57, 0x9D, 0x0C, 0x84, 0xCF, 0xE3, + 0xAB, 0x55, 0xA6, 0x11, 0x6A, 0xBB, 0xB8, 0x3A, + 0x4C, 0x18, 0x53, 0x53, 0x54, 0xAE, 0x1F, 0x48, + 0x81, 0x98, 0x10, 0x13, 0x95, 0xE5, 0xF7, 0xC9, + 0x7A, 0xE5, 0x08, 0x3D, 0xD2, 0xE3, 0xE0, 0x63, + 0x08, 0x2C, 0x53, 0x35, 0x4A, 0xFA, 0xB1, 0x33, + 0x8C, 0xE7, 0x4B, 0xE7, 0x56, 0x9C, 0x97, 0x26, + 0xC8, 0xD7, 0x8F, 0x37, 0xF0, 0x8C, 0x69, 0x30, + 0x6C, 0x6B, 0xE9, 0x50, 0x03, 0xDC, 0xF3, 0x06, + 0x02, 0x6B, 0x73, 0x97, 0xF3, 0xC8, 0x51, 0x90, + 0x56, 0xEE, 0x6B, + + 0xD1, 0x92, 0x49, 0xBE, 0x13, 0xB9, 0x0D, 0xC3, + 0x94, 0x48, 0xF7, 0xAE, 0x8D, 0xB3, 0xCD, 0x40, + 0xBB, 0x01, 0x2F, 0x5E, 0x65, 0xBF, 0x15, 0xE7, + 0xC9, 0x23, 0xD8, 0x8A, 0x31, 0x92, 0xD4, 0x89, + 0x03, 0x92, 0x64, 0x77, 0xC4, 0x02, 0xA1, 0xC8, + 0x06, 0xA5, 0x46, 0xD8, 0x83, 0x19, 0x9B, 0x49, + 0x2C, 0x77, 0x14, 0x1C, 0x37, 0xEC, 0xBC, 0x16, + 0x16, 0x90, 0x38, 0x5D, 0x7B, 0x62, 0xC7, 0x5E, + 0xB9, 0x90, 0x4C, 0x86, 0xB1, 0x04, 0x3F, 0x9B, + 0x97, 0xFF, 0x96, 0x96, 0xF8, 0x8C, 0xED, 0x30, + 0x29, 0x97, 0xCE, 0x39, 0x08, 0xEA, 0xCE, 0xEC, + 0xE4, 0xD5, 0x97, 0x80, + + 0xED, 0x40, 0x76, 0x4D, 0x2A, 0x83, 0x9E, 0xB9, + 0x0E, 0xA6, 0x9B, 0xFF, 0x43, 0xD3, 0x57, 0x22, + 0xA1, 0xE5, 0x19, 0x44, 0x8A, 0x2C, 0x2B, 0xA5, + 0xE0, 0x58, 0x00, 0xEA, 0xDE, 0xD7, 0x77, 0x95, + 0x98, 0x02, 0x43, 0xC8, 0xAC, 0x9E, 0x10, 0x49, + 0xDD, 0xFC, 0x0D, 0x6B, 0x69, 0x0C, 0x5F, 0xA6, + 0xBC, 0x11, 0xCB, 0xB0, 0x40, 0x8C, 0xFD, 0xFD, + 0x28, 0xEF, 0xEB, 0xAC, 0x73, 0xCD, 0x15, 0x74, + 0x49, 0x08, 0x5F, 0xE5, 0xCA, 0x39, 0x3E, 0x07, + 0xAB, 0xF0, 0xE8, 0xC3, 0x6F, 0xEC, 0x41, 0x50, + 0x29, 0x5A, 0xF8, 0xD8, 0x95, 0x68, 0x77, 0xA9, + 0x31, 0x9A, 0x5E, 0xB7, 0xFD, + + 0x4E, 0xB1, 0x03, 0x95, 0xE6, 0x22, 0x49, 0x89, + 0xDE, 0x26, 0x73, 0x65, 0x0B, 0xE2, 0x85, 0xA1, + 0xC5, 0x15, 0x5B, 0x5F, 0x8D, 0xC8, 0xB3, 0x15, + 0xCB, 0x39, 0xD8, 0xD8, 0x12, 0xEF, 0x83, 0x89, + 0x02, 0x81, 0x5A, 0x36, 0xB4, 0xAF, 0xE0, 0xA4, + 0xE3, 0x1E, 0x72, 0xB6, 0x80, 0x1A, 0xCA, 0xB9, + 0xF8, 0x64, 0x80, 0x62, 0x55, 0xA3, 0x50, 0x6F, + 0xD0, 0x4C, 0x37, 0xFC, 0xFE, 0x8D, 0xC6, 0xFE, + 0xD9, 0x6A, 0x6A, 0x1E, 0x44, 0x35, 0xCF, 0x6A, + 0x1F, 0xDC, 0x86, 0x22, 0x74, 0x5D, 0xC9, 0x6A, + 0xFA, 0x32, 0x12, 0xB3, 0x12, 0x8A, 0x9D, 0x29, + 0x6A, 0xB0, 0x10, 0x73, 0xF3, 0xAF, + + 0xAF, 0x25, 0xCA, 0x2F, 0xCC, 0xAC, 0xEB, 0x64, + 0x67, 0xCA, 0x4A, 0xC6, 0xE6, 0x6C, 0x98, 0xC8, + 0xB9, 0x12, 0xCF, 0xCD, 0x56, 0xC1, 0x01, 0x32, + 0x36, 0xEB, 0xE5, 0x58, 0xAC, 0xEC, 0x2D, 0xA6, + 0xF9, 0x95, 0x84, 0xD9, 0x21, 0x13, 0x81, 0xE7, + 0x8B, 0x46, 0x34, 0x3E, 0x29, 0xD7, 0x02, 0xAE, + 0xC7, 0x45, 0x38, 0xC1, 0x69, 0x70, 0xE9, 0x38, + 0x2C, 0x9D, 0x0F, 0xE1, 0x32, 0x48, 0x74, 0x65, + 0x8A, 0x20, 0x50, 0x2A, 0x5C, 0xF9, 0x6F, 0xD7, + 0xAC, 0x8A, 0xFB, 0x63, 0x24, 0x09, 0x6F, 0x9F, + 0xC0, 0x19, 0xA9, 0x84, 0x53, 0x2E, 0x4F, 0x25, + 0x22, 0x19, 0x99, 0x6D, 0x63, 0xD6, 0x2F, + + 0x06, 0x07, 0xEB, 0x05, 0xA8, 0x83, 0xC7, 0xFC, + 0x5B, 0x09, 0xBF, 0x80, 0xC9, 0x86, 0x1C, 0x98, + 0xDD, 0x25, 0xE9, 0xDB, 0x66, 0xC5, 0x49, 0x4F, + 0xF0, 0x12, 0xD6, 0x73, 0x04, 0xD7, 0x1B, 0xC6, + 0xFF, 0xEB, 0xB7, 0x34, 0x09, 0x74, 0x96, 0xB4, + 0xDD, 0xB2, 0x52, 0x3E, 0xB2, 0xDC, 0x9D, 0x4D, + 0x12, 0x77, 0x7C, 0x5B, 0xB1, 0x2D, 0x18, 0x35, + 0xD0, 0xCF, 0x22, 0x40, 0x2B, 0xEF, 0x91, 0x28, + 0xDC, 0x4A, 0xF8, 0xB3, 0xAE, 0x22, 0x7B, 0x9D, + 0x1C, 0x92, 0x19, 0xD2, 0x3E, 0x7D, 0xAF, 0xD5, + 0x31, 0x95, 0xB0, 0x9A, 0x52, 0xD2, 0xFE, 0x3F, + 0x23, 0x37, 0x22, 0xF5, 0xC6, 0xC4, 0x41, 0xCC, + + 0x67, 0x3B, 0x8B, 0xB9, 0x68, 0x4C, 0x7A, 0x96, + 0xA1, 0xB1, 0x89, 0x79, 0x49, 0x24, 0xC4, 0x12, + 0x42, 0x1A, 0x78, 0x6F, 0xE2, 0x7F, 0xB4, 0x92, + 0xCD, 0xC0, 0xAD, 0xF5, 0x2D, 0x87, 0x6D, 0x22, + 0x18, 0xFC, 0xCE, 0x69, 0xAA, 0xD8, 0x01, 0x2D, + 0x49, 0x64, 0x3C, 0x24, 0xEE, 0xFF, 0xCA, 0x32, + 0x34, 0xF5, 0x09, 0x5E, 0x90, 0x50, 0x35, 0xEB, + 0xB8, 0x2D, 0x16, 0x10, 0xAD, 0x38, 0x30, 0x3D, + 0x97, 0x07, 0xD0, 0x99, 0xCF, 0xF0, 0xA8, 0xBB, + 0x21, 0xB0, 0x54, 0xCB, 0x56, 0xC6, 0x72, 0x96, + 0x22, 0x58, 0x9A, 0x10, 0xAE, 0xA5, 0xD5, 0x52, + 0x0F, 0xB6, 0x3C, 0xF3, 0x16, 0x59, 0x3F, 0x46, + 0x56, + + 0xC3, 0xFC, 0x2F, 0xDE, 0xBC, 0xC5, 0xF4, 0xB3, + 0x17, 0x21, 0x88, 0xF7, 0xAB, 0x80, 0x06, 0x7A, + 0x36, 0x20, 0x97, 0x8A, 0x71, 0x16, 0xB9, 0x38, + 0xCF, 0x0E, 0x91, 0xC2, 0x4E, 0x38, 0x99, 0xC8, + 0x5B, 0xAA, 0xC0, 0xFC, 0xD4, 0x48, 0x85, 0x3F, + 0x41, 0xF0, 0x0A, 0x17, 0x2E, 0x32, 0xD3, 0xD4, + 0xF4, 0x43, 0xDE, 0x00, 0x0D, 0xE0, 0xA5, 0x81, + 0x2B, 0xB9, 0xF3, 0x9D, 0xE4, 0xA9, 0x29, 0xF1, + 0x25, 0x1F, 0x44, 0x7C, 0xBC, 0x84, 0xEA, 0xA1, + 0x39, 0xA3, 0x2F, 0x16, 0x7B, 0xEB, 0x47, 0xF6, + 0x33, 0x53, 0xD4, 0x4D, 0xFE, 0x63, 0x72, 0x4E, + 0x32, 0x72, 0x87, 0x1A, 0xA8, 0x94, 0x56, 0x7B, + 0xC0, 0x6E, + + 0xB9, 0x69, 0x4D, 0x32, 0x87, 0xD6, 0xC6, 0x8B, + 0xEC, 0xA1, 0xDF, 0xF8, 0x58, 0xB4, 0xCD, 0xCE, + 0x1E, 0xC5, 0x37, 0x4E, 0x9B, 0x77, 0x8F, 0x8A, + 0xEB, 0x89, 0x03, 0x4A, 0xA0, 0x0F, 0x51, 0x3C, + 0x6C, 0x1B, 0x14, 0x7D, 0x0D, 0x1D, 0xBF, 0xA1, + 0x8D, 0x59, 0x48, 0xA7, 0x95, 0x24, 0xED, 0x09, + 0x8D, 0xDF, 0x89, 0xCA, 0x80, 0xB7, 0x2D, 0x0D, + 0x71, 0xC7, 0x73, 0xFA, 0xB0, 0xFE, 0x70, 0xCE, + 0xEA, 0xA2, 0x53, 0x23, 0x07, 0x41, 0x5B, 0x75, + 0x44, 0x93, 0x0A, 0x36, 0xB3, 0x5A, 0x6C, 0xBD, + 0xDA, 0x66, 0x43, 0x55, 0x3C, 0x87, 0xC2, 0x8E, + 0x51, 0xA3, 0x28, 0xFB, 0xFB, 0x5F, 0x8E, 0x82, + 0xA9, 0x60, 0x5D, + + 0x7E, 0x26, 0x4B, 0x2B, 0x10, 0x93, 0x82, 0xAC, + 0x0B, 0x01, 0x88, 0x29, 0x90, 0x43, 0xA7, 0xAE, + 0xC5, 0xDE, 0xC6, 0xAB, 0x67, 0x49, 0x45, 0x6B, + 0x30, 0x5F, 0x87, 0x59, 0x4D, 0xB2, 0xE0, 0x8B, + 0xEC, 0x9F, 0x9D, 0xB6, 0x5E, 0x1A, 0xA8, 0xE8, + 0xB2, 0xF5, 0xC4, 0xDB, 0xC1, 0x39, 0xC6, 0xF4, + 0x85, 0xE8, 0x59, 0x19, 0xE8, 0xE8, 0xAA, 0xE6, + 0xA7, 0xE1, 0x66, 0x1B, 0x9A, 0xE3, 0x7C, 0xCE, + 0x5A, 0x7A, 0x3B, 0x32, 0x38, 0x89, 0x60, 0x6B, + 0xB8, 0xD9, 0xA1, 0xE2, 0x33, 0x62, 0xDA, 0xED, + 0xC0, 0xAF, 0x10, 0x23, 0xCA, 0xD5, 0x18, 0x5F, + 0x4F, 0xAC, 0x07, 0x02, 0x5D, 0x62, 0x4B, 0xCF, + 0x89, 0x5D, 0xB6, 0x8F, + + 0x4F, 0xB9, 0xC8, 0xBB, 0x61, 0x38, 0x62, 0xC0, + 0x7E, 0xDA, 0xBB, 0x97, 0x1F, 0x14, 0x93, 0x3D, + 0x56, 0x14, 0x06, 0xA0, 0xDA, 0xA6, 0x2F, 0x8D, + 0x61, 0xC6, 0xD3, 0x70, 0x2A, 0xF2, 0xEF, 0xD6, + 0x97, 0x81, 0x1B, 0x18, 0xCB, 0x5D, 0x3F, 0xC0, + 0xAB, 0xF1, 0xE8, 0x16, 0x59, 0xA3, 0x9E, 0xDC, + 0x59, 0x0D, 0x5D, 0x1C, 0x51, 0x81, 0xF6, 0x1A, + 0x12, 0x0C, 0xF7, 0xE3, 0xF0, 0x6E, 0x8D, 0x89, + 0x8D, 0xED, 0x1F, 0xE7, 0x4E, 0xE9, 0xB0, 0x9A, + 0x04, 0xB2, 0x9F, 0xB5, 0x05, 0xBB, 0xE2, 0x70, + 0x4F, 0x9F, 0x86, 0x03, 0x86, 0x9C, 0xE9, 0x63, + 0x8B, 0xA5, 0x8B, 0xFC, 0xD3, 0xF4, 0x24, 0xE1, + 0xE2, 0x46, 0xEB, 0x77, 0x2C, + + 0xD3, 0xE2, 0xB1, 0xBF, 0xE6, 0x28, 0xA2, 0x19, + 0x09, 0x7C, 0xE5, 0xDE, 0x6C, 0x07, 0x79, 0x55, + 0x36, 0xD2, 0x39, 0x8B, 0x1C, 0x1E, 0xBB, 0x67, + 0xF6, 0xE9, 0xA5, 0xD6, 0xCE, 0x83, 0x47, 0xFC, + 0x2D, 0x5D, 0xF3, 0x9D, 0xA8, 0x98, 0x78, 0x2B, + 0x2A, 0x4B, 0x1C, 0xC8, 0x7F, 0x45, 0x3F, 0x58, + 0x01, 0x35, 0xE4, 0x5C, 0xF8, 0xEE, 0x27, 0xC6, + 0x53, 0x88, 0x4B, 0x96, 0xDA, 0xBF, 0x57, 0x37, + 0x45, 0x2F, 0x4B, 0xDC, 0x57, 0x74, 0xD9, 0x69, + 0x15, 0x94, 0x60, 0x45, 0x72, 0xFA, 0x52, 0x05, + 0x2B, 0xA5, 0xF2, 0x85, 0x6F, 0x3C, 0xF6, 0xF1, + 0xF8, 0x4A, 0xAF, 0xF4, 0xC3, 0x0D, 0x6A, 0x8C, + 0xF3, 0xBC, 0x6A, 0x07, 0x02, 0x15, + + 0xBE, 0x63, 0x59, 0xA9, 0x6D, 0x8D, 0x63, 0xB4, + 0x80, 0xB1, 0xEA, 0xCD, 0x8B, 0xB3, 0x98, 0x8A, + 0x63, 0xF3, 0x0C, 0xD6, 0x93, 0xC0, 0x9E, 0x88, + 0x33, 0x19, 0x0F, 0xC0, 0xF0, 0xFE, 0xCC, 0x33, + 0xC7, 0xC5, 0xF0, 0xD6, 0x73, 0x6D, 0x57, 0xA4, + 0x4C, 0x49, 0x20, 0x10, 0x99, 0x68, 0x73, 0x99, + 0x38, 0xE9, 0x25, 0x11, 0x8B, 0xE1, 0xC8, 0x90, + 0x13, 0x6A, 0x96, 0x0F, 0x82, 0x23, 0xFD, 0x5E, + 0x71, 0x8D, 0x6E, 0xA4, 0x37, 0x7C, 0x35, 0xC6, + 0x37, 0xD3, 0xC8, 0xBE, 0x4B, 0x59, 0x94, 0xE2, + 0x5C, 0x70, 0xEB, 0x62, 0xC5, 0xF1, 0x7E, 0x63, + 0x02, 0xCE, 0xE4, 0x07, 0x38, 0x2E, 0x8F, 0x63, + 0x8D, 0xAC, 0xBB, 0x93, 0xAB, 0x8D, 0x71, + + 0x52, 0xBD, 0xA1, 0x06, 0x3C, 0x94, 0x40, 0x14, + 0x24, 0x66, 0x94, 0x84, 0x7F, 0x92, 0x07, 0x8C, + 0x02, 0xB4, 0x9A, 0x9D, 0x77, 0x91, 0xDC, 0xEC, + 0x69, 0xC6, 0x9F, 0xD5, 0x89, 0xDE, 0x3A, 0x55, + 0xF1, 0x8C, 0x2D, 0xAD, 0xBE, 0x56, 0x1B, 0x88, + 0x4D, 0xE1, 0x88, 0x8A, 0xEF, 0xFB, 0x2B, 0x1A, + 0xE0, 0xEF, 0xF3, 0x79, 0xED, 0x25, 0x23, 0xF3, + 0xAA, 0x1B, 0xE1, 0xF6, 0xB3, 0x0E, 0xC4, 0xA7, + 0x02, 0xBB, 0xCC, 0x25, 0x08, 0x67, 0x75, 0x23, + 0xE6, 0x0D, 0x5E, 0x4E, 0xE9, 0x00, 0xB3, 0xA8, + 0x7F, 0xB3, 0x42, 0x08, 0x7B, 0x36, 0xC8, 0x4A, + 0x67, 0xCA, 0xC3, 0x8E, 0xEC, 0x62, 0xB3, 0xA1, + 0x2E, 0x8A, 0xB6, 0x60, 0xE0, 0xD6, 0x38, 0xA9, + + 0x9E, 0x06, 0x4A, 0xB5, 0x71, 0xD7, 0x33, 0x84, + 0x95, 0x9C, 0x5F, 0xF8, 0x12, 0x0D, 0x46, 0xFA, + 0xE5, 0x67, 0x31, 0xE2, 0x71, 0xDC, 0xB6, 0xB4, + 0xE1, 0x3B, 0x16, 0x28, 0xE5, 0x04, 0x20, 0x90, + 0xC1, 0x70, 0xB3, 0x1C, 0x93, 0xF6, 0x6E, 0xC8, + 0x42, 0x8A, 0xAC, 0x85, 0x67, 0xB5, 0xAE, 0x74, + 0x78, 0xFA, 0x32, 0x4B, 0x0D, 0x74, 0x3B, 0x38, + 0xF9, 0x31, 0x01, 0xDA, 0x65, 0xE1, 0xBA, 0x5B, + 0x47, 0xE5, 0xCE, 0x58, 0xC6, 0x16, 0x6D, 0xC2, + 0x56, 0xB7, 0x9B, 0x43, 0x0B, 0x81, 0x65, 0xDD, + 0xF5, 0xB9, 0x44, 0x93, 0x06, 0xD6, 0x07, 0x8B, + 0xDF, 0xE7, 0x1F, 0x14, 0xD6, 0x04, 0x4F, 0xFD, + 0x47, 0x67, 0xEB, 0xBF, 0x23, 0xEB, 0xA7, 0xEE, + 0xB0, + + 0x31, 0xCF, 0x75, 0x5F, 0xFF, 0xBD, 0xB1, 0xE7, + 0x04, 0xBF, 0x32, 0x3F, 0x80, 0x8C, 0x1A, 0xCF, + 0x78, 0xF2, 0x95, 0x2B, 0x4B, 0xEF, 0x30, 0xDF, + 0xE4, 0x49, 0x04, 0xF3, 0x82, 0x11, 0x30, 0x6B, + 0x30, 0x3C, 0xAA, 0x9B, 0x1F, 0xDB, 0xFA, 0xDA, + 0xC3, 0x79, 0x88, 0x1F, 0x4C, 0x06, 0x7E, 0xE5, + 0x89, 0x04, 0x78, 0x7C, 0x0B, 0xA0, 0x2D, 0x50, + 0x88, 0xD4, 0xA8, 0x3C, 0x4D, 0x9F, 0x85, 0x9E, + 0x6A, 0x0C, 0xC6, 0x75, 0xE5, 0x02, 0x19, 0x64, + 0xA6, 0x64, 0x21, 0x76, 0x2F, 0x2E, 0xBC, 0xDA, + 0xF0, 0xDD, 0x19, 0xCE, 0xB1, 0xB6, 0x35, 0x3F, + 0x6B, 0x3F, 0xCF, 0xFD, 0x71, 0x2E, 0x0C, 0x4B, + 0x8B, 0x4D, 0x26, 0xDA, 0x06, 0x46, 0xE3, 0x68, + 0xBA, 0x22, + + 0xA3, 0x90, 0x81, 0xE3, 0xBA, 0x9C, 0x12, 0x57, + 0xE3, 0x53, 0x6E, 0x90, 0x2F, 0xD4, 0x6B, 0x23, + 0x58, 0xCD, 0x1C, 0xBD, 0x6F, 0x8B, 0x16, 0x0C, + 0x40, 0x41, 0x47, 0x86, 0xA4, 0xA2, 0x90, 0x6C, + 0x81, 0x8B, 0x51, 0x53, 0xC8, 0x9A, 0xF4, 0x4F, + 0x04, 0xB0, 0xF3, 0xE2, 0xDE, 0x73, 0x17, 0x3B, + 0xB3, 0xDB, 0x61, 0xFB, 0xBD, 0xC8, 0xBB, 0x13, + 0x8A, 0xE9, 0xB0, 0x5D, 0x38, 0x5F, 0x3F, 0x7A, + 0xDC, 0xB2, 0x25, 0xB7, 0x0B, 0xBD, 0xC6, 0xD6, + 0x8F, 0x15, 0xD5, 0x17, 0x2E, 0x84, 0xD0, 0xA6, + 0xA8, 0x72, 0xEA, 0x2D, 0x2C, 0xE9, 0x31, 0x8D, + 0x22, 0x6B, 0x0F, 0xD8, 0x36, 0x70, 0x3C, 0x11, + 0xBE, 0x32, 0x2D, 0xB1, 0x14, 0xCD, 0x90, 0x18, + 0x99, 0xCA, 0x01, + + 0xA9, 0x3C, 0xC6, 0x55, 0x5C, 0xA3, 0x2C, 0x02, + 0x51, 0xB8, 0x98, 0xF0, 0xDE, 0xF3, 0x51, 0x7A, + 0x1F, 0x6C, 0xA1, 0xCD, 0x15, 0xCB, 0x3B, 0x3A, + 0x7E, 0xD5, 0x3E, 0xF0, 0xD5, 0xE4, 0x6F, 0x30, + 0x3C, 0x1F, 0x92, 0x65, 0xEE, 0x40, 0xAC, 0x8F, + 0x8A, 0xA5, 0x5D, 0x26, 0x38, 0xCE, 0x02, 0xDE, + 0xA4, 0xF6, 0xC1, 0xB5, 0x53, 0x7B, 0x37, 0x40, + 0x38, 0xC6, 0x31, 0x9B, 0x3F, 0x72, 0x0D, 0x91, + 0x46, 0xD9, 0xE3, 0x17, 0xAD, 0x07, 0x1D, 0xDE, + 0x69, 0xF9, 0xBD, 0x72, 0x1E, 0x4E, 0x68, 0x4E, + 0x16, 0x48, 0xAD, 0xEA, 0x9C, 0x18, 0x70, 0xDF, + 0x7E, 0x38, 0x4F, 0x68, 0xC5, 0xE2, 0xA1, 0x09, + 0x5E, 0x5F, 0x42, 0x75, 0x66, 0x20, 0xE6, 0xE3, + 0x1F, 0xAC, 0x76, 0x6D, + + 0xCE, 0x61, 0xD7, 0xE9, 0x85, 0xCF, 0xEF, 0xDC, + 0x2D, 0x75, 0x04, 0x60, 0x76, 0xF1, 0x4E, 0xE9, + 0x72, 0xD3, 0x2E, 0x6A, 0x5A, 0x81, 0xB0, 0xAF, + 0x29, 0x05, 0xAF, 0x9C, 0xEF, 0xF1, 0xF3, 0x96, + 0x97, 0x10, 0xCA, 0x15, 0xA9, 0x73, 0x44, 0xFC, + 0x61, 0x0D, 0x2E, 0xE5, 0x1A, 0x3B, 0x24, 0x5E, + 0x04, 0xAE, 0x5B, 0xCA, 0x40, 0xEC, 0x4B, 0x92, + 0xD8, 0x7C, 0x3F, 0x0B, 0x69, 0x9B, 0x3C, 0xC4, + 0x9E, 0x80, 0x3C, 0x2B, 0xB1, 0x39, 0xFB, 0xC6, + 0x8A, 0x65, 0x98, 0x1A, 0x53, 0xE1, 0x31, 0x90, + 0xE6, 0x26, 0x43, 0x73, 0x07, 0xAD, 0x80, 0xD9, + 0x4C, 0xC0, 0x0E, 0x5F, 0xE7, 0x6D, 0x0B, 0xEB, + 0xD1, 0x16, 0x0A, 0x57, 0xFB, 0x49, 0xF5, 0xA0, + 0x96, 0x6E, 0x9A, 0xB0, 0x82, + + 0xC7, 0x84, 0x16, 0x76, 0x54, 0xAE, 0x96, 0x80, + 0x66, 0x9E, 0xCF, 0xB2, 0x49, 0x57, 0x8B, 0x32, + 0xDA, 0x1C, 0xCD, 0xD1, 0xA7, 0x44, 0x52, 0x19, + 0x5A, 0x77, 0x8D, 0x9D, 0x89, 0xC4, 0x84, 0xD0, + 0x2D, 0xFB, 0x8D, 0xB5, 0xCD, 0x63, 0x48, 0x6E, + 0x18, 0x49, 0x1B, 0xFA, 0x48, 0xD5, 0x32, 0xBB, + 0x85, 0x0A, 0x90, 0xBC, 0x6C, 0xAF, 0x5D, 0x6F, + 0xAC, 0x34, 0xF9, 0xC6, 0x59, 0x85, 0xE8, 0xC2, + 0xA2, 0xA4, 0x9F, 0x77, 0xE4, 0x00, 0xEE, 0x94, + 0xD9, 0x57, 0xEC, 0x31, 0x7E, 0x0F, 0xB1, 0xD2, + 0xD5, 0xA5, 0x1A, 0xBE, 0x0C, 0xC2, 0x85, 0x7B, + 0x5E, 0xCD, 0xD0, 0xB6, 0x1E, 0x04, 0x86, 0xEF, + 0x84, 0x74, 0x6B, 0x97, 0x5D, 0x6B, 0x5C, 0x63, + 0x81, 0x50, 0x6F, 0x4F, 0x8E, 0x1B, + + 0xC7, 0x9C, 0x57, 0x9D, 0xE5, 0x46, 0x4F, 0xC1, + 0x4A, 0x03, 0x63, 0x2E, 0x35, 0x1B, 0x35, 0x9D, + 0xD3, 0xA7, 0xB5, 0xDC, 0xCD, 0x58, 0xEB, 0x25, + 0x52, 0x9E, 0xC0, 0xB3, 0x19, 0x85, 0x11, 0x65, + 0x14, 0x8A, 0x27, 0x0F, 0xDD, 0xB5, 0x06, 0xCE, + 0x9A, 0x1A, 0xD8, 0xB5, 0x07, 0x63, 0x24, 0x5F, + 0xD2, 0xBC, 0x79, 0xB8, 0x62, 0x45, 0x10, 0xBC, + 0x65, 0x00, 0x22, 0x94, 0x83, 0x60, 0x62, 0xF3, + 0x13, 0xE1, 0xD0, 0x5D, 0x47, 0xD8, 0xCB, 0x2C, + 0x59, 0x60, 0x9D, 0x8F, 0x9A, 0x49, 0x7F, 0x60, + 0x71, 0x85, 0xA5, 0x53, 0xCE, 0x55, 0x72, 0x30, + 0x89, 0xD6, 0x74, 0x5B, 0xEE, 0xAF, 0x48, 0x60, + 0x1C, 0x0A, 0xD0, 0x56, 0x54, 0xC5, 0x40, 0x1B, + 0x1F, 0x94, 0xAE, 0x5E, 0x45, 0x60, 0x59, + + 0xD1, 0x73, 0xAA, 0xD6, 0x76, 0x3F, 0x35, 0xDE, + 0x77, 0x82, 0x96, 0xFF, 0x1B, 0x34, 0xAD, 0x16, + 0x77, 0x73, 0xD7, 0x8A, 0x96, 0x19, 0xA0, 0xBA, + 0x22, 0x71, 0x36, 0x9D, 0xAC, 0x41, 0x14, 0xAB, + 0xA8, 0x77, 0x34, 0x7A, 0x70, 0x2A, 0xF6, 0xF6, + 0xEA, 0xFD, 0x6D, 0xDB, 0xAD, 0x65, 0x14, 0x3A, + 0xEA, 0x0E, 0x2C, 0xC4, 0xC1, 0x13, 0x7D, 0x59, + 0x8D, 0xE8, 0x61, 0x29, 0x50, 0x61, 0xC3, 0xC9, + 0x76, 0x20, 0x7C, 0xEF, 0x09, 0xA8, 0xC3, 0x8E, + 0x11, 0xD2, 0x3F, 0x32, 0x09, 0x61, 0x91, 0xF8, + 0x60, 0xF6, 0x83, 0x93, 0x08, 0x94, 0xBF, 0x5D, + 0x6E, 0xDE, 0xA1, 0x04, 0xEE, 0xB2, 0xE3, 0x10, + 0x1D, 0x22, 0xF0, 0xF8, 0x4E, 0x5C, 0xF5, 0x9B, + 0x86, 0x44, 0x57, 0x28, 0xB7, 0x8C, 0x81, 0x14, + + 0x31, 0xDF, 0xA5, 0xD5, 0xF6, 0x17, 0x19, 0x50, + 0xA3, 0x0F, 0x26, 0x1C, 0xD4, 0x98, 0xCA, 0xB0, + 0xDB, 0x0C, 0x2F, 0x8C, 0xCE, 0xCC, 0x56, 0x35, + 0x57, 0xC2, 0x9D, 0xEF, 0x64, 0x82, 0xE4, 0x8A, + 0xFA, 0xFE, 0x07, 0xF1, 0xB7, 0x10, 0xDF, 0x56, + 0x7B, 0x64, 0x88, 0x9C, 0x25, 0xF1, 0x6D, 0x6C, + 0x5F, 0xD3, 0xC8, 0xC4, 0x7E, 0xD5, 0x26, 0xB8, + 0xC3, 0xDD, 0xAD, 0x85, 0x3E, 0xA0, 0x5C, 0x33, + 0x25, 0x9A, 0xD9, 0x52, 0xB7, 0x8C, 0x22, 0x3F, + 0x96, 0xD4, 0x51, 0x7C, 0x9F, 0xAD, 0x01, 0x81, + 0xBE, 0x95, 0x90, 0x38, 0x90, 0xDD, 0x81, 0x43, + 0xB0, 0x66, 0x0D, 0x4E, 0x9E, 0xF6, 0x0C, 0x13, + 0x47, 0xA5, 0xA0, 0x1F, 0x94, 0xFB, 0x86, 0x42, + 0x8B, 0x9B, 0x22, 0x25, 0xF2, 0xB8, 0x83, 0x3C, + 0x87, + + 0x06, 0xFA, 0x95, 0x25, 0x62, 0x35, 0x4D, 0x06, + 0x3F, 0xD2, 0xAE, 0x4E, 0x86, 0x32, 0x08, 0x54, + 0x78, 0x35, 0xAD, 0x84, 0xE1, 0x6D, 0xB1, 0x5E, + 0xD0, 0x91, 0x42, 0x02, 0x39, 0x1F, 0x0D, 0x4C, + 0xE5, 0x4B, 0xDB, 0x9D, 0x1A, 0xE5, 0x05, 0x97, + 0x90, 0x0F, 0xB4, 0xCD, 0xC5, 0xF7, 0xDA, 0x81, + 0xC7, 0x22, 0x25, 0xB8, 0xAA, 0xC5, 0xA6, 0x6C, + 0xCD, 0x21, 0xC3, 0xCA, 0xFA, 0xDB, 0x0C, 0xDC, + 0x35, 0x7B, 0x49, 0x2E, 0xC9, 0xD4, 0xDC, 0x2C, + 0xF5, 0x2A, 0x3E, 0xBA, 0x93, 0x52, 0x88, 0x73, + 0x4B, 0x3A, 0x1E, 0x5B, 0x37, 0xE4, 0x54, 0x8E, + 0xE7, 0x3C, 0x78, 0x37, 0xBA, 0x31, 0x09, 0x3A, + 0xE0, 0x36, 0xFF, 0x6C, 0x7D, 0xA9, 0x68, 0x0F, + 0x33, 0xCD, 0x1B, 0x7E, 0xD0, 0x12, 0x98, 0xC7, + 0xC6, 0x9E, + + 0x59, 0xBC, 0xD3, 0x93, 0xD5, 0x73, 0x5C, 0x4F, + 0xCD, 0x32, 0x8C, 0xA7, 0xEC, 0xB1, 0x92, 0x82, + 0xFF, 0x08, 0x94, 0xED, 0xCE, 0x65, 0x7E, 0xDD, + 0x28, 0x65, 0xEA, 0xDB, 0x3B, 0x77, 0x87, 0x41, + 0x5A, 0xE7, 0xE4, 0x4F, 0x5D, 0xC6, 0x8E, 0xB7, + 0xD5, 0x83, 0x5A, 0xA4, 0x1B, 0xE5, 0x40, 0x50, + 0xA1, 0x0E, 0xB3, 0x8F, 0xE3, 0x31, 0x87, 0xD8, + 0xBF, 0xD9, 0xBE, 0x07, 0x68, 0x9F, 0xAF, 0xD5, + 0x5A, 0xB3, 0xEB, 0x4B, 0x59, 0x0E, 0xDA, 0x36, + 0xE8, 0xCE, 0x29, 0x5A, 0x9D, 0x68, 0xF7, 0x40, + 0xAD, 0xD4, 0x4C, 0xEC, 0xD3, 0xB1, 0xF8, 0x13, + 0x5B, 0x4B, 0x9A, 0xE9, 0x7A, 0x19, 0x37, 0x21, + 0x35, 0x2F, 0x01, 0xE3, 0xF0, 0x7E, 0xF4, 0x80, + 0x3E, 0xBF, 0xB0, 0xDB, 0xB8, 0x5B, 0x46, 0xBF, + 0x81, 0xB2, 0x6D, + + 0xE6, 0x27, 0x7B, 0xD7, 0x3A, 0x57, 0x4A, 0x57, + 0x1F, 0x16, 0x60, 0x67, 0xE3, 0xCB, 0x95, 0x54, + 0x52, 0x0F, 0xD3, 0xF8, 0x2E, 0x4E, 0xFE, 0xAC, + 0x98, 0x99, 0x14, 0x6E, 0x24, 0x91, 0x5A, 0x2C, + 0xA1, 0xDE, 0x40, 0xBB, 0x2E, 0x59, 0x23, 0x98, + 0xCE, 0x15, 0x9A, 0xDC, 0x0D, 0x1B, 0xB2, 0xC4, + 0x6C, 0xC3, 0x23, 0xBE, 0xCB, 0xF3, 0xF6, 0x67, + 0xCF, 0x10, 0x5B, 0x90, 0xEE, 0xAC, 0x62, 0x54, + 0xCA, 0x9C, 0xD4, 0xD4, 0x83, 0x41, 0x1B, 0x46, + 0xD8, 0x42, 0x0B, 0x01, 0x7B, 0xC2, 0x1B, 0xD0, + 0x6A, 0x55, 0x1D, 0x2F, 0x2D, 0xF3, 0x63, 0xCD, + 0xAC, 0xCB, 0x30, 0xF0, 0x95, 0x7C, 0x9E, 0x37, + 0xA8, 0x37, 0x42, 0xA5, 0xAC, 0xCC, 0xA2, 0xFD, + 0x6E, 0x90, 0x0B, 0x64, 0x50, 0x38, 0x72, 0x7A, + 0x0B, 0x7E, 0x50, 0xFF, + + 0xAF, 0xB6, 0xBB, 0x4A, 0x9E, 0x62, 0xFB, 0xD7, + 0xDA, 0x69, 0xA1, 0x60, 0x20, 0x32, 0xE6, 0x56, + 0xA1, 0x6F, 0x37, 0xCA, 0x2D, 0x23, 0xBC, 0x39, + 0xED, 0xEF, 0xB7, 0xEE, 0x47, 0x4E, 0xCB, 0x46, + 0xD3, 0xCA, 0x19, 0xF6, 0x58, 0x4C, 0x31, 0x2B, + 0x65, 0xD6, 0xBC, 0x74, 0x21, 0x05, 0xD7, 0x99, + 0x96, 0x8F, 0x47, 0xE4, 0xD8, 0x4B, 0xD1, 0x60, + 0x27, 0x2E, 0x9B, 0xBF, 0x22, 0xC4, 0xAC, 0x37, + 0xDB, 0x41, 0x61, 0xF6, 0xA7, 0x25, 0x4B, 0xC6, + 0x75, 0x97, 0x0B, 0x17, 0xCB, 0x49, 0x60, 0x5A, + 0x3E, 0xB6, 0xD7, 0x88, 0x8D, 0x02, 0x89, 0xB3, + 0xB0, 0xCC, 0x03, 0xE4, 0x6F, 0x87, 0x44, 0xFF, + 0x01, 0x6D, 0xC0, 0xC9, 0xC5, 0x78, 0x34, 0xD2, + 0x33, 0x91, 0x0D, 0x51, 0x7A, 0xD9, 0x4D, 0x68, + 0x91, 0x47, 0xAB, 0xF9, 0xA1, + + 0x7B, 0x15, 0x4A, 0xEF, 0x0F, 0xD6, 0x75, 0xB7, + 0x1B, 0x32, 0x8B, 0x31, 0xC1, 0xCD, 0x3A, 0xF8, + 0x7F, 0x2F, 0xA5, 0xBD, 0x7C, 0x5C, 0x43, 0x82, + 0x4A, 0x01, 0x3B, 0x50, 0x59, 0x74, 0xB5, 0x61, + 0x40, 0x3B, 0xC0, 0xF3, 0xA1, 0x3E, 0x75, 0x36, + 0x85, 0x74, 0xC3, 0xB3, 0x55, 0xB6, 0xAB, 0xFC, + 0xE9, 0x36, 0x9E, 0x01, 0x1E, 0xCB, 0xEA, 0x1B, + 0xB2, 0x02, 0xD8, 0x42, 0x75, 0xD7, 0x36, 0x5E, + 0x45, 0x17, 0x0E, 0xDF, 0x33, 0xEF, 0x97, 0xCE, + 0xC5, 0x1D, 0x41, 0x4A, 0x06, 0xD3, 0xA1, 0x2F, + 0x5C, 0xD6, 0x7F, 0xE1, 0x45, 0xF7, 0x69, 0xC5, + 0xFA, 0xE6, 0x88, 0x3A, 0xCB, 0x96, 0xC0, 0xA4, + 0xB7, 0x50, 0x9C, 0x67, 0xA2, 0x12, 0x85, 0xC3, + 0x0D, 0xD3, 0x0A, 0xE2, 0x58, 0xD7, 0x94, 0x42, + 0xFD, 0x3D, 0x54, 0xA7, 0x08, 0x85, + + 0x56, 0x28, 0xAF, 0x54, 0xEA, 0x3E, 0xF7, 0xCF, + 0xB9, 0x44, 0xE1, 0xB6, 0x1D, 0x0D, 0xE5, 0x3F, + 0xDF, 0x47, 0x9D, 0xE4, 0x94, 0xA0, 0xBF, 0x0E, + 0xE1, 0xC1, 0x13, 0x73, 0x0F, 0x23, 0xB1, 0xBE, + 0xC1, 0x19, 0xD5, 0x4E, 0x0D, 0x19, 0xA0, 0xD5, + 0x20, 0xDD, 0xEA, 0xA9, 0x05, 0x27, 0xF7, 0x8C, + 0x3C, 0xB3, 0x18, 0x07, 0xDC, 0x11, 0xE8, 0x60, + 0xC2, 0x61, 0x67, 0xAD, 0x0B, 0x6C, 0xA9, 0xD9, + 0x3D, 0x65, 0xE9, 0x31, 0x68, 0xFB, 0x3F, 0xDF, + 0x4B, 0x0C, 0x3B, 0xC6, 0x51, 0xE4, 0x77, 0x73, + 0x9D, 0xB5, 0x5C, 0x37, 0x3B, 0xDD, 0xAD, 0xF2, + 0xA8, 0x22, 0x98, 0x4D, 0x5F, 0x4B, 0xE6, 0xE1, + 0x0A, 0x46, 0x60, 0x0F, 0xDE, 0x02, 0xF9, 0xE6, + 0xFC, 0x3E, 0x22, 0x5D, 0x42, 0x66, 0x50, 0x60, + 0x67, 0x8C, 0x16, 0x28, 0xC4, 0x87, 0x02, + + 0x7E, 0xF5, 0xA3, 0x08, 0x91, 0x76, 0x3F, 0x65, + 0x90, 0xBF, 0xA2, 0xD7, 0x38, 0x6B, 0x41, 0x4E, + 0xC7, 0xD5, 0xBE, 0xEC, 0x60, 0xC5, 0x80, 0x3B, + 0xD6, 0x7A, 0x45, 0x4A, 0x44, 0x0F, 0xA1, 0x28, + 0xB5, 0x5C, 0x58, 0xB4, 0x2F, 0x56, 0xD3, 0xB9, + 0x43, 0x49, 0x09, 0x5E, 0xA6, 0x50, 0xFE, 0xCF, + 0x6A, 0x1D, 0x26, 0xC5, 0x4E, 0x96, 0x1A, 0xD0, + 0xBA, 0x3F, 0x8D, 0x8D, 0xB1, 0x9E, 0x13, 0x66, + 0xCB, 0x9C, 0xEC, 0x57, 0x34, 0x59, 0x7C, 0x8F, + 0xE7, 0xE4, 0x8A, 0x52, 0x77, 0x31, 0x0A, 0x7C, + 0xB2, 0xD4, 0x80, 0x89, 0xCA, 0x09, 0xAD, 0x93, + 0xBC, 0x96, 0x60, 0xBE, 0xB7, 0x92, 0xD5, 0xDA, + 0xBB, 0x2C, 0x3B, 0xF6, 0x80, 0xA1, 0xFA, 0xB7, + 0x06, 0xA9, 0x5D, 0x74, 0x16, 0x5F, 0x4D, 0xBD, + 0xDF, 0x2B, 0x45, 0xA4, 0x14, 0xBA, 0x65, 0xBF, + + 0xDB, 0xE7, 0xA9, 0x45, 0xFF, 0x17, 0xA2, 0xCE, + 0xC3, 0x98, 0x34, 0xD0, 0x2F, 0xC2, 0xC1, 0xAE, + 0x0A, 0xC0, 0x0B, 0xFF, 0x6A, 0x0D, 0xA1, 0xAB, + 0xDA, 0x0B, 0x58, 0xA0, 0x85, 0xFC, 0xF1, 0xC7, + 0x53, 0x09, 0x22, 0x4E, 0xBC, 0x0D, 0x32, 0x83, + 0x2D, 0xF9, 0x06, 0x38, 0x18, 0x55, 0xC3, 0x6D, + 0x79, 0x46, 0x9D, 0x10, 0x5F, 0x14, 0xFB, 0x02, + 0x1D, 0xAD, 0x3A, 0xB2, 0x16, 0x48, 0xB5, 0xAD, + 0xB7, 0x24, 0x59, 0x93, 0x09, 0xA3, 0xDE, 0x52, + 0xE4, 0x4E, 0x63, 0xB8, 0xF4, 0x2E, 0x04, 0x90, + 0x10, 0x70, 0xE6, 0x2D, 0xE9, 0x27, 0xEC, 0x20, + 0x28, 0xF9, 0xBB, 0xF0, 0x1B, 0xF6, 0xB1, 0xA9, + 0x74, 0x60, 0x93, 0xF9, 0x39, 0x5D, 0x45, 0x29, + 0x43, 0x7B, 0x06, 0x50, 0x4B, 0x81, 0x79, 0xC1, + 0xF4, 0xBB, 0x71, 0x60, 0xE6, 0x1F, 0x93, 0xB2, + 0x33, + + 0xA8, 0xE6, 0xE9, 0xEB, 0x5A, 0xE1, 0xDE, 0x41, + 0xE9, 0x3E, 0x93, 0x29, 0xA3, 0x8C, 0x26, 0x4C, + 0x89, 0x01, 0x48, 0x46, 0x39, 0xB7, 0x49, 0x8D, + 0xAD, 0xDB, 0x76, 0x22, 0x74, 0x1C, 0x49, 0x79, + 0x61, 0x36, 0x56, 0x16, 0x10, 0x20, 0x68, 0x5E, + 0xBF, 0x1A, 0x25, 0x87, 0x7F, 0xC6, 0xB8, 0x17, + 0xB6, 0x4F, 0x89, 0xDD, 0x6A, 0x72, 0xD8, 0xF7, + 0xDF, 0x27, 0x50, 0xBF, 0x93, 0x26, 0xFE, 0x7A, + 0xD3, 0x55, 0x54, 0xC7, 0x23, 0x18, 0xFC, 0x88, + 0x47, 0x1A, 0x58, 0x51, 0x49, 0xE7, 0xC0, 0xAB, + 0xF8, 0xC8, 0x54, 0x38, 0xE0, 0x75, 0x6B, 0x47, + 0x1D, 0x5F, 0xC2, 0x60, 0x59, 0x72, 0x92, 0x57, + 0x5C, 0x2E, 0x0D, 0xAC, 0x94, 0x9A, 0x86, 0x74, + 0xF0, 0x42, 0x98, 0x11, 0x41, 0xE8, 0x3A, 0x3F, + 0xBA, 0xE4, 0xB4, 0xB6, 0x0E, 0x85, 0x11, 0xBC, + 0xB3, 0x23, + + 0x3C, 0xD8, 0x11, 0xEC, 0xC7, 0xBB, 0xA6, 0x7C, + 0x7F, 0x06, 0x4F, 0x7E, 0xBF, 0x3F, 0xA1, 0x96, + 0x65, 0x75, 0xC4, 0xDC, 0x2C, 0x2D, 0x89, 0x6D, + 0x75, 0xCB, 0xDD, 0xB2, 0xF9, 0x4F, 0x1B, 0x4C, + 0xE7, 0xCA, 0x02, 0xA5, 0x64, 0x6A, 0xEE, 0xEF, + 0x0B, 0xDF, 0xE8, 0x79, 0x2C, 0xBA, 0x0F, 0x46, + 0x17, 0xA0, 0x45, 0x14, 0x0C, 0x99, 0x2E, 0x66, + 0x09, 0xFC, 0x17, 0xD5, 0x03, 0xA3, 0x50, 0x98, + 0x82, 0xD6, 0x1B, 0x53, 0xBE, 0x27, 0x4D, 0xB3, + 0xBD, 0xC0, 0x43, 0x81, 0x75, 0x7D, 0xCF, 0x11, + 0xC7, 0x70, 0x50, 0x01, 0x0C, 0x08, 0x2E, 0xE3, + 0x81, 0xC7, 0x04, 0x43, 0xDE, 0x6F, 0x59, 0xB7, + 0x9E, 0x82, 0x33, 0x74, 0x6D, 0xF9, 0x0A, 0xE5, + 0x69, 0x99, 0xFC, 0x54, 0x73, 0xD8, 0xC8, 0x5A, + 0x65, 0x43, 0x45, 0xE0, 0x1B, 0xF4, 0xFA, 0x80, + 0xA0, 0x86, 0x7F, + + 0xB3, 0x36, 0xBC, 0x71, 0x8B, 0x9A, 0x93, 0x81, + 0x95, 0xD8, 0x5E, 0xF8, 0xDA, 0x56, 0x9E, 0xDB, + 0xF2, 0xBE, 0xFE, 0xB0, 0x57, 0xA6, 0x85, 0x48, + 0x59, 0x72, 0xEF, 0xB4, 0xF2, 0xFD, 0x5E, 0x98, + 0x9C, 0x74, 0x84, 0x52, 0xED, 0x88, 0xFA, 0x97, + 0x5C, 0x91, 0x4E, 0x34, 0x92, 0xD3, 0xC4, 0x4C, + 0x1B, 0x2F, 0x5F, 0xC8, 0x9B, 0xF1, 0xF6, 0x60, + 0x8F, 0xA5, 0x3E, 0xEC, 0x15, 0x2F, 0xCA, 0xC6, + 0xFF, 0xB9, 0xDD, 0x3E, 0x05, 0x6F, 0xAE, 0xE2, + 0x67, 0xD7, 0xF5, 0xE6, 0x93, 0x74, 0x07, 0x54, + 0x86, 0x62, 0xA3, 0x14, 0x4B, 0x8F, 0x00, 0xEA, + 0x70, 0x29, 0x15, 0xA5, 0x05, 0x9A, 0xFE, 0xFE, + 0xF5, 0x74, 0xE7, 0x29, 0xA1, 0x2C, 0x37, 0xEF, + 0x08, 0x81, 0xE0, 0x63, 0x4C, 0x0B, 0x4C, 0xD8, + 0xAF, 0x3A, 0x13, 0x11, 0x16, 0x03, 0x5C, 0x73, + 0x74, 0x6D, 0xDB, 0xD2, + + 0x84, 0x6D, 0xEF, 0xF2, 0x61, 0x96, 0xD3, 0x49, + 0x3A, 0x6E, 0x30, 0x46, 0xB9, 0x56, 0x8A, 0x81, + 0xC0, 0xCB, 0xDF, 0x5B, 0xCD, 0x5A, 0xAE, 0xF1, + 0xA1, 0x10, 0xE7, 0x03, 0x9A, 0xAE, 0x61, 0x16, + 0x2F, 0xD0, 0x0C, 0x26, 0x7A, 0x96, 0x8E, 0x3A, + 0x97, 0x8A, 0x0A, 0xC9, 0x90, 0x7F, 0x1E, 0x98, + 0xF2, 0x17, 0x74, 0xE7, 0xD1, 0xB2, 0x7F, 0x0F, + 0xE6, 0x19, 0x80, 0x2F, 0x83, 0x22, 0x63, 0xDD, + 0x73, 0x01, 0xEB, 0xC7, 0x72, 0xC7, 0x87, 0xBA, + 0x76, 0xF2, 0x53, 0xD2, 0xDD, 0x23, 0x91, 0x4F, + 0x67, 0x6F, 0x69, 0x74, 0xB4, 0xD8, 0x24, 0x20, + 0xD8, 0x29, 0x91, 0x78, 0xD6, 0xA2, 0xE0, 0x42, + 0x4C, 0xAE, 0x3A, 0xFB, 0xAB, 0x01, 0x70, 0xCF, + 0x57, 0xE7, 0xD0, 0x17, 0xF0, 0x4E, 0x9D, 0x52, + 0x4C, 0x37, 0x25, 0xA3, 0x23, 0x16, 0x82, 0x89, + 0x40, 0x64, 0xA4, 0x0C, 0x5A, + + 0x69, 0xB0, 0x3E, 0x4F, 0x95, 0x66, 0xFD, 0x32, + 0x6D, 0x68, 0xF4, 0xDD, 0x78, 0x1D, 0x54, 0x43, + 0xD1, 0xB2, 0x50, 0x71, 0x1C, 0x48, 0xDB, 0x8E, + 0xE0, 0x58, 0x1A, 0x89, 0xE0, 0x37, 0x64, 0x76, + 0x69, 0x85, 0xB9, 0x34, 0x82, 0xA5, 0x57, 0xAE, + 0x2A, 0x03, 0x00, 0x9B, 0x97, 0xCF, 0xE1, 0x59, + 0x94, 0x74, 0x07, 0x63, 0xD9, 0x6B, 0xBC, 0x1B, + 0x03, 0xD9, 0xE4, 0x40, 0xA5, 0xCB, 0x63, 0xF4, + 0xA1, 0xBA, 0x2F, 0xCE, 0x1A, 0x8F, 0xB7, 0x5A, + 0xB9, 0xFE, 0xEF, 0x8C, 0xA6, 0x74, 0x97, 0xC0, + 0xD6, 0x80, 0xB7, 0x2F, 0x03, 0xD8, 0x9B, 0x6E, + 0x36, 0x5D, 0xCC, 0x92, 0x21, 0x6E, 0xB8, 0x02, + 0xFA, 0xF9, 0xEA, 0x24, 0xA0, 0x3F, 0xDA, 0x2A, + 0xD9, 0x43, 0x1C, 0x07, 0xF2, 0x0A, 0x2C, 0x75, + 0x3D, 0x42, 0xDB, 0xEA, 0x33, 0xAB, 0x9D, 0x95, + 0xBE, 0x53, 0xF6, 0xAC, 0x56, 0xEB, + + 0x80, 0x25, 0xA8, 0x28, 0x34, 0x43, 0x8F, 0xDB, + 0xE4, 0xB8, 0x7A, 0x84, 0xE3, 0x12, 0x2E, 0xD3, + 0x28, 0x14, 0xFE, 0x42, 0x90, 0x95, 0x26, 0x2B, + 0xA1, 0x19, 0x69, 0x23, 0xCF, 0x9D, 0x91, 0xF4, + 0xD4, 0xF3, 0x3A, 0xCF, 0xA0, 0x61, 0x3E, 0x91, + 0xBF, 0xEE, 0x5B, 0xF8, 0x4E, 0xBE, 0xA0, 0x0A, + 0xAB, 0xBC, 0xE4, 0x6A, 0x11, 0x45, 0x20, 0xEA, + 0x3B, 0x29, 0xB7, 0xCA, 0x79, 0x75, 0x06, 0x48, + 0x4B, 0x7E, 0x11, 0xC5, 0xA8, 0x6A, 0x51, 0x9B, + 0x32, 0xBA, 0x3A, 0xA4, 0x06, 0x69, 0xC6, 0xD7, + 0x8F, 0xDE, 0x67, 0x52, 0x63, 0xFC, 0x71, 0x99, + 0x62, 0x10, 0x4B, 0x58, 0x77, 0xAB, 0x16, 0xBC, + 0x5D, 0xDF, 0x25, 0x45, 0xB3, 0x37, 0x03, 0x12, + 0x42, 0xAE, 0x77, 0xBD, 0xD5, 0x59, 0x37, 0x62, + 0x28, 0x8C, 0x0F, 0x70, 0x3B, 0x0B, 0x08, 0x2B, + 0x13, 0xAE, 0x21, 0x58, 0x20, 0x38, 0xDC, + + 0xCE, 0xFA, 0x4C, 0xBD, 0xCA, 0xBC, 0x3A, 0xC0, + 0x4B, 0x91, 0x3F, 0x33, 0x19, 0x46, 0x05, 0x16, + 0x80, 0xC0, 0xE2, 0x63, 0xB0, 0xE0, 0xD5, 0x2B, + 0xCE, 0xBA, 0x01, 0x36, 0x5B, 0xCD, 0x68, 0x17, + 0xCF, 0xEC, 0x0A, 0x31, 0x45, 0x36, 0x1B, 0x28, + 0xB1, 0x85, 0x90, 0x55, 0xB5, 0x27, 0x90, 0xE1, + 0x09, 0x4E, 0x8E, 0x27, 0x91, 0xD7, 0x15, 0x70, + 0x85, 0x89, 0x20, 0x0D, 0xD3, 0xF1, 0x70, 0x74, + 0xAA, 0x29, 0x0A, 0xA2, 0xA3, 0x96, 0x4B, 0x6E, + 0xBB, 0x04, 0x99, 0x4D, 0xC9, 0xD8, 0xFB, 0xA3, + 0xD0, 0xEF, 0x9D, 0x2A, 0x77, 0xC9, 0x0E, 0x85, + 0x33, 0x68, 0xFC, 0x30, 0xA1, 0x48, 0x55, 0x75, + 0x55, 0x21, 0xC8, 0x1F, 0x01, 0xF2, 0xA5, 0x2B, + 0x7D, 0xD7, 0x5E, 0x8C, 0x76, 0x06, 0x18, 0xBD, + 0x74, 0x4A, 0x5F, 0xE4, 0xE9, 0xD7, 0xCB, 0xEB, + 0x37, 0x95, 0x4F, 0x06, 0x26, 0xD2, 0xF1, 0xD4, + + 0x37, 0x0D, 0xA6, 0xE9, 0x34, 0x06, 0x17, 0x74, + 0x20, 0x52, 0x8E, 0x5B, 0xC2, 0x71, 0x8D, 0x6E, + 0x3C, 0xAA, 0xAA, 0xF9, 0x7F, 0x82, 0x09, 0x74, + 0x29, 0xCF, 0x79, 0xC1, 0xF7, 0x42, 0xB8, 0xA9, + 0x36, 0xA5, 0xFF, 0x77, 0x15, 0x09, 0x0B, 0x04, + 0x7E, 0xF4, 0xE1, 0xB1, 0x88, 0x89, 0x7A, 0x88, + 0x98, 0xD3, 0xA7, 0x95, 0x23, 0x69, 0x88, 0xD3, + 0x8F, 0x61, 0x1E, 0xBF, 0x99, 0xAD, 0xB4, 0x56, + 0xDF, 0x37, 0x12, 0x78, 0xDA, 0xF7, 0xDA, 0x42, + 0x8A, 0x43, 0xBD, 0x1A, 0xB2, 0x0A, 0xDA, 0x71, + 0xD6, 0x16, 0xDB, 0x15, 0xCA, 0xEA, 0x74, 0xA2, + 0x11, 0x0D, 0xAE, 0xE5, 0x2B, 0x64, 0x01, 0x61, + 0x91, 0x38, 0x16, 0xF4, 0x6E, 0xB9, 0x01, 0xDF, + 0xFD, 0xCD, 0x56, 0x79, 0xA7, 0x42, 0x7D, 0x8C, + 0xF4, 0x10, 0x4B, 0x00, 0xBA, 0x05, 0x77, 0x35, + 0x29, 0x74, 0x45, 0xDF, 0xCF, 0x2A, 0x6E, 0xBF, + 0x60, + + 0x49, 0x06, 0x7D, 0xD6, 0xE2, 0xC8, 0x54, 0x45, + 0x41, 0x97, 0x98, 0x29, 0xB5, 0x49, 0x3C, 0xE2, + 0x29, 0xC1, 0x87, 0xAC, 0x4A, 0x88, 0x31, 0x54, + 0x12, 0xDF, 0x6F, 0x7C, 0x88, 0xD4, 0x5A, 0x69, + 0xEF, 0x89, 0xB7, 0x26, 0xBD, 0x5D, 0x14, 0x45, + 0x5B, 0xAA, 0xC0, 0x31, 0x77, 0x20, 0x56, 0x22, + 0x32, 0x43, 0x0B, 0x0F, 0x29, 0x9F, 0x2C, 0xA5, + 0x42, 0xFC, 0x25, 0x1C, 0x9C, 0x1B, 0xE7, 0xBE, + 0x65, 0x8F, 0xBD, 0xA8, 0x07, 0xCC, 0x54, 0xFF, + 0xD2, 0x3B, 0xC0, 0x52, 0x9F, 0x21, 0xDE, 0xA4, + 0xA0, 0x8F, 0xB9, 0x05, 0x51, 0x8B, 0x4D, 0x6C, + 0x87, 0x4A, 0xD3, 0x82, 0xD4, 0x0D, 0xE2, 0x11, + 0xAC, 0x48, 0x81, 0x6D, 0xF9, 0xFD, 0xEC, 0x8D, + 0x15, 0x38, 0x8E, 0x6B, 0xE4, 0x5B, 0x04, 0x42, + 0xD5, 0x34, 0xFB, 0xE1, 0xBC, 0x0D, 0xDB, 0xB7, + 0xA9, 0xF7, 0xE6, 0x42, 0x5C, 0xBF, 0x89, 0x57, + 0x63, 0xF6, + + 0x90, 0x0A, 0xF6, 0x05, 0x11, 0x92, 0x82, 0x59, + 0xA1, 0x31, 0x54, 0xE8, 0x93, 0x6C, 0xE5, 0x4B, + 0xE8, 0x6C, 0x14, 0x80, 0xFB, 0x5F, 0xB5, 0x52, + 0xAA, 0x4A, 0x04, 0x64, 0xC5, 0xC5, 0x03, 0x2C, + 0x2D, 0xB1, 0x6F, 0xDC, 0xA0, 0x74, 0xFF, 0xDE, + 0xE5, 0x0D, 0x50, 0xE0, 0xBE, 0x35, 0xBA, 0x42, + 0x5E, 0x56, 0x64, 0x4F, 0xA0, 0x19, 0xD0, 0xAC, + 0xC6, 0x79, 0x09, 0x61, 0x1C, 0x72, 0xE2, 0x38, + 0x66, 0x7E, 0x96, 0x61, 0xC7, 0x69, 0x41, 0xEF, + 0x5A, 0x41, 0x89, 0xB2, 0xC6, 0xA9, 0xF3, 0xCB, + 0x8C, 0xAE, 0x1E, 0xBE, 0xDE, 0xF2, 0x4B, 0x20, + 0x67, 0xFF, 0x89, 0xAD, 0x95, 0x0A, 0x4D, 0x2C, + 0xEC, 0x62, 0x45, 0x53, 0x5C, 0xD8, 0x8F, 0x41, + 0x1B, 0x5E, 0xC6, 0x8E, 0xF6, 0x79, 0xB1, 0x3E, + 0xD5, 0x95, 0x46, 0x4E, 0x85, 0xA2, 0x32, 0x79, + 0x06, 0xE5, 0xBE, 0xD0, 0xEB, 0x77, 0xE0, 0x87, + 0x87, 0x75, 0xDD, + + 0xAC, 0x14, 0x1B, 0x69, 0xEE, 0x01, 0x0E, 0xE8, + 0x55, 0x78, 0x58, 0x91, 0xBE, 0xB4, 0x31, 0xCD, + 0x3D, 0xBE, 0x2F, 0x30, 0x81, 0x9D, 0x5F, 0x3A, + 0x65, 0x49, 0x1E, 0x24, 0x75, 0x38, 0xEA, 0x0F, + 0x45, 0x88, 0x6F, 0x66, 0x98, 0x56, 0x84, 0x41, + 0xB0, 0x7B, 0x08, 0x92, 0xE1, 0xAC, 0x8E, 0xFD, + 0x51, 0x96, 0xAD, 0x8B, 0x2D, 0x8C, 0xB8, 0xFA, + 0xB8, 0xA6, 0x63, 0x34, 0xF3, 0xC1, 0xCB, 0x51, + 0xC2, 0xAB, 0x04, 0x9B, 0x53, 0x28, 0xF9, 0x13, + 0xF0, 0x11, 0x54, 0xFF, 0xB0, 0x47, 0x18, 0x29, + 0xC5, 0x97, 0x43, 0x5E, 0x7C, 0xAA, 0x6F, 0x38, + 0x99, 0x04, 0x5C, 0x79, 0xF0, 0x08, 0xA2, 0x69, + 0xD3, 0xFF, 0x62, 0xC6, 0xDB, 0xA8, 0x2B, 0xF5, + 0xDB, 0xD2, 0x8A, 0xDD, 0x4F, 0xC3, 0xD2, 0x00, + 0xE5, 0xDE, 0x75, 0xD7, 0xC4, 0x8B, 0x76, 0xC8, + 0xDB, 0x55, 0xCB, 0xE6, 0x1B, 0xAB, 0xD2, 0x4E, + 0x3B, 0x93, 0x08, 0x43, + + 0x10, 0x07, 0x49, 0x6C, 0x11, 0x44, 0xEE, 0xFA, + 0x41, 0x19, 0xFA, 0xD1, 0x7D, 0xEC, 0xD2, 0x8F, + 0xA2, 0xBC, 0xB5, 0x38, 0x85, 0xD5, 0x4B, 0x79, + 0xFB, 0x77, 0x69, 0x42, 0x65, 0xEC, 0x29, 0x04, + 0x24, 0xCF, 0x51, 0xE1, 0xC2, 0x23, 0x06, 0x88, + 0x47, 0xAE, 0x7D, 0xA1, 0x08, 0x9A, 0x82, 0x2C, + 0xD6, 0xB4, 0x4D, 0x84, 0x96, 0x19, 0x17, 0x5A, + 0x0F, 0x22, 0x29, 0xDE, 0x0F, 0x8F, 0x71, 0xAE, + 0x12, 0x65, 0x87, 0xC5, 0xB4, 0xAD, 0x58, 0xDB, + 0xCA, 0x66, 0xE6, 0xB8, 0xE4, 0x3A, 0x80, 0x2B, + 0x18, 0x88, 0xD6, 0x21, 0xDC, 0x2B, 0xC8, 0x52, + 0x4B, 0x48, 0x90, 0x37, 0x72, 0x02, 0xCD, 0x01, + 0xEC, 0xE8, 0x03, 0xD4, 0x28, 0x8D, 0xD1, 0x94, + 0xBC, 0x1E, 0xAE, 0xA2, 0x79, 0x12, 0xB0, 0x5D, + 0x34, 0x32, 0x53, 0x1B, 0xC9, 0xA8, 0x6A, 0x1D, + 0x48, 0x30, 0x08, 0xB4, 0xC5, 0x54, 0x0A, 0x1E, + 0x24, 0x9E, 0x8D, 0x58, 0xF2, + + 0x1C, 0x73, 0x21, 0xCA, 0xB9, 0x20, 0x75, 0xEF, + 0xF4, 0x2B, 0xA5, 0xE5, 0x66, 0x62, 0xF3, 0x31, + 0x61, 0x92, 0x8B, 0x34, 0x44, 0x67, 0xC5, 0xAD, + 0xC1, 0x56, 0xC3, 0xB7, 0x23, 0xC6, 0x2B, 0xB1, + 0x34, 0x5F, 0xEF, 0xF7, 0x70, 0x21, 0x5E, 0x35, + 0x36, 0x28, 0xCC, 0xD2, 0x61, 0x58, 0xA3, 0xF6, + 0xB0, 0xD7, 0xA2, 0xBC, 0xF3, 0x02, 0x4E, 0x76, + 0x55, 0x1D, 0x48, 0x45, 0x90, 0x4C, 0xEF, 0x6C, + 0xAC, 0x58, 0x7B, 0xF2, 0x7C, 0x3E, 0x3F, 0xD6, + 0xFB, 0x57, 0x74, 0x3B, 0x91, 0xBE, 0xCE, 0x05, + 0x58, 0x9E, 0x26, 0xE6, 0x8A, 0x96, 0x8B, 0x00, + 0xC3, 0x28, 0x4A, 0xE8, 0x5C, 0xDA, 0x46, 0xF2, + 0x55, 0x14, 0x7C, 0x86, 0x58, 0xE0, 0x78, 0x16, + 0x0B, 0xA6, 0x45, 0xB2, 0xBD, 0x09, 0x83, 0x16, + 0xFE, 0x8F, 0x0D, 0xE6, 0x46, 0xE4, 0x85, 0x80, + 0x95, 0xE5, 0xC7, 0xEC, 0x5A, 0xE2, 0xE8, 0x1F, + 0xCC, 0x33, 0x25, 0x2A, 0x71, 0xB4, + + 0xDF, 0x62, 0x81, 0xFF, 0x5B, 0x88, 0x34, 0xB3, + 0xA9, 0x4A, 0xA6, 0xD9, 0x08, 0x48, 0x65, 0x7D, + 0xFC, 0x07, 0x56, 0xD8, 0xF5, 0xBA, 0x69, 0xD2, + 0xF8, 0x68, 0xAD, 0xDB, 0x14, 0x6F, 0x3F, 0x27, + 0x0B, 0x1D, 0x14, 0x53, 0x2C, 0xC2, 0x9E, 0x7E, + 0x1A, 0x97, 0xA2, 0xE3, 0x0B, 0x9E, 0x78, 0x3C, + 0x79, 0x4B, 0xD9, 0xCC, 0xDD, 0x19, 0x0D, 0x26, + 0x77, 0x65, 0xE6, 0x89, 0x19, 0xAB, 0x58, 0xA3, + 0x91, 0x50, 0x82, 0xA0, 0xB1, 0xB3, 0x7E, 0xD7, + 0x4B, 0xE2, 0xA2, 0xF7, 0x1E, 0x37, 0x33, 0x18, + 0xF6, 0x09, 0x60, 0x6B, 0x00, 0x46, 0xEF, 0xB1, + 0x06, 0x60, 0x1B, 0x0A, 0x4C, 0x0E, 0xE3, 0xFA, + 0xEA, 0xD7, 0x9D, 0xDC, 0x6B, 0x4C, 0x9E, 0x9C, + 0x61, 0x22, 0xAB, 0x19, 0x6E, 0x62, 0xA7, 0x25, + 0x26, 0xC3, 0xDB, 0x9B, 0xE0, 0x6E, 0xD4, 0x2D, + 0xDC, 0x71, 0x2A, 0x13, 0x7C, 0x77, 0xE8, 0xAA, + 0x1D, 0xED, 0x37, 0xB5, 0x6A, 0xB8, 0x3E, + + 0x02, 0xDC, 0x62, 0xA2, 0x98, 0x84, 0x22, 0x1E, + 0xB7, 0x25, 0x9A, 0xED, 0xDD, 0x60, 0x96, 0x44, + 0xEB, 0x1B, 0xC6, 0x9A, 0xEE, 0x76, 0x1B, 0x67, + 0xF4, 0x66, 0xE8, 0x63, 0x55, 0x3F, 0x6F, 0xB9, + 0x35, 0xAE, 0xB4, 0x3D, 0xD4, 0xDC, 0x4B, 0xD9, + 0x42, 0x1F, 0x7A, 0x36, 0x4D, 0x2C, 0x01, 0x2A, + 0x74, 0x5B, 0x67, 0xF9, 0xE1, 0x66, 0x69, 0xEF, + 0x89, 0x17, 0x96, 0xFF, 0x3F, 0xC6, 0x6C, 0xAB, + 0xFA, 0xE8, 0x82, 0x6D, 0x65, 0x48, 0xD2, 0x8D, + 0x0D, 0xCB, 0x0F, 0x5B, 0x2E, 0xCF, 0x17, 0xEA, + 0x60, 0x96, 0x76, 0x64, 0x33, 0x9A, 0xDE, 0x11, + 0xB4, 0x2A, 0xC4, 0x2D, 0x35, 0x2B, 0xF8, 0x36, + 0x80, 0xC4, 0x4E, 0xFE, 0x14, 0xFD, 0xB2, 0x57, + 0x0A, 0x46, 0x29, 0x37, 0x50, 0x7B, 0x26, 0x29, + 0x2B, 0xAE, 0x3D, 0xB9, 0xF8, 0x38, 0x31, 0x4C, + 0x13, 0x67, 0xD5, 0xF2, 0x40, 0x92, 0x09, 0xF1, + 0x5C, 0xE1, 0xF3, 0xE7, 0xE3, 0x6B, 0x25, 0x88, + + 0x70, 0x64, 0x4F, 0x22, 0x92, 0xCC, 0xBA, 0x70, + 0x10, 0xB5, 0xF9, 0x5D, 0xF6, 0xBD, 0x95, 0x7A, + 0x9E, 0xA1, 0xC3, 0x00, 0x77, 0x6A, 0x12, 0x94, + 0x43, 0xC9, 0x0C, 0xBB, 0xE2, 0xCD, 0xBE, 0xB7, + 0xF4, 0x11, 0xB0, 0x86, 0x11, 0xBB, 0x98, 0x31, + 0xBE, 0xC0, 0x82, 0xF9, 0x84, 0xF7, 0x99, 0xA6, + 0x1A, 0x44, 0x66, 0x28, 0x93, 0x32, 0xD9, 0x91, + 0x16, 0x8F, 0x53, 0x0D, 0x21, 0xF4, 0xFC, 0x69, + 0x5F, 0xDD, 0xFE, 0xF5, 0x59, 0x9A, 0x96, 0x4F, + 0x1C, 0x2A, 0xFD, 0xE4, 0x88, 0x66, 0x2A, 0x78, + 0x33, 0x60, 0xF3, 0x10, 0x55, 0xED, 0x68, 0xE6, + 0x34, 0x67, 0x62, 0x04, 0xBF, 0x39, 0x17, 0x3D, + 0x1B, 0x22, 0x8A, 0x77, 0x45, 0x90, 0x7C, 0x5C, + 0xCF, 0x4E, 0xE2, 0xB0, 0x88, 0xB8, 0x2B, 0x4A, + 0x4F, 0xCC, 0x14, 0xDC, 0xD3, 0x6A, 0x77, 0xA7, + 0xA7, 0x52, 0x0A, 0x4A, 0xCC, 0x3C, 0x30, 0xF0, + 0x9B, 0x10, 0x1A, 0xAA, 0xC8, 0x5A, 0xFE, 0x6F, + 0xA6, + + 0xC1, 0x62, 0xCF, 0x2C, 0xBA, 0xC0, 0xC0, 0x84, + 0x67, 0x4E, 0x96, 0xA2, 0xFF, 0x81, 0xE6, 0x74, + 0xFA, 0x22, 0xCE, 0x6B, 0xC4, 0x9C, 0x1D, 0x03, + 0xC0, 0xB1, 0x8B, 0x10, 0x33, 0xC3, 0x1F, 0x61, + 0x2D, 0x67, 0x09, 0x2F, 0x04, 0x51, 0x49, 0xCE, + 0x9F, 0x94, 0x14, 0xAB, 0x0A, 0x7F, 0x39, 0xD9, + 0xA5, 0x4F, 0x4E, 0x5A, 0x3C, 0xCB, 0xB8, 0x74, + 0x51, 0x28, 0x3B, 0xBE, 0x1B, 0x5E, 0x94, 0xFC, + 0xD1, 0xB2, 0x0A, 0x46, 0x20, 0xB3, 0x7E, 0x6E, + 0xD3, 0x9F, 0x76, 0x3F, 0x4A, 0xFF, 0x0B, 0xB7, + 0x52, 0xE2, 0xA4, 0xDF, 0x2E, 0x0C, 0x72, 0xE2, + 0xC7, 0x91, 0x2D, 0x5F, 0xB3, 0x38, 0x4F, 0x03, + 0x5C, 0x19, 0x2F, 0xBD, 0xDC, 0x84, 0xB5, 0xF9, + 0xFF, 0x8C, 0x19, 0x6F, 0x57, 0x4A, 0xD7, 0xA6, + 0xC5, 0x93, 0x2E, 0xEA, 0x35, 0xD7, 0xF8, 0xD4, + 0x08, 0xCA, 0x21, 0x06, 0x21, 0x12, 0x9B, 0xE2, + 0xF5, 0x38, 0x2C, 0xD4, 0x02, 0xD9, 0x56, 0xDE, + 0x5D, 0xB5, + + 0x1F, 0x86, 0xAE, 0xE4, 0xE4, 0xB2, 0x42, 0x60, + 0x9B, 0xBF, 0x1E, 0xA5, 0x16, 0x65, 0xA0, 0xDD, + 0xB3, 0xC6, 0xCA, 0xD7, 0xB8, 0xAE, 0x14, 0xCD, + 0xDF, 0xE9, 0xFF, 0x63, 0x38, 0x87, 0xE8, 0x2F, + 0xAE, 0xC7, 0xC7, 0x43, 0x46, 0x24, 0x54, 0xC0, + 0x41, 0xA6, 0x27, 0x73, 0x4E, 0x63, 0x0D, 0x0F, + 0x2D, 0xAA, 0xD6, 0x62, 0xFE, 0x8E, 0xE4, 0x3F, + 0xA2, 0xC3, 0x98, 0x5B, 0x93, 0x5B, 0x11, 0xEA, + 0xC9, 0x6D, 0xED, 0x9E, 0x71, 0x9D, 0xD9, 0x5E, + 0xA7, 0xB3, 0x4C, 0xB9, 0xBF, 0x2C, 0xE0, 0x90, + 0x3C, 0x19, 0x82, 0xE5, 0x94, 0xB9, 0xD7, 0x67, + 0x3F, 0xA7, 0x78, 0xAE, 0x10, 0x8B, 0x59, 0x69, + 0xD3, 0x73, 0x33, 0x2C, 0xD5, 0x74, 0x76, 0x56, + 0xA5, 0x16, 0xF0, 0x78, 0xB9, 0x4E, 0xFA, 0x0B, + 0x71, 0x77, 0x99, 0xAD, 0xBC, 0xD5, 0x86, 0xE0, + 0xFD, 0x36, 0xF6, 0x35, 0x97, 0x05, 0xEF, 0xB6, + 0xFF, 0x83, 0xA7, 0x0F, 0x65, 0xE8, 0x98, 0x8F, + 0x42, 0xB0, 0x8B, + + 0x90, 0x2A, 0x6C, 0xF6, 0x1D, 0xD4, 0x36, 0xDD, + 0xC3, 0x87, 0x2D, 0xE1, 0x68, 0xED, 0x8F, 0x21, + 0x0E, 0x53, 0xF5, 0x03, 0xE9, 0xA0, 0xD5, 0x3A, + 0xF9, 0xEF, 0x15, 0xCC, 0x0E, 0xE3, 0xD6, 0x27, + 0xB3, 0x30, 0x8B, 0x60, 0x0A, 0x43, 0x2F, 0xA4, + 0x41, 0x0E, 0xE9, 0x8F, 0xFD, 0x6E, 0x7C, 0x8A, + 0xEA, 0xCB, 0x7F, 0x1E, 0xEF, 0x15, 0x97, 0x59, + 0x4A, 0x67, 0x25, 0xFD, 0x72, 0xB6, 0x0D, 0x3A, + 0xC0, 0xCE, 0xD4, 0xA7, 0xF6, 0x61, 0x6B, 0x60, + 0x8C, 0x55, 0xB3, 0xB7, 0xA9, 0xB0, 0x7E, 0xD8, + 0x95, 0xBB, 0xAA, 0xFD, 0x3B, 0x72, 0x40, 0x72, + 0x28, 0xA4, 0x73, 0x19, 0x75, 0x37, 0x39, 0x07, + 0xBD, 0xB8, 0xB6, 0x51, 0x48, 0xC2, 0xB5, 0xFF, + 0xE8, 0xBC, 0x0C, 0x65, 0xD0, 0x8E, 0xB2, 0x32, + 0xA5, 0xCE, 0xE7, 0xB9, 0x3C, 0xC2, 0x56, 0xBF, + 0x4D, 0x7B, 0x8E, 0xA4, 0xCE, 0x2D, 0x7B, 0x32, + 0x48, 0xA9, 0xE3, 0x3A, 0x34, 0x18, 0xB0, 0x6A, + 0x68, 0x88, 0xED, 0x55, + + 0xB6, 0xDF, 0x47, 0x88, 0x2F, 0x70, 0x18, 0x3C, + 0xB9, 0x72, 0x04, 0x1E, 0x75, 0x5F, 0x45, 0xCA, + 0xA4, 0xB0, 0xAC, 0x11, 0x1B, 0x65, 0x4B, 0xAE, + 0xCA, 0x4D, 0xA1, 0xA9, 0x2C, 0xDF, 0x76, 0x14, + 0x94, 0x2A, 0xFC, 0x04, 0xC2, 0xE8, 0xAE, 0x94, + 0x15, 0x11, 0x07, 0x7A, 0x72, 0x25, 0xB6, 0x6D, + 0x70, 0x03, 0xC9, 0xAC, 0xE0, 0xAB, 0xD0, 0xC1, + 0x90, 0x4E, 0x08, 0xF4, 0x9F, 0x13, 0xB4, 0x7B, + 0xB5, 0x56, 0x37, 0x20, 0x83, 0x0C, 0x71, 0xA6, + 0x93, 0xF5, 0x00, 0x2F, 0xC9, 0xD5, 0x6A, 0x5C, + 0xB7, 0xA7, 0x9E, 0xB2, 0x1B, 0x62, 0x49, 0x9B, + 0xA0, 0x2A, 0x54, 0xC5, 0xE4, 0x5C, 0xCF, 0x5A, + 0x63, 0x9D, 0xA2, 0x85, 0x8D, 0xFA, 0xEE, 0x2B, + 0x1A, 0x41, 0x35, 0x97, 0x67, 0x36, 0x53, 0x25, + 0x52, 0x57, 0x8C, 0x8E, 0x53, 0x27, 0x89, 0xBC, + 0x2D, 0x3F, 0x91, 0xC4, 0x36, 0xB1, 0xEF, 0x54, + 0x1A, 0xCB, 0xDA, 0xC9, 0x78, 0x54, 0x78, 0xBA, + 0xDD, 0xA9, 0x23, 0x9D, 0xB4, + + 0xB0, 0xA8, 0x6B, 0x05, 0x72, 0x86, 0xDA, 0xD2, + 0x21, 0xDC, 0xC6, 0x3C, 0x0B, 0x47, 0x2E, 0xAA, + 0x4A, 0x4F, 0x19, 0x7B, 0xAC, 0xEF, 0x6F, 0xA6, + 0xD4, 0x9D, 0x45, 0xEF, 0xB4, 0x14, 0x83, 0x49, + 0xA6, 0x20, 0x55, 0x18, 0xA0, 0x64, 0x49, 0xD0, + 0xBB, 0x1C, 0xA5, 0x49, 0x56, 0x13, 0x8E, 0xD6, + 0x9A, 0x22, 0x3E, 0x1A, 0x28, 0x24, 0x6E, 0x55, + 0xAF, 0xA3, 0xDD, 0x02, 0x1B, 0xBC, 0x1E, 0xF2, + 0xA7, 0x8A, 0x5C, 0xBD, 0x6A, 0xE8, 0x26, 0x21, + 0x81, 0x5D, 0x6C, 0xDF, 0x44, 0xF8, 0xB4, 0xA7, + 0x42, 0x9D, 0x73, 0x9A, 0xC4, 0x7A, 0x4B, 0xF2, + 0x98, 0xFC, 0xB7, 0xE8, 0xEA, 0x8C, 0x0A, 0xC2, + 0xD5, 0xC3, 0x51, 0xCF, 0x3F, 0x71, 0xB5, 0xE4, + 0xC3, 0x5B, 0x30, 0xA6, 0xE4, 0x80, 0xFA, 0x46, + 0xB4, 0xBC, 0x13, 0x01, 0xA0, 0xA5, 0xF8, 0xEF, + 0x6D, 0xA8, 0xD3, 0xCB, 0x92, 0xD7, 0xBF, 0x46, + 0x73, 0xC4, 0xE0, 0x12, 0xC3, 0x57, 0xC1, 0x20, + 0x5E, 0xF2, 0xF2, 0x7A, 0x18, 0x54, + + 0xD5, 0x8C, 0x8D, 0x9B, 0x33, 0xB8, 0x9B, 0xC3, + 0x15, 0x50, 0xC9, 0xC7, 0x25, 0x8B, 0x36, 0xA6, + 0x5C, 0x3E, 0x87, 0x59, 0x3F, 0x6B, 0x0A, 0xD8, + 0x22, 0x39, 0x48, 0x8A, 0xE4, 0x50, 0x23, 0x8F, + 0x3A, 0x6E, 0xE1, 0x60, 0xA3, 0xDE, 0xB3, 0xFA, + 0xEA, 0xD4, 0x8B, 0x25, 0x17, 0xB1, 0x4E, 0xBA, + 0x0E, 0x97, 0x22, 0x37, 0xEE, 0xFE, 0x5D, 0x42, + 0xB5, 0xE5, 0xC1, 0x96, 0x34, 0xA6, 0x0E, 0x11, + 0xAA, 0x41, 0xD4, 0xF5, 0xDA, 0x40, 0x22, 0x2B, + 0xF9, 0x9E, 0x9C, 0x55, 0x6C, 0xB9, 0x73, 0xDF, + 0x94, 0x71, 0x8B, 0x90, 0x91, 0x67, 0xF4, 0xFE, + 0x01, 0x90, 0x64, 0xB8, 0xB8, 0x31, 0x85, 0xAE, + 0x82, 0x1B, 0x65, 0xD4, 0xC8, 0x61, 0x9D, 0x1D, + 0x9A, 0x94, 0x40, 0xD9, 0x7C, 0xE2, 0xE9, 0x09, + 0xE9, 0x2B, 0xD0, 0xEB, 0xBE, 0x57, 0xAD, 0x29, + 0xCB, 0xA5, 0xD4, 0x46, 0xBA, 0xB6, 0x86, 0xB8, + 0xD1, 0x2F, 0x0B, 0xFC, 0xCA, 0x43, 0xBA, 0x60, + 0xA2, 0x0F, 0xA6, 0xC6, 0x2F, 0x05, 0x0A, + + 0xA1, 0x11, 0x6A, 0x04, 0xA8, 0x55, 0xB1, 0x04, + 0xA8, 0x6F, 0x55, 0x85, 0xE9, 0xF1, 0x0D, 0x6F, + 0xDD, 0x04, 0x10, 0x3C, 0xB3, 0xAD, 0xD2, 0x9E, + 0xE7, 0x1E, 0x08, 0xBF, 0x65, 0x0A, 0xB0, 0xB4, + 0x95, 0x6D, 0xC6, 0x3E, 0xD8, 0x71, 0x46, 0x3E, + 0x1B, 0x1E, 0x82, 0x8D, 0x16, 0xF8, 0x98, 0xF1, + 0xEC, 0x0B, 0x0C, 0xFB, 0x73, 0xDB, 0x28, 0x1E, + 0xC1, 0xD0, 0xC2, 0xB1, 0xB0, 0x48, 0x02, 0xD9, + 0x69, 0xC5, 0x72, 0x6D, 0xB2, 0xD2, 0xCE, 0x15, + 0x8C, 0x77, 0xAD, 0x48, 0x7C, 0x4D, 0xEA, 0x87, + 0x5E, 0x13, 0x6D, 0x61, 0xFE, 0xFC, 0x75, 0xAA, + 0x76, 0x55, 0x2E, 0x87, 0x26, 0x92, 0x9D, 0x43, + 0x61, 0x7D, 0x1F, 0xFD, 0xE0, 0xCA, 0xC0, 0x87, + 0xAF, 0xAF, 0xC4, 0x92, 0x37, 0xED, 0xBB, 0x4F, + 0x38, 0x03, 0xE0, 0x1E, 0x1D, 0xB1, 0x4A, 0xBA, + 0x9A, 0xA0, 0x14, 0x84, 0x90, 0x90, 0x70, 0x62, + 0xA2, 0x55, 0x1D, 0x49, 0xD1, 0x51, 0xF1, 0x9B, + 0x1E, 0xD6, 0x8C, 0x02, 0xA4, 0xE2, 0x2D, 0x0E, + + 0xB9, 0xED, 0x83, 0x89, 0xD5, 0x73, 0x97, 0x72, + 0x3A, 0xF3, 0x32, 0x9A, 0xC4, 0xE0, 0x80, 0x5B, + 0xA3, 0x2E, 0x18, 0x82, 0xD9, 0x6D, 0xDC, 0xA3, + 0x4F, 0x00, 0x24, 0x67, 0x52, 0xDC, 0xD9, 0x07, + 0x1E, 0x62, 0x1A, 0xC8, 0xA8, 0xC0, 0xEF, 0x68, + 0x5E, 0xED, 0x2A, 0x23, 0xA2, 0x91, 0xC4, 0x49, + 0x69, 0xF4, 0xC1, 0x84, 0x60, 0x84, 0xAB, 0x34, + 0x91, 0x73, 0x76, 0x4A, 0x70, 0x98, 0xD5, 0x42, + 0xA0, 0x8C, 0x69, 0x1A, 0x6B, 0xC5, 0x90, 0x86, + 0x4E, 0xF3, 0x4C, 0xA0, 0xBA, 0x47, 0x4F, 0x41, + 0x0E, 0x83, 0x30, 0xF7, 0x5B, 0x47, 0x4C, 0x2D, + 0x78, 0xB9, 0x49, 0x51, 0x54, 0xF4, 0x01, 0x23, + 0x77, 0x6D, 0x2D, 0x05, 0x1F, 0xA9, 0xA5, 0x65, + 0x83, 0x92, 0xF3, 0xCE, 0x19, 0x2A, 0x9A, 0xF2, + 0xC6, 0x9C, 0x08, 0x8D, 0xF9, 0x31, 0xCA, 0xD0, + 0xF0, 0x56, 0xB9, 0xD2, 0xDE, 0x09, 0x6E, 0x7B, + 0xF1, 0x33, 0x45, 0xAD, 0x5D, 0x20, 0xC9, 0x6B, + 0x12, 0x91, 0xCC, 0xA0, 0x44, 0xF3, 0xB2, 0x9C, + 0x29, + + 0x28, 0x3B, 0xFC, 0xF7, 0x0B, 0xE0, 0x62, 0x2F, + 0xB3, 0x2E, 0x10, 0xD3, 0x78, 0x0C, 0x33, 0x6D, + 0xD7, 0xA8, 0xB2, 0xF7, 0x1C, 0x6C, 0xBA, 0xD0, + 0x67, 0x5F, 0xB5, 0xD3, 0x71, 0x09, 0xD7, 0x34, + 0xCE, 0xFB, 0xF0, 0xEE, 0x7D, 0x5C, 0xCE, 0x03, + 0x20, 0x85, 0xEA, 0xD6, 0x01, 0xF9, 0x4A, 0x3C, + 0x83, 0xC8, 0x59, 0xA3, 0x42, 0x90, 0xB3, 0x14, + 0x04, 0x86, 0xB1, 0x1A, 0xDB, 0x7C, 0x35, 0x56, + 0x96, 0x15, 0xE4, 0x17, 0x27, 0xB0, 0x47, 0xF2, + 0x75, 0x4E, 0xBD, 0x4D, 0x6D, 0x40, 0xDB, 0x03, + 0xBE, 0x34, 0x23, 0x9C, 0x80, 0xF3, 0x34, 0xF2, + 0x89, 0x43, 0xE2, 0x39, 0x4B, 0x9B, 0xD9, 0x1A, + 0xAB, 0x48, 0x4A, 0x97, 0x66, 0x87, 0xF8, 0x37, + 0x70, 0xCC, 0x05, 0x24, 0x48, 0x9F, 0xEF, 0x19, + 0x9C, 0xB4, 0x5F, 0x76, 0x28, 0xED, 0x59, 0x12, + 0x50, 0x5B, 0x69, 0x44, 0xA9, 0xBE, 0x40, 0xEE, + 0x2C, 0x97, 0xA3, 0x4A, 0x05, 0xCC, 0x57, 0xB8, + 0xC9, 0x26, 0x85, 0xE4, 0xB1, 0x58, 0xF2, 0x4D, + 0x9B, 0xA9, + + 0x36, 0xEF, 0xE2, 0x4F, 0xAE, 0x4C, 0xB1, 0xB3, + 0xB8, 0x22, 0x91, 0xB6, 0xC5, 0x31, 0x60, 0xFF, + 0x7B, 0x00, 0x71, 0x12, 0xAA, 0x5A, 0xD2, 0x10, + 0x5E, 0x0F, 0x4C, 0xB0, 0xDB, 0x09, 0x11, 0xC7, + 0x28, 0x6C, 0x88, 0x96, 0x97, 0xC6, 0xB7, 0x56, + 0x77, 0x20, 0xAB, 0xE4, 0x03, 0xFA, 0x7A, 0xCF, + 0x8E, 0xB7, 0x73, 0xEB, 0xD6, 0x80, 0xD8, 0xAE, + 0x6F, 0xCC, 0x22, 0x90, 0x49, 0x7B, 0x21, 0x57, + 0xAF, 0x39, 0x8E, 0x25, 0x98, 0x54, 0x2C, 0x7A, + 0xFC, 0xF1, 0xAE, 0xA0, 0xD7, 0x69, 0x95, 0x04, + 0x6A, 0x93, 0xDA, 0x41, 0x8F, 0xE3, 0x53, 0x7D, + 0x8C, 0xC4, 0xE6, 0x14, 0xD6, 0xF5, 0x23, 0x10, + 0xFF, 0xF4, 0x3D, 0x87, 0x8E, 0x44, 0x7B, 0xBD, + 0xDF, 0x5B, 0x81, 0x1E, 0x88, 0x9C, 0x8E, 0x3C, + 0xB3, 0xA1, 0x8D, 0xC9, 0x1F, 0xE2, 0x51, 0xFB, + 0x31, 0xBA, 0x07, 0x2D, 0xF8, 0xFA, 0x54, 0x88, + 0x64, 0x00, 0xA0, 0x73, 0x2A, 0xD7, 0x9B, 0x85, + 0xBB, 0xED, 0x0A, 0x2E, 0xA1, 0x98, 0x3D, 0x87, + 0xFA, 0x0A, 0x43, + + 0xAE, 0x78, 0x23, 0x96, 0x97, 0xE1, 0x6D, 0x02, + 0x31, 0xA9, 0x56, 0xBA, 0xDC, 0xA4, 0xDB, 0xD5, + 0x5F, 0x37, 0x26, 0xF8, 0xED, 0x78, 0x79, 0xAA, + 0x7B, 0xCC, 0xC3, 0x67, 0x38, 0x86, 0xB6, 0x58, + 0x7D, 0x2A, 0x5E, 0x77, 0xF8, 0xDB, 0x3A, 0xB0, + 0xB3, 0x83, 0x3A, 0xEF, 0xB5, 0xB0, 0x46, 0xA7, + 0x85, 0x98, 0xA8, 0x71, 0x1C, 0x2C, 0xB6, 0x06, + 0x3F, 0xEC, 0x59, 0x78, 0x15, 0xAD, 0x17, 0x65, + 0x94, 0x37, 0xC1, 0x21, 0xC9, 0x1A, 0x16, 0xEA, + 0x1A, 0xFE, 0x3D, 0x35, 0xF4, 0xBA, 0x5D, 0xA0, + 0x21, 0x9C, 0x89, 0x39, 0x69, 0xAB, 0x8E, 0x4B, + 0x8A, 0x9C, 0x38, 0xFD, 0x53, 0x37, 0xB4, 0x59, + 0xBE, 0xB0, 0x56, 0xD7, 0x6C, 0xF8, 0xB8, 0xF1, + 0x03, 0x26, 0xF5, 0x07, 0x98, 0xDB, 0xDF, 0xF3, + 0x9D, 0x02, 0x65, 0x78, 0x7C, 0xD7, 0x71, 0x06, + 0x93, 0xFF, 0xFA, 0xBE, 0xEF, 0x24, 0x24, 0x21, + 0x32, 0xD8, 0xC2, 0xFD, 0xB9, 0x08, 0xBC, 0x06, + 0xD6, 0xC1, 0xEE, 0x5D, 0xFE, 0xA1, 0x8D, 0x12, + 0x9A, 0x36, 0x5B, 0xB7, + + 0x61, 0x61, 0x14, 0x68, 0xE4, 0x54, 0x04, 0x1F, + 0xB4, 0x42, 0x87, 0x44, 0x7B, 0x01, 0xC6, 0xD6, + 0xF9, 0xBC, 0xE5, 0x1D, 0x25, 0x6E, 0xFB, 0xC9, + 0x2A, 0x50, 0x31, 0xB7, 0x8B, 0x11, 0x50, 0x39, + 0x2C, 0xE9, 0x37, 0xD1, 0x43, 0xD5, 0xD2, 0x9D, + 0x9D, 0x9E, 0x58, 0x1C, 0x14, 0x90, 0x8C, 0x0B, + 0xF0, 0x2D, 0xBE, 0xEB, 0xF4, 0x24, 0xA9, 0xFF, + 0x07, 0x5C, 0x8F, 0x49, 0x26, 0xEF, 0xC4, 0x74, + 0x8E, 0x32, 0x03, 0xCA, 0xBF, 0xB9, 0x8D, 0x3C, + 0x69, 0xE4, 0x3D, 0x35, 0x85, 0xC3, 0xAE, 0x35, + 0x33, 0x95, 0xD4, 0xE8, 0xAC, 0xBE, 0xE2, 0x2E, + 0xD2, 0x75, 0x3A, 0x42, 0x00, 0xBF, 0xC2, 0x61, + 0xF1, 0x0C, 0x5D, 0xFB, 0xC9, 0x59, 0xB1, 0xAC, + 0x37, 0x83, 0x7E, 0x52, 0xB0, 0x32, 0x38, 0x9E, + 0xD5, 0xCD, 0xE4, 0x77, 0x47, 0x08, 0x9B, 0x41, + 0x2A, 0x5D, 0xA7, 0x5E, 0xAA, 0xF2, 0xD3, 0x4F, + 0x76, 0x20, 0xB3, 0xD5, 0x55, 0xEE, 0x41, 0x00, + 0x8C, 0x7C, 0x38, 0x67, 0xF4, 0x38, 0x21, 0xB8, + 0x3F, 0x1E, 0x57, 0x46, 0x45, + + 0x66, 0xF1, 0x58, 0xCA, 0xD3, 0x81, 0x9F, 0x85, + 0x1D, 0x6F, 0xA2, 0xB5, 0xCB, 0x77, 0x12, 0x4C, + 0x41, 0xF2, 0x93, 0xED, 0x56, 0x04, 0xC7, 0xB1, + 0xA0, 0x9B, 0x6D, 0x51, 0x9C, 0xC8, 0xE9, 0xF3, + 0x9C, 0xE1, 0xC2, 0x91, 0x6A, 0x31, 0x05, 0x2A, + 0xB1, 0xEE, 0x19, 0xCD, 0x01, 0x30, 0x2F, 0x80, + 0x37, 0x03, 0xCD, 0xB1, 0x7D, 0xB8, 0xC0, 0x06, + 0x83, 0x00, 0xC7, 0x12, 0x85, 0x43, 0x8D, 0x67, + 0x12, 0xD8, 0xC8, 0x15, 0x62, 0x80, 0xA1, 0xE1, + 0x60, 0x42, 0x04, 0x74, 0x34, 0xBA, 0xBC, 0x67, + 0xF0, 0x04, 0xA7, 0x54, 0x3C, 0x6C, 0x0B, 0x10, + 0x2E, 0x02, 0x4D, 0x4F, 0x4A, 0x45, 0x97, 0x8E, + 0xF6, 0x50, 0x65, 0x44, 0xD0, 0x8B, 0x72, 0x33, + 0xCE, 0xD9, 0xDE, 0x7A, 0xE9, 0x98, 0x6F, 0x0C, + 0xE7, 0x79, 0xA8, 0x11, 0x73, 0x83, 0xF2, 0x93, + 0x5B, 0xE7, 0x3E, 0x4B, 0x81, 0xCE, 0xFB, 0x4E, + 0x27, 0x73, 0x7E, 0x66, 0xFA, 0x55, 0x1F, 0xCE, + 0xE8, 0xC3, 0x38, 0x7D, 0x04, 0xC6, 0xC3, 0x30, + 0x47, 0x8B, 0x02, 0x9D, 0x81, 0x49, + + 0x0A, 0x2A, 0x5B, 0x2B, 0x5E, 0xA4, 0x2B, 0x40, + 0x5E, 0x95, 0x70, 0x40, 0x23, 0x66, 0xD1, 0x1A, + 0x27, 0x79, 0x3F, 0x3C, 0xA9, 0x86, 0xF2, 0x75, + 0x2A, 0x52, 0x2E, 0xFE, 0x4E, 0x8E, 0x7E, 0x20, + 0x79, 0x19, 0x98, 0xDD, 0x01, 0x3F, 0x19, 0x68, + 0x23, 0x0A, 0xF0, 0x18, 0xA7, 0x13, 0x33, 0xF3, + 0x9E, 0x04, 0xA7, 0xA9, 0x01, 0xFA, 0xAC, 0xF3, + 0x81, 0x3D, 0xC6, 0x57, 0x35, 0x8C, 0xFE, 0x5D, + 0xCB, 0xE6, 0xF3, 0xA6, 0xCF, 0x18, 0x96, 0x70, + 0xCF, 0xAD, 0x05, 0xC6, 0x75, 0x05, 0x02, 0x50, + 0xA6, 0xAA, 0x88, 0xBC, 0x57, 0xA9, 0x14, 0x1A, + 0xF9, 0x1A, 0xD3, 0x40, 0xC7, 0x48, 0xFF, 0xE0, + 0x2D, 0xC6, 0xA8, 0x94, 0xBA, 0x3F, 0xFA, 0x76, + 0x44, 0xBA, 0xE8, 0x3E, 0xCC, 0x0D, 0x16, 0x8A, + 0x72, 0x91, 0xD8, 0xB1, 0x29, 0xC7, 0x3C, 0x67, + 0x1E, 0xA2, 0x3A, 0x9C, 0x9F, 0x5B, 0xCD, 0x41, + 0x8C, 0xCB, 0xFF, 0xFE, 0x70, 0x6F, 0xDA, 0xDF, + 0x10, 0x4B, 0xFF, 0x9A, 0xBF, 0x3E, 0xFF, 0x98, + 0x4E, 0x62, 0x15, 0x96, 0x97, 0xE1, 0x4E, + + 0x18, 0xDD, 0xC6, 0xD7, 0x31, 0x4C, 0x44, 0xF5, + 0x63, 0x56, 0x9C, 0xDF, 0xDC, 0x2D, 0x25, 0x5A, + 0xBF, 0x0C, 0x40, 0x69, 0x86, 0xDA, 0xA8, 0x76, + 0x86, 0x9C, 0x74, 0x9F, 0xDD, 0x04, 0x01, 0x9E, + 0x0B, 0x70, 0xEF, 0xE1, 0xF6, 0x26, 0x58, 0x5F, + 0x10, 0x2F, 0x9D, 0xC7, 0xAC, 0x4C, 0x19, 0x85, + 0xC8, 0x3E, 0xE8, 0xFF, 0xC4, 0x6C, 0x17, 0xB0, + 0xB9, 0x2E, 0x00, 0xD6, 0xEA, 0xF0, 0xFA, 0x40, + 0x93, 0x8D, 0x6F, 0xFD, 0x0B, 0xF5, 0x59, 0xEC, + 0xEA, 0x64, 0x26, 0x9D, 0x5F, 0xB2, 0x26, 0x1E, + 0x4C, 0xC8, 0x65, 0xAD, 0xD4, 0xC1, 0xAD, 0x63, + 0x29, 0x6C, 0x11, 0xCB, 0xE6, 0xDC, 0xF8, 0x2E, + 0x18, 0xA7, 0x50, 0xF0, 0x8F, 0x0E, 0x9B, 0x95, + 0xCC, 0x74, 0x3D, 0xB1, 0x9C, 0xD3, 0x50, 0x08, + 0x18, 0x5E, 0x27, 0x15, 0xD3, 0xF3, 0x5A, 0xC0, + 0x63, 0xEC, 0xB1, 0x4C, 0x77, 0x77, 0x9B, 0xE9, + 0x7B, 0x57, 0x0C, 0x31, 0xAA, 0xB5, 0xCE, 0x6C, + 0x4F, 0x46, 0x16, 0x0D, 0x55, 0xB9, 0x36, 0xF1, + 0xFA, 0x36, 0xE8, 0x89, 0xB0, 0x7B, 0xBB, 0x84, + + 0xF3, 0x24, 0x87, 0xDA, 0x52, 0xDC, 0x22, 0x0A, + 0xE1, 0x8E, 0x6A, 0x1A, 0xA6, 0x6C, 0x16, 0x48, + 0xFD, 0x70, 0xF9, 0x3E, 0x45, 0xF7, 0xE3, 0x6A, + 0xAC, 0x92, 0x5A, 0x82, 0xD1, 0xC3, 0x8C, 0x7E, + 0x76, 0x69, 0x3E, 0x34, 0x66, 0x25, 0x46, 0xD0, + 0x17, 0xEE, 0x25, 0xD2, 0xB2, 0x2A, 0xCE, 0xB8, + 0x6A, 0x56, 0x2C, 0x37, 0xB0, 0x51, 0x62, 0x1A, + 0x04, 0xB9, 0x68, 0xAA, 0x9B, 0x30, 0xEE, 0x17, + 0x57, 0xFC, 0x98, 0xCF, 0x7E, 0x4B, 0xAB, 0x25, + 0xA0, 0x91, 0x6E, 0x68, 0x23, 0x55, 0xF0, 0xC7, + 0x20, 0xA7, 0x3B, 0xE1, 0x03, 0xB3, 0x94, 0x2C, + 0x5D, 0xC1, 0x50, 0x32, 0x61, 0xB8, 0x63, 0x69, + 0x61, 0x74, 0x61, 0xCA, 0xC1, 0x49, 0x25, 0x63, + 0x9B, 0xA1, 0x5A, 0x09, 0x23, 0x44, 0x05, 0x97, + 0xCA, 0x73, 0xA6, 0x57, 0x92, 0xA5, 0x22, 0x18, + 0x82, 0x55, 0x0E, 0xFF, 0xE7, 0x53, 0xA9, 0x71, + 0x25, 0xC6, 0x2D, 0x02, 0x07, 0xD4, 0x51, 0x12, + 0x18, 0x03, 0x71, 0x4F, 0x10, 0x23, 0x17, 0xF0, + 0x76, 0xB3, 0x3B, 0x57, 0x8D, 0x88, 0xDA, 0x6F, + 0x5F, + + 0xCB, 0xF5, 0x44, 0xA5, 0x45, 0x49, 0x7D, 0x58, + 0xA6, 0x10, 0x4B, 0x4E, 0x81, 0xF2, 0x15, 0x21, + 0x03, 0xFB, 0xD2, 0x34, 0xE2, 0xF8, 0x99, 0x09, + 0x5D, 0x59, 0x24, 0xFF, 0xB9, 0x0D, 0xBC, 0xF6, + 0x2B, 0x11, 0x55, 0x4D, 0x50, 0x7C, 0xCD, 0x18, + 0x94, 0x92, 0xF3, 0x5C, 0x95, 0x7A, 0x64, 0xF7, + 0x35, 0x27, 0x56, 0x79, 0xD6, 0xD8, 0x81, 0xE0, + 0xF3, 0x3F, 0x80, 0x8F, 0x97, 0x1B, 0xD8, 0x15, + 0x70, 0x15, 0x2D, 0xC0, 0x2E, 0x7E, 0x79, 0xF8, + 0x1F, 0x88, 0xB7, 0xB7, 0xFF, 0x53, 0x67, 0xE8, + 0xC1, 0x59, 0x89, 0x66, 0xFD, 0x66, 0x4E, 0x88, + 0xA0, 0xCD, 0xC6, 0xD0, 0x34, 0x0C, 0x31, 0xE3, + 0xD4, 0x5F, 0x32, 0x32, 0xAC, 0xCC, 0xE1, 0x24, + 0x8C, 0x4E, 0xC9, 0x39, 0xC3, 0x7A, 0x6B, 0xAB, + 0xAE, 0x6C, 0x01, 0x79, 0x6D, 0xB4, 0xAF, 0x49, + 0x12, 0x10, 0xB3, 0xC5, 0x20, 0xB9, 0x63, 0x99, + 0x79, 0xC1, 0x22, 0xE4, 0x74, 0x15, 0x42, 0x61, + 0x98, 0x4E, 0xDC, 0x13, 0xD0, 0xE1, 0xD8, 0x24, + 0x0A, 0xC5, 0xB4, 0x54, 0xDC, 0x3C, 0x00, 0xDE, + 0xFB, 0xEB, + + 0x01, 0x0B, 0xD7, 0x6A, 0x19, 0xF8, 0xD2, 0x4A, + 0xD6, 0xC8, 0xFA, 0x05, 0x69, 0x4A, 0x18, 0x97, + 0x35, 0x61, 0x8B, 0xB9, 0x8B, 0x7B, 0x0C, 0xD9, + 0xF4, 0xF4, 0xC4, 0x2F, 0x1F, 0xA9, 0x98, 0x16, + 0xB7, 0xD6, 0x1F, 0x4A, 0x59, 0x42, 0x37, 0x60, + 0x37, 0x20, 0x37, 0x5C, 0x16, 0x6E, 0x63, 0x49, + 0x25, 0x1A, 0x86, 0x42, 0x00, 0xC3, 0x4A, 0x33, + 0xC7, 0x7D, 0x06, 0x14, 0xC9, 0x98, 0x19, 0x9A, + 0xD3, 0x17, 0xB4, 0x61, 0x4F, 0x52, 0x09, 0x13, + 0x54, 0xFE, 0xE4, 0x47, 0xA4, 0xFF, 0xA5, 0x20, + 0x62, 0x52, 0xB1, 0xDD, 0x42, 0xF2, 0x1C, 0xE9, + 0x0E, 0x2D, 0xEA, 0x19, 0x51, 0xF5, 0x3E, 0x7D, + 0x27, 0xFF, 0x1D, 0x43, 0x96, 0x16, 0x9B, 0xBD, + 0x9D, 0x29, 0x0E, 0x19, 0x4B, 0x6E, 0x98, 0xF4, + 0xA3, 0x51, 0x3C, 0x14, 0x64, 0xBF, 0x93, 0xAA, + 0x3C, 0x86, 0xF8, 0xB5, 0x3A, 0x2C, 0x12, 0x10, + 0x52, 0xD6, 0xE9, 0xB6, 0x36, 0x91, 0x5B, 0x36, + 0x22, 0x9B, 0xD1, 0x00, 0xEC, 0xC6, 0x13, 0x13, + 0x1D, 0x83, 0xF4, 0xF9, 0xBE, 0xC0, 0x3E, 0x71, + 0x0B, 0x64, 0xDF, + + 0xF2, 0xB0, 0xFC, 0xD2, 0x54, 0x85, 0x18, 0xD4, + 0x31, 0x7A, 0x3E, 0xD5, 0xDD, 0x8D, 0x3C, 0xCC, + 0x4E, 0x92, 0x14, 0xE4, 0x21, 0x39, 0xF3, 0x73, + 0x66, 0x71, 0x77, 0x29, 0x37, 0x49, 0x6C, 0x72, + 0xFB, 0x51, 0x17, 0x6C, 0x9E, 0x4A, 0x7C, 0x8C, + 0xBF, 0x96, 0x13, 0x8F, 0xAE, 0x7E, 0x88, 0x15, + 0xE9, 0x5E, 0x1A, 0xC4, 0xA7, 0x42, 0xFA, 0x60, + 0xD5, 0xFB, 0xCF, 0x90, 0x56, 0x97, 0xBB, 0xAD, + 0xF2, 0x2C, 0x6B, 0x07, 0xA5, 0xE6, 0x99, 0x92, + 0x75, 0x55, 0x69, 0xE8, 0xA3, 0xD9, 0x05, 0xC4, + 0x95, 0xED, 0xD0, 0x8E, 0x18, 0x60, 0x86, 0x86, + 0xEB, 0xC3, 0x20, 0xA8, 0xB9, 0x2E, 0xB8, 0x38, + 0xEB, 0xCE, 0x48, 0x2E, 0x4B, 0x42, 0xD6, 0xFB, + 0xDF, 0x97, 0xC4, 0xCD, 0x8C, 0xFD, 0x98, 0x0E, + 0xAC, 0xC2, 0xC4, 0xDA, 0x07, 0xFF, 0x8D, 0x72, + 0xF3, 0x15, 0x6F, 0x69, 0x3A, 0x61, 0x5F, 0xE0, + 0xAE, 0x1B, 0xCB, 0x16, 0x91, 0xEF, 0x54, 0x92, + 0xFC, 0xCD, 0xAF, 0xF4, 0x45, 0x4F, 0x2A, 0xCD, + 0xF8, 0xE4, 0x3F, 0x99, 0x2C, 0x61, 0xEC, 0x23, + 0xE3, 0x8B, 0xAB, 0x8F, + + 0x7C, 0x3F, 0x27, 0xDE, 0xAF, 0xE9, 0x72, 0x9C, + 0x04, 0xDA, 0xB4, 0xBB, 0xE6, 0x6F, 0x56, 0xF1, + 0xE8, 0x7E, 0xB5, 0xDA, 0x14, 0x2D, 0xFA, 0x29, + 0x80, 0x87, 0x53, 0x78, 0x65, 0xF7, 0x98, 0x64, + 0xB7, 0x11, 0x1A, 0x08, 0x4F, 0x36, 0x7E, 0xF8, + 0x4F, 0x0C, 0x70, 0xFE, 0xAF, 0xF1, 0x72, 0xC9, + 0xB8, 0x39, 0x57, 0xCB, 0x10, 0x61, 0x95, 0x49, + 0xEA, 0xB4, 0x2B, 0xA0, 0x77, 0x76, 0x30, 0x5D, + 0x9A, 0xB5, 0xCB, 0xF4, 0x5F, 0xC7, 0xA6, 0xD8, + 0x3A, 0x9E, 0xA8, 0xA1, 0x9F, 0xAB, 0xCC, 0x2C, + 0x2D, 0x8C, 0xCF, 0x3D, 0x7C, 0x11, 0xC6, 0xE9, + 0xD5, 0x15, 0xA2, 0xB8, 0xCE, 0x11, 0x45, 0x52, + 0x94, 0x0D, 0xE3, 0xF4, 0x47, 0x4A, 0xC6, 0x2E, + 0x7A, 0xBF, 0xBB, 0x4D, 0x2A, 0x89, 0xE5, 0x49, + 0x51, 0xDE, 0x25, 0x36, 0x58, 0x52, 0x3F, 0xA3, + 0xAD, 0xFE, 0xE3, 0xA3, 0x31, 0x90, 0xDA, 0xA3, + 0x1D, 0x48, 0xD6, 0xE8, 0xF2, 0x9E, 0x4C, 0xEC, + 0xCA, 0xC7, 0x46, 0x3C, 0xD5, 0x89, 0x01, 0xA7, + 0x33, 0xD3, 0x50, 0x7E, 0x31, 0x1C, 0x8E, 0xFF, + 0xF0, 0xB4, 0x42, 0x70, 0xA5, + + 0xDB, 0xFD, 0x65, 0xEB, 0x8C, 0xA7, 0x97, 0xE5, + 0xC7, 0xF4, 0x2E, 0xD4, 0x19, 0xCD, 0xA6, 0x0F, + 0x56, 0x39, 0xE3, 0x55, 0xF6, 0xFA, 0x43, 0xAC, + 0x3C, 0x0A, 0x1E, 0x00, 0xBF, 0x36, 0x1B, 0x95, + 0x71, 0x7E, 0x73, 0xBF, 0x93, 0x76, 0xF6, 0x2D, + 0xCB, 0x35, 0xBE, 0x43, 0x33, 0x2B, 0x89, 0x2D, + 0x85, 0x8A, 0xCE, 0x2F, 0xE7, 0x9C, 0x39, 0xD7, + 0x01, 0x69, 0x2E, 0xB3, 0xE7, 0xED, 0xEF, 0x41, + 0x06, 0xE7, 0xFC, 0x1F, 0x4B, 0x42, 0x71, 0xB2, + 0x59, 0x55, 0xEB, 0xBD, 0x18, 0x12, 0x63, 0x7F, + 0xEE, 0x10, 0x35, 0x84, 0x4E, 0x58, 0x9C, 0x75, + 0x86, 0xAB, 0x7F, 0x54, 0x8C, 0x90, 0x79, 0xAD, + 0xE7, 0xA6, 0x40, 0xCA, 0xB3, 0x6D, 0x8A, 0x14, + 0x8A, 0xE5, 0x13, 0x8C, 0x6E, 0xE9, 0x99, 0x56, + 0x11, 0xFC, 0xD4, 0x3B, 0xF5, 0xCB, 0x65, 0x33, + 0xEF, 0x98, 0x63, 0x7F, 0x91, 0x22, 0xD1, 0x2E, + 0xF4, 0xE0, 0xB3, 0xE8, 0xA6, 0x9E, 0xF9, 0x10, + 0xC6, 0xF1, 0x21, 0x95, 0x8C, 0x34, 0x2D, 0x7C, + 0x54, 0x92, 0x8D, 0x8F, 0xB6, 0x03, 0x34, 0xF7, + 0xF7, 0xD8, 0x5A, 0xBA, 0x57, 0x50, + + 0x41, 0x62, 0x0B, 0xC6, 0xC6, 0x43, 0xE4, 0x2D, + 0x36, 0x29, 0x87, 0x1D, 0x0D, 0xAC, 0xDB, 0xF0, + 0x00, 0x89, 0xBD, 0xE6, 0x48, 0x04, 0x24, 0x0C, + 0x28, 0x54, 0x88, 0x94, 0x3E, 0x1F, 0x2F, 0x5D, + 0x1C, 0xC1, 0x18, 0x38, 0xA6, 0xA5, 0xCA, 0xC3, + 0xAF, 0x5C, 0xDF, 0xAD, 0x8B, 0x4F, 0x53, 0x9E, + 0x6B, 0x99, 0xAB, 0x09, 0x2F, 0xD8, 0x11, 0xF9, + 0xC9, 0xAB, 0x73, 0x0A, 0xE6, 0x50, 0x6F, 0xBD, + 0xA5, 0xD1, 0x16, 0xFE, 0xC3, 0x11, 0xDE, 0x11, + 0x72, 0xC4, 0x71, 0x80, 0x40, 0x02, 0x14, 0x1F, + 0xC1, 0x6C, 0xE3, 0x28, 0xF8, 0xD8, 0x99, 0x06, + 0x1B, 0x90, 0x55, 0xFB, 0x67, 0x1D, 0x37, 0xA8, + 0xF9, 0xC7, 0xB2, 0xAD, 0x0F, 0x6C, 0xF4, 0x0F, + 0x1B, 0x42, 0xBD, 0x57, 0x51, 0x56, 0xA5, 0x83, + 0x7A, 0x15, 0x1C, 0x1A, 0xCF, 0x8C, 0xA4, 0x1B, + 0xF2, 0xFB, 0xDF, 0xC1, 0xCE, 0xD1, 0xF3, 0x29, + 0x7B, 0xA6, 0xA7, 0xE8, 0xA8, 0xB4, 0xCF, 0xEC, + 0x4E, 0xD7, 0x92, 0x82, 0x3A, 0x27, 0x05, 0xEF, + 0x88, 0x1B, 0x9C, 0x04, 0xAD, 0xF9, 0x51, 0x94, + 0xA6, 0xC1, 0xF8, 0x16, 0x3F, 0x5F, 0xF2, + + 0xFC, 0xF4, 0xBD, 0x0F, 0xE9, 0x09, 0xA4, 0xCE, + 0x31, 0x2D, 0x53, 0xD4, 0x15, 0xE5, 0x62, 0xF6, + 0x72, 0x63, 0x22, 0x53, 0x93, 0x2E, 0xCB, 0x30, + 0x01, 0x5C, 0x1C, 0xBA, 0x04, 0xA6, 0x95, 0x46, + 0x4E, 0x03, 0xEC, 0x36, 0xA2, 0xBE, 0x86, 0xD7, + 0x6E, 0x92, 0x2C, 0xEF, 0x64, 0x45, 0x94, 0x22, + 0xF8, 0x11, 0x43, 0x2D, 0x81, 0x04, 0xE6, 0x7B, + 0xEC, 0xE3, 0xF9, 0x9A, 0x43, 0xEF, 0xA7, 0xC9, + 0x5F, 0x39, 0x56, 0x6D, 0x3A, 0xBC, 0x26, 0xCD, + 0x77, 0x6F, 0x38, 0x30, 0x0A, 0x78, 0xD3, 0x98, + 0x71, 0xE1, 0x2C, 0xEA, 0xC2, 0xD8, 0x69, 0x18, + 0x74, 0xFE, 0x91, 0x1C, 0xAF, 0x5D, 0x8D, 0xDB, + 0x59, 0xDA, 0x52, 0xCD, 0xE4, 0x0D, 0x76, 0x41, + 0x9E, 0x6C, 0xD3, 0x85, 0x96, 0x3C, 0x8E, 0x66, + 0xDF, 0xED, 0x26, 0x03, 0x84, 0x88, 0x9D, 0x25, + 0x39, 0x35, 0xAD, 0xB5, 0x8B, 0xBB, 0xC5, 0x64, + 0xCE, 0xC5, 0xD7, 0x88, 0x5C, 0x2D, 0x46, 0x47, + 0x80, 0x11, 0x43, 0x85, 0xF1, 0xEB, 0x90, 0x71, + 0xA4, 0xB7, 0x5A, 0x3B, 0xB4, 0x51, 0x68, 0x76, + 0x63, 0x4D, 0x8F, 0x9F, 0x65, 0x6F, 0x9D, 0x03, + + 0x80, 0x5F, 0x0F, 0xB1, 0x39, 0x5B, 0xF6, 0x33, + 0xF7, 0x1C, 0xE6, 0x3C, 0x31, 0xC4, 0x31, 0x1A, + 0x14, 0x67, 0x38, 0x6C, 0x79, 0x59, 0x05, 0xF2, + 0x1F, 0xBA, 0xF2, 0xAE, 0x0C, 0xFF, 0xC5, 0x22, + 0x89, 0xB9, 0x2C, 0x88, 0xD1, 0x10, 0x24, 0xD1, + 0xBA, 0xD4, 0xD7, 0x41, 0x45, 0xAF, 0x57, 0xFC, + 0xF6, 0x97, 0x81, 0x4D, 0xA5, 0xF9, 0xC2, 0x25, + 0xFC, 0x3B, 0xBD, 0x0E, 0x96, 0xC2, 0x8B, 0xE3, + 0x93, 0x67, 0x65, 0xC4, 0x1D, 0x2A, 0x86, 0xCC, + 0x8A, 0x87, 0x4C, 0x35, 0xF7, 0x55, 0x51, 0xD6, + 0x8A, 0x8A, 0xE8, 0xE8, 0x69, 0xEF, 0x1A, 0xED, + 0xCB, 0x09, 0x4C, 0xE1, 0x4F, 0x36, 0xA6, 0xBD, + 0x68, 0x6B, 0x87, 0xC1, 0x39, 0x5E, 0x63, 0x61, + 0xA7, 0x19, 0x60, 0x3E, 0x1A, 0x2A, 0xF0, 0x43, + 0xA4, 0xE5, 0xE3, 0xEF, 0x76, 0x20, 0xA1, 0x7D, + 0x61, 0xFB, 0xC0, 0x8D, 0xED, 0xB0, 0x78, 0xDB, + 0xEC, 0x53, 0x44, 0x4A, 0x94, 0x42, 0x39, 0x83, + 0x41, 0x49, 0xBC, 0xA5, 0x17, 0x6C, 0xB4, 0x89, + 0x8D, 0xAB, 0x32, 0x40, 0x05, 0x69, 0x44, 0xF8, + 0x9A, 0x8B, 0x60, 0xD5, 0x47, 0x31, 0xD5, 0x17, + 0x1A, + + 0x99, 0xC8, 0x1F, 0x50, 0x51, 0xE0, 0xCA, 0x64, + 0x60, 0x38, 0x24, 0x34, 0x8B, 0x37, 0x13, 0x87, + 0x05, 0xE5, 0x3D, 0x7E, 0x8F, 0x8D, 0xF7, 0xD5, + 0x92, 0x06, 0xA4, 0x32, 0xD9, 0x64, 0xD8, 0xFC, + 0x1B, 0x5E, 0x46, 0xE4, 0x97, 0x14, 0x80, 0x2D, + 0xE2, 0x7B, 0x2E, 0xC4, 0xC2, 0x50, 0x0C, 0xDC, + 0xC1, 0xE6, 0x6A, 0x5F, 0x37, 0x02, 0x36, 0x24, + 0x98, 0x51, 0xB5, 0x92, 0x4E, 0x95, 0x80, 0x3E, + 0x93, 0x21, 0x03, 0xFB, 0x41, 0x20, 0x85, 0x55, + 0x39, 0xFC, 0xFC, 0x9E, 0xE6, 0x5B, 0x21, 0x29, + 0xC6, 0xCD, 0x63, 0x6B, 0xB8, 0x66, 0xB3, 0xB2, + 0x77, 0xE6, 0xA3, 0x3A, 0x40, 0x6C, 0xD0, 0x7C, + 0xEA, 0x36, 0x5F, 0x3E, 0xA2, 0x47, 0x64, 0xD9, + 0xF5, 0x94, 0x09, 0xE6, 0xC4, 0x90, 0x0E, 0xF6, + 0x5E, 0xE5, 0x9E, 0x54, 0xFC, 0x32, 0x51, 0x0F, + 0xED, 0x6A, 0xEE, 0x50, 0x29, 0x47, 0x0C, 0xEF, + 0xCD, 0x3D, 0x83, 0x2F, 0xA4, 0x62, 0x93, 0x0A, + 0x28, 0xEF, 0xD9, 0xAD, 0x6F, 0xAE, 0x79, 0x1B, + 0x7E, 0xB8, 0xEC, 0x21, 0x53, 0x13, 0x21, 0xDF, + 0x01, 0x81, 0x4C, 0x30, 0x07, 0x58, 0x6E, 0x80, + 0x1A, 0xED, + + 0x78, 0x66, 0x40, 0x07, 0x32, 0x18, 0x83, 0x4D, + 0x35, 0x65, 0x2D, 0xD2, 0x93, 0x09, 0xEF, 0xF7, + 0x5F, 0xD6, 0xB0, 0x99, 0xD9, 0xD0, 0xC5, 0xD7, + 0xF7, 0xC3, 0xDF, 0xD2, 0x01, 0xB2, 0x80, 0x7F, + 0xC5, 0xC8, 0x9A, 0xB3, 0x1B, 0x1D, 0x4A, 0x3E, + 0x05, 0xD4, 0x5B, 0xB5, 0xC5, 0x61, 0x7A, 0x16, + 0x49, 0x0E, 0xB3, 0x17, 0x30, 0x81, 0x10, 0xA0, + 0xC7, 0xE7, 0x3E, 0x1D, 0xAC, 0x2B, 0x36, 0x02, + 0xB2, 0x82, 0x7D, 0xAD, 0xD4, 0x24, 0x34, 0xC6, + 0x90, 0x19, 0x7E, 0xE0, 0xAD, 0xE2, 0xB2, 0xDE, + 0x59, 0xB8, 0xB5, 0x98, 0xC5, 0xEE, 0xA4, 0x14, + 0x8E, 0x4E, 0xEB, 0x9C, 0xA3, 0x27, 0x35, 0xF5, + 0x03, 0x8F, 0x3F, 0x24, 0xED, 0x7D, 0xA1, 0x86, + 0xFE, 0xD3, 0xD7, 0x45, 0xC8, 0x48, 0xDC, 0xA1, + 0x2E, 0xF9, 0xDF, 0xB3, 0x15, 0xD9, 0x16, 0x8E, + 0xEA, 0x52, 0xDE, 0x70, 0x71, 0xA9, 0x6A, 0x48, + 0x75, 0xBD, 0x6C, 0x8C, 0xF4, 0x51, 0x93, 0x35, + 0x7F, 0xD8, 0x59, 0xDB, 0xEE, 0x97, 0xB3, 0x15, + 0xC2, 0x66, 0x95, 0xB9, 0x09, 0x7F, 0x22, 0x4A, + 0x0D, 0xBF, 0xCE, 0x05, 0x11, 0x14, 0x72, 0x83, + 0x89, 0x77, 0x48, + + 0x36, 0x9A, 0x46, 0xA7, 0xD8, 0x92, 0xA3, 0x4A, + 0xBE, 0x55, 0xDA, 0xBE, 0xB4, 0x8D, 0x58, 0x09, + 0x0F, 0xEB, 0x49, 0x0C, 0xFE, 0xDA, 0x5E, 0xB3, + 0xCF, 0xB5, 0xDF, 0x65, 0x4B, 0x37, 0xF4, 0xFF, + 0x0F, 0x68, 0x8C, 0xBE, 0x3C, 0x36, 0x62, 0x54, + 0xF1, 0xC5, 0x76, 0x64, 0x6E, 0x7F, 0xCC, 0x91, + 0x61, 0x77, 0xB5, 0xD1, 0x5F, 0x56, 0x35, 0xAA, + 0xFB, 0x72, 0x8E, 0x21, 0xFF, 0x33, 0xD5, 0x36, + 0xFE, 0xF6, 0x85, 0x63, 0x58, 0x02, 0x6A, 0x35, + 0x0C, 0x3F, 0x42, 0xE2, 0xF7, 0xE7, 0x36, 0xC1, + 0x11, 0x49, 0x75, 0x99, 0x6D, 0x39, 0x68, 0x7F, + 0x17, 0x54, 0x29, 0x5A, 0x88, 0xAF, 0x48, 0xFC, + 0xF7, 0xC9, 0xD1, 0x39, 0xA2, 0xBD, 0x1D, 0xBF, + 0xAA, 0xA2, 0x37, 0x9D, 0x71, 0x7D, 0xEC, 0xF5, + 0x7C, 0xEC, 0x1C, 0x21, 0xBC, 0x73, 0x4D, 0x69, + 0xA5, 0x0C, 0xA1, 0x6E, 0xDA, 0x84, 0x52, 0xB9, + 0xED, 0xE6, 0x3C, 0xAC, 0x0D, 0xEA, 0x78, 0x40, + 0x4A, 0x24, 0x6C, 0xC5, 0xA9, 0xB9, 0x6C, 0x9A, + 0x57, 0xC4, 0xA3, 0xC2, 0x66, 0x8F, 0x4D, 0x9E, + 0x85, 0x14, 0x26, 0xB2, 0x9B, 0xB5, 0xEF, 0x22, + 0xE1, 0xA1, 0x50, 0x41, + + 0x96, 0x16, 0x23, 0x5B, 0x30, 0x81, 0xD1, 0x9A, + 0x66, 0x84, 0x92, 0xD1, 0xC4, 0x59, 0xE1, 0x24, + 0xFF, 0x2D, 0xA8, 0x6B, 0x83, 0x72, 0x38, 0xCD, + 0x7D, 0x4F, 0x5A, 0x85, 0x8A, 0x2E, 0xE9, 0x6B, + 0x48, 0x02, 0x54, 0xE4, 0x3B, 0x9F, 0x76, 0x13, + 0x9F, 0x9F, 0xF3, 0xE0, 0xF0, 0x48, 0x67, 0x9D, + 0x9F, 0x86, 0xCF, 0x7E, 0x7C, 0x1C, 0x0F, 0x61, + 0x64, 0xDA, 0x67, 0xBE, 0x68, 0x02, 0x08, 0x43, + 0x02, 0xF8, 0x68, 0x4C, 0x73, 0x4B, 0xCF, 0xFB, + 0xE8, 0xC7, 0x61, 0xCC, 0x62, 0x18, 0x39, 0xE4, + 0x04, 0x44, 0x36, 0x1E, 0xB7, 0xFB, 0xCC, 0x0A, + 0x05, 0xE7, 0x50, 0x28, 0x7F, 0xD0, 0x4F, 0xCF, + 0x81, 0xC2, 0x61, 0x72, 0x1C, 0x21, 0x76, 0x46, + 0x13, 0x05, 0x38, 0x5D, 0xEA, 0x2B, 0xF3, 0x5D, + 0xD9, 0x02, 0x3D, 0xBA, 0x4D, 0x79, 0x19, 0xB5, + 0xAC, 0xE3, 0xC7, 0x87, 0x0E, 0xA5, 0x40, 0xE5, + 0x68, 0x7A, 0x4A, 0xA1, 0x54, 0x1B, 0x10, 0xA0, + 0x9D, 0x00, 0x74, 0xB6, 0x86, 0x6D, 0x45, 0x77, + 0xBB, 0x7B, 0x4C, 0x8C, 0xD1, 0xCA, 0xC0, 0xA8, + 0xC1, 0x17, 0x17, 0x39, 0xD6, 0xC8, 0x8D, 0x75, + 0x63, 0x03, 0xB7, 0xCC, 0xA8, + + 0x18, 0xB2, 0xD0, 0xF4, 0xB4, 0xCD, 0x4D, 0xB5, + 0x3F, 0x45, 0x8E, 0x05, 0x57, 0x1A, 0x9E, 0xFB, + 0xA7, 0x46, 0xB9, 0x97, 0xC6, 0x72, 0x46, 0x48, + 0x84, 0xB2, 0xB3, 0x28, 0xBC, 0xF8, 0x3A, 0x70, + 0x4A, 0x1A, 0x26, 0x9D, 0x71, 0x31, 0xEC, 0xB2, + 0xA2, 0x26, 0x8A, 0x74, 0x03, 0x7D, 0x12, 0x07, + 0x09, 0x7B, 0xD9, 0x89, 0x3B, 0x76, 0xD6, 0xC5, + 0xB9, 0x25, 0x93, 0xFD, 0x15, 0xDA, 0x26, 0x9E, + 0x0D, 0x74, 0xAE, 0xCE, 0x81, 0xC1, 0x3E, 0x1F, + 0x4C, 0x86, 0x3C, 0x99, 0x0A, 0xC5, 0x28, 0x90, + 0x74, 0x39, 0x03, 0x07, 0x1F, 0x6A, 0xB5, 0xF1, + 0x64, 0xB4, 0xEC, 0xEE, 0x04, 0xEB, 0x46, 0xCA, + 0xCC, 0x2B, 0x3C, 0x6A, 0x9B, 0x06, 0x0A, 0xD9, + 0x76, 0xB6, 0xBB, 0x8B, 0xBD, 0x57, 0x7A, 0x31, + 0x87, 0x1D, 0x37, 0x2B, 0xAC, 0x43, 0xA5, 0x0F, + 0x0F, 0xC4, 0x25, 0x17, 0x65, 0xDF, 0xD3, 0x98, + 0x7F, 0x31, 0x89, 0xAF, 0xE2, 0x1D, 0xED, 0x3B, + 0x29, 0x5F, 0x35, 0x68, 0xEC, 0xC2, 0x77, 0x4A, + 0x9C, 0x5A, 0xAE, 0x52, 0x13, 0x8C, 0x98, 0x47, + 0x03, 0x1B, 0x20, 0x1A, 0x22, 0x4D, 0x87, 0x9D, + 0x40, 0x86, 0x48, 0xF8, 0x60, 0xFB, + + 0x63, 0x82, 0x97, 0xF6, 0x37, 0x44, 0x0E, 0x4B, + 0x54, 0x92, 0xA1, 0xFB, 0x06, 0x95, 0x89, 0x79, + 0x8F, 0x50, 0x5F, 0xD3, 0x46, 0x7A, 0xEB, 0xEC, + 0x98, 0x38, 0x40, 0x0E, 0xCC, 0x6C, 0x35, 0xBF, + 0x50, 0xD1, 0x6A, 0x3E, 0x08, 0x2E, 0x50, 0x8E, + 0xC2, 0xEB, 0xF3, 0xD8, 0x5A, 0xE8, 0xE3, 0xF4, + 0xC0, 0x37, 0x88, 0x04, 0x32, 0xAF, 0x17, 0xFC, + 0xEE, 0x42, 0x88, 0x84, 0xE7, 0xAD, 0x0F, 0xA7, + 0x51, 0xAB, 0x6A, 0xD5, 0x4B, 0xCF, 0xDB, 0xC2, + 0x09, 0xEF, 0x5D, 0x6B, 0x7F, 0x12, 0x79, 0x13, + 0xB0, 0xE8, 0xDE, 0x80, 0x72, 0x71, 0xD8, 0xDB, + 0x4E, 0x08, 0xF0, 0xA8, 0x7A, 0x68, 0xF8, 0x82, + 0xD5, 0xFD, 0xD3, 0x4A, 0x58, 0x2A, 0x99, 0x65, + 0xC2, 0x2C, 0x97, 0x59, 0x13, 0xA8, 0x96, 0x52, + 0xC3, 0xA9, 0x17, 0x47, 0xBA, 0x9C, 0xD9, 0xBB, + 0xBE, 0xAF, 0x91, 0x6F, 0xE0, 0xE3, 0x52, 0x9B, + 0xA5, 0x49, 0x7B, 0xEF, 0x5F, 0x2B, 0x03, 0xD7, + 0x4C, 0x46, 0xC0, 0xE8, 0x3F, 0xE5, 0x68, 0x7D, + 0xC9, 0xCC, 0x63, 0xA8, 0x85, 0x78, 0xFD, 0x0F, + 0x6A, 0x09, 0xBE, 0x1B, 0x1B, 0x62, 0x7A, 0x43, + 0x57, 0xF3, 0x7B, 0xC7, 0xD4, 0x9F, 0xF0, + + 0x48, 0xA5, 0xCC, 0x95, 0x4E, 0xDD, 0xE7, 0xF9, + 0x53, 0x3C, 0x37, 0xAC, 0xAA, 0x4D, 0xD7, 0x46, + 0x53, 0xD8, 0xC5, 0x51, 0x27, 0xFE, 0x09, 0x24, + 0x56, 0x0D, 0x9D, 0x57, 0x3B, 0x07, 0xB6, 0xA1, + 0x0E, 0x75, 0xF3, 0xC4, 0x80, 0x06, 0x49, 0x0B, + 0xFB, 0x36, 0x3A, 0x98, 0xB0, 0x98, 0xB8, 0xD1, + 0x4A, 0x9F, 0x7A, 0x3D, 0x06, 0x32, 0xDE, 0x00, + 0x8C, 0xF5, 0x5C, 0x65, 0xE8, 0xCB, 0x15, 0xF7, + 0x77, 0xE6, 0x93, 0x1F, 0x56, 0x21, 0x48, 0x7B, + 0xFF, 0xD1, 0x7E, 0xA2, 0xB1, 0xDB, 0x36, 0xC1, + 0x3D, 0x23, 0x9F, 0x8B, 0x2B, 0x23, 0x90, 0x58, + 0x9A, 0x60, 0xF2, 0x8D, 0x61, 0xAD, 0x69, 0x5C, + 0xC4, 0xA5, 0xB3, 0x68, 0xF0, 0x98, 0xD1, 0xB2, + 0xEA, 0x03, 0xE7, 0x02, 0x19, 0x81, 0x26, 0x5D, + 0x20, 0x4E, 0x61, 0xF1, 0xEC, 0xE6, 0x6C, 0xEF, + 0x0E, 0x55, 0x6F, 0x6D, 0x11, 0x84, 0x1A, 0x5B, + 0x7E, 0x82, 0x66, 0x88, 0x44, 0x63, 0x99, 0xB1, + 0x5B, 0xC5, 0xFB, 0x47, 0xFF, 0x9C, 0x39, 0xD6, + 0xC2, 0x96, 0xEC, 0xE3, 0xA7, 0xAA, 0xF7, 0xC2, + 0x93, 0xB2, 0x0D, 0x7B, 0x2A, 0xF8, 0xBA, 0x22, + 0x2E, 0xA5, 0x7C, 0x88, 0x41, 0x7E, 0x8A, 0xFA, + + 0x0F, 0x63, 0x92, 0x0D, 0x42, 0x3E, 0x56, 0x78, + 0x82, 0x58, 0xB7, 0x5A, 0xB4, 0xFF, 0x25, 0x5E, + 0xCD, 0x05, 0x8A, 0x3B, 0x00, 0xE7, 0xF0, 0x70, + 0xFE, 0x38, 0xC4, 0x17, 0x4D, 0x0A, 0x26, 0x71, + 0x3F, 0x64, 0x1F, 0x85, 0xE2, 0xF6, 0xED, 0x07, + 0x79, 0xDF, 0x7D, 0x03, 0x45, 0x0E, 0x26, 0xB1, + 0xC8, 0xD7, 0x7C, 0xE0, 0xF6, 0x3E, 0x6C, 0xDC, + 0xB2, 0x58, 0xFD, 0x56, 0x47, 0x69, 0xE1, 0x41, + 0xEB, 0x88, 0xEB, 0xE9, 0x8E, 0x73, 0x68, 0x4A, + 0xB4, 0xC3, 0x35, 0xA0, 0x2F, 0x8D, 0x07, 0x1E, + 0xE9, 0x7E, 0x63, 0x4D, 0x73, 0xEE, 0x79, 0x6A, + 0xA6, 0x84, 0x4A, 0x22, 0xE7, 0x88, 0xBC, 0x59, + 0x83, 0x41, 0xCD, 0x16, 0x73, 0x7C, 0xE3, 0xC0, + 0xEF, 0x23, 0x8C, 0x7A, 0x24, 0x16, 0x3F, 0x77, + 0x72, 0x10, 0xCF, 0x32, 0x1F, 0x2E, 0x37, 0xED, + 0x1B, 0x90, 0xD4, 0x4C, 0x71, 0x4D, 0x81, 0xBD, + 0x36, 0x6B, 0x6A, 0x2E, 0x07, 0xAD, 0x32, 0x35, + 0x76, 0x67, 0x66, 0xE1, 0x76, 0x95, 0x2F, 0x0A, + 0xF3, 0xF7, 0xC3, 0x25, 0x3D, 0xDF, 0xA1, 0x89, + 0xC2, 0xC1, 0x15, 0x7C, 0xD6, 0xA0, 0x07, 0x14, + 0x7D, 0x81, 0x83, 0x3B, 0x96, 0xBA, 0x39, 0x57, + 0x01, + + 0x41, 0xC2, 0x86, 0x92, 0x97, 0xA5, 0x85, 0x6B, + 0xA6, 0xEC, 0x46, 0xB2, 0xA1, 0xF7, 0x9F, 0x4C, + 0x95, 0xA8, 0xEE, 0xE0, 0xB8, 0x83, 0x46, 0x6A, + 0xAD, 0x9C, 0xD1, 0x91, 0x42, 0xD8, 0x18, 0xC1, + 0xA9, 0x54, 0x1A, 0xCA, 0xA6, 0x66, 0xF7, 0xE2, + 0x9F, 0x82, 0x73, 0xE9, 0x17, 0x32, 0x23, 0x35, + 0x3E, 0x18, 0x5C, 0xAE, 0x59, 0xB7, 0x6A, 0x04, + 0x97, 0xD1, 0x1F, 0xB2, 0x58, 0xC9, 0x37, 0xFD, + 0xE0, 0xC5, 0xA4, 0x6C, 0x9A, 0x00, 0x9B, 0x4C, + 0x06, 0x32, 0xF4, 0xA3, 0x94, 0xBF, 0xA8, 0x49, + 0xFE, 0xC2, 0x45, 0xA8, 0xB5, 0x32, 0x86, 0x5F, + 0xBA, 0xFD, 0xD1, 0x60, 0x4D, 0xF1, 0x43, 0xE1, + 0x55, 0x75, 0xD8, 0xD6, 0x1F, 0xD5, 0x7F, 0x35, + 0x67, 0x39, 0x74, 0x9C, 0x3B, 0x50, 0xBE, 0xC0, + 0x67, 0xA1, 0x90, 0x0F, 0x90, 0x27, 0xAD, 0xB9, + 0x97, 0x0C, 0xBC, 0x2A, 0xEF, 0x4D, 0x8F, 0x69, + 0x08, 0x50, 0xBD, 0x69, 0xE9, 0x2B, 0xB3, 0x37, + 0xB5, 0x90, 0x81, 0x73, 0x63, 0x64, 0xE6, 0x6A, + 0xF0, 0xEF, 0xB1, 0xEC, 0x9C, 0x8B, 0x23, 0xE3, + 0xBA, 0xDD, 0x10, 0x1A, 0x0E, 0x6A, 0x76, 0x4C, + 0x58, 0xAF, 0x8C, 0x10, 0xDD, 0xFE, 0xCB, 0x82, + 0x53, 0x9A, + + 0xB5, 0x42, 0x48, 0x28, 0x65, 0x88, 0xE8, 0xB7, + 0xB6, 0xCD, 0xAB, 0x9B, 0x31, 0xFE, 0xEC, 0xD7, + 0xBF, 0x43, 0x1B, 0x30, 0x75, 0x57, 0x96, 0x3E, + 0x34, 0x5C, 0xAA, 0x37, 0x83, 0x1C, 0xA3, 0x08, + 0x88, 0x31, 0xA0, 0x96, 0x40, 0x50, 0x7D, 0x5C, + 0x26, 0x66, 0x8D, 0x71, 0x95, 0xE0, 0xB8, 0x83, + 0x90, 0x8D, 0x9B, 0xBF, 0x85, 0x67, 0x08, 0x88, + 0x9F, 0x96, 0xC4, 0x31, 0xEC, 0xED, 0x6E, 0x9A, + 0x7E, 0x62, 0x20, 0x9A, 0xD2, 0xC6, 0xEA, 0x6B, + 0x65, 0xB2, 0xC5, 0xBB, 0xD3, 0x82, 0xC0, 0x0D, + 0xF6, 0x37, 0x3F, 0xAB, 0x88, 0xFA, 0x7E, 0xFC, + 0x4D, 0xE4, 0x83, 0x32, 0x8F, 0x3A, 0xFF, 0xAC, + 0x12, 0x81, 0xFC, 0x49, 0x0E, 0xA6, 0x37, 0xA0, + 0xFC, 0x40, 0x47, 0x4B, 0x14, 0x42, 0xC0, 0x0B, + 0xE5, 0x2D, 0x26, 0x5C, 0x2B, 0x4D, 0x0C, 0xBE, + 0xC1, 0x63, 0x67, 0x75, 0xB4, 0x1D, 0xB3, 0x9D, + 0xAA, 0xD6, 0x7C, 0xC3, 0x53, 0xD5, 0x0F, 0xE7, + 0x7F, 0xFA, 0xC0, 0xB5, 0x93, 0xBE, 0x18, 0x40, + 0x3B, 0x71, 0x32, 0xF1, 0x0F, 0x78, 0x53, 0xA1, + 0x01, 0xC6, 0xF6, 0x60, 0xEA, 0x50, 0x3A, 0x62, + 0x30, 0xBD, 0x1E, 0xE1, 0x88, 0x7C, 0x30, 0x9F, + 0xE4, 0x8E, 0x3F, + + 0x2A, 0x34, 0xC2, 0x7C, 0xAA, 0x2B, 0xA1, 0xC0, + 0x1A, 0xF5, 0xA8, 0xBC, 0xB8, 0x1E, 0x17, 0x9D, + 0xE3, 0x4E, 0x65, 0xB4, 0x4E, 0x9A, 0xB7, 0x6C, + 0xDD, 0x1E, 0x86, 0xA0, 0x68, 0x4D, 0x83, 0xB7, + 0x06, 0xD3, 0x5E, 0xAC, 0xB0, 0x9F, 0x00, 0x00, + 0x62, 0xD2, 0xCD, 0x67, 0x0C, 0x2D, 0xA9, 0x25, + 0xC1, 0x6E, 0xA8, 0xB0, 0x0E, 0xCF, 0xD9, 0x1D, + 0x5D, 0x5A, 0x04, 0xD9, 0xEA, 0x3F, 0x57, 0xE1, + 0x25, 0x19, 0xF4, 0x9D, 0x3C, 0x7D, 0xE0, 0x65, + 0x98, 0xF2, 0xD1, 0x92, 0xCA, 0x8E, 0x97, 0x6B, + 0x61, 0x58, 0x2B, 0xB4, 0x2A, 0xB4, 0x7A, 0x2A, + 0xEC, 0x93, 0xC4, 0xCB, 0x54, 0x58, 0x96, 0xD1, + 0x9E, 0x90, 0xA2, 0x2E, 0xD8, 0x62, 0x89, 0x97, + 0x2B, 0x43, 0x29, 0x6C, 0xC8, 0x78, 0x5E, 0xB8, + 0x25, 0x9E, 0x23, 0x92, 0x6F, 0x32, 0xAF, 0x4B, + 0x13, 0x6E, 0x1F, 0xB5, 0x8B, 0x8F, 0x46, 0x80, + 0x40, 0xD6, 0x34, 0xD4, 0x0D, 0x23, 0xA6, 0x46, + 0x86, 0x22, 0x51, 0xCF, 0xF5, 0xB6, 0x7E, 0x0B, + 0xD3, 0xE8, 0xD5, 0xAE, 0x47, 0x2C, 0xD9, 0xDA, + 0x61, 0x81, 0x32, 0x0A, 0xAC, 0x32, 0x83, 0x0F, + 0x5D, 0x06, 0x15, 0x19, 0x2D, 0x4E, 0x13, 0x7A, + 0xEC, 0x91, 0xEC, 0xC8, + + 0xB0, 0x44, 0xEA, 0xAC, 0x35, 0x51, 0x2D, 0x29, + 0x50, 0x73, 0x14, 0xC6, 0x5A, 0x7B, 0x9F, 0xD2, + 0x75, 0xE5, 0xE0, 0xE7, 0x66, 0x8A, 0xCB, 0x54, + 0x1D, 0xC4, 0x8A, 0x25, 0x0C, 0x7D, 0xA1, 0xA1, + 0xBA, 0x4E, 0x24, 0xB6, 0xD1, 0xF8, 0x8A, 0x9E, + 0x49, 0xD7, 0xCA, 0x7C, 0x7D, 0x83, 0xDE, 0x3E, + 0xED, 0x6E, 0x26, 0x34, 0x57, 0x6F, 0x00, 0x55, + 0xB9, 0x44, 0x54, 0x82, 0x9B, 0x9A, 0x32, 0xDA, + 0xBB, 0x59, 0x48, 0x80, 0x08, 0x96, 0x2D, 0x34, + 0x68, 0x40, 0x27, 0xB9, 0x00, 0x80, 0xC6, 0x6F, + 0x42, 0x72, 0x3C, 0x9B, 0xD1, 0xA0, 0x01, 0xCC, + 0xD2, 0x0F, 0x33, 0x00, 0x15, 0x6A, 0x65, 0x9B, + 0xED, 0x91, 0xDF, 0x56, 0xE2, 0x81, 0x54, 0x06, + 0xA0, 0xFE, 0x0E, 0xE6, 0x54, 0x16, 0xC5, 0xA6, + 0x89, 0x54, 0x87, 0x7E, 0x49, 0x47, 0x6C, 0x29, + 0x0F, 0x1C, 0x9E, 0xF7, 0x62, 0x23, 0xEB, 0x17, + 0xC2, 0x7B, 0x0D, 0x8B, 0xA0, 0xEF, 0xCE, 0x03, + 0xDE, 0x8D, 0x58, 0x0C, 0x7B, 0x6A, 0xD7, 0x66, + 0x52, 0x6E, 0x93, 0x0C, 0x13, 0xDF, 0x65, 0x28, + 0x66, 0x38, 0xA9, 0x67, 0xE9, 0x22, 0x96, 0x71, + 0xD2, 0xB9, 0xA3, 0xE8, 0x61, 0x49, 0x20, 0x7C, + 0xD5, 0x5B, 0x49, 0xCF, 0x57, + + 0x4B, 0xA0, 0x49, 0xB0, 0xEE, 0xB4, 0xED, 0x67, + 0x08, 0x08, 0x9D, 0xBB, 0x9F, 0xD8, 0x79, 0xE8, + 0x42, 0x71, 0x81, 0xDA, 0x5E, 0x8D, 0x90, 0x1B, + 0x4C, 0x9E, 0x71, 0xCF, 0x46, 0xEB, 0xE7, 0x14, + 0x96, 0x98, 0xA5, 0xDB, 0xFA, 0x35, 0x99, 0x4C, + 0x40, 0x21, 0x5D, 0xF8, 0xB5, 0xC5, 0xAE, 0xE5, + 0x29, 0x68, 0x5F, 0x4A, 0xE9, 0x1D, 0x15, 0x55, + 0xF1, 0x4F, 0x74, 0xD4, 0x15, 0xB3, 0x7D, 0x9F, + 0x37, 0xC8, 0xC8, 0xAF, 0xF1, 0xF0, 0x8D, 0xC4, + 0xF8, 0x36, 0xF0, 0x7A, 0xB9, 0xE6, 0xB8, 0xA9, + 0x66, 0x10, 0xDF, 0xFE, 0x16, 0x7C, 0x8E, 0xDE, + 0x57, 0x0C, 0x75, 0xBF, 0x67, 0x8C, 0x39, 0x49, + 0xF1, 0x66, 0x1D, 0xF2, 0x0D, 0x6D, 0xBB, 0xB4, + 0xC3, 0xC7, 0xD7, 0xE1, 0xB3, 0xEB, 0xE2, 0x0C, + 0x69, 0x4E, 0xC3, 0x60, 0x5B, 0x2B, 0xD5, 0x71, + 0x1D, 0x33, 0xF6, 0x9D, 0xBC, 0xAE, 0x0C, 0x7E, + 0x3B, 0x75, 0x16, 0x73, 0x1D, 0xD5, 0xFA, 0x71, + 0x04, 0xA1, 0x76, 0xA8, 0xCF, 0xB2, 0xD1, 0x8D, + 0x00, 0x83, 0x47, 0x14, 0x28, 0x13, 0x22, 0xF6, + 0x2C, 0xF1, 0xCF, 0xC1, 0xB9, 0x8F, 0x18, 0x42, + 0x88, 0x28, 0x9B, 0x0D, 0xFF, 0xEA, 0x2D, 0xD3, + 0xF8, 0xC5, 0x26, 0x49, 0x67, 0xB4, + + 0x5A, 0xE7, 0x15, 0x4E, 0x9B, 0xC6, 0x57, 0xBD, + 0x13, 0x39, 0xD7, 0xDA, 0x9A, 0xBA, 0x06, 0xDA, + 0x73, 0xEC, 0x64, 0xBF, 0xF4, 0x29, 0xEB, 0x4D, + 0x6B, 0x9A, 0xA2, 0x0F, 0x77, 0x6F, 0xBC, 0x2B, + 0xC5, 0x3F, 0xE8, 0xF0, 0x5A, 0x46, 0x88, 0x3C, + 0x4F, 0xC0, 0x44, 0xE7, 0xAC, 0x89, 0xED, 0xF6, + 0xF3, 0xF2, 0xE1, 0xB7, 0x24, 0x75, 0xAB, 0x72, + 0xC1, 0x06, 0x0E, 0x5D, 0x02, 0x5E, 0x57, 0xA6, + 0xA3, 0x4E, 0x4A, 0xFE, 0x46, 0xF0, 0xB4, 0xDD, + 0x2F, 0xAB, 0xD6, 0xED, 0x49, 0x68, 0x6B, 0xE3, + 0x5D, 0xFF, 0x11, 0x67, 0xA0, 0x38, 0xD1, 0xB6, + 0x6E, 0x98, 0x61, 0x88, 0xA5, 0x60, 0x3E, 0x74, + 0xFB, 0xF6, 0x47, 0x5D, 0xB4, 0xB0, 0x1F, 0xB0, + 0xD0, 0xE8, 0x7B, 0xB7, 0xD4, 0x7D, 0xA1, 0xAF, + 0xD5, 0xD8, 0x5B, 0x83, 0xDF, 0x82, 0x29, 0xA8, + 0xB1, 0x50, 0x2A, 0x06, 0xA6, 0xC0, 0x4C, 0xC0, + 0x96, 0xA4, 0xDB, 0x95, 0x61, 0x19, 0x4E, 0x1E, + 0xB8, 0x79, 0x45, 0x48, 0xCA, 0x22, 0xFD, 0x20, + 0x9E, 0x0E, 0xE1, 0xD7, 0x28, 0x00, 0x16, 0x50, + 0x42, 0xE4, 0x72, 0xB0, 0x61, 0x41, 0xA4, 0x93, + 0x9D, 0xB9, 0x0D, 0x7F, 0x2F, 0xBB, 0xD3, 0x89, + 0xA1, 0xBB, 0xCF, 0xE6, 0xE0, 0x09, 0x52, + + 0x0B, 0x8D, 0x85, 0x02, 0x46, 0xFB, 0x2D, 0x5A, + 0x4A, 0xB7, 0xC1, 0x3A, 0x8C, 0x4D, 0xA0, 0xBD, + 0x43, 0x52, 0xE1, 0x83, 0xA5, 0x6C, 0x78, 0x10, + 0xC1, 0xF1, 0xDF, 0x77, 0x66, 0x2C, 0x30, 0x82, + 0x12, 0x06, 0xBD, 0x79, 0x0A, 0xBD, 0x80, 0x92, + 0xF2, 0xCF, 0xB3, 0x50, 0xF7, 0x3A, 0x80, 0xE2, + 0xE5, 0xB6, 0xC8, 0x65, 0xFF, 0xB9, 0x75, 0x84, + 0x89, 0xB3, 0x63, 0x75, 0xA8, 0xA1, 0x45, 0x3E, + 0x46, 0x97, 0x4A, 0x09, 0xFF, 0xAC, 0x5B, 0xF9, + 0x25, 0x79, 0x49, 0x70, 0xA8, 0x87, 0x95, 0x8D, + 0x59, 0x2F, 0x27, 0x85, 0x02, 0x78, 0x30, 0x9F, + 0x72, 0xDB, 0x11, 0x88, 0x85, 0x09, 0xD4, 0x4B, + 0x71, 0x39, 0xF4, 0x68, 0xFB, 0x40, 0x63, 0x71, + 0xAA, 0xFC, 0x6C, 0xE3, 0x2A, 0xF1, 0x45, 0xF4, + 0xE8, 0x0E, 0x8E, 0xF4, 0xA3, 0xC9, 0x37, 0xA0, + 0xEF, 0xDE, 0x9C, 0x92, 0x42, 0x36, 0x95, 0x30, + 0x0A, 0x9A, 0x06, 0xB8, 0xEB, 0x5C, 0xE2, 0x85, + 0x40, 0x7C, 0x2A, 0xBD, 0xC6, 0x63, 0xCE, 0xBB, + 0x20, 0xC0, 0x1F, 0xE1, 0x5B, 0xDD, 0xD9, 0x62, + 0x2D, 0x30, 0x79, 0xBB, 0x49, 0x65, 0x2A, 0x12, + 0x82, 0x7A, 0x8D, 0x2F, 0xFC, 0xF7, 0xB4, 0x17, + 0x1B, 0x69, 0x5B, 0x90, 0x6D, 0x07, 0x0D, 0x5B, + + 0x99, 0x09, 0x0A, 0xFD, 0xC2, 0x22, 0x9F, 0x2B, + 0x4E, 0xD3, 0x2E, 0x38, 0x10, 0x2F, 0x9D, 0xD4, + 0x5E, 0xFC, 0x93, 0x77, 0x7B, 0x8D, 0xD3, 0xB9, + 0x5E, 0x1C, 0x17, 0x29, 0x4D, 0x0A, 0xA9, 0x5D, + 0x3E, 0xA9, 0x59, 0xD9, 0xBA, 0xF9, 0x5B, 0x21, + 0xF8, 0x59, 0xA8, 0xD5, 0x5C, 0x7E, 0x01, 0xDA, + 0xE5, 0x4F, 0x81, 0x1C, 0xD7, 0x63, 0x16, 0xA4, + 0x2D, 0xE6, 0xFA, 0xAA, 0x18, 0x8C, 0x87, 0xF7, + 0xF2, 0x7C, 0x38, 0x0C, 0x08, 0xD6, 0xA4, 0x1E, + 0x61, 0x19, 0xE7, 0xE9, 0x5B, 0x7C, 0x8F, 0x1A, + 0xB6, 0x4B, 0x7E, 0x78, 0x12, 0x22, 0xF4, 0xCA, + 0x59, 0xAE, 0x69, 0xC7, 0x22, 0x1D, 0xF6, 0xBB, + 0xFC, 0xEF, 0x70, 0x47, 0x0E, 0x5F, 0x85, 0x75, + 0x26, 0xA9, 0x07, 0xFA, 0x6C, 0x59, 0x67, 0x14, + 0x0B, 0x86, 0xCD, 0xA4, 0x84, 0xD9, 0xB1, 0xCF, + 0xC4, 0x26, 0x40, 0x55, 0x3E, 0xFA, 0x5F, 0x08, + 0x0A, 0x89, 0x56, 0x6F, 0x3A, 0xFF, 0xE4, 0x46, + 0x63, 0x93, 0xB9, 0xDE, 0x2C, 0x57, 0x26, 0x96, + 0x38, 0x03, 0x01, 0x80, 0x02, 0x44, 0xBA, 0x96, + 0x20, 0x7C, 0x7C, 0x76, 0x1C, 0x0C, 0x0D, 0x72, + 0x56, 0x28, 0xFD, 0x9F, 0xCB, 0xD5, 0xEE, 0x92, + 0x61, 0x5C, 0x6F, 0x0A, 0x70, 0xBA, 0xD3, 0xFB, + 0xD5, + + 0x79, 0xFE, 0xFA, 0xEB, 0xF2, 0x35, 0xB1, 0x0C, + 0x46, 0x53, 0x2E, 0x26, 0xCE, 0x1A, 0x6E, 0x36, + 0xD0, 0xD1, 0x4C, 0x2B, 0x55, 0x02, 0x8C, 0x39, + 0xA4, 0xC4, 0x14, 0x9B, 0x05, 0x83, 0x80, 0x8A, + 0xE6, 0x05, 0x7E, 0x0A, 0xE9, 0x1A, 0xBC, 0xBD, + 0xAE, 0xDE, 0xCF, 0x33, 0xC4, 0xAB, 0x10, 0x66, + 0x52, 0x56, 0x4D, 0xEA, 0xBD, 0xE2, 0xDA, 0xC8, + 0x77, 0x1D, 0x26, 0x8C, 0xD5, 0x9A, 0x01, 0xFD, + 0xFB, 0x49, 0x89, 0xB8, 0xE1, 0xD0, 0x48, 0x49, + 0x44, 0x23, 0xE2, 0xEF, 0x11, 0x74, 0x67, 0x5E, + 0x14, 0x01, 0x15, 0xEC, 0x39, 0x9B, 0x0A, 0x69, + 0x7C, 0x87, 0xC2, 0xE9, 0x58, 0x05, 0xDE, 0x15, + 0xA2, 0x71, 0x50, 0x73, 0x12, 0x5E, 0x5B, 0x87, + 0x6E, 0xAE, 0xD3, 0x8F, 0x95, 0xE9, 0x77, 0xEF, + 0x2F, 0xD3, 0x63, 0x5B, 0x40, 0xBB, 0xDD, 0xF0, + 0x01, 0x08, 0x7A, 0x5C, 0x92, 0xB6, 0x37, 0xC9, + 0xEB, 0x84, 0x07, 0x65, 0x92, 0xFC, 0xC6, 0xB3, + 0x68, 0x37, 0xED, 0x62, 0xD1, 0x70, 0xD4, 0xBD, + 0x28, 0xD3, 0x46, 0x94, 0x63, 0xD9, 0x56, 0xBE, + 0x93, 0xEC, 0x8A, 0x01, 0xB5, 0xBD, 0xC6, 0x9B, + 0x75, 0x08, 0x06, 0x08, 0xF1, 0xFB, 0x3F, 0xB0, + 0x3E, 0x18, 0x35, 0xF3, 0xFA, 0x85, 0x1A, 0xA7, + 0x9A, 0x8E, + + 0x17, 0x73, 0x8A, 0x98, 0x3B, 0x5B, 0xAD, 0x53, + 0x01, 0x84, 0x65, 0x88, 0xB4, 0x47, 0x4D, 0xC8, + 0x8C, 0x13, 0x47, 0x75, 0xB5, 0x03, 0x43, 0x64, + 0xE5, 0x8D, 0x56, 0xC1, 0xC0, 0x85, 0xE8, 0x25, + 0xE7, 0x2F, 0xC1, 0x98, 0x58, 0xE7, 0x2D, 0xD7, + 0x4D, 0x2B, 0xE0, 0x2D, 0x87, 0x67, 0x72, 0x7E, + 0xA1, 0xAE, 0xF3, 0x86, 0x88, 0xE4, 0x69, 0x23, + 0x30, 0x27, 0xA3, 0x48, 0xDC, 0xA0, 0x67, 0xCC, + 0x54, 0x31, 0xB2, 0xB7, 0x24, 0x23, 0xB9, 0x4A, + 0x5A, 0x07, 0x65, 0x4C, 0x2D, 0x5A, 0x9A, 0x4E, + 0xB4, 0xA6, 0x70, 0xFF, 0x69, 0x3E, 0xD2, 0xC9, + 0x55, 0x2E, 0x4F, 0xC4, 0x2F, 0x1F, 0x89, 0x98, + 0x76, 0x45, 0x5F, 0xBD, 0x3A, 0x8C, 0xB6, 0x55, + 0x93, 0xB0, 0xA7, 0x4E, 0x75, 0xBD, 0x7D, 0x25, + 0x08, 0x8C, 0xAD, 0x13, 0x33, 0x24, 0x57, 0xA9, + 0x1C, 0x44, 0x71, 0x86, 0x7E, 0xC4, 0xC4, 0x1C, + 0x5B, 0x1E, 0x83, 0x37, 0x1B, 0x37, 0x98, 0x9A, + 0xB4, 0xDC, 0xA1, 0xC2, 0x1A, 0x69, 0x89, 0xE1, + 0xD9, 0x67, 0x41, 0x58, 0x72, 0x6A, 0xF8, 0x22, + 0x69, 0xEA, 0x53, 0xF5, 0x3C, 0x5E, 0x53, 0x5D, + 0x98, 0x9A, 0x2A, 0xDA, 0xF6, 0x30, 0xA0, 0xBA, + 0xCE, 0xF8, 0xB7, 0x4D, 0xE2, 0xBF, 0x05, 0xAA, + 0xF7, 0x44, 0x84, + + 0x97, 0xDD, 0xB6, 0xB9, 0xD3, 0xA3, 0x8A, 0x20, + 0x05, 0x15, 0xD1, 0x14, 0x69, 0x33, 0x98, 0xFF, + 0x77, 0xDA, 0x47, 0x11, 0xC3, 0x59, 0x19, 0xFB, + 0x86, 0xEE, 0x3A, 0xB9, 0x4F, 0x61, 0x07, 0x6C, + 0x7B, 0x01, 0x89, 0x87, 0x1E, 0xA0, 0xBB, 0x34, + 0x60, 0x89, 0xAA, 0xE9, 0xE5, 0x03, 0xE4, 0xF7, + 0xA7, 0x16, 0xD0, 0xA9, 0x08, 0x3F, 0xA1, 0x25, + 0x57, 0xB4, 0xAD, 0x52, 0x80, 0x53, 0xB3, 0x3B, + 0x58, 0x58, 0x96, 0x37, 0x25, 0xEB, 0x08, 0xD9, + 0x63, 0xFA, 0x1F, 0xC8, 0x92, 0xF0, 0x50, 0x0D, + 0xAE, 0xFB, 0x16, 0x2E, 0xA7, 0xB1, 0x1E, 0x71, + 0x46, 0xCE, 0xE6, 0xA9, 0x4B, 0x67, 0xAC, 0xD8, + 0xC7, 0x01, 0x18, 0xA0, 0x83, 0xD5, 0xBA, 0xA9, + 0x94, 0xCD, 0x2C, 0x8C, 0x90, 0x86, 0xE9, 0x80, + 0x3E, 0x94, 0x0B, 0x0C, 0xDD, 0xF0, 0xB8, 0xFE, + 0x29, 0x9D, 0x9F, 0xAB, 0x16, 0xE6, 0x08, 0x12, + 0x67, 0x29, 0x45, 0x57, 0x4D, 0xB9, 0x08, 0xF3, + 0x44, 0x4E, 0x5C, 0x9C, 0x92, 0x69, 0xF6, 0x41, + 0x90, 0x17, 0x92, 0xF5, 0x1B, 0x8B, 0xBB, 0x89, + 0x2E, 0x3A, 0x7F, 0xAF, 0x82, 0x59, 0xA4, 0x94, + 0x53, 0x40, 0xF5, 0x6A, 0x2A, 0xF5, 0xA8, 0x4F, + 0x48, 0x2D, 0x01, 0x61, 0x6A, 0x98, 0xFD, 0xF8, + 0xBC, 0x46, 0xFC, 0x6F, + + 0x2F, 0x20, 0x5D, 0x1C, 0xAC, 0x77, 0x49, 0x4E, + 0x6A, 0x21, 0x43, 0x6D, 0x67, 0x9C, 0xF6, 0x87, + 0xC9, 0xAF, 0x8B, 0x58, 0xF0, 0xCB, 0x8B, 0x9C, + 0x41, 0x7D, 0x77, 0x66, 0xFF, 0x9D, 0x6D, 0xA5, + 0x23, 0xAC, 0x7E, 0x35, 0x18, 0xC1, 0x8E, 0x96, + 0x5F, 0x9B, 0xD8, 0xDF, 0xEA, 0xA1, 0x1A, 0x4E, + 0xE5, 0x43, 0x6E, 0x05, 0xE7, 0xBF, 0x0B, 0x81, + 0xD5, 0x73, 0x6C, 0x37, 0x43, 0x82, 0xF4, 0x40, + 0x8F, 0x6E, 0xA2, 0x7B, 0xEC, 0x28, 0x7B, 0xD5, + 0xA1, 0xCB, 0x38, 0xF1, 0x62, 0x5F, 0xCC, 0xCF, + 0xB5, 0x87, 0x38, 0x03, 0x5D, 0x1E, 0xC9, 0x01, + 0x4C, 0xE1, 0x97, 0xD7, 0xC5, 0x92, 0xE2, 0xEB, + 0x5B, 0x49, 0xC3, 0xB9, 0xB9, 0x9D, 0x16, 0x8D, + 0x54, 0x57, 0xB7, 0x08, 0xA9, 0xF2, 0x1E, 0x2B, + 0x6B, 0x8C, 0x0C, 0x1E, 0xD6, 0x8D, 0x0E, 0xA6, + 0x51, 0xB5, 0xC7, 0x02, 0xC1, 0x34, 0x92, 0x95, + 0x8A, 0xEA, 0xF3, 0xCD, 0x37, 0x54, 0x09, 0x74, + 0x47, 0x04, 0x93, 0x73, 0xD9, 0x91, 0x31, 0x33, + 0x91, 0x4E, 0xF5, 0x08, 0x0A, 0x8A, 0x50, 0x15, + 0x9F, 0x08, 0x36, 0xC5, 0x74, 0xEF, 0x2B, 0xD2, + 0x1E, 0x05, 0xD1, 0xB7, 0x2E, 0x57, 0x3B, 0x25, + 0x0F, 0x91, 0x65, 0x48, 0xEB, 0x2F, 0xF3, 0xDB, + 0xF8, 0xE2, 0x7B, 0xAF, 0x93, + + 0xB0, 0xC5, 0x54, 0xAD, 0x36, 0x9B, 0x5C, 0x03, + 0x86, 0x9C, 0x35, 0x73, 0xD5, 0xF9, 0x0F, 0x5F, + 0xEF, 0x3A, 0xFF, 0x73, 0x9E, 0xC4, 0xDB, 0x64, + 0x4F, 0x3E, 0xEF, 0xD2, 0x32, 0x5A, 0x7F, 0xA5, + 0xBF, 0x2C, 0x81, 0x00, 0xBB, 0xFA, 0x5F, 0x98, + 0x86, 0x71, 0x26, 0x39, 0x8F, 0xB7, 0x84, 0x38, + 0x9D, 0xE4, 0xF7, 0x99, 0x21, 0xB9, 0x0D, 0xF7, + 0x6F, 0x7F, 0xB8, 0x68, 0x8F, 0x7E, 0x7E, 0x4F, + 0xA7, 0x15, 0x2A, 0x82, 0xFC, 0x60, 0xCF, 0x70, + 0xE9, 0x86, 0xBD, 0x24, 0xA1, 0xBA, 0x30, 0xB2, + 0x70, 0x66, 0xBC, 0x6F, 0x1C, 0x39, 0x94, 0xB5, + 0x81, 0x3C, 0x54, 0x98, 0x3C, 0x82, 0xE3, 0xF8, + 0x6D, 0x3C, 0x1B, 0x5A, 0x7A, 0x81, 0x7A, 0x29, + 0xEF, 0x48, 0x3B, 0x35, 0x3F, 0x73, 0xF0, 0x05, + 0x12, 0xB6, 0xC9, 0x2D, 0xDA, 0xCB, 0x81, 0xBD, + 0xEE, 0x8F, 0x8E, 0xE7, 0x06, 0x8D, 0xD2, 0x76, + 0x39, 0x60, 0xF2, 0x57, 0xD6, 0xE5, 0xFC, 0x81, + 0x14, 0x49, 0xB4, 0x6B, 0x06, 0x6E, 0x33, 0xDC, + 0x2C, 0x2F, 0x4E, 0x15, 0xC8, 0xC2, 0x41, 0x95, + 0xA8, 0x65, 0x59, 0xCA, 0x97, 0xD8, 0xA0, 0x4A, + 0x1F, 0xCA, 0x35, 0xC5, 0x21, 0xBD, 0x51, 0x29, + 0x2B, 0x0A, 0x1B, 0x37, 0x4C, 0xF7, 0xAA, 0x88, + 0xDF, 0x44, 0x88, 0x05, 0x2F, 0x4B, + + 0x50, 0xDC, 0xA7, 0x8B, 0xED, 0x47, 0x10, 0x06, + 0x63, 0xCB, 0x7D, 0x5B, 0xE6, 0xB0, 0xED, 0x90, + 0x55, 0xF0, 0x38, 0x3C, 0x80, 0x34, 0x2B, 0x62, + 0x92, 0xC5, 0x61, 0x0D, 0xEC, 0x0E, 0xD3, 0xEA, + 0xD6, 0x81, 0xB8, 0x4D, 0xC6, 0x3E, 0xC5, 0x19, + 0x70, 0x31, 0x0F, 0x2C, 0x65, 0x07, 0x0F, 0x43, + 0x2F, 0xA0, 0x63, 0xD7, 0xFB, 0x9B, 0xD1, 0xA9, + 0x60, 0x3C, 0xFE, 0x4E, 0x09, 0xAF, 0xC7, 0x04, + 0x4A, 0xE6, 0x75, 0x18, 0xF6, 0x53, 0x87, 0x91, + 0xD6, 0x33, 0x15, 0x9C, 0x32, 0xA0, 0x52, 0x82, + 0xC7, 0xF9, 0x17, 0x9C, 0x58, 0x2C, 0xBC, 0x75, + 0x88, 0x1B, 0x7D, 0x71, 0xC3, 0xCC, 0xFE, 0x60, + 0x08, 0xDD, 0xB0, 0x5F, 0x45, 0x49, 0x08, 0x91, + 0xF6, 0x42, 0x97, 0x85, 0xBB, 0xF7, 0x04, 0xAB, + 0xFF, 0xB6, 0xB6, 0x37, 0xA3, 0xA8, 0x1D, 0x41, + 0x52, 0x9F, 0x47, 0xC2, 0xD4, 0xE1, 0x32, 0x22, + 0x26, 0xF5, 0x26, 0x0A, 0x03, 0xD5, 0xDD, 0x37, + 0x95, 0xBB, 0xC0, 0xEF, 0x4C, 0x61, 0xC9, 0x87, + 0x43, 0x88, 0x22, 0xE9, 0x5F, 0x30, 0x0A, 0x64, + 0x73, 0xF3, 0x2F, 0xD2, 0x4D, 0xE8, 0x91, 0x1C, + 0x68, 0xBE, 0x35, 0xC3, 0xF4, 0xC4, 0xD3, 0xD2, + 0x01, 0xB2, 0x19, 0x28, 0x30, 0x86, 0xD9, 0xFC, + 0x16, 0x4A, 0x0E, 0xCC, 0xCA, 0xD6, 0xF6, + + 0x74, 0xAF, 0x14, 0xA0, 0x6E, 0x50, 0x25, 0x74, + 0x8F, 0xC7, 0x16, 0x03, 0x56, 0x10, 0x01, 0x76, + 0x5B, 0x63, 0xD0, 0xEF, 0x4E, 0xA7, 0x59, 0x27, + 0x43, 0x0C, 0x3F, 0x8C, 0xFD, 0xB6, 0x09, 0x17, + 0x81, 0xD7, 0xEC, 0x94, 0x50, 0x4B, 0xC8, 0x22, + 0x3F, 0x82, 0x11, 0xA1, 0x58, 0x8C, 0x23, 0xBB, + 0x8B, 0xFB, 0x4F, 0x34, 0x31, 0x98, 0x63, 0x1B, + 0xC4, 0x8E, 0xCF, 0x12, 0x57, 0x68, 0x14, 0x2B, + 0x23, 0xA9, 0x9D, 0x17, 0x84, 0x2A, 0x53, 0xE7, + 0x67, 0x5A, 0xC1, 0x6E, 0x65, 0x25, 0x70, 0x25, + 0x76, 0x70, 0x30, 0x24, 0x85, 0xF8, 0x1F, 0x9D, + 0xFD, 0x8D, 0x84, 0xAD, 0x33, 0x07, 0xFD, 0x21, + 0x01, 0x13, 0xC0, 0x14, 0x20, 0xF2, 0xDC, 0x81, + 0x21, 0xEF, 0x3A, 0xCB, 0x32, 0x23, 0xB2, 0x76, + 0x3B, 0xA4, 0x30, 0xB6, 0x8F, 0x90, 0xE3, 0x20, + 0x4C, 0x81, 0x6A, 0xF4, 0x2C, 0xC3, 0x4C, 0x86, + 0x08, 0x86, 0x1E, 0x31, 0x48, 0x55, 0x7E, 0xF2, + 0xA7, 0xF5, 0xC6, 0x22, 0x19, 0x87, 0xE5, 0x6E, + 0xA6, 0xC5, 0x31, 0xF6, 0x1D, 0xA4, 0xD8, 0x75, + 0x90, 0x1C, 0x57, 0x01, 0xF5, 0xE8, 0x53, 0x3E, + 0x0A, 0x16, 0xDD, 0x40, 0x58, 0x0C, 0xE0, 0x8F, + 0xBF, 0x57, 0xFA, 0x1D, 0x37, 0x15, 0xC6, 0x63, + 0xC1, 0x57, 0x0C, 0x6D, 0x83, 0x6C, 0xA4, 0x0E, + + 0x6A, 0x33, 0x55, 0x52, 0x04, 0x3E, 0x41, 0x83, + 0x22, 0xED, 0x2A, 0xAC, 0x33, 0xEF, 0xA6, 0xA9, + 0x8E, 0x21, 0x9D, 0x2B, 0xFB, 0x20, 0x80, 0x22, + 0x0F, 0x7A, 0xB4, 0x67, 0xFF, 0x76, 0xFA, 0x1D, + 0x1B, 0x26, 0xF9, 0xD4, 0x3A, 0x66, 0x99, 0x4C, + 0xFD, 0x45, 0x61, 0x96, 0x02, 0x3F, 0xD3, 0x13, + 0xE4, 0x44, 0x30, 0x30, 0x6B, 0x76, 0x77, 0xEA, + 0x66, 0x69, 0x1B, 0x82, 0xE6, 0xA2, 0x50, 0x69, + 0xFD, 0x5D, 0xAD, 0x59, 0x82, 0x94, 0xA1, 0xF3, + 0x78, 0x5B, 0x00, 0x7B, 0x6E, 0xE9, 0xA2, 0xB9, + 0xB4, 0x56, 0xF9, 0xD5, 0x5C, 0x42, 0x89, 0xA5, + 0x7E, 0x86, 0xFE, 0x61, 0x6C, 0xF1, 0x0A, 0xFC, + 0xC9, 0x7D, 0x9C, 0xF0, 0xE7, 0x7F, 0xFE, 0xCD, + 0x85, 0xEC, 0x68, 0x68, 0xC5, 0x6F, 0x06, 0x35, + 0x4B, 0xA6, 0x15, 0xF8, 0x38, 0xF5, 0x1B, 0x56, + 0x20, 0x75, 0xCE, 0xA4, 0xCB, 0x5F, 0x60, 0x96, + 0xE7, 0xEF, 0x71, 0x1B, 0x1D, 0xF5, 0xD1, 0x96, + 0xA1, 0x9C, 0x64, 0xFA, 0x2F, 0x88, 0x9C, 0x87, + 0x53, 0xC5, 0x08, 0xE5, 0x93, 0xD0, 0x6E, 0xDB, + 0xA1, 0x84, 0x1C, 0x49, 0x79, 0x38, 0x48, 0xDD, + 0x6B, 0xD0, 0x80, 0x52, 0x51, 0x4A, 0x96, 0x9C, + 0x4A, 0x48, 0xB3, 0x9B, 0x86, 0x2F, 0xDC, 0x32, + 0x34, 0x27, 0x04, 0xAB, 0x37, 0xB2, 0x50, 0x6C, + 0xB8, + + 0x86, 0x42, 0xAF, 0x92, 0x97, 0x70, 0x4B, 0x6A, + 0xC3, 0x85, 0x01, 0xE0, 0xFE, 0x10, 0x0A, 0x58, + 0xD8, 0xF8, 0x1F, 0x0C, 0xA0, 0xF3, 0x41, 0x40, + 0x1F, 0x90, 0x54, 0x07, 0x52, 0x34, 0x2C, 0xC8, + 0x20, 0x3A, 0xA5, 0x1D, 0x12, 0x59, 0xC5, 0xCA, + 0x3F, 0x60, 0x7E, 0x9F, 0xB0, 0xB3, 0x66, 0x99, + 0x67, 0xD6, 0x0B, 0x05, 0x54, 0xB5, 0xE3, 0x7E, + 0xC6, 0x97, 0xF3, 0xD5, 0xC0, 0x73, 0xE9, 0xE2, + 0x70, 0x20, 0x78, 0x15, 0x74, 0x2F, 0x19, 0xCC, + 0x0F, 0xA9, 0xCC, 0xE1, 0xAE, 0x60, 0x6A, 0x05, + 0x97, 0xE4, 0x5A, 0x6F, 0xF9, 0xB6, 0x40, 0x31, + 0xE1, 0x41, 0xF2, 0x72, 0x3E, 0xB2, 0xEB, 0x78, + 0x33, 0x7E, 0x0A, 0xB4, 0x39, 0xE3, 0xEE, 0x99, + 0x17, 0x6C, 0x2F, 0x2F, 0xA8, 0x3C, 0x2C, 0xFC, + 0x70, 0x53, 0x53, 0x14, 0x82, 0x62, 0xCA, 0x55, + 0x23, 0x20, 0xFF, 0x7F, 0xC5, 0xE9, 0x28, 0xB9, + 0xA2, 0x15, 0x82, 0x6B, 0xED, 0x1C, 0xBB, 0xD6, + 0x74, 0x8E, 0xE5, 0x2F, 0x54, 0x97, 0x05, 0xAB, + 0x88, 0xF8, 0x6E, 0x5E, 0x45, 0x52, 0x61, 0x3B, + 0xCD, 0x9F, 0x3E, 0xE0, 0x43, 0x30, 0x37, 0x73, + 0x50, 0xE3, 0x21, 0x29, 0xAA, 0x48, 0x7B, 0xDE, + 0x50, 0x2B, 0xBC, 0x34, 0xBF, 0xB3, 0x0F, 0xF7, + 0xCB, 0x78, 0x4B, 0xDE, 0x7B, 0x1D, 0xAC, 0xFC, + 0xEB, 0x03, + + 0x76, 0xD3, 0x4B, 0xE8, 0x19, 0x32, 0xEE, 0xA7, + 0xD5, 0x21, 0xE4, 0xFF, 0x60, 0x32, 0xED, 0xE4, + 0x6D, 0xC3, 0xE2, 0xA4, 0xD2, 0xEC, 0x0B, 0x41, + 0x8E, 0xF2, 0xE3, 0x83, 0x84, 0x18, 0xE5, 0xF4, + 0xBA, 0xE7, 0x17, 0xED, 0xF7, 0xF6, 0xC8, 0x6C, + 0xA9, 0xC7, 0xF7, 0x23, 0x9E, 0x0F, 0xEC, 0x4C, + 0x51, 0x20, 0xB8, 0xEF, 0x02, 0xCC, 0xFF, 0xBB, + 0xDE, 0x1C, 0x47, 0x8A, 0xAB, 0x2D, 0xDF, 0xF6, + 0x86, 0x0B, 0xC8, 0xFB, 0xDE, 0x24, 0x64, 0x1F, + 0x99, 0x4F, 0x44, 0xC9, 0x78, 0x45, 0xD2, 0x2A, + 0x7A, 0x3B, 0x1C, 0xC5, 0xD8, 0x87, 0x29, 0xEB, + 0x5E, 0x02, 0x12, 0x93, 0xF7, 0xED, 0x21, 0xFF, + 0x50, 0xDB, 0xD9, 0xD4, 0x0B, 0x1C, 0xC9, 0x1D, + 0xF2, 0x1F, 0x9C, 0x93, 0x2F, 0xDA, 0x90, 0xB0, + 0xF9, 0x25, 0x4F, 0x25, 0xE7, 0x64, 0xB4, 0xD6, + 0x78, 0xB3, 0x68, 0xD8, 0x46, 0xCF, 0xE4, 0xC7, + 0x15, 0x28, 0xC2, 0x34, 0x6E, 0xB2, 0x4F, 0x12, + 0xD2, 0x89, 0xDE, 0x77, 0xDA, 0x58, 0x40, 0x62, + 0x8B, 0x55, 0xF7, 0x80, 0x82, 0x3C, 0xC3, 0xAC, + 0x7C, 0xF4, 0x2E, 0xDD, 0xC4, 0x70, 0x52, 0x63, + 0x17, 0x7F, 0x44, 0xF7, 0x65, 0x59, 0x3D, 0x91, + 0x95, 0x18, 0xB0, 0xA4, 0xA0, 0xAF, 0x52, 0x3A, + 0xD3, 0xC0, 0xDD, 0x0C, 0x00, 0xC1, 0xD7, 0xA6, + 0x1D, 0x5E, 0x35, + + 0xC5, 0x4F, 0x57, 0x22, 0xF0, 0xE2, 0x42, 0xEE, + 0x03, 0x5C, 0xDE, 0x88, 0x0A, 0x6E, 0xEB, 0xA4, + 0x41, 0xEF, 0x55, 0x9D, 0x37, 0x21, 0xAE, 0x2A, + 0xA9, 0x9D, 0x92, 0xDC, 0xCF, 0x5F, 0xD3, 0x28, + 0x23, 0x5D, 0x22, 0xDB, 0x89, 0x31, 0x4D, 0x60, + 0x08, 0x92, 0x78, 0x3A, 0x5D, 0xAE, 0x91, 0x1A, + 0x93, 0xCD, 0x4D, 0x62, 0x40, 0xA2, 0x18, 0x1A, + 0x6B, 0xCE, 0x34, 0x0D, 0x3B, 0x09, 0xC6, 0xE6, + 0x3F, 0x1B, 0x88, 0x19, 0x14, 0x29, 0xAD, 0x75, + 0x06, 0x1B, 0xD9, 0xE2, 0xEC, 0xE7, 0x1B, 0xC9, + 0x7A, 0xD3, 0x18, 0x86, 0xE7, 0x36, 0xAD, 0x21, + 0x7D, 0xA2, 0xDC, 0x1C, 0x97, 0xBA, 0xB2, 0xCB, + 0x59, 0x19, 0x7D, 0x20, 0xC5, 0x68, 0xB8, 0xBD, + 0x51, 0x49, 0x5B, 0x45, 0xAB, 0x47, 0x33, 0x63, + 0xA2, 0xEC, 0x4C, 0x2D, 0x69, 0x91, 0x27, 0x86, + 0x72, 0x28, 0xDB, 0x96, 0x55, 0x5D, 0x1A, 0x2F, + 0x7E, 0x5D, 0xC6, 0x0A, 0x69, 0xAB, 0x8C, 0x8B, + 0x36, 0x87, 0xB4, 0x1A, 0x15, 0xE4, 0x68, 0x21, + 0xDB, 0x65, 0x87, 0xBA, 0x24, 0xBD, 0x1F, 0xFA, + 0x5C, 0x4B, 0x48, 0x21, 0x83, 0xD8, 0x04, 0x50, + 0x31, 0x83, 0xF7, 0x21, 0xC5, 0xA8, 0xA9, 0x8A, + 0x5E, 0xC6, 0x1C, 0x40, 0x8E, 0x29, 0xB3, 0xF2, + 0xA8, 0x86, 0xED, 0x60, 0xCA, 0xF8, 0x24, 0x7F, + 0x09, 0xAE, 0x36, 0x3F, + + 0x6D, 0x99, 0x39, 0x36, 0xA1, 0x3E, 0x29, 0x65, + 0x55, 0xA1, 0x90, 0x10, 0xB5, 0x49, 0x64, 0xE3, + 0x09, 0xB2, 0xDB, 0x65, 0xF1, 0x5E, 0x05, 0x1E, + 0x0E, 0x6A, 0x8C, 0x38, 0xDF, 0xE1, 0xB8, 0x87, + 0x15, 0x2C, 0xCB, 0x4D, 0xD7, 0x44, 0xDB, 0x3B, + 0x80, 0xA2, 0xEA, 0x9A, 0x7A, 0xA8, 0x39, 0xE2, + 0x33, 0xFC, 0x40, 0xCD, 0x92, 0xB8, 0x62, 0x1D, + 0x9E, 0xC7, 0x65, 0x65, 0x3C, 0x24, 0x6A, 0x77, + 0x11, 0xA5, 0xEE, 0x86, 0x19, 0x5E, 0xCF, 0x01, + 0xF7, 0x74, 0x64, 0xAA, 0xDF, 0xD3, 0x0B, 0x54, + 0xF8, 0xEB, 0x9F, 0xE5, 0x3B, 0x9B, 0x3A, 0xCB, + 0x36, 0x65, 0xA6, 0xD3, 0x8B, 0x5D, 0xD3, 0x55, + 0xC4, 0xD6, 0x26, 0x46, 0x5D, 0x66, 0x4E, 0xEB, + 0x7F, 0xB3, 0x1F, 0x36, 0x12, 0x92, 0x50, 0xF4, + 0xE3, 0x2B, 0x90, 0x32, 0xFF, 0x56, 0x90, 0x81, + 0xC3, 0x52, 0x7A, 0x26, 0x67, 0xA5, 0x4E, 0xC1, + 0x3B, 0xB9, 0x44, 0x4B, 0x6F, 0x96, 0xD7, 0xD4, + 0xE9, 0x67, 0x10, 0x36, 0xD8, 0xAB, 0xC3, 0x0C, + 0x17, 0xCF, 0xC1, 0x38, 0xC9, 0xD6, 0x7B, 0xB9, + 0xFC, 0xF9, 0x1D, 0x49, 0x87, 0x84, 0xCF, 0x86, + 0x72, 0xFD, 0x95, 0x15, 0xBF, 0x27, 0x1F, 0xAB, + 0x64, 0x81, 0xCF, 0x99, 0x96, 0x2E, 0x15, 0x57, + 0xA5, 0xD7, 0x7D, 0x0E, 0xB9, 0xDC, 0x6A, 0x44, + 0xFC, 0x80, 0x80, 0x66, 0x2E, + + 0x9C, 0x95, 0xB5, 0x62, 0xE3, 0x90, 0x98, 0xF3, + 0x02, 0x26, 0x65, 0x18, 0x99, 0x4B, 0xCC, 0x67, + 0x42, 0xCF, 0x7B, 0x21, 0xC4, 0xB7, 0x97, 0x99, + 0x50, 0xBD, 0x05, 0x49, 0xB4, 0xA3, 0x9E, 0xCA, + 0x85, 0xD1, 0xD0, 0x65, 0xF3, 0x69, 0x8E, 0x21, + 0x49, 0xCA, 0x23, 0x89, 0x8F, 0x9A, 0x03, 0x7B, + 0xB0, 0x55, 0xE4, 0x21, 0x7D, 0x00, 0xC1, 0xFA, + 0xBC, 0x24, 0x65, 0x5C, 0x83, 0x67, 0x5B, 0x97, + 0x01, 0xCB, 0x00, 0x82, 0xF2, 0xA1, 0x3E, 0xE8, + 0xCC, 0xCE, 0x00, 0x5A, 0x79, 0xB5, 0xF7, 0x13, + 0xD8, 0x9D, 0x57, 0x8F, 0x98, 0x49, 0x80, 0x72, + 0xC4, 0xA5, 0x7C, 0x03, 0x91, 0x77, 0x1F, 0x82, + 0x07, 0x42, 0x88, 0x36, 0x00, 0x9B, 0x09, 0x87, + 0x90, 0xE6, 0x6C, 0x53, 0xF6, 0x3A, 0x5F, 0x6E, + 0x71, 0xA3, 0xDB, 0x58, 0x49, 0x69, 0xCC, 0x9B, + 0x69, 0x85, 0x43, 0xFF, 0x1E, 0xEA, 0x53, 0x3C, + 0xF5, 0xD9, 0x7C, 0x63, 0xF6, 0x85, 0xEB, 0xE0, + 0xE9, 0x20, 0x6F, 0xB1, 0x5F, 0xFE, 0xEA, 0xF1, + 0x30, 0x1F, 0x7E, 0x61, 0x10, 0x74, 0x29, 0x06, + 0xB4, 0x9F, 0xAC, 0xA5, 0x3E, 0xC1, 0xAF, 0xF8, + 0x6A, 0x3F, 0x7E, 0xDE, 0x75, 0x67, 0xB7, 0x79, + 0xAB, 0x96, 0x82, 0xD9, 0x52, 0x08, 0xC9, 0xEA, + 0x1F, 0x69, 0xBF, 0xF6, 0xEA, 0xE2, 0x6F, 0x7B, + 0xB7, 0x2F, 0xED, 0xA8, 0x50, 0xD4, + + 0x5E, 0xAA, 0x52, 0xBD, 0xD4, 0x77, 0xAF, 0x8B, + 0x18, 0x01, 0xE0, 0xF7, 0xC4, 0xE7, 0x4B, 0x86, + 0xAB, 0x7D, 0x11, 0xE6, 0x70, 0x98, 0x34, 0x7C, + 0x53, 0x63, 0x75, 0xFE, 0xE8, 0xB4, 0x7A, 0x95, + 0x59, 0x0A, 0x4D, 0x78, 0x65, 0x7E, 0x93, 0xEE, + 0xD0, 0x84, 0x3D, 0xE0, 0xB6, 0xA2, 0x2D, 0x8A, + 0x36, 0x68, 0x04, 0xB4, 0x84, 0x38, 0x14, 0x1E, + 0x7A, 0x61, 0x6B, 0x60, 0xA0, 0x4A, 0xE1, 0x7D, + 0x4B, 0xB8, 0x8F, 0x31, 0x49, 0x66, 0xE2, 0x3E, + 0x73, 0xE5, 0xE1, 0x73, 0xB9, 0x9A, 0x4D, 0xAD, + 0xD5, 0xED, 0x42, 0x53, 0x41, 0x42, 0x21, 0x2E, + 0xC3, 0x36, 0x8B, 0x0A, 0x40, 0xB5, 0xB4, 0x0C, + 0xB3, 0xF0, 0x53, 0x34, 0xD7, 0xE5, 0xE0, 0x70, + 0xB1, 0xEA, 0x86, 0x5E, 0x9A, 0x39, 0x30, 0x95, + 0x84, 0xC7, 0x57, 0x93, 0xC9, 0x7A, 0xF6, 0x10, + 0x3D, 0x3F, 0x68, 0x33, 0xC3, 0x4F, 0x45, 0x36, + 0xB0, 0xA4, 0xDF, 0x58, 0xE8, 0xB7, 0x4A, 0x42, + 0x8C, 0x6D, 0x04, 0xCF, 0x24, 0xA5, 0x69, 0x95, + 0xDE, 0x04, 0xC3, 0xA8, 0xDD, 0xE3, 0x78, 0x44, + 0xA0, 0x9F, 0x11, 0x9B, 0xB4, 0xA2, 0x27, 0x7A, + 0x15, 0xA3, 0x9D, 0x27, 0x80, 0x35, 0xB4, 0x9F, + 0x33, 0xBE, 0x27, 0x3A, 0xE1, 0x1F, 0x67, 0x97, + 0x1D, 0x1A, 0x7D, 0x11, 0x59, 0xEF, 0x01, 0x5E, + 0x8E, 0xD9, 0xA8, 0x16, 0x94, 0x54, 0xD9, + + 0x49, 0x52, 0x78, 0x3A, 0x42, 0x33, 0x66, 0xEF, + 0x71, 0xB1, 0xF3, 0x8B, 0x98, 0xB2, 0x65, 0x8A, + 0x8A, 0x5D, 0xE8, 0x6B, 0x9B, 0xFB, 0xEF, 0x15, + 0x86, 0x3C, 0x68, 0x1D, 0x3A, 0x5C, 0xA7, 0xD8, + 0x3B, 0x33, 0x95, 0xF0, 0x9C, 0xB8, 0xA6, 0x92, + 0x11, 0x79, 0xB2, 0xD9, 0x3C, 0x18, 0x7F, 0xBB, + 0xF9, 0xAA, 0x43, 0x01, 0xD1, 0x7D, 0xC7, 0xB7, + 0x0D, 0x49, 0x44, 0x0D, 0x36, 0x0B, 0xD9, 0xC6, + 0x54, 0x79, 0x0A, 0x63, 0x79, 0x86, 0xBD, 0x0B, + 0xC4, 0x03, 0xF5, 0xFC, 0x1E, 0x37, 0xE5, 0x24, + 0x30, 0x5A, 0x35, 0x1D, 0x13, 0xE8, 0x35, 0x9E, + 0x42, 0x0F, 0xDA, 0xB1, 0x80, 0xD1, 0xE6, 0xE5, + 0x7A, 0xD5, 0xFE, 0x66, 0x8B, 0x38, 0xD7, 0x5E, + 0xD8, 0xE0, 0x67, 0xC0, 0xE0, 0x06, 0x10, 0xE6, + 0x18, 0xC7, 0x7A, 0xF4, 0xCF, 0xFD, 0xB2, 0xB4, + 0x1C, 0xF5, 0x46, 0x7D, 0xDF, 0x7C, 0x83, 0xA5, + 0xAB, 0xC3, 0x7C, 0xE1, 0x3F, 0x0A, 0xA3, 0xAA, + 0x37, 0x9F, 0x86, 0x8F, 0xAD, 0x26, 0xB8, 0x84, + 0xF4, 0x91, 0xF7, 0x19, 0x0A, 0x7B, 0x1B, 0x46, + 0x63, 0x43, 0x08, 0x41, 0x07, 0x0D, 0x19, 0xF1, + 0xFF, 0x8D, 0x23, 0xF1, 0xE8, 0x42, 0x54, 0x4C, + 0xBC, 0x89, 0x34, 0xA3, 0x90, 0xDC, 0x8A, 0x9F, + 0xA0, 0xFD, 0xC9, 0x65, 0xAB, 0x6B, 0x29, 0x71, + 0x6C, 0xA9, 0xF4, 0x77, 0x50, 0xA5, 0xEA, 0xBB, + + 0x9C, 0xB1, 0xAA, 0x0D, 0xDB, 0xC1, 0x1A, 0x9C, + 0x5C, 0x98, 0x93, 0xD8, 0x01, 0xC7, 0xFE, 0x24, + 0xBC, 0x60, 0x5F, 0x0D, 0xA4, 0x50, 0xC2, 0x9D, + 0x11, 0x34, 0xDE, 0x31, 0xE9, 0xD2, 0x45, 0x49, + 0x6F, 0xC2, 0x91, 0x8C, 0x75, 0x1D, 0xB8, 0xD8, + 0x27, 0xA1, 0x5F, 0xF2, 0x66, 0xBA, 0xD2, 0x5C, + 0xD6, 0xBB, 0x5B, 0x45, 0x57, 0x08, 0xF3, 0x0A, + 0x5C, 0x58, 0xAA, 0x0B, 0x79, 0x12, 0x2F, 0x2D, + 0x42, 0x37, 0xCD, 0x5C, 0xB3, 0xF1, 0x8F, 0x34, + 0xE2, 0x61, 0xC3, 0x45, 0xFC, 0xFF, 0x96, 0x53, + 0x0B, 0x1A, 0x71, 0xB5, 0x5F, 0xA2, 0x12, 0x26, + 0x78, 0xCC, 0xBD, 0x5A, 0x84, 0x35, 0xAE, 0xF2, + 0xA3, 0xC3, 0x42, 0x5F, 0x51, 0x22, 0x77, 0x91, + 0x08, 0xDF, 0x1C, 0x68, 0xAE, 0x0F, 0x51, 0x79, + 0x4E, 0x75, 0xED, 0x8D, 0x55, 0x2A, 0x54, 0x88, + 0x97, 0xF8, 0x90, 0x24, 0x14, 0xE3, 0x07, 0x4D, + 0xCD, 0x26, 0x06, 0xA7, 0x35, 0xCF, 0x6A, 0x38, + 0xB7, 0x98, 0x2F, 0xA8, 0xAE, 0x6C, 0x3D, 0xB5, + 0x1E, 0x37, 0xD1, 0xE9, 0xD4, 0x53, 0x67, 0x4B, + 0xA4, 0xAE, 0xFA, 0x51, 0x01, 0x40, 0x8B, 0xD1, + 0x09, 0x74, 0x4C, 0x7F, 0xB2, 0xFA, 0xF9, 0xA8, + 0x27, 0xAF, 0xC8, 0x24, 0x2C, 0x31, 0xA1, 0xF6, + 0xF8, 0x81, 0xAC, 0xB4, 0x02, 0x83, 0x6F, 0x49, + 0xCF, 0xEC, 0xDF, 0x71, 0x5E, 0x2F, 0x33, 0x07, + 0xBA, + + 0x55, 0xA8, 0x19, 0x38, 0x4C, 0x45, 0x5C, 0xF7, + 0x03, 0x9A, 0x21, 0x1B, 0xFF, 0xA8, 0xF7, 0x76, + 0x3E, 0xF2, 0x8E, 0xF1, 0xCD, 0x69, 0xDB, 0x0F, + 0xF6, 0x1C, 0x6A, 0x92, 0x71, 0xEF, 0x4A, 0x3E, + 0xCE, 0xF9, 0xEA, 0xAB, 0x76, 0x6B, 0x1E, 0xB5, + 0x02, 0x61, 0xA7, 0x02, 0x76, 0xBA, 0x6B, 0x1D, + 0xE5, 0xF0, 0x12, 0xDF, 0x1D, 0x61, 0x82, 0x90, + 0x91, 0xDA, 0x96, 0x60, 0x89, 0x88, 0x83, 0xCD, + 0xBF, 0xAC, 0xA8, 0x86, 0xC4, 0x7F, 0xA5, 0xA3, + 0x3E, 0x50, 0xC4, 0x8B, 0x30, 0xD8, 0x98, 0x89, + 0x0E, 0x10, 0xA3, 0x77, 0x64, 0xBF, 0x44, 0xE8, + 0x7B, 0xF4, 0x56, 0xA2, 0x87, 0x06, 0xF6, 0xF0, + 0x98, 0x77, 0x92, 0x5D, 0xED, 0x6A, 0x29, 0x33, + 0x22, 0x31, 0xD5, 0x3A, 0xD4, 0xDB, 0x11, 0x34, + 0x7D, 0xA0, 0xFC, 0x96, 0x54, 0x61, 0x16, 0x2C, + 0x48, 0x6C, 0x55, 0x2B, 0xE0, 0x8C, 0xE3, 0x7F, + 0x05, 0x32, 0xFB, 0xCE, 0xD4, 0x2F, 0x47, 0x54, + 0xE5, 0x9D, 0x6B, 0x68, 0x85, 0xF0, 0xD6, 0xCD, + 0xEA, 0xB6, 0x48, 0x59, 0xA8, 0xE6, 0x0B, 0x80, + 0x21, 0x2A, 0x62, 0x74, 0x1E, 0xD9, 0x11, 0x9A, + 0x16, 0x8A, 0xB0, 0xC5, 0x2C, 0xF2, 0x77, 0x80, + 0x0D, 0x74, 0x24, 0xE9, 0x29, 0x65, 0x47, 0x1F, + 0xEE, 0xF0, 0xA4, 0x26, 0xAF, 0xC5, 0x4B, 0x83, + 0x67, 0x23, 0x7C, 0x2E, 0x54, 0x29, 0x88, 0xD0, + 0x6A, 0xCB, + + 0x35, 0x07, 0x1D, 0x30, 0xAA, 0x5F, 0xC8, 0x44, + 0xDA, 0x6D, 0xB6, 0xCB, 0x0B, 0xD6, 0x54, 0x54, + 0x48, 0x98, 0x07, 0xE6, 0xB0, 0x33, 0x48, 0xCF, + 0xB7, 0xAF, 0x58, 0xF6, 0x2A, 0x09, 0xD2, 0x7A, + 0xB5, 0xB4, 0x93, 0x6C, 0xC3, 0x83, 0xFB, 0x17, + 0xE5, 0xBF, 0xDD, 0xE3, 0x10, 0x37, 0x69, 0xF9, + 0x90, 0xEE, 0x65, 0x1E, 0x8F, 0x82, 0x14, 0xC5, + 0x38, 0xF3, 0x96, 0x22, 0x63, 0x81, 0xD4, 0x7A, + 0x23, 0x2E, 0x9A, 0xFD, 0xD4, 0xBB, 0xE1, 0x56, + 0xDD, 0xB6, 0xD0, 0x77, 0x0C, 0x88, 0x50, 0x18, + 0xE3, 0x25, 0xBC, 0x33, 0x36, 0xB0, 0xD9, 0x65, + 0xD2, 0xC2, 0xAA, 0x26, 0xB4, 0x52, 0xEF, 0x8B, + 0x19, 0x74, 0x14, 0x69, 0xB9, 0x60, 0x0B, 0x59, + 0x2C, 0xC7, 0x74, 0x0F, 0x6B, 0xF7, 0x5C, 0x4F, + 0xC7, 0xC8, 0xED, 0xFF, 0x1F, 0x02, 0x46, 0x46, + 0x93, 0x38, 0x6F, 0x34, 0x2A, 0x0C, 0xEC, 0x3E, + 0x3F, 0xAA, 0xA0, 0xEB, 0x43, 0x24, 0x84, 0x55, + 0xAF, 0x43, 0x08, 0x0B, 0xDD, 0x0D, 0x9D, 0x01, + 0x5C, 0x47, 0x27, 0x47, 0x3A, 0x0D, 0xA8, 0x27, + 0xAE, 0x04, 0x25, 0x27, 0x5D, 0xF6, 0x19, 0x6B, + 0x2E, 0x5A, 0x1B, 0x70, 0xBD, 0xB3, 0x44, 0x23, + 0x59, 0x4F, 0xE4, 0xA0, 0x02, 0x78, 0x22, 0xA6, + 0x25, 0xA8, 0x55, 0x59, 0xB5, 0xA0, 0x60, 0x47, + 0x57, 0x1F, 0x62, 0xC2, 0x16, 0x38, 0x7D, 0x86, + 0xB9, 0x0F, 0x8A, + + 0xDD, 0x6E, 0xDE, 0x6B, 0x5B, 0x0B, 0xEA, 0xD1, + 0xB1, 0xB9, 0xD8, 0xA3, 0xCE, 0xE3, 0x95, 0x79, + 0x16, 0x68, 0x90, 0x54, 0x7A, 0xC4, 0x4E, 0x77, + 0x95, 0xD6, 0xBE, 0xAF, 0x0E, 0xE0, 0x88, 0xDA, + 0x28, 0xF2, 0xEA, 0x52, 0x77, 0xFE, 0x7F, 0xAA, + 0x3D, 0xD4, 0xCA, 0x1B, 0xBC, 0xAC, 0xC5, 0x0D, + 0xE2, 0x50, 0x70, 0x57, 0x12, 0x14, 0x54, 0x97, + 0x22, 0x3E, 0x43, 0x82, 0x0F, 0xA1, 0xA8, 0x93, + 0x4A, 0xD3, 0x7E, 0xE1, 0x1E, 0xBE, 0xD5, 0x3E, + 0x36, 0x61, 0xB1, 0x0A, 0x85, 0x6F, 0x3B, 0xF4, + 0x60, 0x39, 0xEE, 0xE5, 0x81, 0x88, 0xC2, 0x6E, + 0x24, 0xAC, 0xBD, 0x0C, 0x25, 0xE7, 0xAB, 0xB0, + 0xC8, 0xA1, 0x8F, 0x09, 0xE3, 0xCA, 0x77, 0xE3, + 0x50, 0x80, 0x6A, 0x42, 0x94, 0x2C, 0x43, 0x85, + 0x71, 0xB8, 0x4A, 0xCC, 0xBA, 0x0C, 0x5D, 0xBF, + 0x2C, 0xF8, 0x36, 0x5D, 0x79, 0xFB, 0x3C, 0x11, + 0x15, 0x7C, 0x47, 0xDD, 0xC7, 0x26, 0x71, 0x44, + 0xAF, 0x17, 0xAE, 0x74, 0xF1, 0xC5, 0xE0, 0x00, + 0x5C, 0xF0, 0x96, 0x38, 0x86, 0x1A, 0x7F, 0xA1, + 0xBC, 0x0E, 0x32, 0xCA, 0x54, 0xBF, 0x5F, 0xEA, + 0x76, 0x31, 0x1B, 0x1B, 0x70, 0xE5, 0xB9, 0xA8, + 0x18, 0x58, 0xF4, 0x31, 0x92, 0xDD, 0x25, 0xB6, + 0xF5, 0xC1, 0x6B, 0x0D, 0xFC, 0x97, 0x29, 0xD1, + 0x6F, 0xE2, 0xCD, 0xC6, 0x41, 0x24, 0x28, 0x68, + 0x42, 0x23, 0x34, 0xF5, + + 0xC7, 0xD2, 0x23, 0x12, 0x22, 0x4E, 0x47, 0x8E, + 0xB9, 0x0E, 0x31, 0x80, 0xA3, 0xB3, 0x72, 0xE1, + 0xB4, 0xE6, 0x43, 0x4C, 0x9C, 0xDE, 0xBD, 0x34, + 0x79, 0xD8, 0x2D, 0x82, 0xA2, 0x79, 0x64, 0x54, + 0x13, 0x9C, 0xFC, 0x21, 0x3A, 0x7C, 0xFC, 0x84, + 0x87, 0xB6, 0x94, 0xD8, 0x8E, 0x6A, 0xBD, 0xA7, + 0xC5, 0x2E, 0xC6, 0x88, 0x46, 0xF9, 0xA3, 0xFE, + 0x66, 0x6D, 0x10, 0xB3, 0x07, 0x27, 0xDE, 0xDC, + 0x84, 0xEC, 0xFB, 0x15, 0xC7, 0x6C, 0x9E, 0x3E, + 0x03, 0x41, 0x29, 0x8F, 0x06, 0xDB, 0xF1, 0x5E, + 0x21, 0xB7, 0x5E, 0x42, 0x9C, 0x7D, 0x21, 0xC8, + 0x78, 0x5E, 0x6E, 0x19, 0x77, 0x21, 0x41, 0xF6, + 0x5D, 0x2F, 0x6A, 0xC1, 0xCB, 0xB8, 0x62, 0x4B, + 0xDD, 0xD4, 0xBE, 0x2E, 0xAD, 0x05, 0x6E, 0x4F, + 0x96, 0x4C, 0x02, 0x5D, 0x75, 0xE7, 0x0E, 0x50, + 0xA5, 0x45, 0xB3, 0x47, 0xAC, 0xAE, 0xED, 0x0C, + 0x94, 0x6A, 0x5E, 0x4A, 0x66, 0xE9, 0x2A, 0x2A, + 0x5B, 0x00, 0xA7, 0xEC, 0xDE, 0xE7, 0xE8, 0xAA, + 0x01, 0x51, 0x4F, 0x2B, 0x67, 0x95, 0x2E, 0xA7, + 0xE3, 0x05, 0x9D, 0x45, 0x40, 0x68, 0x7F, 0xBB, + 0x98, 0xCB, 0x54, 0x8C, 0xEB, 0x29, 0xAD, 0xE2, + 0xA6, 0x8C, 0xBB, 0x33, 0xCD, 0xB2, 0x79, 0x6E, + 0x37, 0x01, 0xEB, 0xF6, 0x19, 0x70, 0x08, 0x08, + 0x17, 0x4F, 0x8E, 0x45, 0x2A, 0x8A, 0x97, 0x91, + 0x8D, 0x4F, 0x53, 0x4B, 0x3F, + + 0xCA, 0x0D, 0x28, 0x4B, 0x0A, 0x4D, 0xD4, 0x03, + 0xDA, 0xAA, 0x7E, 0x33, 0x7D, 0x98, 0x9D, 0xE0, + 0x5B, 0x29, 0x94, 0x19, 0xA4, 0xD8, 0xC7, 0xF8, + 0x11, 0xF0, 0xD9, 0x18, 0x9A, 0x17, 0x1A, 0x14, + 0xE1, 0x4E, 0x4F, 0x09, 0x45, 0x7D, 0x17, 0xE9, + 0xB7, 0xA2, 0x6B, 0x0A, 0xE6, 0x17, 0x57, 0x05, + 0x24, 0xDC, 0xC6, 0x75, 0xAE, 0xBC, 0xAE, 0x32, + 0x1B, 0x60, 0x5A, 0x5D, 0x77, 0xB4, 0x42, 0x48, + 0x99, 0xE7, 0xB5, 0xEB, 0xE5, 0x7A, 0x10, 0x93, + 0x5D, 0x81, 0xCA, 0x01, 0x2F, 0x41, 0xD4, 0x0F, + 0xDE, 0xBE, 0xC4, 0x59, 0xC3, 0xDB, 0xDE, 0xF3, + 0x14, 0xFC, 0xC5, 0x8B, 0x22, 0xCC, 0x6A, 0x3F, + 0x0C, 0xCC, 0x53, 0x3D, 0x39, 0x0C, 0x83, 0xED, + 0x51, 0x54, 0x4A, 0xD9, 0x2D, 0x0C, 0x5E, 0x1D, + 0x0B, 0x82, 0x73, 0x0C, 0x41, 0xCD, 0x8D, 0xD0, + 0xD9, 0xD3, 0x7C, 0x8D, 0x3D, 0xFA, 0xA9, 0x51, + 0xE5, 0x13, 0x8B, 0x81, 0x32, 0x62, 0xAB, 0xB6, + 0xB1, 0xF2, 0x1C, 0x5C, 0xE6, 0x9A, 0xB0, 0x83, + 0x40, 0x92, 0xB8, 0x85, 0x22, 0x7E, 0x53, 0x9A, + 0x0F, 0x87, 0xDD, 0xBA, 0x20, 0x83, 0xE4, 0x93, + 0xDE, 0x35, 0x8E, 0xBD, 0x2F, 0xA3, 0x04, 0xF2, + 0x87, 0x62, 0x9E, 0xD9, 0x72, 0xBC, 0xC7, 0x0C, + 0x8F, 0x6F, 0x48, 0x93, 0x0D, 0x48, 0x9B, 0x21, + 0xA7, 0xD4, 0x12, 0x0C, 0x06, 0x61, 0x9D, 0xC2, + 0x45, 0x51, 0x17, 0x6D, 0xD2, 0x95, + + 0x15, 0x94, 0x79, 0xF5, 0xEB, 0x7F, 0xDD, 0x18, + 0x2E, 0x9C, 0x4B, 0xA0, 0xD2, 0x3D, 0xEF, 0x37, + 0x82, 0xDB, 0xDC, 0xFB, 0x8D, 0x07, 0x87, 0x30, + 0x89, 0x79, 0x31, 0xB1, 0x27, 0xAF, 0x6B, 0x9B, + 0x0C, 0xAB, 0xA3, 0x72, 0xA4, 0xE3, 0x96, 0x7B, + 0x61, 0x4F, 0xB4, 0x0D, 0xD1, 0x64, 0x9D, 0xD5, + 0x3D, 0x0F, 0x24, 0x3C, 0xFF, 0x39, 0xA3, 0x08, + 0x7E, 0xD0, 0x4A, 0x14, 0xF2, 0x16, 0x08, 0x12, + 0x58, 0x6F, 0xE4, 0xC3, 0xEE, 0x77, 0xDA, 0xF0, + 0x21, 0x0E, 0x8A, 0xFB, 0x19, 0x46, 0x08, 0xCF, + 0x47, 0x93, 0x76, 0xE8, 0x15, 0x7F, 0x07, 0xC7, + 0x44, 0x4A, 0x35, 0xA9, 0x65, 0x58, 0xF6, 0x21, + 0xCA, 0x2E, 0xAD, 0xE1, 0x21, 0xE2, 0x25, 0x8F, + 0x87, 0xA4, 0xFD, 0xE1, 0xEF, 0xE9, 0x25, 0x70, + 0x7E, 0x41, 0x4D, 0x5A, 0x20, 0xC6, 0x0C, 0xD4, + 0xE5, 0x49, 0xF3, 0xB9, 0xDB, 0xE5, 0xCE, 0x21, + 0x1D, 0xE5, 0xA9, 0x73, 0x5E, 0x91, 0xFA, 0x86, + 0x5A, 0x25, 0x52, 0x27, 0xF5, 0x4C, 0x92, 0xC1, + 0x14, 0x52, 0x0E, 0x78, 0x6E, 0xCD, 0x8F, 0x0F, + 0xD5, 0x40, 0x42, 0x01, 0xD1, 0x6A, 0xD2, 0xCE, + 0xD8, 0xC0, 0x6A, 0x3E, 0x82, 0xF0, 0x41, 0x0D, + 0x44, 0x24, 0xE2, 0x43, 0xA3, 0xE8, 0x68, 0x12, + 0x46, 0x2E, 0x7A, 0x72, 0x04, 0xE0, 0xE6, 0x38, + 0x4D, 0x62, 0x7F, 0x02, 0x59, 0x17, 0x8F, 0xB9, + 0x75, 0x74, 0x25, 0x7F, 0x95, 0xBF, 0x9C, + + 0xC5, 0x38, 0x2D, 0xA3, 0x3D, 0xF8, 0x27, 0x28, + 0x56, 0x3E, 0x35, 0x24, 0x8D, 0x8F, 0x56, 0xBD, + 0xA9, 0x6D, 0x58, 0x99, 0x12, 0xC7, 0xAB, 0x4A, + 0xE0, 0xF7, 0xDE, 0x1E, 0xF0, 0x40, 0x89, 0x0C, + 0xE4, 0x7B, 0xF8, 0x7B, 0x8C, 0x1B, 0x6F, 0xC1, + 0xD4, 0x6E, 0xEF, 0x45, 0x2E, 0x7E, 0x03, 0x0F, + 0x3B, 0x0F, 0x48, 0x28, 0x8D, 0x8C, 0xAF, 0x9E, + 0xB3, 0x55, 0x6B, 0xA7, 0xAA, 0x03, 0x94, 0x21, + 0xED, 0x7A, 0x92, 0x81, 0x12, 0x37, 0xAF, 0x4B, + 0xE1, 0x34, 0x62, 0xC6, 0x7D, 0x5E, 0xA8, 0xD6, + 0x9A, 0xB8, 0x12, 0xF0, 0xB8, 0x7E, 0x92, 0x88, + 0xDB, 0x67, 0x97, 0x56, 0x88, 0xA4, 0x22, 0x18, + 0xFC, 0xC3, 0xCD, 0x1B, 0x12, 0x09, 0xC9, 0xD6, + 0x71, 0xE1, 0x76, 0xED, 0x95, 0x61, 0x96, 0xF9, + 0xB1, 0xFA, 0x16, 0x9F, 0xDC, 0x3A, 0x3C, 0x9A, + 0xFB, 0x25, 0x0A, 0x0C, 0x8B, 0xFB, 0xD1, 0x7E, + 0x13, 0x27, 0x5B, 0x24, 0x95, 0xC4, 0x6B, 0xAC, + 0x32, 0xB5, 0x1D, 0xC9, 0x96, 0x67, 0x84, 0x43, + 0x5C, 0xAD, 0xD2, 0xF2, 0x15, 0xDA, 0x83, 0x84, + 0x71, 0xB2, 0x14, 0x04, 0x20, 0xDD, 0x04, 0x78, + 0x6E, 0xCD, 0x7F, 0x73, 0xD1, 0xAD, 0xBE, 0xD4, + 0x4F, 0xED, 0xF8, 0xE9, 0xEA, 0x07, 0xBD, 0xB7, + 0xDD, 0x0F, 0xFB, 0xF5, 0x88, 0x6A, 0x3E, 0x8A, + 0xCD, 0x79, 0xBA, 0xDE, 0x98, 0xB3, 0x74, 0x3D, + 0x0F, 0x92, 0x40, 0x10, 0xE4, 0x26, 0x85, 0x2D, + + 0x0E, 0x46, 0xBD, 0x8B, 0xDC, 0xE8, 0x28, 0x6A, + 0x31, 0x78, 0xE6, 0xDE, 0x37, 0xC0, 0x68, 0x2D, + 0xE0, 0x38, 0xD0, 0x2F, 0x28, 0xBB, 0xA2, 0xF4, + 0x8F, 0x82, 0x35, 0xDF, 0x0F, 0xB9, 0x31, 0x98, + 0xF6, 0x03, 0x66, 0x80, 0xCF, 0xDA, 0xF0, 0x0B, + 0x4C, 0x62, 0x2F, 0x6E, 0x7A, 0x1B, 0x80, 0x98, + 0x7A, 0xDB, 0x1F, 0x2B, 0xC2, 0x2F, 0x96, 0x80, + 0x58, 0x98, 0x21, 0xFC, 0xBB, 0x1A, 0x13, 0xAF, + 0x56, 0xA5, 0x4A, 0x89, 0xDB, 0xF0, 0x28, 0x97, + 0x43, 0xB6, 0x45, 0xBF, 0x58, 0x76, 0x78, 0x8A, + 0x83, 0xF8, 0x6E, 0xC1, 0x90, 0x99, 0x59, 0x0A, + 0xF2, 0x1E, 0x95, 0x8A, 0x13, 0x58, 0xC0, 0xC7, + 0x8F, 0x27, 0xD9, 0x53, 0xEC, 0xD0, 0x24, 0xFC, + 0x83, 0x60, 0x74, 0x24, 0x2D, 0xD5, 0xE5, 0x51, + 0x27, 0x0E, 0x62, 0x17, 0xD4, 0xAA, 0xF1, 0x30, + 0x6F, 0x35, 0x4C, 0xE0, 0x91, 0x2D, 0xDA, 0x11, + 0x68, 0xDF, 0x6F, 0xEA, 0x29, 0xC0, 0xB4, 0x75, + 0x04, 0x4E, 0xB7, 0x49, 0x47, 0x19, 0xA1, 0x7F, + 0x99, 0x0B, 0x45, 0x95, 0x3F, 0x6A, 0x97, 0x8B, + 0xA8, 0x27, 0x1C, 0xBF, 0x07, 0x7D, 0x30, 0xD9, + 0x97, 0xD7, 0xA5, 0x2D, 0x22, 0x23, 0xF7, 0x1D, + 0xFD, 0x4A, 0xE9, 0xA8, 0xFD, 0x10, 0xE4, 0xEF, + 0x0F, 0xBB, 0x54, 0x2B, 0xFC, 0x74, 0xDE, 0x55, + 0xF7, 0x51, 0xBF, 0x8B, 0x73, 0x38, 0xF8, 0x5E, + 0xFF, 0x8C, 0x96, 0xFF, 0xFA, 0x82, 0x67, 0xC7, + 0xA6, + + 0x78, 0xC3, 0xA1, 0xCB, 0x49, 0x80, 0x93, 0x83, + 0x6D, 0x3D, 0x8C, 0xB6, 0x38, 0x79, 0x45, 0xCF, + 0x65, 0x32, 0x71, 0xE6, 0x00, 0x24, 0x23, 0x45, + 0x47, 0x37, 0x84, 0x54, 0x1B, 0x7E, 0x25, 0x5B, + 0x86, 0xA5, 0x55, 0x07, 0xB4, 0x0B, 0xCD, 0x23, + 0x6B, 0xF3, 0x33, 0xCB, 0xCA, 0x7C, 0xBC, 0x7F, + 0x43, 0x50, 0x02, 0xA2, 0x45, 0x1C, 0xD3, 0x32, + 0x7C, 0x28, 0x6D, 0xA1, 0x24, 0x2A, 0x58, 0x29, + 0xC1, 0xB2, 0x6C, 0x71, 0x1A, 0xA4, 0xA9, 0xB3, + 0x27, 0xAB, 0xBC, 0xC6, 0x9F, 0x9D, 0x92, 0xB6, + 0x70, 0x99, 0xA6, 0x9B, 0xAD, 0x8A, 0x59, 0xC9, + 0x08, 0xE0, 0xFB, 0x92, 0xB0, 0x0B, 0x03, 0x75, + 0xBA, 0xC0, 0x88, 0x56, 0xF2, 0x8B, 0xCD, 0x22, + 0xB8, 0x2B, 0xEA, 0xD8, 0x79, 0xD1, 0xA5, 0xF4, + 0x98, 0xEF, 0x71, 0xE9, 0xFE, 0xBC, 0x0F, 0xEA, + 0x5B, 0x8D, 0x96, 0xF6, 0xB7, 0x03, 0xEF, 0xA6, + 0x61, 0x05, 0x8F, 0xB3, 0x0D, 0xB0, 0xCA, 0xC1, + 0xCF, 0x25, 0xB2, 0x87, 0x98, 0x13, 0xB8, 0xEC, + 0xA8, 0x54, 0xF6, 0xF5, 0x5F, 0xB2, 0x11, 0x52, + 0x14, 0xD7, 0x9E, 0x36, 0x93, 0x62, 0x3B, 0x24, + 0x92, 0x9C, 0x63, 0xB7, 0x2D, 0x18, 0xAA, 0x10, + 0x89, 0x84, 0x29, 0x16, 0xF0, 0xDF, 0x7C, 0x31, + 0x0C, 0x3E, 0x25, 0xB3, 0x72, 0x50, 0xE3, 0x51, + 0xDC, 0x12, 0x58, 0xA7, 0xED, 0x38, 0x43, 0x92, + 0x1B, 0xA5, 0x54, 0xE1, 0xC6, 0x56, 0x30, 0x65, + 0x0A, 0xA5, + + 0x02, 0xF5, 0xEC, 0x03, 0x39, 0xF9, 0x74, 0xC8, + 0xAC, 0xC7, 0xF7, 0xE5, 0x62, 0x30, 0xB3, 0x0E, + 0xBA, 0x02, 0xD6, 0x48, 0x76, 0x84, 0xDC, 0x9F, + 0xF0, 0x79, 0x39, 0x06, 0xA9, 0x82, 0x53, 0x00, + 0xAB, 0x09, 0x0C, 0x16, 0xDE, 0xC1, 0x05, 0xC8, + 0x2C, 0x92, 0x02, 0x61, 0xEA, 0x87, 0x8C, 0xFC, + 0x8A, 0x0B, 0x9F, 0x04, 0x9F, 0x51, 0x5F, 0x7B, + 0x4F, 0xAC, 0xF1, 0x4F, 0x9A, 0x29, 0x61, 0x42, + 0x8C, 0xD7, 0x23, 0x49, 0x63, 0xEB, 0xFD, 0x2C, + 0xDC, 0x76, 0xF1, 0xF0, 0xC8, 0xA2, 0x97, 0x5C, + 0x20, 0x23, 0x7C, 0x9F, 0x5D, 0xDE, 0x59, 0x87, + 0x3A, 0x33, 0xE6, 0x77, 0x83, 0xE8, 0xF7, 0xA8, + 0x31, 0x7E, 0xFA, 0x02, 0x79, 0x96, 0x13, 0xCB, + 0x08, 0xB3, 0x0E, 0x18, 0x2E, 0x2C, 0x48, 0x1B, + 0x8D, 0xF7, 0x40, 0x0F, 0xD0, 0x95, 0x29, 0x99, + 0xA9, 0x8C, 0xF5, 0xBA, 0xC3, 0xE7, 0x1E, 0x3F, + 0x34, 0x13, 0x02, 0x24, 0xF0, 0x4E, 0xC6, 0xCD, + 0xEE, 0xA1, 0xF0, 0x0F, 0xAE, 0xB8, 0x31, 0x0F, + 0x5F, 0x34, 0x4F, 0xAC, 0x17, 0x52, 0x26, 0x84, + 0xA0, 0x65, 0x88, 0x2E, 0xA2, 0x75, 0xC0, 0x18, + 0x6A, 0x2C, 0xDD, 0x0F, 0xF9, 0x0E, 0xFA, 0x56, + 0xBB, 0x71, 0xAD, 0x69, 0xCB, 0x96, 0x31, 0xCF, + 0x66, 0x1C, 0x87, 0x71, 0x77, 0x11, 0x39, 0xB7, + 0xE9, 0x25, 0x7A, 0x88, 0x8A, 0x0C, 0xE9, 0xCD, + 0x0F, 0xB9, 0x82, 0x18, 0x66, 0x2A, 0xD1, 0x91, + 0xD9, 0x4F, 0x8D, + + 0xE9, 0xF8, 0x7F, 0xAE, 0x1B, 0x66, 0x68, 0x95, + 0x73, 0xE2, 0x74, 0x01, 0xE1, 0x7D, 0x2A, 0x45, + 0xC0, 0x88, 0x27, 0xB0, 0x1A, 0x6F, 0xD0, 0x5E, + 0xA6, 0x05, 0x9D, 0x18, 0xB8, 0xA2, 0x86, 0x0E, + 0xB3, 0xF7, 0x79, 0xC3, 0x41, 0xBE, 0x1D, 0x34, + 0x69, 0x19, 0x07, 0x2F, 0x81, 0x48, 0xFC, 0xC1, + 0x35, 0xA4, 0x98, 0xFF, 0xAA, 0xA7, 0xF9, 0xC7, + 0x32, 0x63, 0xBB, 0x56, 0xA7, 0xBE, 0x31, 0x88, + 0xA1, 0x35, 0x57, 0x17, 0x1B, 0x00, 0x5A, 0x0C, + 0xAF, 0x48, 0xE8, 0xA6, 0x63, 0x5F, 0x6B, 0xB9, + 0x4D, 0x44, 0x0E, 0xCB, 0xA2, 0xDB, 0x7E, 0xBD, + 0xC1, 0x99, 0x7A, 0x02, 0xAE, 0xDF, 0x01, 0xA6, + 0x19, 0x8A, 0xA0, 0x91, 0xA8, 0x4E, 0x34, 0xF6, + 0x4A, 0x53, 0xD3, 0x44, 0xF6, 0x3C, 0x5A, 0x2D, + 0x16, 0xAD, 0x5F, 0x09, 0x0B, 0xE2, 0xE8, 0xD0, + 0xFE, 0x09, 0x6F, 0x7A, 0xDB, 0x86, 0x57, 0xA9, + 0x7B, 0x06, 0x7D, 0xC5, 0x99, 0x4C, 0xA5, 0xE2, + 0xEA, 0x18, 0x0A, 0xFD, 0xB6, 0xF2, 0x03, 0xEA, + 0xEC, 0xAF, 0x7B, 0xA1, 0x9C, 0x31, 0xDF, 0x17, + 0x74, 0x6D, 0x01, 0x9E, 0xBF, 0x76, 0x63, 0x2D, + 0x5B, 0xA0, 0xF6, 0xD1, 0xC2, 0x01, 0x40, 0xDF, + 0xE1, 0x81, 0xD6, 0xCB, 0x67, 0xC7, 0x96, 0x6C, + 0xE6, 0x34, 0x9E, 0xA5, 0x23, 0xCA, 0x9B, 0x06, + 0x96, 0x45, 0xFA, 0xB8, 0x96, 0x3A, 0x66, 0x32, + 0x5F, 0xF1, 0x92, 0xA1, 0x64, 0xF8, 0x2B, 0x90, + 0x65, 0x5D, 0xD7, 0xF8, + + 0x8F, 0xEC, 0x60, 0x90, 0x57, 0x5B, 0x8B, 0x0F, + 0xF5, 0xF9, 0xF1, 0xA6, 0x11, 0x9A, 0xE5, 0x47, + 0x50, 0x3A, 0x7D, 0x92, 0x1C, 0x2D, 0xBE, 0x3F, + 0x0B, 0x75, 0x18, 0x78, 0xD1, 0x29, 0xBA, 0x37, + 0x3F, 0xD6, 0x89, 0xE6, 0x14, 0x54, 0x58, 0x70, + 0x0F, 0x17, 0x62, 0x4E, 0xE3, 0x8E, 0xC0, 0x18, + 0x7B, 0x5C, 0xCB, 0x31, 0x95, 0x16, 0x9E, 0xEC, + 0x0B, 0x7B, 0xF4, 0x1D, 0xC6, 0x30, 0xB4, 0xBD, + 0xAA, 0x29, 0x33, 0x94, 0xCC, 0x30, 0x98, 0x44, + 0x20, 0x4E, 0xF3, 0x50, 0x9C, 0x75, 0x5C, 0xB0, + 0xB9, 0x1F, 0x60, 0xDF, 0xFA, 0x57, 0xAF, 0xC1, + 0x69, 0x50, 0xFD, 0x09, 0x9B, 0x62, 0xEB, 0xE5, + 0x9C, 0x09, 0xAB, 0x83, 0x34, 0xDE, 0x9F, 0x48, + 0xF7, 0x2B, 0x21, 0xB7, 0xC5, 0x90, 0x15, 0xFF, + 0x9D, 0x5F, 0xD7, 0x5A, 0x4F, 0x6D, 0xB7, 0x8C, + 0xD5, 0x74, 0x17, 0xEB, 0xD2, 0xF5, 0xE2, 0xCF, + 0x6E, 0xE0, 0xE3, 0xCD, 0xD7, 0x11, 0xD7, 0xA6, + 0x89, 0xF4, 0xDE, 0xEF, 0xEB, 0x77, 0xCD, 0xA3, + 0x2C, 0x1F, 0xDF, 0xED, 0x93, 0xA6, 0x51, 0xC8, + 0xD4, 0x45, 0x72, 0x11, 0x7F, 0xC8, 0x68, 0x86, + 0x4B, 0x6E, 0x13, 0x92, 0x2B, 0xDA, 0x6F, 0xE4, + 0x86, 0xBB, 0xF4, 0x71, 0x8E, 0xA4, 0x2A, 0x55, + 0x3C, 0xC6, 0x37, 0x67, 0x96, 0xFF, 0x40, 0xF9, + 0x1E, 0xDD, 0x95, 0x5A, 0x89, 0x0C, 0x07, 0x59, + 0x90, 0x4F, 0xCF, 0x83, 0xE8, 0x0B, 0x93, 0x73, + 0xAA, 0x8A, 0x15, 0x0A, 0x21, + + 0x8F, 0xB7, 0xC6, 0xB8, 0x22, 0xAE, 0x29, 0x71, + 0x39, 0xA5, 0x99, 0xC3, 0x6F, 0xBD, 0x8D, 0xF2, + 0x74, 0x24, 0x7E, 0xFF, 0x4B, 0x35, 0x63, 0xF4, + 0xD2, 0xA8, 0x55, 0xCD, 0x1A, 0x1A, 0x40, 0x64, + 0x45, 0x61, 0xD8, 0x26, 0xA0, 0x23, 0x3E, 0xDC, + 0x57, 0x05, 0xB8, 0xC4, 0xC0, 0x0C, 0xF4, 0x2E, + 0x3F, 0xBE, 0x36, 0xFB, 0x84, 0xDF, 0x5A, 0x19, + 0x87, 0x78, 0x6B, 0x31, 0x2D, 0xB5, 0x03, 0x98, + 0x92, 0x3C, 0x5F, 0xD7, 0x5F, 0x06, 0x2A, 0x00, + 0x5C, 0x7C, 0xF1, 0x4F, 0x70, 0x36, 0xBB, 0xE0, + 0xDC, 0x5B, 0x9A, 0x10, 0x87, 0x13, 0x05, 0x58, + 0xB2, 0x9C, 0xEB, 0xFE, 0xCF, 0x82, 0x03, 0x18, + 0x6A, 0x37, 0x8D, 0x11, 0xD9, 0x15, 0x1E, 0x27, + 0x54, 0x8E, 0x7A, 0x30, 0x13, 0xD8, 0x1A, 0xBB, + 0x6C, 0xAD, 0xC4, 0xFD, 0x61, 0x2E, 0x03, 0xEB, + 0x2C, 0x2D, 0x01, 0x4A, 0x3A, 0xCA, 0xDF, 0x23, + 0x8E, 0x39, 0x81, 0x6D, 0x62, 0xEE, 0x12, 0x89, + 0xC6, 0xA3, 0x1D, 0x38, 0xA9, 0xDE, 0x5D, 0x1C, + 0x3F, 0xAE, 0x79, 0xAC, 0x2A, 0x5B, 0xCD, 0x94, + 0x9F, 0xE3, 0xB8, 0x93, 0x21, 0x4E, 0x0E, 0xB4, + 0x78, 0xE6, 0xC2, 0x69, 0x7D, 0x58, 0x26, 0xDD, + 0xE1, 0xC0, 0xAB, 0xF9, 0x9F, 0xDE, 0xB0, 0xB5, + 0x24, 0x78, 0x4C, 0x5A, 0x42, 0x91, 0x8E, 0x03, + 0x95, 0xAA, 0x08, 0xD4, 0x56, 0x6D, 0x64, 0x41, + 0xC7, 0xC9, 0x2E, 0xEC, 0xE7, 0x1A, 0xEB, 0xE8, + 0x24, 0x8D, 0xE3, 0x31, 0xA5, 0x11, + + 0x05, 0x2F, 0xC0, 0x7D, 0xD7, 0xC5, 0x12, 0xF3, + 0x37, 0x94, 0x79, 0xEF, 0x44, 0xEE, 0xB0, 0xD0, + 0xED, 0x39, 0xCB, 0x5E, 0x64, 0xE9, 0x83, 0xD2, + 0x76, 0xF0, 0x65, 0x47, 0x25, 0x1D, 0x0D, 0x6B, + 0x16, 0x23, 0x98, 0xE5, 0x1D, 0xF2, 0xB1, 0x68, + 0x0D, 0xBA, 0xFE, 0x9D, 0x1A, 0x1D, 0xBA, 0x5F, + 0x92, 0x6F, 0x17, 0x76, 0xF5, 0xB3, 0xBA, 0x5A, + 0x71, 0x0C, 0x72, 0xFA, 0x32, 0xCC, 0x7B, 0x17, + 0x52, 0xB7, 0xF9, 0x86, 0x70, 0xF7, 0x39, 0x22, + 0xA1, 0xF6, 0xB3, 0xAA, 0xE9, 0xC5, 0x8B, 0x69, + 0xE4, 0x48, 0xD2, 0xAA, 0x8E, 0xAF, 0x7C, 0xE5, + 0x77, 0xE1, 0x33, 0xEC, 0x30, 0x20, 0xB8, 0xCD, + 0x3E, 0xD6, 0xB6, 0xD0, 0x64, 0x86, 0x39, 0x01, + 0x0D, 0x4F, 0xAB, 0xF7, 0x7B, 0xBE, 0x97, 0x21, + 0xCD, 0x96, 0x69, 0x16, 0x73, 0x61, 0x7D, 0x84, + 0x21, 0x3A, 0xA0, 0x07, 0xDE, 0xCA, 0x17, 0x0E, + 0x82, 0xA4, 0x8B, 0x2D, 0xE4, 0x99, 0x11, 0x3C, + 0x3C, 0x5B, 0x16, 0xB8, 0x00, 0xEE, 0xD1, 0xDF, + 0x68, 0x30, 0x0E, 0x12, 0x5E, 0x12, 0x4F, 0x1B, + 0xBE, 0xC2, 0x9B, 0x99, 0x64, 0xDB, 0xCE, 0x29, + 0xE5, 0x8E, 0x66, 0x96, 0x65, 0x37, 0x6E, 0xE2, + 0xE9, 0x05, 0x34, 0x56, 0x8D, 0xDF, 0x24, 0x34, + 0x09, 0x77, 0xB0, 0x76, 0xDD, 0x1E, 0x76, 0x5D, + 0x67, 0x7D, 0xCC, 0xCF, 0xB2, 0x7E, 0x15, 0x5E, + 0xE0, 0x4E, 0x80, 0x4B, 0xE0, 0xD2, 0x5A, 0xD4, + 0x1F, 0x5F, 0x6E, 0x65, 0x9C, 0x07, 0xBD, + + 0x08, 0x49, 0x9F, 0x83, 0x46, 0x0F, 0x0E, 0x04, + 0x94, 0x6C, 0x3F, 0x75, 0x4D, 0x98, 0xE5, 0x5D, + 0x12, 0xCB, 0xF6, 0x53, 0x0D, 0xFD, 0x30, 0x75, + 0x92, 0x02, 0xA9, 0x69, 0xD3, 0x71, 0xBC, 0x28, + 0xBC, 0x18, 0x88, 0x48, 0x27, 0x0B, 0x3B, 0x5C, + 0x2C, 0xFF, 0x7C, 0xFA, 0xB1, 0x02, 0x00, 0x79, + 0x6D, 0x8A, 0x39, 0x3F, 0xF2, 0x11, 0xA8, 0xA3, + 0x95, 0x68, 0xCA, 0x97, 0x1E, 0xD9, 0x80, 0xD8, + 0x9D, 0x4C, 0x62, 0x3E, 0xA5, 0xD0, 0x61, 0xE3, + 0x0D, 0x3D, 0xBA, 0xE7, 0x0E, 0x7F, 0x23, 0xBF, + 0x3D, 0x04, 0xB4, 0x1F, 0x20, 0x49, 0x5A, 0x40, + 0x50, 0x59, 0x2C, 0x09, 0x05, 0x5B, 0x8D, 0x07, + 0xA9, 0x79, 0x75, 0x13, 0xFF, 0xB5, 0x33, 0x58, + 0x41, 0x5D, 0x1D, 0xF1, 0x39, 0x54, 0x3A, 0x41, + 0x09, 0xDB, 0x5F, 0xC7, 0x5F, 0x7A, 0xE6, 0x27, + 0xA4, 0xFF, 0x20, 0xE8, 0x5F, 0x25, 0x89, 0xCB, + 0x77, 0x8D, 0xD7, 0x79, 0x16, 0x50, 0x68, 0xE0, + 0x24, 0xEC, 0x87, 0x60, 0xC2, 0x75, 0x87, 0xB8, + 0xAD, 0x66, 0x64, 0xF1, 0x6B, 0x01, 0x7E, 0xB0, + 0xE3, 0x79, 0x7E, 0x84, 0x29, 0x51, 0x47, 0x24, + 0xB9, 0x5D, 0xC6, 0x13, 0xEC, 0x0D, 0x5E, 0x8B, + 0x3E, 0x68, 0x97, 0x74, 0xB5, 0x1C, 0xE6, 0x9E, + 0x74, 0xD1, 0x9A, 0xE6, 0x1A, 0x6C, 0xFD, 0xBB, + 0x27, 0xC1, 0x73, 0xB1, 0x4E, 0xAC, 0x97, 0x1B, + 0x8B, 0xB2, 0x0A, 0x6A, 0x67, 0xA0, 0xA9, 0xDD, + 0x88, 0xF0, 0x55, 0x58, 0x10, 0x79, 0x9C, 0xC5, + + 0xAF, 0x48, 0x98, 0xFF, 0xF1, 0xC9, 0x67, 0xB3, + 0x74, 0xA9, 0xAC, 0xF5, 0x17, 0x7D, 0x95, 0x53, + 0x6A, 0xDD, 0xD6, 0x44, 0x3B, 0x09, 0x32, 0x78, + 0x2E, 0xEC, 0x19, 0x33, 0xD8, 0x4C, 0xFD, 0xE6, + 0xCE, 0x4A, 0x08, 0x78, 0xB5, 0xE8, 0x90, 0x1B, + 0x32, 0x04, 0x51, 0xC1, 0x4A, 0x1A, 0x69, 0xA2, + 0x0A, 0x76, 0x86, 0x73, 0x4B, 0x4C, 0xF7, 0x62, + 0xF7, 0xD0, 0x2E, 0x91, 0x8B, 0x7C, 0xFA, 0x8F, + 0xC9, 0xBE, 0x49, 0x9B, 0x1C, 0x58, 0xF8, 0x14, + 0xD1, 0x07, 0x4A, 0x4D, 0xE4, 0xB3, 0x83, 0x0A, + 0xD3, 0xF9, 0xDD, 0xC1, 0x2F, 0x84, 0x15, 0x02, + 0xA8, 0xB7, 0xB8, 0x45, 0x05, 0x99, 0x71, 0xEE, + 0xC6, 0x3B, 0xC4, 0xC3, 0x6F, 0x10, 0x63, 0x17, + 0x11, 0xD0, 0x1F, 0x1C, 0x63, 0xB9, 0x3F, 0x3D, + 0x68, 0x0A, 0x39, 0x25, 0x95, 0xB9, 0x81, 0xA7, + 0x04, 0x64, 0x6B, 0x2E, 0x52, 0xD0, 0x56, 0x04, + 0x99, 0x4F, 0x1B, 0x8E, 0xB0, 0x29, 0xA5, 0x3C, + 0x17, 0x46, 0xEC, 0x36, 0xC2, 0xD0, 0xAD, 0x92, + 0xB7, 0x58, 0x70, 0x33, 0xA9, 0xA3, 0xD8, 0xB7, + 0xF1, 0x04, 0xA7, 0xFA, 0x9D, 0x2C, 0x6B, 0x5A, + 0x52, 0x89, 0xAC, 0xD0, 0x12, 0x44, 0x8F, 0x7E, + 0x97, 0xA1, 0x82, 0x82, 0xB2, 0xEA, 0x47, 0x60, + 0x9B, 0x22, 0x32, 0x74, 0x77, 0x62, 0xE3, 0x46, + 0xF5, 0x55, 0x79, 0xEF, 0x9D, 0xB0, 0x2A, 0xC8, + 0x10, 0x2E, 0x7B, 0x3F, 0x00, 0xE8, 0x04, 0xA0, + 0x7E, 0x7F, 0x34, 0xB2, 0x35, 0x0E, 0x3A, 0x2F, + 0x65, + + 0x0C, 0x94, 0x90, 0x76, 0x67, 0xAB, 0xE0, 0x58, + 0x2E, 0x22, 0xF4, 0x48, 0xE7, 0x3E, 0x44, 0xB6, + 0x6D, 0xD4, 0xBD, 0x46, 0xEB, 0x9E, 0x01, 0xF9, + 0xB3, 0x06, 0x6F, 0xBA, 0xEE, 0x06, 0x1F, 0xB9, + 0x22, 0xE3, 0x49, 0x27, 0x80, 0x86, 0xB5, 0x38, + 0x47, 0x77, 0x14, 0x68, 0x0B, 0xF2, 0x6C, 0x9A, + 0xF1, 0x1F, 0x20, 0xED, 0x86, 0xF9, 0xEE, 0x04, + 0x92, 0xBC, 0xAB, 0xB8, 0x6B, 0x4A, 0x9D, 0x63, + 0xEB, 0x1B, 0x69, 0x18, 0x3D, 0x81, 0x4D, 0x16, + 0x68, 0x63, 0xF1, 0x96, 0x96, 0x0B, 0x51, 0x66, + 0x93, 0xFE, 0x49, 0xEA, 0xF6, 0x55, 0x8A, 0x2A, + 0xD7, 0x2E, 0xD0, 0x2D, 0xBF, 0x85, 0xD5, 0x97, + 0x9D, 0x8D, 0x2D, 0xD3, 0xB3, 0x62, 0x61, 0xB6, + 0x3B, 0x7B, 0xD1, 0x17, 0xB3, 0xB4, 0x94, 0x2D, + 0xEC, 0x76, 0xD1, 0x39, 0x75, 0x39, 0xFA, 0xAA, + 0x5B, 0x47, 0x0D, 0x9F, 0xBC, 0xEC, 0x12, 0x4F, + 0x76, 0x7C, 0xCB, 0xAD, 0x19, 0x80, 0xCF, 0x65, + 0x7F, 0x1E, 0x64, 0x2D, 0xE7, 0xF1, 0x4B, 0x22, + 0x9D, 0xEE, 0x46, 0x48, 0xBA, 0x54, 0x32, 0x5D, + 0x33, 0xE0, 0x81, 0xF6, 0x9C, 0x2F, 0x1C, 0xBC, + 0x17, 0xCA, 0x34, 0x0C, 0x9A, 0xEF, 0x27, 0x8E, + 0x19, 0xD8, 0x8C, 0xC4, 0xED, 0x0C, 0x88, 0xBA, + 0x60, 0x8B, 0xCF, 0x84, 0xB8, 0xF0, 0x25, 0x8C, + 0x9E, 0xEA, 0x00, 0xE0, 0xB6, 0xC1, 0xAA, 0x02, + 0x51, 0xD9, 0xFF, 0xDA, 0x87, 0x9D, 0x62, 0xB1, + 0xD1, 0x52, 0x7D, 0xE8, 0xB1, 0xC2, 0x45, 0x7D, + 0x4D, 0xF8, + + 0x20, 0xC9, 0xAD, 0x20, 0xED, 0x26, 0x96, 0x8F, + 0xF9, 0xEA, 0xD1, 0x3C, 0x54, 0xA2, 0x45, 0xAF, + 0x13, 0x85, 0x90, 0x43, 0xC3, 0xFD, 0x90, 0xBA, + 0x19, 0xAF, 0xB3, 0x6F, 0x3E, 0xD7, 0x01, 0xB3, + 0xCD, 0x1F, 0xAC, 0x35, 0x48, 0x29, 0x7E, 0xE3, + 0x7B, 0x5F, 0x2A, 0x48, 0x86, 0x27, 0x43, 0xAA, + 0x9C, 0x30, 0x6A, 0x4B, 0x13, 0x77, 0x2D, 0xE5, + 0xB4, 0xB2, 0x66, 0x82, 0xC0, 0x4E, 0xDE, 0x81, + 0x18, 0x9E, 0x4A, 0xC4, 0x0A, 0x20, 0x2E, 0x70, + 0xED, 0x7D, 0x48, 0x28, 0xF8, 0xE4, 0x68, 0x01, + 0xEF, 0x54, 0x43, 0x42, 0x3A, 0xA8, 0x65, 0xC6, + 0xF5, 0x94, 0x19, 0x8A, 0x23, 0x75, 0xBD, 0x08, + 0xAE, 0xA4, 0x78, 0x42, 0xD1, 0xF4, 0xF0, 0xA3, + 0x5A, 0x21, 0x74, 0x1B, 0x90, 0xD8, 0x05, 0x99, + 0xA7, 0x22, 0x7C, 0x79, 0xE9, 0x7D, 0xFF, 0xB2, + 0x1F, 0x04, 0x37, 0xAE, 0xFA, 0xD5, 0x93, 0x97, + 0x32, 0x7E, 0xFD, 0xBB, 0xAC, 0x6E, 0x96, 0xA5, + 0x4F, 0xB4, 0x89, 0x21, 0xB1, 0x3F, 0xB2, 0x3D, + 0xFA, 0x08, 0xCE, 0xED, 0x70, 0x23, 0xAF, 0x75, + 0x22, 0xDE, 0x2E, 0x12, 0x37, 0xE4, 0xB9, 0x92, + 0xA2, 0xB0, 0x4D, 0x56, 0xDE, 0x5E, 0xD3, 0x7F, + 0xBF, 0xBD, 0x5E, 0x6F, 0x4A, 0xBA, 0xC3, 0x27, + 0x22, 0x19, 0xA3, 0x4E, 0x90, 0x2E, 0x72, 0x2E, + 0xEB, 0x6B, 0x48, 0xD5, 0xC6, 0x00, 0x94, 0x56, + 0x29, 0x74, 0x13, 0x0B, 0x85, 0xCF, 0xE5, 0x51, + 0x83, 0xB5, 0x20, 0x49, 0xF0, 0xC6, 0x08, 0xEE, + 0x18, 0x26, 0x19, + + 0x74, 0x41, 0x6D, 0x4E, 0x6C, 0x5E, 0x82, 0xB9, + 0xA6, 0x6E, 0x53, 0x6C, 0xEF, 0x7E, 0x43, 0x36, + 0x6A, 0xAA, 0x94, 0x99, 0xAA, 0x92, 0x44, 0xE6, + 0x41, 0x1D, 0x09, 0xE6, 0x5D, 0xF5, 0x8D, 0xCF, + 0x34, 0xE3, 0xAC, 0x10, 0x0B, 0x5D, 0xC1, 0x59, + 0xB7, 0x60, 0x6C, 0xCB, 0x75, 0x67, 0x85, 0x40, + 0xB8, 0x06, 0x54, 0xE0, 0xB7, 0xB9, 0x4E, 0x4A, + 0x52, 0xD0, 0x39, 0x9F, 0x2C, 0x01, 0xFE, 0xB2, + 0x09, 0x73, 0xA1, 0x6C, 0xD6, 0x0E, 0xB4, 0x8F, + 0x40, 0xA2, 0x15, 0x12, 0x88, 0x3D, 0x65, 0x49, + 0x0C, 0xE1, 0xF5, 0x95, 0xF4, 0xC0, 0xF2, 0x63, + 0x5F, 0xF6, 0x1B, 0xF2, 0x30, 0xC8, 0x5B, 0xE9, + 0xC0, 0x84, 0x0C, 0x6E, 0xDF, 0xC4, 0x19, 0xB9, + 0xCE, 0xA6, 0x49, 0xA5, 0x64, 0xE9, 0x66, 0xC3, + 0x6C, 0xE5, 0x93, 0x76, 0xAC, 0x59, 0x65, 0x0E, + 0xE6, 0xF5, 0x80, 0xCE, 0x1C, 0x72, 0x9A, 0x53, + 0xB0, 0xC7, 0xB6, 0x11, 0x65, 0xDE, 0xEC, 0x89, + 0x18, 0xD8, 0x05, 0x6E, 0x41, 0xD2, 0x31, 0xBD, + 0xDB, 0xE5, 0xEF, 0xF5, 0x76, 0x5C, 0xBD, 0x03, + 0x6D, 0x04, 0x00, 0x16, 0x64, 0x19, 0xFE, 0x4B, + 0x73, 0x9C, 0xDB, 0x31, 0x13, 0x50, 0xD6, 0xCB, + 0xE4, 0xFC, 0x73, 0x89, 0x0F, 0x50, 0x31, 0xBF, + 0x0E, 0xAB, 0xD8, 0xF2, 0x9C, 0xB8, 0x04, 0x88, + 0xAD, 0xE3, 0x9F, 0xDA, 0x0D, 0xE3, 0x5B, 0x34, + 0x94, 0xCB, 0x50, 0x61, 0xA4, 0x01, 0x03, 0xFA, + 0x4D, 0x85, 0xE4, 0x29, 0xFC, 0x11, 0x77, 0x97, + 0x75, 0x6D, 0xF3, 0xC1, + + 0x16, 0x34, 0x6D, 0x2E, 0x36, 0x03, 0xC4, 0x4E, + 0xC5, 0xB4, 0xF8, 0xFA, 0x20, 0x49, 0x81, 0x68, + 0x7E, 0xC8, 0xC2, 0x13, 0x18, 0x84, 0x0C, 0x84, + 0xE8, 0xBF, 0xD9, 0x0D, 0x1B, 0x9F, 0xF0, 0x1F, + 0x8D, 0x41, 0x56, 0x5F, 0xBB, 0x1A, 0x21, 0x5F, + 0x0B, 0x7E, 0x79, 0xFC, 0x7C, 0x72, 0xD5, 0x80, + 0x64, 0x8A, 0xFD, 0xC5, 0xF9, 0xDC, 0x61, 0x27, + 0x75, 0x65, 0x0A, 0x2C, 0x2A, 0x4C, 0xE9, 0x7A, + 0x3A, 0xFA, 0x1E, 0xE6, 0x2A, 0x31, 0xFD, 0xD1, + 0xA0, 0xD8, 0xBF, 0xAB, 0x40, 0x61, 0x87, 0x9F, + 0xA8, 0x65, 0x18, 0x7C, 0x87, 0xEE, 0xA2, 0x93, + 0xC2, 0xE4, 0xED, 0xEF, 0x5C, 0x3D, 0x09, 0xC8, + 0xD7, 0x75, 0x76, 0xF2, 0x1A, 0x9E, 0x19, 0xB8, + 0x44, 0xE8, 0xBE, 0x4F, 0x71, 0xD2, 0xEF, 0x0A, + 0x83, 0x1C, 0xFC, 0xA5, 0x6F, 0x43, 0x0A, 0x1D, + 0xDA, 0xD7, 0x4D, 0x14, 0xE3, 0x5C, 0x32, 0x74, + 0x45, 0x19, 0xC4, 0xF4, 0x3D, 0x5A, 0x6E, 0xEC, + 0x5E, 0x54, 0xF1, 0xB3, 0xF1, 0x4B, 0x05, 0x52, + 0x92, 0x41, 0x49, 0x27, 0x18, 0x40, 0x38, 0x4E, + 0x0A, 0x7D, 0xD1, 0x31, 0x0A, 0xC8, 0x82, 0x60, + 0x5A, 0xBE, 0x4A, 0x5A, 0xAE, 0xBE, 0x86, 0x7D, + 0x2B, 0x27, 0x07, 0x2C, 0xFA, 0x65, 0xB0, 0x73, + 0x50, 0x68, 0x58, 0x36, 0x50, 0x74, 0x61, 0x57, + 0xAB, 0xF4, 0xE8, 0xCD, 0xEE, 0xBB, 0x29, 0x68, + 0x0E, 0x6C, 0x38, 0x0E, 0x0C, 0xDC, 0x79, 0x12, + 0xC7, 0xF4, 0x25, 0x74, 0x66, 0xD6, 0xC1, 0xF6, + 0xF0, 0xF6, 0x1D, 0x27, 0xA1, + + 0xFA, 0x0C, 0xB5, 0xEE, 0x97, 0x04, 0x06, 0xF8, + 0x04, 0xE8, 0xBF, 0x1C, 0x3D, 0x19, 0x5A, 0x1C, + 0x04, 0xBC, 0x6F, 0x76, 0x50, 0x3D, 0x0C, 0xE7, + 0xCE, 0xE5, 0xDE, 0x6F, 0xA1, 0xE6, 0xA3, 0xE4, + 0x3C, 0xC6, 0x17, 0xBF, 0xDC, 0xDF, 0x56, 0xFC, + 0x63, 0xE9, 0x9F, 0x57, 0x0C, 0xF0, 0xA8, 0x19, + 0x1B, 0x8A, 0x33, 0xA3, 0xBF, 0xA8, 0xCD, 0xC4, + 0x24, 0x71, 0xA2, 0x4D, 0x2D, 0xF4, 0x3E, 0xB7, + 0xF9, 0xAD, 0x3B, 0xA9, 0xDF, 0xCF, 0x81, 0xBD, + 0x9A, 0x5A, 0x45, 0xC0, 0x94, 0xA2, 0xAF, 0x9A, + 0x86, 0xF6, 0xBF, 0x3B, 0x99, 0xDB, 0x1E, 0x41, + 0xFD, 0xA5, 0x57, 0xB3, 0x2E, 0x7B, 0x73, 0x4F, + 0x6A, 0xBF, 0xAD, 0x5F, 0x87, 0xFC, 0xA7, 0xEC, + 0xC9, 0xD6, 0x70, 0xDA, 0xED, 0x75, 0x84, 0x50, + 0x61, 0x7C, 0x73, 0x18, 0x8D, 0x7B, 0xF2, 0x47, + 0x85, 0x75, 0x0A, 0x19, 0xBF, 0xFE, 0x3B, 0x81, + 0x81, 0x15, 0x57, 0xD8, 0xE7, 0x13, 0xD6, 0xF6, + 0x0D, 0x49, 0xB9, 0x71, 0x23, 0x51, 0x3F, 0x6A, + 0x50, 0x70, 0xB6, 0x42, 0x18, 0xE9, 0xD9, 0xF5, + 0xEF, 0x60, 0x15, 0xE3, 0x73, 0xCD, 0x49, 0x09, + 0x4A, 0x87, 0x05, 0x5D, 0x45, 0xE1, 0x40, 0xAC, + 0x6E, 0xA0, 0xD0, 0x1C, 0xD4, 0xFE, 0x76, 0xE4, + 0xD8, 0x4E, 0x3E, 0x93, 0xC9, 0xC8, 0xC7, 0x4A, + 0x49, 0x8E, 0x79, 0x46, 0x5D, 0xB0, 0xEB, 0xDC, + 0x46, 0x88, 0x25, 0x5B, 0xE4, 0xE2, 0x0E, 0x0C, + 0xC9, 0xD3, 0xA2, 0x79, 0x1A, 0xF2, 0x94, 0xF2, + 0xC2, 0xE2, 0x98, 0x6E, 0x99, 0x87, + + 0xDE, 0xEE, 0x45, 0x68, 0x9D, 0xC8, 0x03, 0xC0, + 0x02, 0x41, 0x3D, 0x9F, 0x33, 0x70, 0x73, 0x62, + 0x96, 0x25, 0x02, 0xF4, 0x74, 0x5D, 0xE2, 0xF1, + 0x67, 0xF2, 0xFD, 0xE1, 0x65, 0x47, 0x33, 0x6D, + 0xF4, 0x86, 0x11, 0x7C, 0xD0, 0x48, 0x02, 0x7C, + 0xA7, 0x26, 0x85, 0x27, 0xBE, 0x13, 0x96, 0x85, + 0x40, 0x1F, 0x6A, 0xB0, 0x0D, 0x8E, 0xD2, 0x02, + 0xD7, 0x03, 0xFD, 0x45, 0xC8, 0x08, 0xED, 0x3E, + 0x32, 0x04, 0x30, 0x48, 0x63, 0xA3, 0x65, 0x8C, + 0x11, 0x9D, 0x7B, 0x65, 0xE9, 0x02, 0x37, 0xF3, + 0x9D, 0x0B, 0x5E, 0xAD, 0x9D, 0xFF, 0x7D, 0x56, + 0x3D, 0x50, 0x74, 0x37, 0xAD, 0x39, 0x06, 0x85, + 0x10, 0xC5, 0x69, 0x37, 0x57, 0x3C, 0x4F, 0xE8, + 0x4A, 0xAC, 0x1D, 0x06, 0xDA, 0x62, 0xB3, 0x3E, + 0x0B, 0xB0, 0xE4, 0x1F, 0x3F, 0x2F, 0x29, 0x88, + 0x14, 0xC1, 0xAE, 0xD1, 0x62, 0x89, 0xB7, 0xC5, + 0x51, 0x72, 0xFE, 0xE3, 0xDF, 0x56, 0x9E, 0xDB, + 0x37, 0xE4, 0x64, 0xAC, 0x99, 0x08, 0xF7, 0x87, + 0xFA, 0xCE, 0x5B, 0xF3, 0xCD, 0x21, 0xF6, 0x8A, + 0xED, 0xA3, 0x7B, 0xEC, 0x3F, 0x30, 0x14, 0x3D, + 0x00, 0xD4, 0x40, 0xBE, 0x35, 0x36, 0x89, 0xCF, + 0x29, 0xDA, 0x13, 0xE8, 0x69, 0x0D, 0xDE, 0xE8, + 0x05, 0x22, 0x0D, 0x02, 0x18, 0xDB, 0x12, 0xAC, + 0x01, 0x12, 0xD0, 0xEF, 0xD2, 0x82, 0x21, 0xC9, + 0xF7, 0x52, 0x94, 0x98, 0x0E, 0xE7, 0xCB, 0x9C, + 0x3F, 0xD1, 0x0D, 0xA6, 0x0C, 0x53, 0x60, 0x8B, + 0x13, 0x3F, 0x77, 0xD5, 0xDC, 0xC5, 0xE2, + + 0x7D, 0x3B, 0xAE, 0x67, 0x64, 0x19, 0xC8, 0x66, + 0xF1, 0x0F, 0x31, 0xAD, 0x43, 0x35, 0xD4, 0x44, + 0x2C, 0xA5, 0x5D, 0x76, 0x78, 0x70, 0x4C, 0x2F, + 0x71, 0x11, 0xB9, 0xF3, 0x69, 0x16, 0xFA, 0x09, + 0x42, 0xE7, 0x6C, 0x09, 0x2E, 0xDA, 0xEB, 0x9A, + 0x53, 0x82, 0x1D, 0x31, 0x3E, 0x3E, 0xD8, 0x48, + 0xEA, 0x86, 0xE8, 0x76, 0x8E, 0xC6, 0xA7, 0xEA, + 0xBB, 0x58, 0x7D, 0xB7, 0x39, 0x76, 0xEC, 0xE6, + 0x35, 0x19, 0xAA, 0xFA, 0x6E, 0x98, 0x2C, 0x38, + 0xC2, 0xA2, 0x0E, 0x36, 0xA9, 0x4F, 0x88, 0xDA, + 0x6E, 0x3D, 0x1C, 0xFB, 0x25, 0xF5, 0x96, 0x1E, + 0x18, 0xBE, 0xEB, 0x0A, 0x48, 0xB8, 0x5A, 0x42, + 0xD3, 0x77, 0xEB, 0xD1, 0x06, 0x93, 0x4D, 0x56, + 0xB0, 0x60, 0xAA, 0x72, 0x8B, 0xC4, 0x29, 0x2E, + 0xE5, 0x36, 0x53, 0x46, 0xA3, 0x4F, 0x27, 0xED, + 0xED, 0x0A, 0x19, 0xCC, 0xF1, 0x1C, 0xBB, 0x0C, + 0x43, 0x2C, 0x6E, 0x40, 0xCF, 0x0F, 0x58, 0x23, + 0xC0, 0xE1, 0x5F, 0x2A, 0x63, 0x06, 0xD0, 0x91, + 0x97, 0x9C, 0x16, 0x0E, 0x0A, 0xE6, 0xAF, 0x1D, + 0x7C, 0x07, 0xD6, 0xC4, 0x64, 0x01, 0xB9, 0xE4, + 0x6D, 0x75, 0x92, 0x4F, 0x35, 0x1B, 0x4C, 0x37, + 0xCE, 0x05, 0x88, 0x06, 0x08, 0x1C, 0xD6, 0x75, + 0xE2, 0x07, 0x2E, 0x54, 0x58, 0xA1, 0x00, 0x39, + 0xA4, 0x80, 0xBF, 0xB2, 0x1F, 0xC4, 0x69, 0xC1, + 0x3D, 0x4B, 0xFE, 0x7F, 0x20, 0x1F, 0x49, 0x8B, + 0x08, 0xC6, 0x33, 0x86, 0xEB, 0x7B, 0x3E, 0x16, + 0xDE, 0xE3, 0x34, 0xD8, 0x66, 0x04, 0x55, 0xBA, + + 0xBE, 0x42, 0xC4, 0xEA, 0xAB, 0x31, 0xF5, 0x2E, + 0xF3, 0xF6, 0xBC, 0x86, 0xB6, 0xA4, 0x48, 0x74, + 0x15, 0xE9, 0xA7, 0x65, 0xE6, 0xDA, 0xF0, 0x94, + 0x5F, 0x1F, 0xC4, 0xCA, 0xD3, 0xFE, 0x66, 0x78, + 0x03, 0xE3, 0xBE, 0x9D, 0xE8, 0xAC, 0x45, 0x29, + 0xFA, 0x59, 0xE0, 0xBA, 0xD0, 0xAC, 0x62, 0x9A, + 0xA6, 0x6F, 0x6C, 0x5B, 0x0E, 0x86, 0xC8, 0x3E, + 0xD6, 0xE2, 0x84, 0x31, 0x79, 0xD1, 0xAF, 0xCB, + 0x78, 0x1D, 0xF5, 0x1D, 0x76, 0x72, 0xCC, 0xAA, + 0x7A, 0x22, 0x35, 0xBD, 0x3A, 0x26, 0x7B, 0x2B, + 0x08, 0xD8, 0x27, 0x26, 0x07, 0xA2, 0xAA, 0x6E, + 0x30, 0x8C, 0x38, 0x70, 0x40, 0x3C, 0x61, 0x9F, + 0x5C, 0x57, 0x72, 0x9B, 0x5B, 0x4C, 0x20, 0xB0, + 0x84, 0x1A, 0x85, 0x0C, 0xF3, 0x3E, 0x5B, 0x67, + 0x3D, 0xF2, 0xB4, 0x4F, 0xB1, 0xE6, 0x3D, 0xDC, + 0xF1, 0x3C, 0x49, 0x9A, 0x38, 0x95, 0x47, 0xF2, + 0xCA, 0x43, 0xB7, 0x0A, 0x80, 0x06, 0x9F, 0x06, + 0x4D, 0x02, 0x98, 0x44, 0xB0, 0x8B, 0x73, 0xC6, + 0x26, 0x5B, 0x14, 0xA1, 0xF6, 0x64, 0x37, 0xDE, + 0xF2, 0x22, 0x1A, 0x59, 0x85, 0xAE, 0xFD, 0x5A, + 0xE5, 0x71, 0xC8, 0xCF, 0x6C, 0xFA, 0x64, 0x27, + 0xFF, 0x55, 0x45, 0x88, 0xA4, 0x5A, 0x50, 0x82, + 0x47, 0x61, 0x4C, 0xE5, 0x43, 0x9A, 0xA9, 0x5A, + 0xCC, 0xA3, 0xCA, 0x1B, 0xA0, 0x28, 0x65, 0x6E, + 0xA4, 0xCE, 0xE2, 0x17, 0x41, 0x07, 0x50, 0x31, + 0x76, 0xCB, 0x61, 0x14, 0xE3, 0x50, 0x68, 0x2B, + 0xF2, 0x96, 0x6B, 0xCF, 0xFE, 0xF7, 0x91, 0xD6, + 0x6F, + + 0x55, 0x68, 0x17, 0x44, 0xA4, 0xAE, 0x0A, 0xBE, + 0xB6, 0xF4, 0x72, 0xAA, 0x55, 0x65, 0x33, 0x22, + 0xC5, 0x86, 0x02, 0xC5, 0xB6, 0x13, 0x9B, 0x68, + 0x1E, 0xE8, 0xFD, 0x2D, 0xEB, 0x9E, 0xF2, 0x72, + 0xA3, 0xA7, 0x38, 0xC1, 0xDB, 0xDB, 0x72, 0x03, + 0xE9, 0x7E, 0x5B, 0x55, 0x12, 0x0A, 0x8B, 0x87, + 0x89, 0xA5, 0xB7, 0x93, 0xFA, 0x8E, 0x80, 0xAA, + 0xB5, 0xDC, 0xA4, 0x78, 0xD7, 0x76, 0x21, 0x7B, + 0xF0, 0x1B, 0x41, 0x89, 0x9F, 0x9C, 0x41, 0xE6, + 0xDE, 0x3A, 0xF6, 0x16, 0x66, 0xDF, 0xF1, 0xC9, + 0x59, 0x75, 0x18, 0xBE, 0xC5, 0xE3, 0x55, 0xA7, + 0x39, 0xF5, 0x04, 0xBA, 0x3A, 0x11, 0x53, 0x36, + 0x69, 0x58, 0x49, 0xC3, 0xB1, 0x4E, 0x65, 0x88, + 0xDA, 0x46, 0xB8, 0x79, 0x58, 0x32, 0x18, 0xBA, + 0x3E, 0x3C, 0x5C, 0x02, 0x34, 0xFD, 0xD1, 0x2F, + 0x32, 0xCA, 0x4D, 0x1A, 0x68, 0x3B, 0x73, 0xC6, + 0xD0, 0xA8, 0x71, 0x24, 0xA8, 0xD5, 0x82, 0x83, + 0x26, 0x99, 0xCA, 0x8E, 0xC9, 0x55, 0xF2, 0x92, + 0xD1, 0x95, 0x4E, 0xA7, 0x5F, 0x16, 0x56, 0xD7, + 0xEA, 0xCF, 0xD3, 0xC7, 0xD7, 0xEA, 0x79, 0xF4, + 0x12, 0xC4, 0x7E, 0x5B, 0xB3, 0x1D, 0xAE, 0x0A, + 0xFD, 0xE1, 0x9F, 0x27, 0xCC, 0x95, 0xC6, 0x03, + 0xFD, 0x2F, 0xD3, 0xC5, 0x4E, 0xEF, 0x42, 0x10, + 0xF4, 0x6B, 0x24, 0x78, 0x53, 0xC5, 0xE1, 0xB6, + 0xB7, 0x80, 0xBD, 0xEB, 0x65, 0x5B, 0xA8, 0xE5, + 0x8E, 0xE5, 0x7F, 0x1E, 0x5B, 0x93, 0xA4, 0xDD, + 0xD5, 0xAB, 0xF2, 0x4A, 0x75, 0xE0, 0xAC, 0xC1, + 0x0C, 0x2D, + + 0x3A, 0x63, 0xF3, 0x06, 0x48, 0xB8, 0x7A, 0x18, + 0x11, 0x6F, 0x96, 0x89, 0x2C, 0x01, 0x1F, 0x47, + 0x73, 0xF4, 0x9E, 0x28, 0x77, 0xE8, 0xCD, 0x57, + 0x36, 0x53, 0xB4, 0x33, 0x62, 0x83, 0x51, 0x7A, + 0x4A, 0x4D, 0xC3, 0xF7, 0x58, 0x19, 0x73, 0xB5, + 0xFF, 0x36, 0x3E, 0x63, 0xB0, 0xD1, 0x12, 0x07, + 0xB9, 0x17, 0xF1, 0xC6, 0x78, 0x79, 0xA1, 0x2D, + 0x4F, 0x00, 0xAF, 0xCD, 0xA3, 0x73, 0x09, 0xDD, + 0x9C, 0x3D, 0x8E, 0x6B, 0x2B, 0xA5, 0xF5, 0x91, + 0x1C, 0x2B, 0xFE, 0xB8, 0xE5, 0x6E, 0xA5, 0x9D, + 0x5D, 0x5C, 0x6A, 0xF2, 0xA1, 0x7E, 0x82, 0xB0, + 0x47, 0xB5, 0x53, 0xE4, 0x49, 0x00, 0x5B, 0x60, + 0x5C, 0x94, 0x6E, 0xD1, 0xDE, 0x27, 0x7C, 0xC2, + 0xA2, 0xFF, 0xB4, 0xAF, 0x5F, 0x52, 0x0F, 0x5B, + 0x3B, 0xA5, 0x48, 0x93, 0x90, 0x97, 0x30, 0x10, + 0x30, 0x96, 0x84, 0x68, 0x8D, 0xB4, 0x47, 0x9E, + 0x77, 0x23, 0x2A, 0x96, 0xA9, 0x29, 0x2E, 0xBC, + 0x40, 0x59, 0x92, 0xE4, 0x55, 0xD7, 0x30, 0x2E, + 0x62, 0x15, 0xA6, 0xEA, 0x77, 0x5D, 0x2C, 0x1C, + 0x10, 0xF5, 0x8A, 0x43, 0x2B, 0x72, 0xC3, 0xD0, + 0x9E, 0xB9, 0x80, 0x4C, 0x8D, 0xCD, 0x5B, 0xB5, + 0xAD, 0xF6, 0x44, 0xDD, 0x9D, 0x37, 0x8E, 0x28, + 0xF1, 0xB5, 0xCE, 0xF2, 0xDD, 0x35, 0x6F, 0x63, + 0xB3, 0x32, 0xAC, 0x13, 0x4B, 0xC9, 0x67, 0x58, + 0x63, 0x2F, 0xB4, 0x23, 0x0C, 0xA3, 0x4F, 0xF8, + 0xB6, 0x52, 0xE7, 0xD1, 0xA7, 0x0D, 0x0D, 0x5B, + 0x66, 0x1D, 0x77, 0x82, 0xCA, 0xE5, 0x11, 0x62, + 0xF4, 0xA9, 0x95, + + 0xE7, 0x1E, 0xF9, 0x44, 0xCD, 0x9F, 0xB5, 0xC5, + 0x80, 0xDC, 0x78, 0xA9, 0x4E, 0xAB, 0xD3, 0x1D, + 0xA9, 0xC6, 0xCC, 0x67, 0x49, 0xC2, 0x9C, 0x99, + 0x60, 0x86, 0xBA, 0x95, 0xDD, 0x10, 0x02, 0x37, + 0xE8, 0x2B, 0xF9, 0x2B, 0xB3, 0x97, 0x44, 0xDA, + 0xEF, 0x65, 0xB6, 0xB2, 0x0D, 0xA4, 0xAB, 0xFE, + 0xD7, 0x19, 0x07, 0xBD, 0x5B, 0xCC, 0x56, 0x78, + 0x90, 0xBA, 0x9C, 0x85, 0x7B, 0xD7, 0xDE, 0xD2, + 0x07, 0x29, 0xB2, 0x82, 0xF1, 0x37, 0x7A, 0x87, + 0xB9, 0x04, 0xF6, 0xE2, 0xC9, 0xF7, 0xDD, 0x1D, + 0xA4, 0x25, 0xB0, 0x18, 0x49, 0x72, 0x6F, 0x02, + 0xB1, 0x49, 0xB9, 0x15, 0xA6, 0x00, 0x87, 0x23, + 0x88, 0xED, 0xB7, 0xD5, 0xA2, 0x12, 0xC2, 0xA6, + 0xF3, 0x8A, 0x8C, 0x50, 0xE2, 0xC9, 0xBC, 0x62, + 0x50, 0xF8, 0x2C, 0xB1, 0x11, 0x00, 0x36, 0x79, + 0x13, 0x75, 0xFB, 0x87, 0xDA, 0x49, 0x59, 0x42, + 0x57, 0xDD, 0x7C, 0xE4, 0xFA, 0xD1, 0x5B, 0xF9, + 0xB5, 0xB8, 0x56, 0xB0, 0x98, 0xF9, 0x63, 0xB1, + 0x1B, 0xEC, 0xF7, 0x05, 0x4C, 0xBC, 0x32, 0x1C, + 0x59, 0xC8, 0x75, 0x7E, 0xBC, 0xAD, 0xCF, 0x32, + 0x1A, 0x3D, 0xAE, 0x1F, 0x27, 0x01, 0x85, 0x60, + 0xCB, 0xDE, 0xAB, 0x39, 0xFD, 0x1E, 0x45, 0x82, + 0x36, 0xC1, 0xC3, 0x69, 0xA7, 0xE4, 0x5B, 0x16, + 0x36, 0x5A, 0xD5, 0x20, 0x5E, 0x4D, 0x1C, 0xBA, + 0x6E, 0x28, 0x30, 0x66, 0xDA, 0x6C, 0x66, 0x42, + 0xD4, 0x9A, 0x98, 0x31, 0xF8, 0x11, 0x8A, 0xB5, + 0xF9, 0x9E, 0x96, 0xE9, 0x42, 0x0D, 0xDF, 0x28, + 0x2D, 0x03, 0xC6, 0xFF, + + 0x05, 0x1F, 0xCE, 0x41, 0xE4, 0x8C, 0x74, 0x81, + 0x36, 0x78, 0x17, 0x9E, 0x28, 0xCC, 0xA0, 0xA8, + 0x03, 0x13, 0xEB, 0x8D, 0xD9, 0xF5, 0x75, 0x8C, + 0x58, 0x0B, 0xA5, 0x3F, 0xB5, 0x5D, 0x48, 0x94, + 0xA9, 0x7D, 0x61, 0x34, 0x5F, 0x07, 0xA2, 0x84, + 0x6A, 0xF9, 0x6C, 0xCB, 0x4C, 0x5D, 0x2D, 0xB2, + 0x05, 0x0B, 0x03, 0x61, 0x4A, 0x68, 0xB3, 0xA2, + 0x08, 0x33, 0x68, 0xB0, 0xD9, 0x95, 0x63, 0x98, + 0xBA, 0xF9, 0x70, 0x81, 0xDC, 0x34, 0xD2, 0xA3, + 0x5C, 0x5E, 0x85, 0x22, 0x8D, 0xEB, 0xEE, 0x81, + 0xEC, 0xEE, 0x43, 0xAC, 0x70, 0x93, 0x2C, 0xBC, + 0x66, 0x33, 0x37, 0xD9, 0xE1, 0x71, 0x2F, 0xD0, + 0x5A, 0xB8, 0x32, 0x8C, 0xE7, 0x98, 0x13, 0x8C, + 0x61, 0x94, 0x6C, 0xAA, 0x38, 0xCF, 0xAD, 0xF6, + 0xBE, 0x40, 0xA9, 0x6F, 0x02, 0xFA, 0x16, 0x5C, + 0x70, 0x2E, 0x55, 0xCC, 0x5F, 0x5A, 0xF7, 0x07, + 0x95, 0xB0, 0x18, 0xB7, 0xF0, 0x4A, 0xFA, 0xCD, + 0xB4, 0xA8, 0x92, 0x3F, 0x71, 0xED, 0x8F, 0x54, + 0xC0, 0x35, 0x1F, 0x2E, 0xC7, 0xF2, 0xBE, 0x4B, + 0x96, 0x4F, 0x05, 0xB7, 0x3E, 0x9E, 0x40, 0xA9, + 0x2A, 0xC7, 0x1C, 0x2D, 0x91, 0x5A, 0xBB, 0x31, + 0xB1, 0x4F, 0xE1, 0x3F, 0x34, 0x27, 0x4D, 0xAD, + 0x19, 0x34, 0xC5, 0x4F, 0x2C, 0x32, 0x24, 0x3E, + 0x9E, 0x50, 0x1F, 0xC2, 0x57, 0x63, 0xFF, 0x45, + 0xBE, 0x73, 0x72, 0xED, 0xE6, 0x01, 0x35, 0x33, + 0xCD, 0x14, 0xC2, 0xF4, 0xFB, 0xEF, 0x47, 0x55, + 0x3F, 0x4B, 0xD0, 0x05, 0xF0, 0x38, 0x2A, 0x37, + 0xAF, 0x02, 0xD9, 0x25, 0xDD, + + 0x20, 0xCE, 0x9F, 0xBC, 0x8E, 0x72, 0x30, 0xBB, + 0xE1, 0xC8, 0x3C, 0x08, 0x89, 0x34, 0x73, 0x4C, + 0x8D, 0x0C, 0x00, 0x1E, 0xA4, 0xD4, 0xDA, 0x55, + 0x18, 0x8C, 0xF0, 0xA4, 0x2F, 0xE9, 0x06, 0x30, + 0xDE, 0x73, 0xDA, 0x14, 0xA8, 0x82, 0xC3, 0x94, + 0xAE, 0x12, 0xC5, 0x55, 0x5B, 0x15, 0x42, 0x75, + 0x7A, 0xC3, 0x79, 0x05, 0x09, 0x63, 0x9A, 0xC4, + 0xD4, 0xCA, 0x1D, 0x08, 0x75, 0x68, 0x78, 0x07, + 0x7D, 0xD2, 0x37, 0xEB, 0x8B, 0x25, 0xAC, 0xF4, + 0x90, 0x5F, 0x4A, 0x2D, 0xE4, 0x4F, 0x08, 0x3B, + 0x3D, 0xF3, 0x9F, 0xA4, 0x8E, 0xEE, 0xE6, 0x47, + 0x4F, 0x3A, 0x6D, 0xBC, 0xB7, 0xA9, 0x4C, 0x1D, + 0x82, 0x4E, 0x7A, 0x29, 0xC9, 0x01, 0xFF, 0xC6, + 0x6F, 0x63, 0x4C, 0xE3, 0x0A, 0x10, 0x3F, 0x07, + 0xB4, 0x3F, 0x71, 0x55, 0x8D, 0xE3, 0xEF, 0xFC, + 0x76, 0xF6, 0x0A, 0xC3, 0xE9, 0xA9, 0x28, 0x03, + 0xB0, 0xDF, 0x15, 0x0E, 0xD0, 0x68, 0x17, 0x7D, + 0xC7, 0xC2, 0x51, 0x1A, 0x0D, 0x24, 0x21, 0x21, + 0x45, 0xFF, 0xEA, 0x17, 0xFB, 0xBF, 0x59, 0x63, + 0x03, 0x4F, 0x62, 0xEF, 0x1C, 0xDA, 0xF5, 0x00, + 0x8F, 0x9D, 0x2B, 0x81, 0x62, 0x9F, 0xED, 0xA6, + 0x6D, 0xA0, 0x57, 0x16, 0x08, 0x9E, 0x07, 0xB9, + 0xF3, 0x8B, 0x78, 0xA8, 0x6E, 0x15, 0x53, 0x26, + 0xE5, 0x7A, 0xE4, 0xBA, 0x09, 0xC6, 0x25, 0x41, + 0x1A, 0x24, 0x9B, 0xE0, 0x16, 0x62, 0xCF, 0x67, + 0xB6, 0xA1, 0xEF, 0x8B, 0x4D, 0xCC, 0xC3, 0xB6, + 0xB6, 0x89, 0x6C, 0x79, 0x02, 0x56, 0x79, 0x87, + 0xF4, 0xA7, 0x4B, 0x1D, 0xBC, 0xC0, + + 0x34, 0xF6, 0x75, 0xEA, 0x0F, 0x48, 0x36, 0xB3, + 0x59, 0x85, 0x62, 0x0F, 0xEF, 0x08, 0xA8, 0xEB, + 0x6F, 0x83, 0x96, 0x3D, 0xDA, 0x81, 0x49, 0xF3, + 0x9D, 0xBD, 0x99, 0x93, 0x3B, 0x86, 0xF3, 0x9F, + 0xEF, 0x0F, 0x16, 0x0F, 0xBD, 0x58, 0x11, 0x93, + 0x1E, 0xF2, 0xAB, 0x31, 0xB0, 0x2E, 0x8B, 0x3D, + 0x57, 0x97, 0x6F, 0x54, 0xA2, 0x75, 0x04, 0xBE, + 0x9E, 0xF2, 0x57, 0x23, 0xC7, 0x3C, 0x4A, 0x4B, + 0xF0, 0xBC, 0x61, 0x53, 0x88, 0xC5, 0x91, 0x34, + 0x58, 0xEE, 0x16, 0xA3, 0xB7, 0x68, 0xDE, 0x60, + 0x99, 0x50, 0xF6, 0x3B, 0x14, 0x55, 0xC0, 0xE7, + 0xEE, 0x34, 0xA4, 0x29, 0xED, 0xD5, 0x5E, 0x6A, + 0xD2, 0xAD, 0x09, 0xCD, 0x21, 0x63, 0x7D, 0xAD, + 0xCC, 0xB1, 0x15, 0xD4, 0x4A, 0x12, 0x7A, 0xD2, + 0xB5, 0xE3, 0x79, 0x7A, 0x88, 0xFE, 0x57, 0x77, + 0xB9, 0xE6, 0x08, 0xE4, 0xA4, 0x62, 0x7A, 0xED, + 0xBF, 0x4F, 0xC2, 0xD8, 0x66, 0x4A, 0x3D, 0xA8, + 0xEC, 0xC6, 0x1C, 0xE7, 0xAF, 0xC4, 0x2B, 0x3B, + 0xB5, 0x5D, 0xF0, 0x33, 0xBA, 0xF2, 0x61, 0x99, + 0x92, 0xCF, 0x34, 0x19, 0x99, 0x43, 0xF5, 0x9F, + 0xF6, 0x64, 0x5A, 0x40, 0x87, 0x53, 0x2D, 0x16, + 0x75, 0x68, 0x31, 0xAA, 0x61, 0xCF, 0x1F, 0xC3, + 0x32, 0x5B, 0x78, 0xFB, 0x8D, 0x67, 0x1F, 0x16, + 0x80, 0x3A, 0x7E, 0x05, 0x45, 0x7A, 0x5E, 0x43, + 0x0A, 0x2E, 0xE1, 0x22, 0xA8, 0x96, 0x79, 0xD5, + 0xC4, 0x2E, 0xE0, 0x1F, 0x43, 0x1B, 0x8D, 0xDC, + 0xBA, 0xCF, 0x7D, 0xF2, 0xD1, 0x70, 0xF6, 0x65, + 0x44, 0xCE, 0x2B, 0x08, 0x0D, 0x43, 0xC4, + + 0xF1, 0x1E, 0x0E, 0xFC, 0x7A, 0x10, 0x39, 0x3A, + 0x1E, 0xAD, 0x9E, 0x81, 0xC9, 0x04, 0xDB, 0x02, + 0x15, 0xC4, 0x9F, 0x6F, 0xD8, 0xF4, 0xCE, 0x77, + 0x00, 0x46, 0xB9, 0x0C, 0xD1, 0x4B, 0x1D, 0x6C, + 0x44, 0xFA, 0x19, 0x09, 0xB6, 0xEB, 0x34, 0x4A, + 0xC2, 0xDF, 0xF3, 0xF2, 0xE7, 0x3A, 0xE3, 0x6C, + 0xD4, 0xAF, 0x22, 0xFF, 0x40, 0xBC, 0x5C, 0x4A, + 0xBA, 0x7E, 0x54, 0xB1, 0xDB, 0xDF, 0x02, 0x2D, + 0xC2, 0xAD, 0x7B, 0x3E, 0x4C, 0x8E, 0x42, 0x97, + 0xDA, 0x00, 0xAA, 0x9F, 0x6A, 0x33, 0xB1, 0xFF, + 0xBB, 0x5E, 0x5F, 0x10, 0xE6, 0xA0, 0xF3, 0x25, + 0x8B, 0xAC, 0x36, 0xCF, 0xB6, 0x4A, 0x4D, 0x12, + 0x77, 0xDA, 0x17, 0xC5, 0xD5, 0xD2, 0xCB, 0xA1, + 0x95, 0xBB, 0xF1, 0xC9, 0xD8, 0xD3, 0xC1, 0xCC, + 0x67, 0xCE, 0xAB, 0x2B, 0x6A, 0x69, 0x41, 0x7C, + 0x7A, 0x47, 0x25, 0xE8, 0x39, 0xDC, 0x29, 0x31, + 0x36, 0x20, 0xA0, 0x58, 0x2A, 0x1A, 0xF0, 0x22, + 0xB9, 0x04, 0x10, 0xDA, 0x42, 0x2A, 0x6E, 0x1F, + 0x78, 0x01, 0x7C, 0x05, 0xE3, 0x1B, 0xA1, 0xC3, + 0x1A, 0x26, 0xA6, 0xF6, 0xBF, 0x54, 0xE9, 0x45, + 0x7F, 0x87, 0x08, 0xB8, 0xAF, 0xF0, 0xF0, 0xB4, + 0x96, 0xA4, 0xE3, 0xC0, 0x6A, 0x0B, 0xF9, 0x49, + 0x89, 0x1B, 0x9E, 0x69, 0x42, 0xD8, 0x21, 0x57, + 0x20, 0xC3, 0x95, 0xE5, 0xC6, 0x98, 0x06, 0x5E, + 0x69, 0x1F, 0x14, 0x8E, 0x9F, 0xF8, 0x58, 0x7C, + 0xEE, 0x13, 0xC7, 0x96, 0xC1, 0xE7, 0x71, 0x88, + 0x96, 0x54, 0xF9, 0xA7, 0xD6, 0x56, 0x7B, 0x8C, + 0xA5, 0x44, 0x42, 0xD3, 0x6B, 0x2E, 0x2E, 0x03, + + 0x7D, 0x39, 0xA9, 0xFF, 0x6A, 0x3D, 0x14, 0x95, + 0x1C, 0xB6, 0xD8, 0x13, 0x4E, 0x41, 0xF5, 0xD5, + 0x3F, 0x0F, 0xEC, 0x55, 0x1E, 0xAC, 0x95, 0x79, + 0x28, 0x5D, 0xBD, 0xBE, 0xC4, 0x7D, 0x31, 0x1F, + 0x64, 0x11, 0x9D, 0x0B, 0x8F, 0x06, 0xAB, 0x23, + 0x2D, 0x8D, 0xC4, 0x10, 0xE7, 0x20, 0x95, 0x60, + 0x76, 0xFC, 0xFA, 0xE3, 0x64, 0xC3, 0x67, 0x32, + 0xFA, 0x3D, 0x5D, 0x8F, 0xEA, 0xE3, 0x4F, 0x95, + 0x0A, 0x37, 0x4A, 0x30, 0x98, 0x93, 0x76, 0x20, + 0x7F, 0xB7, 0xA9, 0xE0, 0x6C, 0x42, 0xE7, 0xF8, + 0x57, 0xC8, 0xBE, 0xD3, 0x7A, 0x1E, 0xBE, 0xF8, + 0x30, 0x8C, 0x29, 0x95, 0x71, 0x29, 0xFD, 0x79, + 0x0E, 0x1D, 0xDD, 0x4B, 0x41, 0xE9, 0x5F, 0x7E, + 0xF5, 0x4C, 0x7F, 0xA2, 0x10, 0x06, 0x57, 0x86, + 0xAB, 0x10, 0xBF, 0x5A, 0xFE, 0xA2, 0x5F, 0xE8, + 0x70, 0x8F, 0xCC, 0x00, 0xD9, 0x86, 0x86, 0x2C, + 0x31, 0x2E, 0xF9, 0xAD, 0x56, 0x0C, 0xE9, 0xB9, + 0x42, 0x39, 0x3B, 0x0D, 0x47, 0x60, 0x6F, 0xF9, + 0xFB, 0xE8, 0xBE, 0xFC, 0x7D, 0x0B, 0xA3, 0xEC, + 0x09, 0x6E, 0x0E, 0x0B, 0x6D, 0xEC, 0x60, 0x17, + 0xE9, 0x34, 0x65, 0x6F, 0xA4, 0x84, 0x61, 0x13, + 0xB2, 0xA6, 0xD3, 0x56, 0x06, 0xD9, 0xAE, 0x9A, + 0x57, 0x78, 0x93, 0xF2, 0x86, 0xA5, 0x39, 0x27, + 0x20, 0x36, 0x7A, 0xE7, 0xDE, 0x63, 0x02, 0x90, + 0x52, 0x3B, 0x7D, 0x32, 0x24, 0xFA, 0x77, 0x3A, + 0xFF, 0x6D, 0x6D, 0x38, 0xB1, 0xDC, 0x78, 0x06, + 0x5A, 0xCE, 0x72, 0xE9, 0x72, 0x22, 0x72, 0x60, + 0x90, 0x25, 0x72, 0x00, 0x28, 0xA2, 0xC0, 0x4A, + 0x31, + + 0xFE, 0xCE, 0x1F, 0x8E, 0xEF, 0xB9, 0x81, 0xD1, + 0x1D, 0x7F, 0x88, 0x64, 0xF5, 0x96, 0xE5, 0xD0, + 0xCD, 0x3E, 0xBE, 0x2D, 0x39, 0x22, 0x61, 0xBA, + 0xC9, 0x91, 0xA1, 0xF6, 0x6E, 0x5F, 0x7E, 0x2A, + 0x90, 0xD0, 0x26, 0xB7, 0x6D, 0x1B, 0xAE, 0xE2, + 0x54, 0xDE, 0x79, 0xF8, 0x39, 0x1E, 0xA0, 0xFC, + 0x65, 0xE1, 0x45, 0x22, 0x7A, 0x1A, 0x06, 0x0A, + 0xBB, 0x59, 0x41, 0xF5, 0xCF, 0xC0, 0x4C, 0x76, + 0xB7, 0x98, 0xF8, 0x2F, 0x32, 0xE6, 0x5B, 0xC3, + 0x70, 0xF3, 0xF5, 0x18, 0xC5, 0x0B, 0xAF, 0x82, + 0x4A, 0x17, 0xEF, 0xA5, 0x96, 0xE2, 0x20, 0xBA, + 0xE5, 0x23, 0x55, 0xD2, 0x85, 0xA3, 0x1C, 0x1E, + 0x46, 0xDA, 0xCF, 0xD3, 0xAC, 0x56, 0xF6, 0x94, + 0xFE, 0x14, 0xBB, 0x15, 0xD6, 0xA0, 0xF3, 0x5B, + 0x5C, 0x62, 0xA3, 0xEC, 0xF8, 0x23, 0x75, 0x62, + 0x5D, 0xB9, 0x47, 0x46, 0x25, 0xF1, 0x9E, 0x88, + 0xC0, 0xF7, 0x5A, 0xC2, 0xA7, 0x97, 0xEA, 0xB1, + 0x35, 0x70, 0x02, 0x33, 0x29, 0xA9, 0xF9, 0x36, + 0xC8, 0xF0, 0x70, 0xCB, 0xD0, 0xD4, 0x07, 0x26, + 0xD6, 0x9C, 0x62, 0x37, 0xEB, 0xDD, 0xE1, 0x71, + 0x10, 0x49, 0x52, 0x86, 0x71, 0xC1, 0xB7, 0x78, + 0xE4, 0x85, 0xC2, 0x34, 0x3E, 0x83, 0xF2, 0xBE, + 0x31, 0x51, 0x65, 0xF4, 0x42, 0xE4, 0x66, 0x85, + 0xE8, 0xEF, 0xDD, 0xD9, 0xE0, 0x41, 0x3E, 0x25, + 0xF2, 0x9D, 0xCA, 0x48, 0xF3, 0x55, 0x99, 0x83, + 0xD6, 0xF3, 0x96, 0x37, 0xF5, 0x18, 0x90, 0x2E, + 0xA4, 0xA7, 0xE1, 0x08, 0x89, 0xFA, 0x54, 0x22, + 0xE8, 0x1D, 0x8E, 0xFE, 0x94, 0xED, 0x86, 0xF2, + 0x21, 0xE4, + + 0xE1, 0x07, 0xBB, 0xC9, 0x51, 0x1C, 0xA7, 0x07, + 0xE9, 0x61, 0x25, 0xB4, 0x69, 0x8D, 0x72, 0xF1, + 0xF0, 0x12, 0xBB, 0x01, 0xD0, 0xCA, 0x4F, 0x29, + 0x42, 0x6B, 0x97, 0x7E, 0xC1, 0x8B, 0x1D, 0x9B, + 0x64, 0xD9, 0x21, 0x24, 0xF3, 0xE0, 0xEA, 0x72, + 0xD3, 0x5E, 0xEB, 0x71, 0x27, 0xEE, 0xEF, 0x09, + 0x3A, 0xDF, 0x73, 0x2E, 0xBE, 0x30, 0x57, 0xCD, + 0xEB, 0x49, 0x28, 0x83, 0x58, 0xB6, 0xBB, 0x91, + 0x90, 0xAC, 0x38, 0xBF, 0xC5, 0x6A, 0x6F, 0x6E, + 0x2F, 0xFF, 0x98, 0xD2, 0xFF, 0xE1, 0xB6, 0x5C, + 0x10, 0x3F, 0xBB, 0xA5, 0xDB, 0xC8, 0x56, 0x64, + 0x0D, 0xD6, 0xBE, 0xD2, 0x76, 0xF0, 0x33, 0xA0, + 0x37, 0xD1, 0xC6, 0xF1, 0x32, 0x96, 0x84, 0x17, + 0xE9, 0x4D, 0x37, 0x1B, 0x76, 0x60, 0x5F, 0xAA, + 0xD0, 0x70, 0xEF, 0xA7, 0x83, 0x48, 0xC6, 0xAE, + 0xB0, 0xCF, 0x6B, 0x72, 0x2D, 0x43, 0x7A, 0x7C, + 0x18, 0x25, 0x6B, 0xC7, 0x16, 0x60, 0x5C, 0x5D, + 0xF9, 0x1E, 0xE4, 0x0B, 0xAD, 0x7B, 0x06, 0x23, + 0xCA, 0xB8, 0x46, 0x05, 0xFC, 0x47, 0xBF, 0xCC, + 0xF7, 0x78, 0x9A, 0xB6, 0xDE, 0x12, 0xA0, 0x5D, + 0x1C, 0x1B, 0xF5, 0x36, 0x77, 0x9E, 0x8F, 0x95, + 0x7E, 0x3F, 0x5F, 0x82, 0xE7, 0xF5, 0x3D, 0xF6, + 0xEF, 0x13, 0x95, 0xB5, 0xEE, 0x3B, 0x1F, 0x0E, + 0x20, 0x02, 0xEA, 0x85, 0xFB, 0x09, 0x84, 0xCE, + 0x93, 0x8D, 0x48, 0x67, 0xCC, 0xA0, 0x98, 0x2E, + 0xFF, 0xD4, 0x5D, 0x45, 0x81, 0x0D, 0x43, 0xA5, + 0xD5, 0xC9, 0xD1, 0x4D, 0x5B, 0x3A, 0x9F, 0x4D, + 0x85, 0x8E, 0x95, 0x6A, 0xD7, 0x98, 0x85, 0x95, + 0x6F, 0x3E, 0x1E, + + 0x8F, 0x79, 0x64, 0x19, 0x20, 0xB6, 0x73, 0xAD, + 0x05, 0xF9, 0x92, 0xB5, 0x64, 0xFD, 0x00, 0x8A, + 0xD1, 0x35, 0x86, 0xF9, 0x1B, 0x1C, 0x6C, 0x48, + 0x2A, 0x54, 0x07, 0xCD, 0x59, 0xD7, 0xC2, 0x1B, + 0xA5, 0xF6, 0x25, 0x80, 0xF2, 0xC7, 0x4D, 0xE6, + 0xC8, 0xB1, 0x6B, 0x02, 0x90, 0x19, 0x82, 0xCD, + 0xEB, 0x35, 0xC5, 0xB9, 0x9C, 0xE6, 0x18, 0xBF, + 0xD5, 0xFA, 0x16, 0x72, 0x5E, 0x41, 0x1B, 0x85, + 0xB3, 0xA6, 0x96, 0xA8, 0x3C, 0x84, 0x7A, 0xB9, + 0xCE, 0xA5, 0x18, 0xA8, 0xE5, 0x78, 0x9C, 0x1D, + 0x2D, 0x5F, 0x8C, 0x7C, 0x09, 0xF9, 0xE5, 0xFB, + 0xDD, 0x56, 0xD9, 0x95, 0x60, 0xB1, 0x12, 0xD6, + 0x86, 0x6C, 0x3B, 0xE8, 0x2C, 0x22, 0xE3, 0xAB, + 0xEF, 0xC5, 0x8E, 0x0A, 0x3F, 0x6E, 0x3A, 0x1B, + 0x5D, 0x39, 0x96, 0x1B, 0xC3, 0x8B, 0x59, 0x1C, + 0xC3, 0xE4, 0x10, 0xD7, 0x29, 0x43, 0x14, 0xEB, + 0x63, 0x88, 0x53, 0x6E, 0x44, 0x8F, 0xAD, 0x5A, + 0xDD, 0xF4, 0x8A, 0xD0, 0x20, 0x21, 0x02, 0x6B, + 0x81, 0x05, 0xB1, 0xC4, 0xD2, 0xA1, 0x48, 0x70, + 0xF7, 0x66, 0xE3, 0xBE, 0x15, 0xB5, 0xF5, 0x43, + 0x66, 0x12, 0x94, 0x56, 0x88, 0x31, 0xE6, 0xAC, + 0xC4, 0x54, 0x48, 0x9F, 0x51, 0x09, 0x3D, 0x95, + 0xA4, 0x83, 0x62, 0xD8, 0x47, 0x3D, 0xEB, 0xC4, + 0x5B, 0x6D, 0x38, 0x98, 0x93, 0x89, 0xF0, 0x1C, + 0x40, 0x00, 0x02, 0xE6, 0xCA, 0xDB, 0x95, 0xE6, + 0x8E, 0x44, 0xE0, 0x5F, 0xC9, 0x62, 0x55, 0x3F, + 0xC8, 0x48, 0x5D, 0x12, 0xE7, 0x01, 0x87, 0x5C, + 0x07, 0xF3, 0x0E, 0x0F, 0xD7, 0x89, 0x04, 0x3F, + 0x2A, 0x10, 0x70, 0xCC, + + 0x3C, 0xB9, 0x3D, 0x28, 0x90, 0xEB, 0x21, 0x7D, + 0x9E, 0xCC, 0x4D, 0xA5, 0x84, 0xF6, 0x96, 0x93, + 0x5D, 0x12, 0x84, 0x9E, 0x71, 0x56, 0x5C, 0xD4, + 0x71, 0xB9, 0x9F, 0xDF, 0x2B, 0x51, 0x43, 0xC5, + 0x1E, 0x98, 0xBE, 0x8D, 0xB8, 0xFE, 0x3A, 0x9C, + 0x22, 0x25, 0xF2, 0x0F, 0x7F, 0x52, 0xB3, 0x9A, + 0xB6, 0xD8, 0x31, 0xE9, 0xC3, 0x9A, 0x86, 0x89, + 0xB6, 0x1B, 0x63, 0x3F, 0xC0, 0x37, 0x7D, 0xFF, + 0x80, 0xC3, 0x28, 0x0D, 0xF1, 0x09, 0xB1, 0xD1, + 0x38, 0xA8, 0x99, 0xD9, 0x81, 0x32, 0x62, 0x16, + 0xDE, 0x2D, 0x16, 0x07, 0x78, 0x5D, 0xCB, 0xB8, + 0x3E, 0xB8, 0x01, 0x5A, 0xB5, 0x21, 0x6E, 0xA1, + 0x7B, 0xD8, 0x64, 0x00, 0xFC, 0x6B, 0xDF, 0xA4, + 0x4D, 0x07, 0x81, 0xEE, 0x76, 0x69, 0x43, 0x9F, + 0x90, 0x09, 0x24, 0x26, 0x72, 0xC5, 0x2F, 0xF5, + 0x50, 0x31, 0xC9, 0xB9, 0x3B, 0xAE, 0xDE, 0x1F, + 0x6B, 0xCC, 0xFA, 0xC6, 0xCB, 0xBC, 0xEC, 0x75, + 0x91, 0x3A, 0x0C, 0x5D, 0x13, 0xB9, 0x3E, 0x16, + 0x3C, 0xE4, 0xAC, 0x56, 0x60, 0x0C, 0x92, 0x2D, + 0x05, 0xD6, 0x1A, 0x01, 0xC4, 0x94, 0xAD, 0x19, + 0xEE, 0x3C, 0x79, 0x5D, 0x5C, 0x49, 0x8A, 0x67, + 0xAF, 0x19, 0x1B, 0xBA, 0x2C, 0x30, 0xA2, 0x47, + 0xF2, 0x35, 0x00, 0x15, 0xF0, 0x7B, 0xC1, 0xA2, + 0xB3, 0x9C, 0x49, 0x83, 0x81, 0x26, 0x71, 0x7E, + 0xF0, 0x34, 0x01, 0x02, 0xC0, 0xDE, 0x44, 0xFA, + 0xFA, 0x5F, 0x84, 0xBA, 0x23, 0x16, 0x39, 0x29, + 0x77, 0xD7, 0x5D, 0x17, 0xBA, 0x9A, 0x39, 0x93, + 0xBE, 0xBB, 0x01, 0x67, 0xD6, 0x23, 0x2B, 0x7F, + 0x9E, 0x29, 0x61, 0xCC, 0x4D, + + 0xCE, 0x24, 0x29, 0x8D, 0x54, 0x03, 0x84, 0x07, + 0xF8, 0x5A, 0x69, 0x9A, 0x3E, 0x01, 0xF5, 0x63, + 0xFC, 0x16, 0xB6, 0xF0, 0x20, 0x39, 0x81, 0x10, + 0xCD, 0x82, 0xD5, 0x5D, 0xAE, 0xED, 0xA6, 0x86, + 0xA5, 0xFF, 0xF8, 0x85, 0x6E, 0x0A, 0x36, 0x2F, + 0x6B, 0xF6, 0x62, 0xAB, 0x12, 0xE6, 0x41, 0x2B, + 0x3D, 0x4D, 0xDB, 0x80, 0x26, 0xC9, 0xAD, 0xE4, + 0x93, 0x05, 0x0C, 0x28, 0x23, 0xFF, 0x9B, 0xBF, + 0x85, 0x43, 0x82, 0xCD, 0x6E, 0x5F, 0xD4, 0x08, + 0x31, 0xFA, 0x52, 0x78, 0x99, 0x15, 0xD0, 0xD5, + 0xBD, 0x7C, 0xD4, 0x91, 0xCB, 0x0F, 0x53, 0xE7, + 0x5D, 0x53, 0xE8, 0xDA, 0xAB, 0x32, 0xDF, 0xD8, + 0xCF, 0xF5, 0x95, 0xF1, 0x41, 0xCF, 0x37, 0x2B, + 0xF0, 0x51, 0x93, 0x33, 0xAA, 0xFF, 0x36, 0x07, + 0x3C, 0xF9, 0x40, 0x18, 0x05, 0xA6, 0x1B, 0xEF, + 0x9E, 0x5E, 0x71, 0x77, 0x75, 0xD2, 0x23, 0xD6, + 0x0F, 0x5A, 0x84, 0x73, 0x6C, 0x23, 0x17, 0x18, + 0x78, 0x84, 0x41, 0xEC, 0x76, 0xD5, 0x66, 0xDE, + 0xF3, 0x22, 0x6E, 0x03, 0xD0, 0xF0, 0xFE, 0x67, + 0x8C, 0x4B, 0x4F, 0x43, 0xC8, 0x94, 0xBE, 0x8D, + 0x3C, 0x34, 0xA9, 0x1E, 0xC2, 0x27, 0x64, 0x90, + 0x13, 0x85, 0xA7, 0xC1, 0xC9, 0xF3, 0x6E, 0x50, + 0x0B, 0xD5, 0xD1, 0x38, 0xB0, 0x53, 0x0D, 0xDC, + 0x5A, 0xE8, 0x6B, 0x30, 0x91, 0xA2, 0x73, 0xDA, + 0x5C, 0xB3, 0x77, 0x36, 0xBC, 0xE1, 0xBF, 0xE0, + 0x85, 0x3B, 0xAC, 0x73, 0x13, 0xD1, 0x72, 0x0D, + 0x36, 0x47, 0xAE, 0x77, 0xA9, 0x91, 0x3B, 0x65, + 0x3F, 0x20, 0xED, 0x65, 0x02, 0x98, 0xAE, 0x1B, + 0x6B, 0x22, 0x17, 0x9F, 0x10, 0x64, + + 0x43, 0xA6, 0xF3, 0x60, 0x88, 0x3A, 0x74, 0x66, + 0xA5, 0x48, 0xB2, 0x8F, 0x82, 0x94, 0xCC, 0xFD, + 0xCB, 0x15, 0x13, 0x60, 0x9B, 0xE4, 0x97, 0x96, + 0x2E, 0x36, 0xF9, 0xB3, 0x7B, 0xEC, 0xF1, 0xC3, + 0x54, 0xF0, 0xBB, 0xA0, 0xA8, 0x4A, 0x28, 0xB7, + 0x3A, 0x2E, 0xEC, 0x36, 0x5D, 0x0F, 0x26, 0xDE, + 0x3A, 0x24, 0x53, 0x13, 0x3F, 0xEA, 0x7C, 0x03, + 0xEB, 0x83, 0x53, 0x76, 0x8E, 0x83, 0xBC, 0x15, + 0x77, 0x04, 0xCC, 0xEF, 0x16, 0x7A, 0x40, 0xBA, + 0x14, 0xAB, 0x79, 0xB3, 0x2C, 0x18, 0xCE, 0xEC, + 0xC0, 0xF0, 0x66, 0x61, 0x99, 0xF7, 0x31, 0x3C, + 0x69, 0x66, 0xB5, 0xC0, 0xF4, 0x22, 0x4E, 0xCC, + 0x8A, 0xE9, 0xAC, 0x94, 0xC7, 0xC4, 0xC0, 0x88, + 0xCB, 0xF3, 0x4C, 0x49, 0xD1, 0x87, 0x55, 0xB8, + 0x15, 0x34, 0x47, 0x4B, 0xF0, 0x5B, 0xB3, 0xBB, + 0x77, 0x15, 0xED, 0x3F, 0xF8, 0x4F, 0xD3, 0x9D, + 0xFE, 0x8C, 0xD5, 0x4C, 0xE1, 0x2B, 0x74, 0x6F, + 0xA3, 0xBF, 0x03, 0x8A, 0xDF, 0xC2, 0xBF, 0xC5, + 0x27, 0x0F, 0xAF, 0x53, 0x42, 0x9A, 0x69, 0x39, + 0x33, 0xC7, 0x73, 0x67, 0x2E, 0xCE, 0x88, 0xD6, + 0xCF, 0xBB, 0x7C, 0xCB, 0x0D, 0x84, 0x0E, 0xB9, + 0x54, 0xFD, 0x51, 0x9F, 0xE3, 0x62, 0x87, 0xC7, + 0x5F, 0x08, 0xFE, 0x4C, 0x2E, 0xEA, 0x7F, 0xF2, + 0xC6, 0xB8, 0xEB, 0xDC, 0x35, 0x02, 0x1A, 0x6C, + 0xEB, 0xC0, 0x73, 0x82, 0x34, 0x52, 0xBE, 0x55, + 0x14, 0xB9, 0x36, 0x3D, 0xC8, 0x88, 0x03, 0x51, + 0x35, 0x7D, 0x89, 0x1B, 0x36, 0xA9, 0xD4, 0x03, + 0xA0, 0x86, 0x66, 0x90, 0x10, 0xC0, 0xBD, 0x39, + 0x5D, 0xB5, 0x4A, 0x67, 0x49, 0x2A, 0xBC, + + 0x05, 0x95, 0xB2, 0x93, 0x14, 0x73, 0xB3, 0x70, + 0x89, 0xE4, 0xCC, 0x29, 0x8C, 0x60, 0x49, 0x46, + 0xBD, 0xC5, 0x33, 0x19, 0x32, 0xEE, 0xC7, 0xFA, + 0x6B, 0x93, 0x8B, 0x09, 0x75, 0x6D, 0xC6, 0x81, + 0xFA, 0xE9, 0xB1, 0x91, 0xBE, 0x74, 0xDF, 0x09, + 0xB6, 0xDB, 0x98, 0x67, 0x26, 0x7E, 0x8C, 0x0F, + 0x27, 0x5D, 0x38, 0x22, 0xCE, 0x70, 0x60, 0x7A, + 0xA1, 0xA5, 0x2F, 0xCC, 0x71, 0x18, 0x0C, 0x17, + 0x3D, 0x2A, 0xDD, 0xEC, 0xFA, 0xCB, 0x5B, 0x0E, + 0xD4, 0x4C, 0x3D, 0xED, 0x8A, 0xDE, 0xA5, 0x3D, + 0x1E, 0x35, 0xE4, 0xAB, 0xAF, 0x14, 0x5F, 0xF0, + 0x3F, 0xA0, 0x11, 0x5A, 0xC5, 0x64, 0x40, 0xEC, + 0x11, 0x90, 0x70, 0xDE, 0x01, 0x7F, 0xAD, 0xAE, + 0xE1, 0x30, 0x94, 0x6E, 0x1E, 0xE3, 0x22, 0xCD, + 0xC3, 0x91, 0x25, 0x77, 0x25, 0x9A, 0x62, 0xFA, + 0x43, 0xAC, 0x32, 0x8E, 0xE7, 0xB7, 0xF2, 0xD0, + 0x54, 0xD4, 0xC4, 0x6C, 0xB3, 0x88, 0xDD, 0xDA, + 0x82, 0xD6, 0xA4, 0x33, 0xC1, 0xAA, 0x42, 0xD1, + 0x26, 0x0C, 0xE7, 0xEC, 0x81, 0x87, 0x50, 0x56, + 0x00, 0xC0, 0xAC, 0xEE, 0x96, 0xBC, 0x67, 0xEB, + 0x03, 0x58, 0x38, 0x67, 0x71, 0x1B, 0xD8, 0x59, + 0xA2, 0xC5, 0x77, 0xA4, 0xD5, 0x39, 0x95, 0x13, + 0x60, 0x3C, 0x4F, 0x28, 0xD4, 0xB2, 0x9E, 0x15, + 0x3D, 0xB5, 0x24, 0x37, 0x32, 0xCC, 0x2C, 0x22, + 0xD3, 0x02, 0xAF, 0x60, 0x7F, 0x8E, 0x56, 0x59, + 0xC7, 0x52, 0x1A, 0xF7, 0x43, 0x70, 0x6E, 0xE6, + 0xFF, 0x2C, 0x94, 0x22, 0x85, 0x28, 0xEF, 0x24, + 0x83, 0x7F, 0x80, 0xAF, 0x4E, 0x7F, 0x37, 0x21, + 0x78, 0x9B, 0x31, 0x2E, 0x3A, 0xC0, 0xCE, 0x49, + + 0x1C, 0x1A, 0x99, 0x58, 0xBA, 0x52, 0xC5, 0x41, + 0xFB, 0x0A, 0x17, 0xAF, 0x23, 0x3B, 0xBF, 0x3D, + 0x5B, 0x70, 0x45, 0xB9, 0xC2, 0xF4, 0xD5, 0xB2, + 0xF9, 0x5E, 0x82, 0xC0, 0x19, 0x99, 0x3F, 0xCB, + 0x22, 0xEC, 0x10, 0xF3, 0x26, 0xBA, 0xC7, 0xD4, + 0x9B, 0x2D, 0xFF, 0x3C, 0x39, 0xE4, 0xFB, 0x4D, + 0xC5, 0x5A, 0x01, 0x43, 0xBC, 0x83, 0x9F, 0x17, + 0x4E, 0xDC, 0xFE, 0x4B, 0x2E, 0x3C, 0x67, 0xA9, + 0x2A, 0xDB, 0xC4, 0x28, 0xB6, 0xD7, 0xB1, 0x24, + 0xDB, 0x10, 0xE6, 0x27, 0xF9, 0x29, 0xFC, 0x63, + 0x57, 0x72, 0xB6, 0xA0, 0x8C, 0x25, 0x7F, 0x67, + 0x94, 0x70, 0xBB, 0xBF, 0x2F, 0x60, 0xF4, 0xF3, + 0x98, 0x85, 0xBD, 0xE6, 0x50, 0xDC, 0xA6, 0x0E, + 0x96, 0xE7, 0x9F, 0x3C, 0x4F, 0xAE, 0xC7, 0x95, + 0xDB, 0x67, 0xEC, 0x20, 0x54, 0x2B, 0x34, 0xFA, + 0x04, 0x98, 0x77, 0xEE, 0xAD, 0xE4, 0x65, 0x94, + 0x94, 0xD6, 0x6D, 0xE0, 0x81, 0x15, 0x1F, 0x10, + 0x0F, 0x34, 0xEE, 0x64, 0x47, 0xD4, 0x15, 0x07, + 0xF4, 0x38, 0xC5, 0xEE, 0x06, 0x6F, 0x8A, 0xE6, + 0x7A, 0x18, 0x2E, 0x2E, 0xAB, 0xE7, 0xD9, 0x5C, + 0xD6, 0x58, 0xE4, 0x22, 0x21, 0xFB, 0xE0, 0x34, + 0x46, 0xE1, 0xBE, 0x89, 0x17, 0xC7, 0x8A, 0xD7, + 0x22, 0xE6, 0xE4, 0xDF, 0xA8, 0xCE, 0xFF, 0x2D, + 0xC4, 0x63, 0xF8, 0x83, 0x70, 0x3B, 0x4F, 0xB6, + 0x62, 0xA0, 0x50, 0x46, 0x30, 0xB1, 0x3E, 0xE8, + 0x2E, 0xBE, 0xFC, 0xAA, 0x5C, 0xF5, 0x68, 0xB3, + 0x47, 0xBF, 0x65, 0x3E, 0x64, 0x72, 0x6F, 0x90, + 0x89, 0x88, 0x2F, 0x82, 0x35, 0xE9, 0xF6, 0xD1, + 0xFA, 0xEE, 0x25, 0xDC, 0xA0, 0x04, 0xD7, 0x0B, + 0x1E, + + 0xED, 0x32, 0x54, 0xE8, 0x2D, 0x03, 0x35, 0xD5, + 0x55, 0x62, 0x1F, 0xD2, 0x2A, 0xE5, 0x69, 0x47, + 0xD6, 0xD8, 0x92, 0xBC, 0x3D, 0xF1, 0xAB, 0x57, + 0xFE, 0x03, 0x12, 0xCE, 0xAD, 0xF8, 0x1D, 0x37, + 0xB2, 0x40, 0x72, 0xD0, 0xC8, 0x38, 0xE2, 0xD1, + 0xA4, 0x0F, 0xA0, 0x7F, 0x19, 0x72, 0xAF, 0x84, + 0x53, 0x8B, 0x71, 0x66, 0xBF, 0x56, 0x19, 0x3A, + 0xEA, 0x27, 0xFD, 0xF5, 0xB6, 0x43, 0xD4, 0xB8, + 0x8B, 0x27, 0xE8, 0x82, 0x0B, 0x24, 0x3C, 0xD7, + 0xFF, 0x31, 0xF3, 0x6D, 0x15, 0x5D, 0xBD, 0x1D, + 0x93, 0x0F, 0x98, 0x4E, 0x16, 0x00, 0x94, 0xEE, + 0xE6, 0x27, 0xBA, 0x19, 0xC2, 0xCE, 0x73, 0x63, + 0x0C, 0x71, 0xEC, 0x27, 0x70, 0x69, 0x2E, 0x96, + 0xA3, 0x20, 0x98, 0xCF, 0x2B, 0xDF, 0x50, 0x07, + 0xC8, 0x10, 0xCD, 0xA0, 0x6B, 0x9E, 0xBF, 0xEC, + 0xD3, 0x6E, 0x94, 0x70, 0x6B, 0x3F, 0xE1, 0x73, + 0x10, 0xDB, 0x9E, 0x98, 0x5B, 0x5B, 0x97, 0xB9, + 0x07, 0xF4, 0xD6, 0x55, 0xEC, 0x52, 0x86, 0x0E, + 0x14, 0xD5, 0xF9, 0x5F, 0xA9, 0xFB, 0xE1, 0x96, + 0x6E, 0xB1, 0xA8, 0xB0, 0xD3, 0xB1, 0x44, 0x08, + 0xF8, 0xBC, 0x97, 0xC8, 0xF7, 0xE8, 0xD5, 0xC9, + 0xD7, 0x9F, 0x2C, 0xCA, 0xC6, 0x35, 0x26, 0x4F, + 0x2F, 0x83, 0xC0, 0x88, 0x91, 0x8D, 0x9A, 0xD7, + 0xFC, 0x8A, 0x2A, 0x9C, 0x06, 0x8C, 0xFA, 0xC3, + 0xF3, 0xD0, 0x0A, 0x21, 0xE3, 0x4E, 0xDF, 0x6A, + 0xB4, 0x00, 0x9F, 0xF4, 0xB6, 0x6E, 0x41, 0xF2, + 0x1A, 0x5E, 0xC8, 0x8B, 0x36, 0xC2, 0x81, 0xDA, + 0x0C, 0x74, 0x20, 0xC5, 0x41, 0x60, 0xD1, 0x2A, + 0xEB, 0xAA, 0x51, 0xCB, 0x38, 0x10, 0x94, 0x8B, + 0xA2, 0x89, + + 0x90, 0xBB, 0xE5, 0x2E, 0xDE, 0xBA, 0xB1, 0x0F, + 0x5C, 0xB8, 0x39, 0x67, 0xF9, 0x10, 0x1A, 0x72, + 0x33, 0xA4, 0x9B, 0x47, 0x5C, 0xC3, 0x97, 0x66, + 0xA9, 0x31, 0xC6, 0xD6, 0xD1, 0x64, 0x51, 0x19, + 0x3A, 0xAC, 0xBF, 0x99, 0x1B, 0x1C, 0xEC, 0x32, + 0x4F, 0x69, 0xC7, 0x6D, 0xBD, 0x4A, 0xEE, 0x29, + 0x75, 0x66, 0x42, 0xF7, 0x40, 0x58, 0xE5, 0x05, + 0x84, 0x18, 0x8A, 0x82, 0xE8, 0x8E, 0x13, 0x19, + 0x89, 0x6F, 0xC1, 0xDD, 0x43, 0x0C, 0xC5, 0x63, + 0xE2, 0xC4, 0xCC, 0x33, 0x61, 0xF4, 0xE6, 0x6B, + 0x9B, 0x39, 0x5E, 0xA1, 0x8E, 0x80, 0x8C, 0x13, + 0x1B, 0xE5, 0xD4, 0x4D, 0x7A, 0xDD, 0xF4, 0x52, + 0x51, 0x0C, 0x0B, 0x1F, 0x23, 0x52, 0xC8, 0x52, + 0xF8, 0xD4, 0x88, 0x3E, 0xAE, 0xB8, 0x98, 0xF8, + 0x76, 0xB3, 0xAD, 0x6B, 0x20, 0xD4, 0x83, 0x87, + 0x68, 0x45, 0x5C, 0xA8, 0xB3, 0xA0, 0xA4, 0xB9, + 0xE7, 0x16, 0x06, 0x48, 0xEF, 0x45, 0x33, 0x29, + 0xAB, 0x75, 0xE6, 0x9D, 0x83, 0x74, 0xF9, 0xF7, + 0x22, 0xA0, 0xC5, 0xFF, 0x9E, 0x35, 0x6A, 0x46, + 0x7B, 0x80, 0x21, 0xE7, 0x47, 0xD8, 0x4C, 0x37, + 0xB1, 0x96, 0x05, 0xBD, 0xE2, 0x1B, 0xDF, 0xE9, + 0x34, 0x4B, 0xBF, 0x03, 0x72, 0xB8, 0x47, 0x6E, + 0xE4, 0xB8, 0xDB, 0x63, 0xD6, 0xC2, 0x62, 0x8E, + 0xA8, 0x28, 0x1F, 0xC3, 0x1C, 0x35, 0x1F, 0x2C, + 0xCD, 0x24, 0xAF, 0x6A, 0x38, 0x1D, 0xA1, 0xC8, + 0x07, 0xA7, 0xB7, 0x04, 0x5A, 0xC6, 0x08, 0x4E, + 0x29, 0xBB, 0xA2, 0x19, 0xFE, 0x54, 0x2F, 0xD8, + 0xF3, 0xB3, 0x3E, 0x60, 0xFF, 0x27, 0xB1, 0x88, + 0x2F, 0x2C, 0xB7, 0x66, 0x09, 0x97, 0xE5, 0x09, + 0x77, 0x5F, 0x53, + + 0xD3, 0xA5, 0x23, 0x44, 0x45, 0xCA, 0x7B, 0xF1, + 0x84, 0xF2, 0x59, 0x2F, 0x75, 0xC6, 0xC3, 0x49, + 0xEC, 0x4C, 0xA2, 0x4A, 0xF9, 0xD1, 0xBB, 0x1D, + 0xBB, 0x30, 0x2E, 0x18, 0xDD, 0xFF, 0xC8, 0x77, + 0x2D, 0x8F, 0x09, 0x6F, 0x65, 0x5A, 0x64, 0x6B, + 0xEB, 0x8A, 0xDF, 0xA2, 0x50, 0xBA, 0x5A, 0x54, + 0x79, 0xE5, 0x14, 0x69, 0x42, 0x34, 0xE8, 0xA0, + 0x62, 0xA5, 0x3A, 0x7A, 0x49, 0xB1, 0x8B, 0xA3, + 0xD8, 0x73, 0x57, 0x70, 0xE3, 0x93, 0x04, 0xE4, + 0x59, 0x86, 0x8A, 0x7B, 0xBE, 0x65, 0x48, 0x16, + 0xB5, 0xE6, 0xAF, 0xC3, 0xBD, 0xFF, 0x3C, 0xDF, + 0xF6, 0xCB, 0x60, 0xE4, 0xBA, 0x77, 0xF4, 0x4B, + 0x95, 0x79, 0xCE, 0xD6, 0x36, 0xBD, 0xBF, 0x36, + 0x42, 0x53, 0x15, 0xA3, 0x77, 0xB3, 0x9F, 0x68, + 0x98, 0x6E, 0xB5, 0x01, 0x16, 0xA2, 0x26, 0x79, + 0xB0, 0x1A, 0x65, 0x45, 0x30, 0xBB, 0x00, 0x4F, + 0xE4, 0x7A, 0xD0, 0x31, 0xE5, 0x77, 0xD4, 0xC6, + 0x6A, 0x72, 0xC5, 0xF2, 0xC1, 0xFC, 0x60, 0x74, + 0x99, 0xD5, 0x25, 0xF2, 0x7B, 0x6D, 0xFE, 0x32, + 0x1C, 0x90, 0xD0, 0xF9, 0xF0, 0xAE, 0x93, 0x20, + 0xB4, 0xA0, 0xF7, 0xA5, 0x75, 0xE4, 0x83, 0x94, + 0x80, 0x8C, 0x1E, 0x18, 0xD7, 0x1C, 0xA4, 0x5F, + 0x0A, 0x08, 0xD2, 0xB1, 0x27, 0xC4, 0x0D, 0xA4, + 0xBE, 0xE0, 0x36, 0x69, 0x19, 0x14, 0x9A, 0x58, + 0x9C, 0xD5, 0x36, 0xE5, 0x46, 0xE1, 0x94, 0x66, + 0xC3, 0x77, 0x78, 0x52, 0xF9, 0x2B, 0xDA, 0x95, + 0xDC, 0xED, 0x6A, 0x6E, 0x58, 0xE9, 0x16, 0x34, + 0x2A, 0x6B, 0xD5, 0x4E, 0xF2, 0x7E, 0xB8, 0x96, + 0xEB, 0x9B, 0x4D, 0xD3, 0xFD, 0xB4, 0x33, 0x0D, + 0x13, 0x26, 0x42, 0x3E, + + 0xF6, 0x0F, 0x59, 0xEC, 0xB0, 0xE1, 0x3D, 0x20, + 0xB8, 0xD7, 0x3D, 0xF9, 0x59, 0xCF, 0xEF, 0xA9, + 0xD7, 0xB2, 0x47, 0xBC, 0x87, 0x54, 0xD3, 0x7E, + 0xF9, 0x2C, 0xDF, 0xB6, 0x0F, 0x86, 0x13, 0x02, + 0x1C, 0xFA, 0xC0, 0x26, 0xDB, 0x49, 0x3B, 0x36, + 0x60, 0xA2, 0x64, 0xD8, 0x91, 0xB1, 0x7C, 0x35, + 0xEA, 0x2F, 0x5E, 0xF6, 0x99, 0xE2, 0x0B, 0x74, + 0x1F, 0x76, 0xF6, 0x8F, 0x7E, 0x58, 0x63, 0x3E, + 0xB6, 0xA2, 0xF3, 0x0A, 0xD4, 0xA5, 0x19, 0xB7, + 0x45, 0x08, 0xDB, 0x52, 0x17, 0x1D, 0xB1, 0x00, + 0x23, 0x0B, 0xD4, 0xC0, 0x86, 0x52, 0x49, 0xA8, + 0x33, 0xAB, 0x0A, 0xD1, 0x51, 0x9C, 0x5D, 0x4B, + 0x23, 0xF1, 0x93, 0x17, 0x6A, 0x48, 0xA6, 0x2F, + 0x9D, 0x0D, 0x9A, 0x09, 0xBD, 0x19, 0xA0, 0x39, + 0x60, 0xDE, 0xD1, 0xE4, 0x42, 0xD8, 0x34, 0xC0, + 0x1D, 0xD3, 0x88, 0x29, 0xA8, 0x48, 0x75, 0x5C, + 0xDF, 0x1D, 0xD4, 0x09, 0x53, 0x5E, 0x5D, 0x0A, + 0x9A, 0x2D, 0x95, 0x83, 0xF6, 0x85, 0x2F, 0xAD, + 0x8C, 0xFF, 0x55, 0xD8, 0x19, 0x56, 0xEE, 0x38, + 0xD2, 0x25, 0x30, 0x27, 0x21, 0xB5, 0x10, 0xED, + 0x24, 0xFB, 0x0E, 0x22, 0x55, 0xA2, 0xC3, 0x31, + 0xDC, 0x1E, 0xA0, 0xC7, 0x4B, 0x1B, 0xC0, 0x14, + 0x95, 0x25, 0x8F, 0x37, 0x3C, 0x75, 0x61, 0x44, + 0x0B, 0x09, 0x81, 0x8C, 0x32, 0xE5, 0x59, 0x3D, + 0xE3, 0xD5, 0x45, 0xDF, 0x11, 0xFF, 0x61, 0x9E, + 0x01, 0x10, 0x5E, 0x91, 0x70, 0x18, 0x1D, 0x76, + 0xC9, 0x74, 0x3C, 0xDD, 0x30, 0xB2, 0x01, 0xF5, + 0xCD, 0xCD, 0x9F, 0xFC, 0xE3, 0x7A, 0xB9, 0xD1, + 0x7F, 0xA4, 0x3C, 0x2E, 0x2C, 0x28, 0x25, 0xCC, + 0x6C, 0x56, 0x3A, 0x80, 0xF9, + + 0x7E, 0x13, 0xEF, 0xE6, 0x6B, 0x69, 0x25, 0xE0, + 0x81, 0xE9, 0x64, 0x4E, 0xE9, 0xFC, 0x00, 0x0C, + 0xDD, 0x81, 0x66, 0xB1, 0xC9, 0x12, 0xC4, 0x98, + 0x5F, 0x71, 0x2F, 0xFC, 0xFB, 0x24, 0x9E, 0x49, + 0x5E, 0xFB, 0x20, 0xB9, 0x56, 0x06, 0x23, 0xD3, + 0xD5, 0x80, 0x51, 0x25, 0xE6, 0x33, 0x55, 0xC0, + 0x48, 0x28, 0x32, 0xDB, 0xBB, 0x48, 0x6D, 0xF6, + 0x30, 0xA7, 0x4D, 0xC6, 0x54, 0x7A, 0x63, 0x5E, + 0x54, 0x7A, 0xE4, 0xEB, 0x71, 0x03, 0xA7, 0x65, + 0x1F, 0x36, 0x25, 0x32, 0xD0, 0x3F, 0xA1, 0x07, + 0xAB, 0xE0, 0x17, 0x57, 0x18, 0x06, 0xCB, 0x2B, + 0x78, 0x9F, 0xC3, 0xBD, 0x57, 0x13, 0x4B, 0x0A, + 0x52, 0xFC, 0x87, 0x39, 0xFF, 0xE6, 0xE8, 0x89, + 0x1D, 0x65, 0x61, 0x36, 0x6B, 0x93, 0xB8, 0xA9, + 0x71, 0x4B, 0xB3, 0xD4, 0x87, 0xBF, 0xAF, 0x89, + 0xB7, 0x57, 0x8F, 0x11, 0x3D, 0x36, 0xF2, 0x13, + 0x89, 0x92, 0x7C, 0xD6, 0xFE, 0x18, 0x9F, 0x4A, + 0x7F, 0xBE, 0x34, 0x1F, 0xAF, 0xCB, 0xFB, 0xCA, + 0x74, 0x7B, 0x4D, 0x93, 0x71, 0x45, 0xE4, 0xA0, + 0x4E, 0xE7, 0x4B, 0x9E, 0xFE, 0x45, 0x13, 0xDB, + 0xE9, 0x26, 0xD8, 0x75, 0xA5, 0xB6, 0x8A, 0x5E, + 0xF7, 0x7A, 0xE1, 0xA6, 0x78, 0xEB, 0xBA, 0xBA, + 0xC6, 0xB2, 0xC2, 0xCF, 0x04, 0x8A, 0x72, 0x6C, + 0xA2, 0x53, 0xDE, 0xC8, 0x91, 0xDB, 0x05, 0x46, + 0xA4, 0x86, 0x0C, 0xB8, 0xD0, 0x0F, 0x15, 0x10, + 0xD4, 0xC3, 0xA1, 0x53, 0xEA, 0x9F, 0x9A, 0x20, + 0x5A, 0xB3, 0xE8, 0x7A, 0x47, 0xC8, 0xCF, 0x87, + 0xA3, 0x7D, 0x54, 0x5C, 0xF1, 0x84, 0xE2, 0x5E, + 0x8A, 0x98, 0x8E, 0x7F, 0xAE, 0x18, 0x2F, 0x97, + 0xB3, 0x5D, 0x84, 0xFF, 0xEC, 0xAB, + + 0x81, 0x65, 0x82, 0x11, 0xCB, 0x36, 0xCA, 0xE9, + 0x04, 0x0E, 0x35, 0x85, 0xBE, 0xB3, 0x99, 0xDF, + 0xCF, 0xD5, 0x77, 0x38, 0xD4, 0xDC, 0xFE, 0x0D, + 0x01, 0xD3, 0x06, 0x2E, 0x83, 0x2E, 0x3A, 0x8C, + 0x90, 0x84, 0x17, 0x74, 0x28, 0x79, 0xFB, 0x3C, + 0x4B, 0x6D, 0x22, 0x43, 0xD6, 0x54, 0x6C, 0x6D, + 0x04, 0x36, 0xD7, 0x75, 0x95, 0xA0, 0xA8, 0xD1, + 0x42, 0xAC, 0x4B, 0x97, 0xAD, 0x69, 0x3F, 0xBA, + 0x2C, 0x0B, 0xC2, 0xCD, 0x3D, 0x70, 0x31, 0xEE, + 0xE6, 0x9E, 0x81, 0x28, 0x42, 0xAF, 0x67, 0x5D, + 0x3C, 0xFE, 0xDA, 0xF8, 0x89, 0x2F, 0xF8, 0xA0, + 0x19, 0x4E, 0x77, 0x87, 0x45, 0xBC, 0x0D, 0xB6, + 0xC0, 0x16, 0xE3, 0x4D, 0x46, 0x03, 0x89, 0x70, + 0xB0, 0xF3, 0xD3, 0x6F, 0x9A, 0x30, 0xD7, 0x51, + 0x05, 0xAE, 0xCC, 0x3A, 0xC5, 0x68, 0x56, 0x93, + 0x7B, 0x0F, 0x37, 0x96, 0x0E, 0x91, 0xD5, 0x7D, + 0xF9, 0xA6, 0xEB, 0x2C, 0x4E, 0xF6, 0x19, 0x0A, + 0xBA, 0x0F, 0x84, 0xA9, 0xD1, 0xFC, 0xD4, 0x72, + 0x0B, 0xCD, 0x79, 0xDE, 0x05, 0x49, 0x62, 0x4A, + 0x89, 0xEE, 0xB5, 0x6D, 0x5C, 0x28, 0xA7, 0xC7, + 0x96, 0x99, 0xF1, 0x0D, 0x35, 0xE2, 0xB3, 0x0E, + 0x20, 0xDB, 0x0A, 0xAD, 0x32, 0x72, 0x42, 0x40, + 0x60, 0x68, 0x39, 0xE1, 0xD9, 0x2E, 0x74, 0x90, + 0x59, 0xC7, 0xF1, 0xAE, 0x35, 0xC4, 0x0D, 0x8B, + 0xCE, 0xB1, 0xDC, 0x60, 0xD7, 0x03, 0x5A, 0x03, + 0xCD, 0x6F, 0xED, 0xC8, 0x8A, 0xF2, 0x5A, 0xE5, + 0x88, 0xBB, 0x24, 0xA5, 0x6C, 0x8E, 0x95, 0x84, + 0xF3, 0x02, 0x78, 0x5E, 0x7C, 0x8E, 0xDF, 0xCF, + 0xB1, 0x48, 0x5F, 0x16, 0x73, 0x38, 0x46, 0x69, + 0x3E, 0x41, 0x82, 0xBE, 0x29, 0xEC, 0xAF, + + 0x35, 0x6C, 0x92, 0x8B, 0x5B, 0xA9, 0xD1, 0x04, + 0x67, 0x82, 0x3C, 0x7E, 0x26, 0xA3, 0x0B, 0x58, + 0xD2, 0xC7, 0xC2, 0x3E, 0xC3, 0xDF, 0x79, 0x69, + 0xA6, 0x73, 0x38, 0xDC, 0x01, 0x60, 0x17, 0x37, + 0xD7, 0x46, 0xF4, 0xE6, 0x62, 0x72, 0xC7, 0x09, + 0xDB, 0x6F, 0x45, 0xDE, 0x59, 0x85, 0x48, 0xA1, + 0xA4, 0xF7, 0x6D, 0x83, 0x52, 0xC0, 0x64, 0xE3, + 0x4B, 0xFB, 0xCD, 0xAB, 0x62, 0x10, 0xF7, 0x40, + 0x07, 0xAA, 0x51, 0x83, 0xCF, 0xD8, 0xFD, 0xC1, + 0x35, 0x27, 0x0A, 0xCE, 0x21, 0x5E, 0x85, 0xF8, + 0x10, 0x0C, 0xAD, 0xCE, 0xD3, 0xB2, 0xF0, 0xCB, + 0x03, 0x4A, 0xE1, 0x8E, 0x8E, 0xF1, 0x05, 0xE3, + 0x1E, 0xBD, 0x35, 0xB3, 0x41, 0xEA, 0x39, 0x93, + 0xAD, 0xE2, 0xBC, 0xFD, 0x68, 0xCF, 0xAF, 0xDE, + 0x3F, 0xB3, 0xDD, 0xB3, 0x1A, 0x4C, 0x81, 0x6D, + 0x3E, 0x7E, 0x76, 0xA3, 0xB8, 0x26, 0x9D, 0xA4, + 0xD9, 0xAC, 0x88, 0x71, 0xEC, 0xE9, 0x4F, 0xA5, + 0xBF, 0x53, 0xB6, 0xFF, 0x52, 0xDA, 0xCB, 0x9B, + 0x2B, 0x67, 0xAF, 0x50, 0xEE, 0xCF, 0xA5, 0xD0, + 0x35, 0xAA, 0xB5, 0xE9, 0x34, 0x8E, 0x62, 0xD6, + 0x11, 0x94, 0xD0, 0xA7, 0xEF, 0xB9, 0xA2, 0x19, + 0x22, 0x17, 0xE4, 0x20, 0x35, 0xB6, 0x60, 0x8F, + 0x26, 0xAA, 0x3C, 0x41, 0xC8, 0xFC, 0xBC, 0xEE, + 0x5E, 0x42, 0xF6, 0x9B, 0x79, 0xBA, 0xAA, 0x4D, + 0x59, 0x18, 0xC9, 0x00, 0x9F, 0x28, 0x17, 0x3A, + 0x1F, 0xFC, 0x3B, 0x4C, 0xD5, 0xBF, 0x1B, 0x72, + 0x88, 0x5D, 0x22, 0x57, 0x7A, 0x47, 0x8A, 0x2C, + 0x19, 0x97, 0x80, 0x9A, 0x1C, 0x8A, 0x70, 0xA7, + 0xDA, 0xEB, 0xAE, 0x21, 0x81, 0x93, 0x63, 0xE9, + 0xDE, 0x12, 0xB2, 0xA6, 0xC3, 0x57, 0xD0, 0xD7, + + 0x04, 0xCD, 0xA5, 0x8D, 0x82, 0x25, 0xCC, 0xAE, + 0xDB, 0x8A, 0xBB, 0xCE, 0x96, 0x7D, 0x69, 0x62, + 0x5F, 0x34, 0x39, 0x4C, 0x82, 0xD3, 0xC6, 0x1E, + 0x27, 0x44, 0xDF, 0x66, 0xF0, 0x66, 0xF1, 0xA4, + 0x3E, 0xC8, 0x72, 0x58, 0x7C, 0x78, 0x50, 0x1B, + 0xAE, 0x6D, 0x22, 0x40, 0x27, 0x70, 0x6C, 0x12, + 0x1D, 0x44, 0x70, 0x1B, 0xC6, 0xD5, 0x76, 0x76, + 0xDD, 0xC4, 0x63, 0xE9, 0x17, 0xFF, 0xE4, 0x93, + 0x67, 0x24, 0xE0, 0x2C, 0x51, 0x3E, 0xCA, 0x62, + 0xC7, 0x0B, 0x47, 0x84, 0xDF, 0x98, 0x94, 0x85, + 0x40, 0xF0, 0xAA, 0xFC, 0x74, 0xCC, 0x15, 0x7E, + 0x9B, 0x14, 0x2D, 0x78, 0x38, 0x88, 0x12, 0x4D, + 0xB3, 0xE4, 0x64, 0xEB, 0x38, 0x3C, 0x0F, 0xC7, + 0x08, 0x26, 0x06, 0x9D, 0xD4, 0xCD, 0xCD, 0xCA, + 0x10, 0xA1, 0x9B, 0xCD, 0x03, 0x92, 0x75, 0x32, + 0xA5, 0x0F, 0xAA, 0xA4, 0xB0, 0xFE, 0x6B, 0xB3, + 0x47, 0xFD, 0x58, 0x9F, 0x69, 0x6D, 0xD5, 0x93, + 0xE7, 0x46, 0x92, 0xF5, 0x6B, 0xA7, 0x07, 0xBC, + 0x5E, 0xE1, 0x9D, 0x7D, 0xF6, 0xB5, 0x01, 0x64, + 0x6D, 0xDE, 0x24, 0x8F, 0xEF, 0x17, 0x4F, 0x74, + 0x3A, 0x13, 0x2B, 0x67, 0x05, 0x3C, 0x3B, 0xE2, + 0x17, 0x01, 0xD7, 0xAC, 0x2C, 0xD2, 0xEE, 0x89, + 0xE7, 0x50, 0xAB, 0x0B, 0x3A, 0x03, 0x6A, 0x05, + 0x2B, 0xAF, 0x7A, 0x71, 0x6D, 0x59, 0x13, 0x22, + 0xD4, 0x7F, 0xE0, 0xD4, 0xD5, 0xE6, 0x37, 0x4E, + 0x81, 0x04, 0xB1, 0x5C, 0xE4, 0x81, 0xE4, 0xE0, + 0x1D, 0x11, 0xF6, 0x3E, 0xE7, 0xB8, 0x7E, 0xDB, + 0xB3, 0x72, 0xE9, 0x63, 0x6B, 0xB7, 0xAA, 0x20, + 0x94, 0x14, 0x8E, 0x1C, 0x6D, 0xD3, 0xF4, 0xE6, + 0x3F, 0x14, 0xDD, 0x3F, 0xA3, 0x8A, 0x5B, 0xC3, + 0x0A, + + 0x10, 0x5A, 0xA3, 0x65, 0x9B, 0x9C, 0x5D, 0xBD, + 0x92, 0x5A, 0x84, 0x1B, 0x18, 0xA6, 0x4A, 0x43, + 0x69, 0xA2, 0xD2, 0x67, 0x8C, 0xC5, 0x90, 0xD6, + 0x33, 0xD7, 0xE5, 0x12, 0xEF, 0xCB, 0x68, 0x24, + 0xB9, 0x66, 0xF6, 0x69, 0xA5, 0x2D, 0x43, 0xDD, + 0xFC, 0x2C, 0x08, 0x3E, 0x71, 0xF3, 0x33, 0xF1, + 0xED, 0xBA, 0x0E, 0x8B, 0xE6, 0xF3, 0xA7, 0x90, + 0x61, 0xD9, 0x3B, 0xC6, 0xB6, 0x89, 0xEF, 0xE3, + 0x9C, 0x55, 0xCC, 0x92, 0xE0, 0xB7, 0xA8, 0xA2, + 0xBE, 0x6E, 0x3B, 0xF4, 0xC2, 0x47, 0x21, 0x0E, + 0x1B, 0xD8, 0x76, 0x19, 0x99, 0xCE, 0x97, 0x02, + 0x25, 0x37, 0x28, 0xC0, 0x8E, 0x13, 0x6E, 0xB7, + 0x1B, 0x6B, 0x7C, 0x40, 0x3E, 0x78, 0xD1, 0xD1, + 0x55, 0x84, 0xA7, 0x1E, 0x82, 0x5C, 0x5D, 0x8E, + 0x14, 0x2E, 0xF4, 0x5B, 0x76, 0xC7, 0xCB, 0x82, + 0x74, 0xB3, 0x6F, 0xF5, 0xFD, 0xDE, 0x74, 0xD5, + 0xBD, 0xFB, 0x37, 0xA9, 0x54, 0x90, 0x97, 0x08, + 0x5C, 0xA7, 0x13, 0x07, 0xC4, 0x8C, 0x0C, 0x51, + 0x5D, 0x22, 0x71, 0xFE, 0x25, 0x77, 0x13, 0x23, + 0x3C, 0x57, 0x04, 0xEC, 0xE5, 0xD4, 0x41, 0x4E, + 0xE7, 0xFA, 0x1B, 0x4A, 0x31, 0xE1, 0xC6, 0x35, + 0x99, 0x0D, 0x8B, 0xAC, 0x37, 0xAB, 0x38, 0x8C, + 0xEC, 0x59, 0x44, 0x8A, 0x5A, 0xD9, 0x7A, 0x99, + 0x95, 0x33, 0x7E, 0x65, 0xEF, 0x78, 0x63, 0xE2, + 0x6D, 0xFE, 0x7D, 0xAC, 0xA5, 0x05, 0x13, 0xB7, + 0x8E, 0xF2, 0x9B, 0x76, 0x7E, 0x6C, 0x54, 0x86, + 0xA2, 0xAA, 0x2F, 0x3B, 0x38, 0x46, 0x1D, 0x4E, + 0xDB, 0x36, 0x42, 0x88, 0x0D, 0x0C, 0x7B, 0xAF, + 0xAC, 0x58, 0x0B, 0x24, 0x99, 0xCB, 0x5E, 0x9D, + 0x6D, 0xDC, 0xE8, 0xE1, 0xDC, 0xD5, 0xC3, 0x31, + 0xBE, 0xD5, + + 0xB0, 0xD1, 0xFC, 0x60, 0x3A, 0x61, 0x99, 0x7C, + 0xDD, 0x25, 0x09, 0x27, 0x2F, 0x4F, 0xEA, 0x8D, + 0x71, 0x0C, 0xE3, 0x47, 0x8A, 0xBC, 0xB6, 0xBD, + 0x8B, 0x6E, 0xFC, 0x63, 0x4A, 0x49, 0x59, 0xA4, + 0x4D, 0x2C, 0x8B, 0xDB, 0x9C, 0xFA, 0x23, 0xAE, + 0xDF, 0xBA, 0x3A, 0x1A, 0x21, 0xED, 0x74, 0x3F, + 0x20, 0xC1, 0x66, 0xCF, 0xBB, 0x21, 0x96, 0x57, + 0xD4, 0x9A, 0xFF, 0xCD, 0xB6, 0x21, 0xE4, 0xA6, + 0xC1, 0x38, 0xDA, 0x54, 0x20, 0x9B, 0x21, 0xC9, + 0x22, 0x5D, 0x1E, 0xCD, 0x48, 0x8C, 0x85, 0xE2, + 0xCA, 0x4D, 0xE3, 0xE3, 0x82, 0x9F, 0x3A, 0xB9, + 0xC1, 0xB9, 0x01, 0x50, 0x1F, 0x13, 0xB0, 0xDF, + 0x12, 0x2D, 0x09, 0x85, 0xA2, 0xD7, 0x0D, 0x9D, + 0x01, 0x92, 0xC9, 0xEC, 0xE5, 0x50, 0x58, 0xF0, + 0xF8, 0x58, 0x7F, 0xD1, 0xCF, 0xFD, 0x77, 0xBD, + 0x73, 0x6B, 0x9B, 0x9D, 0x35, 0x25, 0x1D, 0x52, + 0x6B, 0xF0, 0x8E, 0x78, 0xF2, 0xCF, 0x52, 0x11, + 0x17, 0xF3, 0xB2, 0x20, 0x80, 0x22, 0x90, 0x7B, + 0xBD, 0x1B, 0x32, 0x1D, 0x17, 0xF8, 0xB0, 0xB0, + 0xBC, 0x82, 0xC1, 0x20, 0x8E, 0x79, 0x17, 0x18, + 0x6B, 0x8D, 0xD3, 0x57, 0xBE, 0xB6, 0xB0, 0x48, + 0x23, 0x5D, 0x70, 0x50, 0xA7, 0x2C, 0x55, 0xC4, + 0x39, 0x88, 0x5C, 0x7C, 0xA5, 0x74, 0x43, 0xA4, + 0x8E, 0x02, 0x4C, 0x8E, 0x7E, 0x05, 0x73, 0x6B, + 0x89, 0x44, 0xAA, 0x84, 0xF4, 0xD4, 0x0F, 0xB9, + 0xB1, 0x8B, 0x0D, 0xD5, 0x38, 0x32, 0xBD, 0x84, + 0x49, 0xB6, 0x3E, 0xD9, 0x65, 0xAB, 0x96, 0x2A, + 0x6A, 0x47, 0xD5, 0x0E, 0x21, 0x4F, 0xF7, 0xF9, + 0xE4, 0xE9, 0x46, 0xA1, 0x09, 0x7A, 0x7B, 0x0E, + 0x10, 0x3D, 0x3D, 0xE8, 0xB1, 0xBB, 0x07, 0x1A, + 0x54, 0xBA, 0xC2, + + 0x3C, 0xDD, 0x72, 0x30, 0xB1, 0xD2, 0x79, 0x40, + 0x8E, 0x03, 0x65, 0x7D, 0x82, 0x70, 0x77, 0xEB, + 0x77, 0x9B, 0x6C, 0x46, 0x20, 0x27, 0x40, 0xCF, + 0xAA, 0xF3, 0x2D, 0xBC, 0xF8, 0xE0, 0xA4, 0x04, + 0xAE, 0x72, 0xE7, 0x95, 0x38, 0xA2, 0xAA, 0x45, + 0x7F, 0xDB, 0x72, 0x58, 0x0C, 0x30, 0x70, 0x4E, + 0x8A, 0xE2, 0xDD, 0x2D, 0xA8, 0x03, 0x9A, 0xEB, + 0x99, 0x96, 0x8E, 0x9E, 0xC1, 0x65, 0x8C, 0xB9, + 0xD1, 0xE1, 0xED, 0xEC, 0x3C, 0x3F, 0xA8, 0xAB, + 0x54, 0x81, 0x2C, 0x16, 0x77, 0x3B, 0x6A, 0xB9, + 0x09, 0x51, 0xF0, 0x98, 0x38, 0xF3, 0x69, 0xC6, + 0x07, 0xB6, 0x98, 0x2C, 0x00, 0xDA, 0xFF, 0xD4, + 0x4B, 0x51, 0x00, 0xF4, 0xF4, 0xC6, 0x59, 0xFF, + 0x4D, 0x2F, 0xF0, 0x55, 0x91, 0x33, 0x58, 0xAC, + 0x0B, 0xA7, 0x43, 0x4B, 0x11, 0xDA, 0x6F, 0x3A, + 0x7A, 0xF1, 0xE5, 0xE4, 0x58, 0xB0, 0xA3, 0x5D, + 0x89, 0xDD, 0x6B, 0x84, 0x28, 0x04, 0x1E, 0x0B, + 0xD5, 0x3F, 0x5E, 0x87, 0x47, 0xE5, 0xCC, 0xCC, + 0xF8, 0x46, 0xD0, 0x41, 0xD4, 0x89, 0xC6, 0x31, + 0x4B, 0x9B, 0xF6, 0x64, 0xCB, 0xDE, 0x11, 0x36, + 0x7F, 0x1C, 0xC4, 0x4A, 0x10, 0xA0, 0xF0, 0xE2, + 0xA8, 0x9D, 0x80, 0x22, 0xAF, 0xFA, 0x1D, 0xCB, + 0x99, 0x08, 0x56, 0x12, 0x0C, 0xE8, 0x23, 0xF9, + 0x13, 0x68, 0x7C, 0x89, 0x5A, 0xAC, 0x00, 0x25, + 0x0A, 0xEF, 0xDD, 0xF1, 0xF4, 0xDC, 0xC1, 0x92, + 0x71, 0x12, 0xF2, 0xBF, 0x7F, 0xA9, 0x30, 0x5C, + 0x75, 0x43, 0x4F, 0x19, 0x7C, 0xD6, 0x39, 0xF2, + 0xDC, 0xAB, 0xE7, 0x36, 0x75, 0x26, 0x2C, 0xC5, + 0x4D, 0xBF, 0xD0, 0x4A, 0x20, 0x26, 0x50, 0x9A, + 0x31, 0x41, 0x29, 0xD0, 0x73, 0x53, 0x7A, 0x81, + 0xF4, 0x5D, 0xDB, 0x8E, + + 0x21, 0x55, 0x95, 0x56, 0x2A, 0xFA, 0x88, 0x2E, + 0xC9, 0x9B, 0x1E, 0xE9, 0xA4, 0x4C, 0x1A, 0xC7, + 0xFB, 0xF6, 0xA5, 0xE8, 0x5A, 0xFB, 0xF6, 0x53, + 0x4C, 0xCD, 0x0F, 0xE7, 0x0A, 0x97, 0x73, 0x95, + 0x7C, 0x0E, 0x11, 0x82, 0x07, 0x8F, 0x77, 0x2B, + 0xDE, 0x4D, 0x95, 0xDB, 0x27, 0x6D, 0x70, 0x89, + 0xC8, 0x5C, 0x1B, 0xC8, 0xEE, 0xEE, 0x8E, 0x75, + 0xDB, 0x1B, 0x5E, 0xF2, 0x1D, 0x6D, 0xD8, 0x8C, + 0x81, 0x3B, 0x58, 0x71, 0xBA, 0x12, 0x70, 0x12, + 0x6E, 0x8D, 0x13, 0x2E, 0x4B, 0x4A, 0x81, 0x93, + 0xA9, 0xAD, 0xA6, 0xB2, 0xB2, 0x4D, 0xE2, 0x26, + 0x2E, 0xC7, 0x31, 0xD1, 0xFB, 0x02, 0xAB, 0xE9, + 0x76, 0xBF, 0x84, 0xEF, 0xE2, 0x02, 0xDA, 0xDE, + 0x93, 0x08, 0x3F, 0x02, 0x37, 0x04, 0xC3, 0x37, + 0xB0, 0x5B, 0x7F, 0x04, 0x37, 0xC0, 0xA3, 0x67, + 0x3F, 0xFA, 0x31, 0x43, 0x10, 0x27, 0xA1, 0x36, + 0x3D, 0x56, 0xF9, 0x70, 0xDF, 0x6B, 0x51, 0x61, + 0x76, 0xD2, 0x22, 0xCC, 0x19, 0x66, 0x30, 0x63, + 0xBC, 0x25, 0x7A, 0x7E, 0x8B, 0x7B, 0x9D, 0xD7, + 0x49, 0x99, 0x67, 0x8C, 0x19, 0x2F, 0x51, 0x0F, + 0x01, 0xD7, 0x35, 0xF0, 0xA2, 0x20, 0x38, 0x03, + 0x9F, 0xCB, 0x42, 0x65, 0xC3, 0x6A, 0x0E, 0xA8, + 0xF6, 0x4F, 0xBF, 0x73, 0x3A, 0x1A, 0xDF, 0x48, + 0x03, 0x72, 0xF5, 0xB9, 0x94, 0x56, 0xD4, 0x46, + 0x93, 0xDD, 0x6B, 0xB3, 0xF9, 0x6B, 0xDF, 0xEC, + 0x88, 0x34, 0x6D, 0x39, 0x51, 0xEE, 0xFD, 0xA6, + 0x4B, 0xC7, 0x2B, 0xAE, 0xC6, 0x2A, 0x14, 0x15, + 0xDF, 0xB3, 0x7E, 0x02, 0x1C, 0x8D, 0xA8, 0xD4, + 0xDB, 0x19, 0xCF, 0x19, 0xEA, 0x8A, 0x14, 0xBC, + 0x67, 0xB1, 0x62, 0x35, 0x69, 0x84, 0x21, 0x08, + 0xF8, 0x5D, 0x44, 0x10, 0xD9, + + 0x0E, 0xE7, 0x88, 0x5B, 0x12, 0x67, 0xA8, 0x08, + 0x53, 0xD1, 0x65, 0x84, 0xE8, 0x9C, 0x12, 0xE3, + 0xBA, 0x44, 0x83, 0xA1, 0x1E, 0x73, 0xDE, 0x63, + 0x6C, 0xCC, 0xF7, 0xA4, 0x6B, 0xD0, 0x6B, 0xBF, + 0x3D, 0xAE, 0x4D, 0xF2, 0xB7, 0xF7, 0xC4, 0x30, + 0x2F, 0xB0, 0xEE, 0x09, 0x10, 0x20, 0xE1, 0x77, + 0x7B, 0xD4, 0xD1, 0x6B, 0x7F, 0x88, 0xA6, 0xE6, + 0x51, 0xD5, 0x4E, 0x9F, 0xFD, 0xFB, 0x1F, 0x4A, + 0x7C, 0xA7, 0x99, 0x32, 0x3F, 0x7C, 0xEA, 0xD9, + 0x36, 0xD4, 0x2C, 0xE1, 0xE0, 0x84, 0x2E, 0xFE, + 0x2A, 0x57, 0xA5, 0x56, 0xBD, 0xD3, 0x16, 0x8F, + 0x5A, 0x5A, 0x02, 0x20, 0xF1, 0x1B, 0xF0, 0x96, + 0x22, 0xBF, 0x1B, 0x24, 0xA4, 0xD2, 0x5A, 0x35, + 0x9E, 0xBA, 0x71, 0xB4, 0x5D, 0x13, 0x19, 0x8D, + 0x64, 0x4C, 0x5B, 0x22, 0xAA, 0x0E, 0x87, 0x1E, + 0xF6, 0x62, 0x8A, 0x94, 0xA6, 0x36, 0x03, 0xEA, + 0x6F, 0xB4, 0xFC, 0xA5, 0xC9, 0x98, 0x73, 0x54, + 0x38, 0x97, 0x6D, 0xC8, 0x08, 0x01, 0xCA, 0xD8, + 0x88, 0xE7, 0xAA, 0x9E, 0xCE, 0x3B, 0xA7, 0xBA, + 0x69, 0x50, 0xAB, 0x78, 0x9C, 0x83, 0x20, 0x23, + 0x31, 0x1C, 0xCC, 0x01, 0x52, 0xDF, 0x6F, 0xC2, + 0x56, 0x09, 0x57, 0xFF, 0xDE, 0x27, 0xD4, 0x17, + 0x4E, 0x6B, 0xD5, 0x60, 0x3A, 0x9F, 0xC8, 0xA4, + 0x1A, 0xAB, 0x82, 0x9A, 0x05, 0x15, 0xC8, 0x66, + 0x89, 0x40, 0x2A, 0x90, 0xF8, 0xEB, 0xD1, 0x2F, + 0x6E, 0x68, 0x13, 0xAD, 0x66, 0x39, 0x6C, 0xB1, + 0x7C, 0xEE, 0x33, 0xB7, 0xA6, 0x88, 0x69, 0xE1, + 0x32, 0x34, 0xA4, 0x87, 0xB1, 0x0C, 0xF3, 0x59, + 0xBE, 0x88, 0x72, 0x77, 0x76, 0x61, 0x45, 0x6F, + 0xF7, 0x75, 0x12, 0xB6, 0x03, 0x17, 0xE9, 0x2E, + 0x15, 0x93, 0xDA, 0xA9, 0xAE, 0x12, + + 0x4E, 0xB8, 0x67, 0xB1, 0x3C, 0x12, 0xCD, 0x1E, + 0x2D, 0xA3, 0x9C, 0xE5, 0xA6, 0x4A, 0x08, 0x0E, + 0x0D, 0x1C, 0x9B, 0xE7, 0xE5, 0x6D, 0x0A, 0x75, + 0xE0, 0xE4, 0x33, 0x3B, 0x43, 0x3D, 0x2C, 0x39, + 0x96, 0x43, 0x8F, 0xF6, 0xA4, 0xAA, 0x5E, 0x32, + 0xFE, 0x00, 0xCD, 0xD6, 0x9D, 0x75, 0x6F, 0x3A, + 0x20, 0x4E, 0x05, 0xB5, 0x7C, 0xE8, 0xDA, 0xE1, + 0x32, 0x10, 0xC0, 0x85, 0x8D, 0x34, 0x35, 0x12, + 0x41, 0x50, 0xBF, 0x58, 0xB8, 0xFF, 0x4E, 0x6B, + 0x04, 0x40, 0x76, 0xAD, 0xCC, 0x31, 0xDB, 0xF4, + 0x12, 0x7F, 0x30, 0x4E, 0x28, 0x28, 0x73, 0x67, + 0xED, 0x35, 0x38, 0x18, 0xD9, 0x9D, 0xEA, 0x68, + 0xFA, 0x65, 0x28, 0x7B, 0x99, 0x3A, 0x89, 0x7D, + 0x52, 0xE1, 0x59, 0x4C, 0x68, 0xC9, 0xDA, 0xFC, + 0x3D, 0x39, 0xE0, 0x81, 0xDB, 0x22, 0xBD, 0xBF, + 0xF3, 0xDA, 0x45, 0x1D, 0x3A, 0x8D, 0xF3, 0x97, + 0x9E, 0xDA, 0x2A, 0xD5, 0x4E, 0x2C, 0x23, 0x74, + 0x3A, 0xC9, 0x73, 0x4D, 0x24, 0x7E, 0x1A, 0x9B, + 0xF9, 0xD7, 0x21, 0x4D, 0x9A, 0x28, 0x21, 0x44, + 0xD4, 0xE8, 0x93, 0xC5, 0x4F, 0x9A, 0xF9, 0x66, + 0x09, 0xA5, 0x46, 0x31, 0x59, 0xB3, 0xCC, 0xF3, + 0xD4, 0x58, 0x9E, 0x8E, 0xB5, 0x35, 0x47, 0x5C, + 0x23, 0xC9, 0xFC, 0xE8, 0x64, 0x5D, 0x47, 0x6C, + 0x43, 0xAC, 0x47, 0x30, 0xAE, 0x40, 0x7A, 0x9E, + 0x1F, 0xF9, 0x74, 0x55, 0x10, 0x6F, 0x2A, 0xEB, + 0x50, 0x63, 0x51, 0xDD, 0x8E, 0x38, 0x6F, 0x27, + 0x1F, 0x21, 0x3C, 0xDC, 0x65, 0x63, 0xE4, 0xE8, + 0xD8, 0x63, 0x20, 0x67, 0x96, 0x22, 0xFD, 0xC3, + 0xA0, 0xDB, 0x90, 0x64, 0x56, 0xE6, 0xB0, 0xFE, + 0xB3, 0x7C, 0x74, 0x2C, 0x01, 0xD5, 0xCC, 0xD4, + 0x3C, 0x1B, 0xBA, 0x79, 0x68, 0x33, 0x7C, + + 0x3E, 0x82, 0xD7, 0x53, 0xF6, 0x16, 0xE3, 0x10, + 0x01, 0x36, 0xA8, 0xEF, 0x33, 0xCA, 0x26, 0xC9, + 0x21, 0xBF, 0xCA, 0x3B, 0x7D, 0x89, 0xC2, 0x59, + 0x1D, 0x57, 0x2B, 0x02, 0x05, 0xEA, 0x49, 0x99, + 0x31, 0x95, 0xFF, 0x0A, 0x45, 0x56, 0x1D, 0xB9, + 0xD3, 0x01, 0x44, 0xC4, 0x8C, 0x88, 0xAD, 0xC9, + 0x83, 0x6A, 0x35, 0x83, 0x81, 0xBC, 0x59, 0x0A, + 0xB0, 0x2A, 0x82, 0xE5, 0x89, 0x54, 0xA0, 0xAC, + 0x69, 0x1A, 0x63, 0x5B, 0x2C, 0x8A, 0x61, 0xAE, + 0x72, 0xD9, 0xDB, 0xF0, 0x6C, 0xAA, 0x8F, 0x61, + 0x46, 0x0C, 0x0A, 0x5D, 0xE6, 0x15, 0x92, 0x65, + 0x83, 0xCF, 0x80, 0xB6, 0x78, 0x9E, 0x87, 0x9B, + 0x13, 0xD5, 0x94, 0xD2, 0x1E, 0x7A, 0x28, 0x8B, + 0x14, 0x76, 0x0C, 0x7E, 0x41, 0xAE, 0x5B, 0x36, + 0x40, 0xD9, 0x30, 0x31, 0xFD, 0x73, 0x81, 0xCC, + 0x83, 0x22, 0x03, 0xFF, 0xB6, 0xCC, 0xFA, 0xD7, + 0x3A, 0x1C, 0xB4, 0xA8, 0x48, 0x47, 0xD9, 0xA9, + 0x54, 0xCE, 0x26, 0x92, 0x84, 0x19, 0x6D, 0x57, + 0x1B, 0x24, 0x3B, 0x5F, 0xBD, 0xBB, 0x7F, 0x18, + 0x97, 0xE2, 0x79, 0x81, 0x7B, 0x19, 0xB6, 0x9C, + 0x4F, 0xE6, 0xD5, 0x01, 0x8B, 0x41, 0xE5, 0x21, + 0x18, 0x76, 0x2A, 0x16, 0xC2, 0xEF, 0x20, 0xAC, + 0xB0, 0x0E, 0x58, 0x8C, 0x6D, 0xE7, 0x02, 0x35, + 0x15, 0x94, 0xDB, 0xC6, 0x58, 0xE3, 0xF0, 0x0F, + 0xBF, 0x6A, 0x63, 0xE0, 0x4A, 0x51, 0x32, 0x90, + 0x40, 0x84, 0xB6, 0x05, 0x92, 0xB1, 0x6B, 0xF8, + 0xCD, 0xCD, 0x7F, 0xF1, 0x43, 0x72, 0xBB, 0x8B, + 0x1E, 0xAF, 0xE5, 0x78, 0x75, 0x72, 0xE5, 0x72, + 0x14, 0x2D, 0x5B, 0x83, 0xD2, 0x40, 0x55, 0xFC, + 0x8C, 0x9B, 0xFB, 0xAE, 0xCC, 0x51, 0xBE, 0x56, + 0x9D, 0x4C, 0xC1, 0xFC, 0xF1, 0xC3, 0xC3, 0xAD, + + 0xA9, 0x2F, 0xB7, 0xB1, 0x24, 0x2E, 0xD1, 0x6E, + 0xAF, 0x5B, 0xC5, 0xF2, 0xF8, 0x5E, 0x43, 0x83, + 0xB4, 0x3D, 0x57, 0xD6, 0x16, 0x8D, 0x56, 0x31, + 0xE5, 0xEB, 0x44, 0x01, 0x9F, 0xCA, 0x6E, 0x77, + 0xC2, 0xAC, 0xAD, 0x84, 0x1E, 0x4B, 0x38, 0xCC, + 0x48, 0x36, 0xD6, 0x8E, 0xCA, 0xAD, 0x67, 0x3E, + 0x20, 0xD2, 0x3A, 0x84, 0xA2, 0x79, 0x60, 0xBD, + 0xA2, 0x1B, 0x7E, 0x41, 0x57, 0x2D, 0x52, 0x41, + 0x41, 0x1C, 0x32, 0x5F, 0xE4, 0x1B, 0x21, 0x55, + 0xA9, 0xAE, 0xFE, 0xB1, 0x80, 0xB2, 0x85, 0x0E, + 0x5A, 0xA8, 0x06, 0x4C, 0x73, 0x96, 0xC7, 0xDF, + 0x39, 0x6D, 0x5A, 0x69, 0x7F, 0x3C, 0xC1, 0x71, + 0xEF, 0xEC, 0x84, 0x23, 0x5F, 0x92, 0xD9, 0x07, + 0x2D, 0x73, 0x4A, 0xAB, 0x55, 0x46, 0xE8, 0xCC, + 0x46, 0x2C, 0x09, 0x7B, 0x65, 0xD7, 0xCF, 0x1A, + 0x3B, 0x27, 0xD3, 0x8C, 0x3B, 0x8A, 0xDC, 0xDB, + 0x36, 0x95, 0x06, 0x8D, 0x5B, 0x44, 0xBA, 0xBF, + 0x7E, 0x50, 0xAF, 0xC3, 0x63, 0x66, 0xB9, 0xD3, + 0xB0, 0xC4, 0x2C, 0x03, 0xBF, 0x7E, 0x70, 0xCF, + 0x93, 0xEB, 0x3D, 0xDC, 0x74, 0x16, 0x49, 0x0A, + 0x02, 0x98, 0x4F, 0x81, 0x6C, 0x29, 0x53, 0x39, + 0x25, 0xBA, 0xD4, 0x59, 0xF2, 0xB9, 0x92, 0xE6, + 0x83, 0x41, 0xE2, 0x7B, 0xE1, 0x6E, 0xA0, 0x8F, + 0xC4, 0xE8, 0x35, 0x76, 0x5A, 0x3A, 0xA4, 0x35, + 0x83, 0x85, 0x77, 0xA9, 0x63, 0x00, 0xA1, 0x29, + 0xD5, 0x43, 0x05, 0x59, 0xA3, 0x52, 0x3E, 0xE4, + 0xDA, 0xC1, 0x72, 0x36, 0x8F, 0x5E, 0xA0, 0x8B, + 0x88, 0x3D, 0xE9, 0x19, 0x11, 0x89, 0x3F, 0x0E, + 0xF1, 0x04, 0xA9, 0x4C, 0x87, 0xFF, 0x08, 0x89, + 0xF9, 0x13, 0xEB, 0xE7, 0x28, 0x41, 0x0B, 0x58, + 0xA4, 0xA9, 0x19, 0xC7, 0x4F, 0x34, 0xFD, 0x54, + 0x0A, + + 0x79, 0x14, 0x36, 0xA5, 0x6B, 0x3F, 0x22, 0xFA, + 0x12, 0x4B, 0x4F, 0xC4, 0x97, 0xD7, 0xC7, 0x61, + 0x94, 0x53, 0x53, 0xD3, 0xF5, 0x07, 0x64, 0x7D, + 0xE0, 0x11, 0x63, 0xC5, 0xE7, 0x4A, 0x88, 0xEC, + 0x6C, 0x0D, 0xA5, 0x05, 0x13, 0xE4, 0xC6, 0x94, + 0x3D, 0xEE, 0x87, 0xB1, 0x77, 0xCE, 0xB6, 0x7E, + 0xC9, 0x99, 0xB5, 0xAA, 0xB2, 0xC8, 0x0F, 0x5F, + 0xE9, 0x92, 0x9F, 0x1E, 0x49, 0x6D, 0xC8, 0xD7, + 0x6D, 0x1E, 0xD7, 0x63, 0x6D, 0xDD, 0x64, 0xCB, + 0xFF, 0x45, 0xB0, 0xF6, 0x89, 0xC5, 0xF3, 0xFB, + 0x82, 0xB9, 0x5B, 0xF1, 0x42, 0x4A, 0x8C, 0x9E, + 0xCD, 0x9D, 0xEF, 0x9D, 0x36, 0x79, 0x04, 0x7D, + 0x16, 0x6D, 0xC6, 0x66, 0xAA, 0xFE, 0x1D, 0xAB, + 0x4D, 0xDF, 0xF8, 0xE8, 0xC3, 0x12, 0xB3, 0xAD, + 0x49, 0xD1, 0x85, 0x7D, 0x2C, 0x76, 0xD9, 0x66, + 0x85, 0xA0, 0x81, 0x29, 0x2B, 0x13, 0x47, 0x1E, + 0x98, 0x77, 0x79, 0x3F, 0x23, 0xD2, 0xFC, 0xA5, + 0xA5, 0x64, 0xDF, 0xBB, 0x3E, 0xA8, 0x85, 0x98, + 0xB1, 0x34, 0x2B, 0xB7, 0xA0, 0xD1, 0x7A, 0x47, + 0x42, 0xFE, 0x98, 0x80, 0xBB, 0x21, 0x19, 0x4F, + 0xE0, 0x58, 0x2D, 0xD9, 0xE2, 0x0F, 0x46, 0x13, + 0xC7, 0x4A, 0x11, 0xDD, 0x49, 0xEC, 0x32, 0x0C, + 0x1C, 0x3C, 0x96, 0x75, 0x3C, 0xB4, 0x73, 0x07, + 0x3E, 0xBC, 0xA4, 0xB8, 0x17, 0x05, 0x38, 0x92, + 0x6B, 0x56, 0xF3, 0x28, 0xE3, 0x71, 0x73, 0x2A, + 0x30, 0x4C, 0xF5, 0xCF, 0x2A, 0xC5, 0x1B, 0x24, + 0x4E, 0xA0, 0x2C, 0x9A, 0xCA, 0x98, 0x8C, 0xCA, + 0x16, 0xD3, 0xA6, 0x77, 0xC7, 0x83, 0x3C, 0x25, + 0x96, 0x0D, 0x15, 0xBE, 0x33, 0x7E, 0xCA, 0x3A, + 0xC0, 0x37, 0x7C, 0x91, 0x04, 0xF0, 0x4D, 0x8D, + 0xAE, 0xBF, 0x6B, 0x99, 0x57, 0x63, 0x90, 0x10, + 0x41, 0xF1, + + 0x83, 0xD6, 0xF5, 0x41, 0x9F, 0x3B, 0x2C, 0x9B, + 0xAB, 0xAF, 0x1B, 0xAE, 0x69, 0xB4, 0xAA, 0x5B, + 0xF9, 0x5F, 0x0F, 0xC7, 0xD4, 0x7F, 0x90, 0xAF, + 0xB2, 0xBA, 0xAB, 0x86, 0x92, 0x8E, 0x66, 0x46, + 0xD5, 0x73, 0x08, 0xB7, 0x3E, 0x46, 0x86, 0xC0, + 0x1C, 0x72, 0xB1, 0xDF, 0x7A, 0x3A, 0xC4, 0xEF, + 0x85, 0x36, 0x21, 0x3C, 0x29, 0xB9, 0x68, 0xFD, + 0x48, 0xBD, 0x1A, 0x5C, 0x83, 0xA3, 0x02, 0xFD, + 0x67, 0xBF, 0xC3, 0xD1, 0x68, 0xE1, 0xB8, 0x91, + 0x57, 0xA5, 0x7B, 0xE8, 0x4B, 0x82, 0x7C, 0x76, + 0xEB, 0x1C, 0x38, 0x4C, 0x1E, 0x54, 0xE8, 0x66, + 0x47, 0x47, 0x8A, 0x41, 0xD7, 0x38, 0xCC, 0x8E, + 0xD8, 0x58, 0x20, 0x26, 0x79, 0x7B, 0x5A, 0xCF, + 0xD0, 0x0E, 0x6C, 0xE4, 0x91, 0x01, 0xE4, 0x95, + 0xF8, 0x6D, 0x7F, 0xFD, 0x38, 0x04, 0x41, 0x23, + 0x72, 0xC7, 0x32, 0xD9, 0x65, 0x4F, 0xCF, 0x3D, + 0xE8, 0xA3, 0xA7, 0x9C, 0xEF, 0x05, 0xDE, 0x12, + 0x70, 0x96, 0x04, 0x2C, 0x75, 0x06, 0xBE, 0xEC, + 0xA0, 0x37, 0x43, 0xF7, 0x39, 0x7E, 0x90, 0x39, + 0xAB, 0xFF, 0x97, 0x27, 0x05, 0xBC, 0x9D, 0xB9, + 0xDB, 0x8C, 0xFB, 0x10, 0x55, 0xC1, 0x63, 0xAA, + 0x59, 0xD3, 0x09, 0xC7, 0x49, 0xDB, 0x18, 0x2B, + 0x4A, 0xAE, 0x2B, 0x0E, 0xE0, 0x45, 0x3E, 0x96, + 0xF8, 0x82, 0x0F, 0xC4, 0xB7, 0x17, 0x3A, 0x0B, + 0x1D, 0x43, 0x81, 0x33, 0xA5, 0xDD, 0x26, 0x12, + 0xBF, 0xD9, 0x56, 0x13, 0xD8, 0xBB, 0xBE, 0xA8, + 0xAE, 0xCE, 0xF0, 0x99, 0x95, 0x66, 0xA0, 0xB5, + 0xD1, 0x94, 0xA3, 0xF8, 0x42, 0x3F, 0x3B, 0x0F, + 0x56, 0x9A, 0xBF, 0xAE, 0xEE, 0xC1, 0xA8, 0x25, + 0xFA, 0xF5, 0x0D, 0xAE, 0x4F, 0x40, 0x2B, 0xB2, + 0xEF, 0xB1, 0x61, 0xCF, 0x41, 0x6D, 0x96, 0x4D, + 0x8E, 0x0B, 0xFE, + + 0x24, 0xE7, 0xE5, 0x6C, 0xA2, 0x9D, 0xFB, 0xD1, + 0x90, 0xAA, 0xF0, 0xE7, 0xA6, 0x08, 0x5C, 0x80, + 0x69, 0xEE, 0x83, 0xE9, 0x8B, 0x70, 0x0B, 0x97, + 0xFB, 0xF0, 0xE5, 0x43, 0x81, 0x6D, 0xDC, 0xE9, + 0x4C, 0x14, 0xFA, 0xEA, 0x1F, 0x39, 0x31, 0x2A, + 0x60, 0x87, 0x10, 0x95, 0x19, 0x3A, 0x97, 0x09, + 0xF6, 0x7A, 0xDF, 0xF1, 0xAE, 0xB5, 0x43, 0x0D, + 0x6C, 0x1E, 0x2C, 0xC9, 0x2A, 0xF3, 0x76, 0xDA, + 0x6A, 0xEB, 0xE4, 0x92, 0x74, 0x82, 0xF1, 0x4C, + 0x64, 0x28, 0x01, 0xB0, 0xE1, 0xDF, 0x9A, 0x6B, + 0x89, 0x02, 0xE0, 0x43, 0xC6, 0x77, 0x18, 0xE8, + 0xC4, 0xC9, 0x98, 0xF2, 0x8F, 0xE0, 0xB4, 0x38, + 0x50, 0x81, 0xC7, 0xF4, 0x3F, 0xE2, 0xD9, 0xCB, + 0x5E, 0xE9, 0x5B, 0xC5, 0x98, 0xD2, 0xEB, 0xC6, + 0x13, 0x3E, 0xC1, 0x13, 0xFD, 0x54, 0x48, 0xA0, + 0x09, 0x64, 0x71, 0xE5, 0xCA, 0xC0, 0x75, 0x2D, + 0xF7, 0x89, 0x5B, 0x00, 0x05, 0xE1, 0x4B, 0xA8, + 0xDA, 0x12, 0x6A, 0x4E, 0xCE, 0xAB, 0x3A, 0xDF, + 0x4A, 0x90, 0xF4, 0xCA, 0x6C, 0x40, 0x00, 0xF9, + 0x9F, 0x92, 0xF7, 0x94, 0x53, 0x77, 0x55, 0x7F, + 0xA8, 0xA5, 0xBC, 0xC2, 0xC2, 0x45, 0xBB, 0x07, + 0x13, 0x4D, 0x9E, 0x0D, 0xCF, 0x49, 0xF1, 0x5A, + 0x69, 0xDF, 0x2D, 0x53, 0x54, 0xB7, 0x7A, 0xD4, + 0x2F, 0x1B, 0x99, 0x78, 0x84, 0x81, 0x04, 0xC4, + 0x5C, 0x26, 0x35, 0x01, 0xED, 0x75, 0xBC, 0x54, + 0x71, 0xA3, 0x96, 0x9E, 0xD4, 0x41, 0xCB, 0x05, + 0xB3, 0x08, 0x98, 0xAD, 0x93, 0x15, 0xF7, 0xC2, + 0xF4, 0xCB, 0xE6, 0xB7, 0xEB, 0x3F, 0xF7, 0x62, + 0x45, 0x40, 0xE3, 0x97, 0x58, 0xC4, 0x49, 0xED, + 0xBA, 0x92, 0xA3, 0x94, 0x1F, 0xCD, 0x66, 0x9C, + 0xA6, 0x85, 0x1F, 0xBF, 0xA1, 0xAA, 0x03, 0x1B, + 0xB2, 0x70, 0x9D, 0xE3, + + 0x0B, 0x45, 0xA1, 0x98, 0x47, 0xD8, 0xB2, 0x5D, + 0x41, 0xA7, 0x35, 0xE4, 0x41, 0x4B, 0x45, 0x6A, + 0x9A, 0x91, 0xA5, 0x66, 0xDA, 0x63, 0xE7, 0xB8, + 0x4E, 0x88, 0x0A, 0x80, 0x2E, 0xEC, 0x08, 0x74, + 0x8E, 0xEB, 0xDA, 0xC4, 0x6D, 0xB5, 0xDA, 0x27, + 0xEC, 0x67, 0xAC, 0x7D, 0x63, 0x7A, 0xF4, 0x9B, + 0xB6, 0x43, 0xE5, 0x87, 0xA7, 0x52, 0x34, 0xFD, + 0x15, 0x99, 0xC7, 0x13, 0x3E, 0xC6, 0x4F, 0x38, + 0xA3, 0x8B, 0xD1, 0xB4, 0x5E, 0x0E, 0xC0, 0xA8, + 0x9B, 0x34, 0x47, 0xC3, 0x61, 0x82, 0x0D, 0xBF, + 0x78, 0x2F, 0x90, 0x7B, 0x07, 0x5A, 0x2B, 0xA2, + 0xB6, 0x9D, 0xB0, 0x15, 0x0A, 0x32, 0xA1, 0x70, + 0x4E, 0x8D, 0x98, 0xC4, 0xB7, 0xE0, 0xD0, 0xBE, + 0x1D, 0xB4, 0xA3, 0xC9, 0x6A, 0xA4, 0xE6, 0x4F, + 0x12, 0xC2, 0x35, 0xD7, 0xA6, 0x69, 0x67, 0x18, + 0x2C, 0xB0, 0xCF, 0x39, 0x78, 0xDB, 0xB7, 0x66, + 0x50, 0xFD, 0xB7, 0x3F, 0x77, 0x7F, 0x4E, 0x3C, + 0xF8, 0xBD, 0xC5, 0xD2, 0xCA, 0xCB, 0xCB, 0x10, + 0x94, 0x9F, 0x3E, 0xA0, 0x5B, 0xBA, 0x74, 0xB9, + 0x84, 0xFE, 0xB1, 0x91, 0x93, 0x5D, 0x8B, 0x23, + 0x86, 0x8F, 0xCB, 0xF0, 0x0E, 0x27, 0xA8, 0x6A, + 0x57, 0xF3, 0x7A, 0xEE, 0x94, 0x5F, 0x29, 0x3F, + 0xF8, 0xD3, 0xD1, 0x30, 0xCD, 0x8B, 0x31, 0xFC, + 0x6E, 0xC6, 0x31, 0xB7, 0x76, 0x26, 0x12, 0x7A, + 0xB9, 0xB0, 0x29, 0x4D, 0xAF, 0x10, 0xFC, 0xCC, + 0xD1, 0xD6, 0x9C, 0x19, 0x81, 0x15, 0xC4, 0x19, + 0xDD, 0x5D, 0x56, 0x65, 0x6C, 0xE0, 0x39, 0x25, + 0x5C, 0xE5, 0xE2, 0x6E, 0x5D, 0x48, 0x44, 0xF8, + 0x53, 0x4A, 0x36, 0x48, 0xDB, 0x0D, 0x89, 0xF7, + 0x1B, 0xF5, 0xD0, 0x8E, 0xA2, 0xD8, 0xD7, 0x9E, + 0xCE, 0x35, 0xA0, 0x10, 0xE5, 0xBC, 0x22, 0xF9, + 0xC3, 0x35, 0xEC, 0x35, 0x6C, + + 0x59, 0x77, 0x61, 0xB9, 0xD2, 0xA0, 0x7C, 0xD6, + 0x95, 0x93, 0x17, 0x1B, 0x25, 0x09, 0x47, 0xF1, + 0x1B, 0x73, 0x28, 0xA8, 0xA1, 0xF6, 0x0F, 0x7F, + 0x4B, 0x86, 0xED, 0xC5, 0xBD, 0x15, 0x92, 0x75, + 0x23, 0x3E, 0x38, 0x30, 0xE0, 0x64, 0x80, 0x7B, + 0x10, 0xD5, 0x54, 0x08, 0x6E, 0x3D, 0x78, 0xFE, + 0x40, 0x0C, 0xFD, 0x86, 0xC1, 0xD1, 0xD4, 0xE7, + 0xF0, 0xD2, 0xFF, 0x52, 0xA4, 0x8F, 0xA8, 0x0A, + 0x9C, 0x6E, 0x49, 0x70, 0xC6, 0x7D, 0x7C, 0xDD, + 0xCE, 0x75, 0x09, 0xE3, 0xBF, 0x5A, 0x4A, 0x30, + 0xFD, 0xC0, 0x2B, 0x8F, 0x23, 0x39, 0x6B, 0x41, + 0x17, 0x51, 0x1F, 0x16, 0xAC, 0x33, 0x69, 0x42, + 0xD2, 0xE2, 0x32, 0x91, 0x81, 0xCB, 0x7C, 0x04, + 0xC8, 0xD9, 0x77, 0x1A, 0x59, 0xC7, 0x37, 0x5C, + 0x5B, 0xC3, 0x9F, 0x22, 0xE5, 0xDA, 0xD8, 0x59, + 0x3C, 0x01, 0xE6, 0xCC, 0x46, 0x5C, 0x90, 0xE0, + 0x3F, 0x4D, 0x77, 0xAD, 0x96, 0x2A, 0x5D, 0x37, + 0x0F, 0x59, 0x10, 0xF0, 0x23, 0xF0, 0xA9, 0x75, + 0xED, 0xDE, 0xFB, 0x74, 0x06, 0x2B, 0xBF, 0x20, + 0xED, 0xEA, 0xCD, 0x49, 0x8A, 0x41, 0x09, 0x6C, + 0x0F, 0x0E, 0x79, 0xF7, 0x61, 0x18, 0xBF, 0x77, + 0x09, 0xB9, 0x05, 0xEF, 0x89, 0xEE, 0x79, 0xD9, + 0x20, 0xAF, 0xE3, 0x3F, 0x0E, 0xCE, 0x3E, 0x94, + 0x0C, 0x3B, 0xC1, 0xA0, 0x88, 0xA8, 0x8D, 0xDB, + 0x4D, 0x70, 0xC6, 0x19, 0x2A, 0xCE, 0xE1, 0x9D, + 0x9E, 0x60, 0xBD, 0x93, 0x2D, 0xF1, 0xC6, 0x50, + 0x1B, 0xA7, 0x21, 0x7B, 0x11, 0x86, 0xCD, 0xF9, + 0x17, 0xAE, 0x4B, 0x88, 0x7B, 0xAF, 0xD1, 0xCA, + 0x80, 0xF7, 0xA1, 0x7F, 0x0A, 0x4D, 0xF8, 0x35, + 0x6E, 0xB1, 0x61, 0xEC, 0xAB, 0xD7, 0x60, 0x2D, + 0xB8, 0xB7, 0x59, 0x77, 0x90, 0xED, 0xC5, 0x24, + 0xCA, 0x02, 0xF2, 0x35, 0xD8, 0xB4, + + 0xE5, 0x07, 0x55, 0x53, 0x6C, 0x5E, 0xD2, 0x9F, + 0xE4, 0x23, 0xA5, 0x58, 0x45, 0x18, 0x2B, 0x0B, + 0x17, 0x00, 0xE8, 0xD7, 0x89, 0x06, 0xE6, 0x75, + 0x56, 0x25, 0xC0, 0x92, 0x79, 0xCD, 0xA2, 0xC0, + 0xBD, 0x8E, 0x52, 0x0D, 0xF3, 0xA2, 0xA1, 0x66, + 0x0F, 0x94, 0x23, 0xE7, 0x2D, 0x14, 0xB6, 0x82, + 0xB0, 0x9A, 0xE1, 0xE8, 0xF3, 0x15, 0x92, 0xFB, + 0xDE, 0x8D, 0xA2, 0x1A, 0xB3, 0xB2, 0xF7, 0xC0, + 0xAB, 0xA9, 0x79, 0x70, 0xBE, 0xE8, 0x14, 0x65, + 0x79, 0x10, 0x1C, 0x7C, 0x29, 0x2C, 0x16, 0x33, + 0xBB, 0xEF, 0x91, 0x5A, 0xC0, 0xA5, 0x7D, 0x97, + 0x79, 0x42, 0xB9, 0xA3, 0x7E, 0x9E, 0x87, 0xBB, + 0xDC, 0x65, 0x12, 0xDC, 0xD9, 0x2D, 0x73, 0x8A, + 0x73, 0x38, 0xF1, 0xA5, 0x60, 0x7E, 0xD1, 0xF3, + 0x97, 0xAB, 0xCF, 0xFF, 0x5C, 0x5E, 0xE1, 0xAC, + 0x1A, 0x41, 0xC2, 0x6D, 0xB1, 0x24, 0xAF, 0x19, + 0x55, 0x61, 0x4D, 0xDA, 0xD4, 0xE7, 0x10, 0x78, + 0x14, 0x2B, 0xA4, 0x88, 0x9D, 0x2F, 0x96, 0xF8, + 0x03, 0xF6, 0xB5, 0x13, 0x2B, 0xEA, 0x52, 0x24, + 0xB2, 0xA1, 0x46, 0xEC, 0x57, 0x59, 0x19, 0x17, + 0x83, 0x05, 0x20, 0x44, 0x4C, 0xEC, 0xC7, 0xE0, + 0xB1, 0x84, 0x00, 0x62, 0xE5, 0xE5, 0xAA, 0x0B, + 0xE6, 0x0E, 0x44, 0x5D, 0x55, 0x1D, 0x15, 0xDC, + 0xCE, 0x53, 0x2C, 0xF9, 0x7B, 0xDE, 0x95, 0x05, + 0xAF, 0x88, 0x59, 0xF1, 0xC2, 0x59, 0x3A, 0xFC, + 0x2E, 0x43, 0x37, 0x2F, 0xB8, 0x83, 0xD5, 0x42, + 0xE3, 0xA2, 0xFC, 0xA1, 0x62, 0xC6, 0x99, 0x9C, + 0x4C, 0x7A, 0x72, 0xD6, 0xF5, 0xF8, 0x3E, 0xE1, + 0xD0, 0x21, 0xE1, 0x74, 0x69, 0xB4, 0xE5, 0xB5, + 0x26, 0x2C, 0x37, 0x73, 0x90, 0xD3, 0x1D, 0x5B, + 0x08, 0xF4, 0x64, 0xE4, 0x9F, 0xA1, 0x95, 0xAE, + 0xCA, 0xB5, 0x6A, 0xD4, 0x50, 0x12, 0xDC, + + 0xED, 0xE8, 0x53, 0x43, 0xCA, 0x1B, 0xB7, 0x40, + 0x82, 0x4A, 0x01, 0x55, 0xD6, 0x0F, 0x9F, 0xFE, + 0x2F, 0x1B, 0x94, 0x9F, 0x49, 0xFA, 0x86, 0x45, + 0x3C, 0x63, 0x14, 0x2E, 0xAF, 0x66, 0x78, 0x97, + 0xA3, 0x40, 0x11, 0x32, 0x52, 0x3F, 0x22, 0x26, + 0xCA, 0xCC, 0x61, 0x3F, 0x31, 0x5E, 0x67, 0x5D, + 0x71, 0x7D, 0x5F, 0x69, 0xBF, 0xDC, 0x93, 0x1E, + 0xA8, 0x5F, 0xA2, 0x56, 0x91, 0xEC, 0xCE, 0x61, + 0x67, 0xF3, 0xDC, 0xE8, 0xF4, 0xF7, 0x46, 0xE9, + 0xE3, 0xB8, 0x21, 0x2A, 0x6E, 0xB9, 0xDD, 0x69, + 0x14, 0xFF, 0x1C, 0xC1, 0xF4, 0x27, 0x6B, 0x6E, + 0x2D, 0xC0, 0x75, 0x56, 0xF9, 0x75, 0x21, 0x3D, + 0x39, 0xE0, 0x67, 0x3C, 0xCC, 0x4D, 0x95, 0xDD, + 0xFE, 0x99, 0x1C, 0x77, 0xA6, 0xF2, 0x62, 0x23, + 0x79, 0x49, 0xAB, 0x65, 0x34, 0x2F, 0x71, 0x6F, + 0xCD, 0xA3, 0xBF, 0xF3, 0xAE, 0x08, 0xF8, 0xF3, + 0x18, 0x67, 0x51, 0x33, 0xD7, 0x3B, 0xF1, 0xD0, + 0x37, 0xA9, 0x07, 0x52, 0x77, 0xF0, 0x75, 0x0C, + 0xC6, 0x4A, 0xDC, 0x6B, 0x4C, 0xBF, 0x80, 0xEC, + 0x42, 0x89, 0x19, 0x22, 0xE1, 0x90, 0x2F, 0xC9, + 0x5E, 0x5D, 0xC8, 0xCF, 0xD3, 0x9F, 0x37, 0xAF, + 0x60, 0xAE, 0x34, 0x5F, 0xD8, 0x3F, 0xA9, 0x55, + 0x0E, 0x5C, 0xC9, 0xA8, 0xA2, 0x0E, 0xE3, 0xC2, + 0xAC, 0x9E, 0x87, 0x38, 0xBB, 0x53, 0x86, 0x82, + 0xDF, 0x05, 0xE4, 0x23, 0xF3, 0x77, 0xDA, 0x7A, + 0x1E, 0x9C, 0x88, 0x53, 0xB9, 0x14, 0x56, 0x49, + 0x2F, 0x6A, 0xE8, 0x3A, 0xF1, 0x5C, 0x72, 0xAF, + 0x2A, 0x19, 0x0A, 0xBB, 0x2B, 0xFD, 0x91, 0x59, + 0x43, 0x12, 0x9C, 0xC3, 0x0B, 0x7A, 0x7F, 0x85, + 0x1C, 0x98, 0x34, 0xF6, 0xDE, 0x59, 0x3F, 0x7C, + 0x49, 0x37, 0x75, 0x6B, 0xC1, 0xE1, 0xD7, 0x70, + 0xB9, 0xFB, 0xCA, 0xD8, 0x41, 0x6B, 0x8C, 0x01, + + 0xB9, 0xC3, 0x0F, 0x35, 0xEB, 0x2F, 0x12, 0x4E, + 0xE4, 0x78, 0x2D, 0x24, 0x77, 0xA4, 0x89, 0x1F, + 0x64, 0xAD, 0xE7, 0x2B, 0x49, 0xE0, 0xDC, 0x05, + 0x7D, 0x6C, 0xEC, 0x4E, 0x9E, 0xAE, 0x2E, 0xDF, + 0xE6, 0xF2, 0x3F, 0xC6, 0xD5, 0xAA, 0xFC, 0x23, + 0xAB, 0xCB, 0x96, 0x49, 0xC4, 0xEB, 0xAF, 0x18, + 0x14, 0x27, 0xFB, 0xE7, 0x1C, 0x34, 0xF7, 0x22, + 0x69, 0xA3, 0xD2, 0xFD, 0x9E, 0x9F, 0x29, 0xA9, + 0x50, 0x34, 0x3C, 0x4F, 0xDD, 0xE5, 0xAB, 0xE6, + 0xAC, 0x99, 0x80, 0x50, 0x7A, 0x4F, 0x79, 0xD2, + 0xC2, 0xC6, 0x31, 0x8F, 0xF6, 0xD6, 0xAA, 0x57, + 0x00, 0xA2, 0x4B, 0x61, 0xBA, 0xD6, 0x28, 0xD3, + 0xFA, 0x93, 0xE4, 0x65, 0x53, 0x81, 0xD3, 0x01, + 0xF1, 0xDA, 0x7A, 0x12, 0x85, 0x17, 0x5A, 0x7E, + 0x35, 0x21, 0x6C, 0xF0, 0x18, 0x34, 0xA4, 0xF4, + 0xDD, 0x24, 0xEB, 0x86, 0xDC, 0xD0, 0xF7, 0xAB, + 0x41, 0xB5, 0x59, 0x3F, 0x22, 0x7B, 0xCF, 0xDB, + 0x61, 0x4D, 0x61, 0x58, 0x55, 0xA5, 0x23, 0xCE, + 0x69, 0x2D, 0x5C, 0x24, 0x73, 0xA2, 0x80, 0x3F, + 0x67, 0xB7, 0x66, 0xD8, 0x30, 0x87, 0xFE, 0x74, + 0x23, 0x35, 0xFD, 0xD8, 0xA7, 0xD4, 0xAC, 0x02, + 0x40, 0xF6, 0xCA, 0x9B, 0xB3, 0xB4, 0x73, 0xEA, + 0x67, 0x39, 0xB4, 0x1B, 0xB4, 0x45, 0xFB, 0xB2, + 0xF9, 0xDB, 0x8E, 0x90, 0x29, 0x62, 0x9D, 0x9D, + 0x73, 0x30, 0x6C, 0x51, 0x56, 0xA6, 0x9B, 0x9A, + 0xE9, 0x33, 0xCA, 0xC8, 0xED, 0xE4, 0x58, 0x91, + 0x82, 0x17, 0x10, 0x0F, 0x2D, 0xF7, 0x82, 0xCD, + 0x25, 0x61, 0x45, 0xCD, 0xDD, 0x66, 0xF1, 0x8A, + 0xDC, 0x08, 0xF8, 0x53, 0xF6, 0x07, 0x8E, 0x3A, + 0x6F, 0x0B, 0xF0, 0x9D, 0x8F, 0xFE, 0xDD, 0xCF, + 0x94, 0xDD, 0xB2, 0x1F, 0x1A, 0xFF, 0x08, 0x22, + 0x3D, 0xEE, 0x45, 0x6B, 0xD2, 0x5A, 0xF3, 0x15, + 0x93, + + 0xCC, 0x0E, 0xCA, 0xDF, 0xEF, 0xC6, 0xC6, 0x35, + 0x66, 0x95, 0xFF, 0xCE, 0x3F, 0x13, 0x97, 0xEA, + 0xEC, 0xB9, 0xEB, 0x1F, 0x82, 0x4E, 0x6A, 0xFF, + 0xB0, 0x0A, 0x75, 0xAB, 0xBC, 0x6B, 0xF1, 0xC4, + 0xEE, 0xB8, 0x8C, 0xAE, 0x52, 0xED, 0x7C, 0x9E, + 0xF3, 0xE2, 0x74, 0xAD, 0x95, 0x65, 0x8F, 0x2D, + 0x1A, 0x93, 0xF5, 0x35, 0x5D, 0x5E, 0x7F, 0x5A, + 0x22, 0x9F, 0x48, 0x81, 0x25, 0xDE, 0xB1, 0xC3, + 0x0A, 0xD6, 0x7E, 0x9E, 0x77, 0xF0, 0x1F, 0x77, + 0xE0, 0x85, 0xBB, 0xFA, 0xC5, 0x87, 0xC7, 0x17, + 0x0A, 0x7B, 0x3D, 0x85, 0xD4, 0xA9, 0xCA, 0x98, + 0xCC, 0x08, 0xD5, 0x40, 0x58, 0x6A, 0x0D, 0xFE, + 0xBC, 0x4D, 0xBE, 0x46, 0x9E, 0xC0, 0x84, 0xF4, + 0x63, 0xE7, 0xEA, 0xFD, 0x7B, 0x73, 0x1D, 0xDB, + 0xE2, 0xD7, 0x51, 0x6D, 0xB2, 0x4F, 0x79, 0x37, + 0x9E, 0x37, 0x39, 0xE9, 0xD7, 0xCB, 0x7F, 0x56, + 0x5E, 0x68, 0xCC, 0x73, 0x7B, 0xBA, 0x3D, 0x76, + 0x0A, 0x41, 0x0B, 0x83, 0xC5, 0xAA, 0xCF, 0x7E, + 0xDA, 0x40, 0xB6, 0xCB, 0xC1, 0x76, 0xE5, 0x21, + 0xC3, 0xC8, 0xDB, 0x01, 0x2A, 0x87, 0xFF, 0x9E, + 0xC7, 0x58, 0xD5, 0xC8, 0x22, 0x37, 0x3F, 0x1F, + 0x49, 0xF0, 0x9F, 0x7C, 0x60, 0x91, 0x8C, 0xC5, + 0x51, 0xE3, 0x5F, 0x7A, 0x98, 0x0B, 0x3E, 0xE1, + 0xAA, 0xC8, 0xE4, 0x3C, 0xC5, 0x98, 0xC0, 0xE5, + 0x00, 0x5C, 0xEB, 0x57, 0xAF, 0xF2, 0x67, 0x30, + 0x11, 0xB0, 0xD8, 0x82, 0x8A, 0x5A, 0x97, 0xC8, + 0xFC, 0x09, 0xD7, 0x74, 0x98, 0xC9, 0x8D, 0xB5, + 0x1A, 0x96, 0x79, 0x47, 0xDE, 0x9B, 0x7C, 0xF3, + 0x86, 0x80, 0x87, 0x2C, 0x2F, 0xC6, 0xA6, 0x17, + 0x85, 0xF3, 0xD1, 0xEE, 0x33, 0x68, 0x7A, 0xCC, + 0x54, 0x4A, 0x08, 0x18, 0x8F, 0x20, 0x08, 0x33, + 0x43, 0x25, 0x05, 0x9B, 0x21, 0xB2, 0x49, 0xA5, + 0x33, 0xC0, + + 0x62, 0xD2, 0x23, 0x2D, 0x6D, 0xC4, 0x02, 0x15, + 0x9C, 0xC7, 0x37, 0x08, 0xEA, 0x73, 0x56, 0xB4, + 0x77, 0xEE, 0x14, 0xEC, 0x2B, 0x86, 0x51, 0xA0, + 0x63, 0x54, 0x00, 0xD4, 0xDE, 0x91, 0xE9, 0x94, + 0x3F, 0x32, 0xE6, 0x44, 0x49, 0xF7, 0xBD, 0x4C, + 0xFA, 0x07, 0xFB, 0xCB, 0x86, 0xFC, 0xBA, 0x1B, + 0x66, 0x52, 0xE3, 0x2C, 0x52, 0x5C, 0x07, 0xD7, + 0xFF, 0x08, 0x93, 0x73, 0x30, 0x4E, 0xB8, 0x97, + 0x8E, 0xB5, 0xEB, 0x24, 0xF7, 0x26, 0xB5, 0x21, + 0xEA, 0x1A, 0x62, 0x1B, 0xAC, 0x12, 0x83, 0xB1, + 0xB2, 0xAB, 0x1C, 0x1C, 0x69, 0x7D, 0x5C, 0x9D, + 0x4E, 0x20, 0x13, 0x52, 0x6B, 0x88, 0xB6, 0xBE, + 0x0E, 0x8D, 0x23, 0xD4, 0x14, 0xF5, 0x99, 0xEB, + 0x2E, 0xC8, 0x4D, 0x38, 0x57, 0x47, 0x70, 0x18, + 0x65, 0xB5, 0xB8, 0xB4, 0x29, 0x99, 0xA2, 0x4B, + 0xAA, 0x5A, 0xEC, 0x8B, 0xCA, 0x9F, 0xE9, 0x6D, + 0x8B, 0x0D, 0xEC, 0x0A, 0xCB, 0xD8, 0xF7, 0x0C, + 0x7B, 0x22, 0xB0, 0xE8, 0x3C, 0x4F, 0x0C, 0xEC, + 0x7E, 0x2D, 0x8F, 0x93, 0x2C, 0xC0, 0xA8, 0x40, + 0x48, 0xAA, 0xAF, 0x83, 0x08, 0xBF, 0xBF, 0x5C, + 0xBE, 0xB8, 0xAD, 0xC0, 0xCC, 0xDC, 0x7D, 0x00, + 0x2B, 0x2B, 0xC7, 0x74, 0xB0, 0x77, 0x95, 0x5F, + 0xE9, 0xA1, 0x65, 0x45, 0xB0, 0xBB, 0xEF, 0xD8, + 0xFA, 0x1D, 0x1F, 0x66, 0xEF, 0x3B, 0x68, 0x7B, + 0x67, 0x9F, 0xFF, 0xA4, 0xB5, 0x24, 0x69, 0xAB, + 0x84, 0xE3, 0x75, 0x69, 0x56, 0x72, 0x19, 0x0D, + 0x47, 0xA3, 0xF8, 0xAE, 0xA1, 0x4E, 0xB0, 0x4C, + 0xAA, 0x0F, 0xF9, 0x08, 0xEA, 0x8F, 0x69, 0xFC, + 0x60, 0xF4, 0x91, 0xFF, 0x08, 0xD5, 0xD4, 0xB4, + 0xD2, 0x4B, 0xBD, 0x4E, 0x3F, 0x53, 0x34, 0x06, + 0x4A, 0x26, 0x57, 0x0F, 0xF2, 0xDE, 0x9D, 0x02, + 0xA4, 0xE0, 0x0D, 0xD7, 0x2C, 0x5F, 0x5F, 0x05, + 0x4F, 0x60, 0x38, + + 0x0D, 0xEC, 0xE4, 0x86, 0xF5, 0x6D, 0xC1, 0x52, + 0x88, 0x55, 0xB9, 0x1D, 0x2D, 0xD7, 0x0A, 0xB4, + 0x5C, 0xB2, 0xDE, 0xF6, 0xBD, 0x91, 0x5D, 0x8D, + 0x0D, 0xB0, 0xD8, 0x54, 0x56, 0x62, 0xF1, 0x94, + 0xB5, 0xEE, 0x73, 0x23, 0xF2, 0x25, 0xF5, 0x7E, + 0x6A, 0xBF, 0x8A, 0xAA, 0x1C, 0x66, 0xCB, 0xA0, + 0xD6, 0xB2, 0xFC, 0x94, 0x6E, 0x26, 0x49, 0xF8, + 0xDE, 0xC0, 0xD8, 0x04, 0x93, 0x80, 0x16, 0x52, + 0xA6, 0xDE, 0x3F, 0x87, 0x4E, 0x2F, 0x93, 0xBD, + 0xAA, 0x8D, 0xA8, 0x86, 0x27, 0xAC, 0x6D, 0xA0, + 0x13, 0x81, 0xF6, 0xE7, 0x7D, 0xBC, 0xF1, 0x09, + 0x38, 0x09, 0x93, 0xC5, 0x94, 0x84, 0x0F, 0x4E, + 0x28, 0xCA, 0x29, 0x4D, 0xED, 0xDC, 0x91, 0xDC, + 0xEC, 0x16, 0xF7, 0x86, 0x4C, 0x0B, 0x2C, 0xDA, + 0xCE, 0x2B, 0x1B, 0xB4, 0xFC, 0x6F, 0xA5, 0x7C, + 0xE2, 0xC0, 0xAD, 0xC7, 0xA7, 0xE1, 0x28, 0x03, + 0xD5, 0xB3, 0x30, 0x51, 0xA2, 0x24, 0x2F, 0x9E, + 0x16, 0x48, 0x54, 0x6B, 0x36, 0x60, 0x22, 0x58, + 0x00, 0xFF, 0x40, 0x59, 0x17, 0x36, 0x1C, 0x2C, + 0x58, 0x0F, 0xC0, 0x5D, 0x41, 0x47, 0x7F, 0xE3, + 0xB1, 0x5F, 0x0A, 0x88, 0xBC, 0xBA, 0x83, 0xBF, + 0x3D, 0x0B, 0xDF, 0xFC, 0xD3, 0x55, 0xDF, 0x72, + 0x0D, 0x8A, 0xAF, 0x4D, 0xF4, 0x0C, 0x0F, 0x8C, + 0xE9, 0xEE, 0xA5, 0xA7, 0xFF, 0x87, 0x81, 0x2E, + 0x38, 0x04, 0x76, 0xAE, 0xA2, 0xE6, 0x84, 0x73, + 0xFF, 0xEC, 0xEE, 0xA3, 0x40, 0xA8, 0x67, 0x8C, + 0xD6, 0x68, 0x70, 0xA0, 0x6B, 0x3F, 0x0D, 0x45, + 0xE0, 0xA0, 0x29, 0x38, 0xF8, 0xD5, 0x58, 0x59, + 0xBD, 0x9B, 0x2B, 0xD3, 0x8B, 0x45, 0x3D, 0xDB, + 0x79, 0x0F, 0x25, 0xE7, 0xF9, 0xC7, 0x30, 0xC8, + 0x92, 0xC1, 0x99, 0xBE, 0xEC, 0xAF, 0x68, 0xDF, + 0x9F, 0xEC, 0x4C, 0x8C, 0xD8, 0x7A, 0xEF, 0x07, + 0x6E, 0x14, 0xF4, 0x41, + + 0x93, 0x45, 0x33, 0x61, 0xF0, 0xF2, 0x27, 0x76, + 0x4C, 0x53, 0x60, 0xAE, 0x83, 0xB0, 0x90, 0x70, + 0xDB, 0xAE, 0x2F, 0x1A, 0xCF, 0xF2, 0xC6, 0x50, + 0x36, 0x1B, 0x2E, 0x75, 0xF2, 0x4F, 0x1B, 0x9B, + 0x81, 0x2F, 0x49, 0x96, 0xED, 0x05, 0x69, 0x07, + 0x0C, 0x6B, 0x5A, 0x35, 0x11, 0x6B, 0x29, 0xC6, + 0x07, 0xF5, 0x68, 0xAF, 0x26, 0xE1, 0xEB, 0x71, + 0x53, 0x4A, 0xC0, 0x5A, 0x1B, 0xDD, 0x49, 0x28, + 0x90, 0xE3, 0xDB, 0x1F, 0x86, 0xB1, 0xAB, 0x4A, + 0x64, 0x39, 0x8F, 0x83, 0xA7, 0x37, 0x1B, 0xC9, + 0xB6, 0xEA, 0x5E, 0xA8, 0x25, 0x87, 0x78, 0x52, + 0xA0, 0xE5, 0xA3, 0x26, 0x74, 0x66, 0xCC, 0x0A, + 0x92, 0x7D, 0x9B, 0x4B, 0xAD, 0x79, 0x7F, 0x87, + 0x9E, 0x0A, 0xF9, 0xDE, 0xB0, 0x31, 0x2B, 0xDC, + 0xC8, 0x29, 0xD0, 0xAC, 0x3C, 0xD8, 0x60, 0x19, + 0xA5, 0xF6, 0x50, 0xC1, 0xBA, 0x0F, 0xE4, 0x4A, + 0x07, 0xE8, 0xA5, 0xB7, 0x6C, 0x88, 0xF1, 0xBE, + 0xAF, 0x2F, 0x40, 0x9B, 0xB3, 0x98, 0x28, 0x43, + 0x25, 0xBB, 0x23, 0x1C, 0xF3, 0x98, 0x19, 0x9E, + 0x9E, 0x3D, 0xC0, 0xFF, 0x05, 0xA8, 0x35, 0xCD, + 0x47, 0xB7, 0xB3, 0xEF, 0xC9, 0x38, 0x36, 0xE7, + 0xF9, 0x6F, 0x5B, 0x6E, 0x79, 0xCB, 0x08, 0x49, + 0x6F, 0x4C, 0x17, 0xC2, 0x91, 0x7E, 0x8B, 0x86, + 0x57, 0x30, 0x8F, 0x92, 0x94, 0x34, 0x10, 0x1B, + 0xE5, 0x8F, 0xCC, 0xAF, 0xD0, 0x87, 0xDA, 0x9A, + 0xF2, 0x09, 0x99, 0x6C, 0x8E, 0x50, 0x91, 0x7D, + 0x7C, 0x4D, 0x3E, 0x24, 0xFF, 0xD4, 0xC1, 0xAA, + 0xA7, 0x80, 0x89, 0xB5, 0x8E, 0x50, 0x7D, 0x49, + 0xD4, 0xA0, 0xA1, 0xFD, 0x34, 0xCA, 0xB8, 0xCB, + 0x64, 0x76, 0x07, 0x91, 0x39, 0x7D, 0xAE, 0xE2, + 0xD9, 0x5A, 0xCB, 0xB7, 0xAD, 0x9E, 0x8C, 0xE8, + 0x0A, 0xE8, 0xE9, 0xCC, 0x49, 0x97, 0xC3, 0xE9, + 0x96, 0x1A, 0xCE, 0xFF, 0x16, + + 0x3D, 0x76, 0xF1, 0x1D, 0x88, 0x56, 0x8E, 0x23, + 0x96, 0xE0, 0x55, 0xE9, 0xF3, 0x36, 0xCE, 0xEA, + 0x3C, 0x72, 0x34, 0x12, 0xA4, 0x19, 0x29, 0x74, + 0x26, 0xCA, 0xF9, 0xDB, 0xA4, 0x2F, 0x2E, 0xBD, + 0xD1, 0x64, 0x97, 0xE2, 0x7E, 0x30, 0x59, 0xDB, + 0xBB, 0x7D, 0x42, 0xD2, 0xC1, 0x84, 0x18, 0x1F, + 0x67, 0x61, 0x5D, 0x40, 0xE5, 0xD8, 0x83, 0x36, + 0x98, 0xAB, 0x2F, 0xE8, 0x24, 0x13, 0xC7, 0x61, + 0x0A, 0x71, 0x59, 0x9E, 0x51, 0xE1, 0xBB, 0xCE, + 0xEA, 0xE7, 0xFC, 0x7E, 0x92, 0xE0, 0x1F, 0xA5, + 0xE3, 0x89, 0x80, 0xBC, 0xA8, 0xCB, 0xDB, 0xFD, + 0x49, 0x8D, 0x7F, 0x01, 0x15, 0xA5, 0x35, 0x89, + 0x46, 0xB5, 0xBC, 0x8E, 0x96, 0x80, 0x11, 0xCA, + 0x6C, 0x56, 0x94, 0x1C, 0x0C, 0xEC, 0x56, 0x78, + 0xC9, 0x7E, 0x4A, 0x44, 0xE7, 0xDF, 0x03, 0xA9, + 0x32, 0xF5, 0xA2, 0x4C, 0x80, 0xBB, 0x31, 0x9E, + 0x00, 0x5D, 0xCD, 0xB2, 0x33, 0x41, 0xCA, 0xA4, + 0x8A, 0xB3, 0x52, 0x59, 0xD9, 0x19, 0xD4, 0x98, + 0x78, 0xFE, 0xB1, 0x02, 0x6D, 0x52, 0x6F, 0x23, + 0xC8, 0xF7, 0xA8, 0xC2, 0xB4, 0x90, 0x69, 0x68, + 0x5A, 0xA5, 0xDB, 0x26, 0x93, 0xF0, 0x78, 0x25, + 0xC3, 0x94, 0x1F, 0x0A, 0x0B, 0x0F, 0xA8, 0xC2, + 0xCB, 0x7B, 0x0D, 0xC9, 0x53, 0x1D, 0x5A, 0xB4, + 0x30, 0xF2, 0xDD, 0x15, 0x8D, 0xDE, 0x49, 0x82, + 0x94, 0x9B, 0x6E, 0x2D, 0x2D, 0xD7, 0x21, 0x38, + 0x98, 0x61, 0xEB, 0xF3, 0xDE, 0xB1, 0xCE, 0x54, + 0xB9, 0x7F, 0x9C, 0x4B, 0xF0, 0x8B, 0xD1, 0xBF, + 0x6A, 0xA4, 0x57, 0x28, 0x86, 0xE2, 0xB2, 0x74, + 0x31, 0x51, 0x9E, 0x30, 0xF5, 0x98, 0x3E, 0x9D, + 0x98, 0x21, 0x7C, 0xAD, 0x68, 0x44, 0x91, 0x5C, + 0x11, 0x5A, 0x42, 0x0C, 0x84, 0x69, 0x62, 0xD0, + 0x98, 0x3D, 0x89, 0x4D, 0xBC, 0x65, 0x38, 0x03, + 0x44, 0x76, 0xFF, 0x20, 0x3D, 0x28, + + 0xD4, 0xAE, 0xDA, 0xA8, 0x24, 0x19, 0x06, 0xFB, + 0xE9, 0xAD, 0x9F, 0x3C, 0x1D, 0xD6, 0x92, 0x5E, + 0x83, 0x58, 0x54, 0xBB, 0xCB, 0x7D, 0x8E, 0x24, + 0x0F, 0x0A, 0x43, 0xF5, 0x6D, 0x89, 0x99, 0x4A, + 0xB7, 0xDF, 0x8A, 0x84, 0x00, 0x1A, 0xF5, 0x6E, + 0x1C, 0xC2, 0xFA, 0x20, 0xE7, 0xC2, 0x41, 0x60, + 0x7C, 0xCE, 0x90, 0x8E, 0x16, 0x64, 0x94, 0xDA, + 0xE2, 0x3A, 0x8D, 0xDF, 0x21, 0x61, 0x17, 0x3C, + 0x72, 0xE3, 0x66, 0x35, 0x0B, 0xF6, 0x30, 0x5C, + 0x82, 0x5C, 0x48, 0xA1, 0xE8, 0x21, 0x9C, 0x92, + 0xA1, 0x0F, 0xBF, 0x89, 0xC8, 0x7A, 0xEE, 0x18, + 0x87, 0x5B, 0x51, 0xF3, 0xF7, 0x0A, 0xA3, 0xB4, + 0x2E, 0xDA, 0x4E, 0xAA, 0xAD, 0x6E, 0x70, 0x04, + 0xF8, 0x47, 0x1E, 0x5F, 0x43, 0x69, 0x0B, 0x26, + 0x4C, 0xBC, 0xDB, 0x46, 0x77, 0x87, 0xA1, 0x9A, + 0x04, 0xEF, 0x74, 0x99, 0xEA, 0x29, 0x71, 0x55, + 0x9C, 0x2E, 0x47, 0xE3, 0x4A, 0x15, 0xA4, 0xF6, + 0xED, 0x5D, 0xBE, 0x4F, 0x94, 0x3F, 0xFD, 0xD3, + 0x6E, 0x0E, 0xD9, 0x26, 0x68, 0x9F, 0xC2, 0x8C, + 0xA5, 0xA8, 0xF0, 0xFB, 0x53, 0x5F, 0x18, 0xCA, + 0xDB, 0xBD, 0x98, 0x96, 0x28, 0xFC, 0xE9, 0x2E, + 0x81, 0xE1, 0x0E, 0x3A, 0x77, 0x18, 0x25, 0x9D, + 0xB7, 0x67, 0x8C, 0x35, 0x68, 0x4A, 0x88, 0x18, + 0x45, 0x6C, 0xE5, 0xCC, 0x22, 0xD2, 0x77, 0x9A, + 0x68, 0x0E, 0xC5, 0xA6, 0x1D, 0xAD, 0xDB, 0xB5, + 0xFF, 0xEA, 0x7C, 0x7D, 0x19, 0x1B, 0x9D, 0xB9, + 0xD0, 0xA7, 0xAB, 0x4D, 0x4A, 0x7D, 0x1A, 0xA5, + 0x09, 0x54, 0x84, 0x5C, 0x14, 0x4E, 0xA6, 0x14, + 0x6B, 0x22, 0x46, 0x7E, 0x5E, 0xB9, 0x33, 0x97, + 0xB5, 0x63, 0x5C, 0xCE, 0xF4, 0xD0, 0xD8, 0x8C, + 0xCC, 0xE7, 0x67, 0x01, 0x1B, 0x56, 0x68, 0x54, + 0x56, 0x4C, 0x19, 0x1D, 0x05, 0xF8, 0x55, 0xD6, + 0x45, 0xC0, 0xAD, 0xD6, 0xEE, 0xD9, 0x03, + + 0x7F, 0x07, 0xFA, 0x8C, 0x77, 0xF1, 0xDA, 0x4E, + 0x4B, 0x65, 0x55, 0xA4, 0x12, 0xE8, 0x7F, 0x04, + 0x0A, 0xEC, 0x57, 0xFF, 0x30, 0xD1, 0xE2, 0x08, + 0x71, 0xEC, 0x5F, 0x72, 0x88, 0x37, 0xC1, 0x33, + 0x79, 0xC8, 0x49, 0x47, 0x11, 0xC9, 0x8C, 0xD3, + 0x3B, 0x4F, 0x2C, 0x5A, 0xDD, 0x8C, 0x00, 0x8B, + 0xF6, 0xC4, 0x07, 0x7E, 0x2C, 0xFA, 0x3A, 0xBF, + 0x84, 0xBA, 0x13, 0x31, 0x20, 0x69, 0xAF, 0xBD, + 0x61, 0xB0, 0xFF, 0x28, 0x40, 0x1B, 0x5F, 0x1D, + 0x87, 0x99, 0x23, 0x95, 0x77, 0x88, 0x3F, 0xBB, + 0xFA, 0x55, 0xB5, 0xB2, 0xF7, 0xF3, 0xA6, 0x0B, + 0x57, 0x71, 0xF5, 0x7A, 0xE7, 0x23, 0x61, 0x54, + 0x13, 0xCB, 0x71, 0x97, 0xDE, 0xFF, 0x0E, 0x23, + 0x5C, 0xD4, 0xCC, 0xB1, 0xB8, 0x2F, 0xA1, 0xA5, + 0x15, 0xEB, 0xB4, 0x47, 0xA7, 0x7C, 0xEA, 0xD1, + 0x23, 0xE7, 0xFE, 0x9D, 0x56, 0xC5, 0x73, 0x9D, + 0xE8, 0x90, 0x4E, 0x00, 0xE5, 0x7F, 0x6E, 0x36, + 0x6D, 0xEA, 0x8C, 0xBA, 0xC6, 0x9C, 0xA0, 0x27, + 0x13, 0x90, 0x35, 0xE7, 0xD5, 0x27, 0x56, 0x50, + 0x70, 0x64, 0x03, 0xD2, 0x43, 0xDC, 0x1F, 0x60, + 0x4B, 0x5D, 0x48, 0xF1, 0x82, 0xE6, 0x9A, 0xDE, + 0xC7, 0xDB, 0x2F, 0x0D, 0xD9, 0xF4, 0xAD, 0xD0, + 0xB9, 0xDC, 0x01, 0x09, 0x74, 0x4F, 0x29, 0x71, + 0x61, 0x6D, 0xE2, 0xAC, 0xE3, 0x60, 0x9C, 0x4D, + 0x9A, 0x26, 0xC9, 0x3D, 0x11, 0x04, 0x83, 0x9F, + 0x39, 0x39, 0x0E, 0x44, 0xB2, 0xD3, 0x7A, 0x0D, + 0xD7, 0x0B, 0xDB, 0x14, 0x4A, 0x46, 0xA7, 0xB5, + 0x34, 0x2C, 0x22, 0x98, 0xBA, 0x6A, 0xBA, 0x4A, + 0xDA, 0x30, 0x8C, 0xE7, 0xDF, 0xD8, 0x73, 0x83, + 0x8C, 0xB6, 0x7A, 0x73, 0x74, 0xE5, 0x04, 0x32, + 0x66, 0x24, 0xC9, 0x45, 0xDA, 0x86, 0xE2, 0xCD, + 0xF9, 0xDB, 0x2F, 0x1D, 0xBA, 0x2C, 0xC0, 0x91, + 0x06, 0xF7, 0x44, 0xE8, 0x30, 0x34, 0x94, 0x91, + + 0xD5, 0x3B, 0xA6, 0x5A, 0x56, 0xB4, 0xDD, 0xBC, + 0xD8, 0xE7, 0x85, 0x2B, 0x3E, 0xFC, 0xBC, 0xD1, + 0xB9, 0x68, 0x09, 0xC3, 0xA5, 0xC1, 0x1D, 0x5C, + 0x4C, 0x11, 0xAC, 0x4A, 0xA3, 0x96, 0xAB, 0xD2, + 0xFD, 0x33, 0xD7, 0x69, 0xD1, 0x95, 0x50, 0xE6, + 0x4D, 0x3A, 0xE9, 0x9D, 0x67, 0x68, 0x16, 0x01, + 0xE7, 0x8A, 0xE3, 0x90, 0xC8, 0x4D, 0xD4, 0xDF, + 0xB0, 0xA1, 0x90, 0x14, 0xC2, 0x32, 0x9A, 0xC2, + 0x86, 0xA2, 0x53, 0x72, 0x1A, 0x9A, 0xFE, 0x8E, + 0xB1, 0x4C, 0xCD, 0x9F, 0xFF, 0x3F, 0xA6, 0x6A, + 0x8E, 0xEB, 0x5E, 0x7C, 0x9D, 0xF3, 0x4B, 0x3B, + 0x09, 0xC7, 0x68, 0x71, 0xD5, 0xBA, 0x32, 0x2D, + 0xBA, 0x15, 0xE3, 0x63, 0xD7, 0x5A, 0x87, 0x5E, + 0x9E, 0xAF, 0xB0, 0x9C, 0xF9, 0x35, 0xA3, 0x67, + 0x1B, 0xD5, 0xC7, 0x9C, 0xB5, 0x63, 0x0E, 0x16, + 0x9B, 0x2D, 0x25, 0x1E, 0x22, 0x96, 0x0A, 0x96, + 0xBE, 0xEF, 0x65, 0xAA, 0xFE, 0x28, 0xB9, 0x55, + 0xD0, 0xDC, 0xB2, 0x5C, 0x21, 0x9B, 0x31, 0xF7, + 0xDE, 0xD9, 0xA6, 0x86, 0x3D, 0xD8, 0x5F, 0xB4, + 0xC5, 0x7A, 0x4D, 0xAB, 0xE5, 0xBC, 0x10, 0xB7, + 0x26, 0x15, 0x08, 0x64, 0x58, 0xB0, 0x4F, 0x77, + 0xCE, 0xDC, 0xBD, 0x1D, 0xD5, 0x21, 0x9A, 0x9A, + 0x93, 0x72, 0x2D, 0x4D, 0x82, 0x36, 0x29, 0xCA, + 0xAB, 0x80, 0xD2, 0x02, 0x1D, 0x6C, 0x49, 0x30, + 0x56, 0x20, 0x8D, 0xFA, 0xA1, 0x58, 0x3F, 0xA6, + 0xCB, 0xF0, 0x41, 0xFB, 0xDD, 0xD0, 0x6D, 0x80, + 0x75, 0xE1, 0x36, 0xAC, 0xF8, 0xAE, 0xDB, 0x37, + 0xB0, 0xDE, 0x4B, 0x89, 0xFB, 0xC1, 0x1B, 0x23, + 0x05, 0xBC, 0x02, 0x87, 0x42, 0x9A, 0x77, 0x23, + 0x99, 0xB4, 0x56, 0x7E, 0x7C, 0xD7, 0x61, 0x18, + 0xD2, 0x4F, 0x19, 0xE6, 0x05, 0x4D, 0x72, 0xC8, + 0xB7, 0xA9, 0x9F, 0xF9, 0x9F, 0xE9, 0x54, 0x34, + 0x54, 0x45, 0x7C, 0xA4, 0xCC, 0x3B, 0xFF, 0x2B, + 0x58, + + 0xB7, 0x93, 0x32, 0xE4, 0xCA, 0xD7, 0xB5, 0x4F, + 0x11, 0xB0, 0x5B, 0x38, 0xB8, 0xC0, 0x90, 0xA8, + 0x0E, 0x4B, 0x34, 0x6C, 0xCC, 0x81, 0x82, 0xC5, + 0x41, 0x91, 0x0D, 0x1A, 0x47, 0x0E, 0xE6, 0x39, + 0x7F, 0xDD, 0xF9, 0xBE, 0xF1, 0xB0, 0xDC, 0x76, + 0xB8, 0x2C, 0x2B, 0xAD, 0xA9, 0xE5, 0xCA, 0x70, + 0x8D, 0xF1, 0xCA, 0x60, 0x5C, 0x85, 0x2E, 0x73, + 0xE7, 0xF8, 0x0A, 0x33, 0xB3, 0x32, 0xC0, 0xCD, + 0x64, 0x4C, 0x9C, 0x65, 0x55, 0x2A, 0x60, 0x42, + 0xF3, 0xBA, 0xF5, 0xC2, 0x28, 0xFC, 0xFE, 0x32, + 0x96, 0xBF, 0x6F, 0x7E, 0x09, 0x82, 0xA5, 0xD0, + 0xE4, 0x11, 0x66, 0x67, 0x66, 0xDB, 0x8A, 0x3D, + 0x08, 0x40, 0xC4, 0x40, 0x66, 0xF8, 0x1F, 0x86, + 0x39, 0xDB, 0xB6, 0x12, 0x11, 0x4E, 0xE4, 0x52, + 0xA5, 0x18, 0x4A, 0x3F, 0x04, 0x01, 0x3D, 0x8D, + 0x15, 0xEE, 0x28, 0xBD, 0xED, 0x32, 0x11, 0xB8, + 0xE9, 0x5E, 0x2A, 0xB7, 0xD3, 0x3C, 0xDD, 0xC6, + 0x42, 0xE0, 0x15, 0x20, 0x0B, 0x13, 0x7E, 0x21, + 0xFE, 0x7B, 0x5F, 0x46, 0x70, 0xF6, 0x64, 0x73, + 0x71, 0x1A, 0x29, 0xD9, 0x07, 0xE0, 0xA9, 0x65, + 0x5B, 0x90, 0x17, 0x5E, 0xE6, 0xFC, 0x29, 0xA2, + 0x5B, 0xB0, 0x00, 0x54, 0x6C, 0x15, 0xA1, 0x44, + 0x66, 0x0F, 0x87, 0xCF, 0x66, 0x04, 0x6F, 0x3F, + 0x04, 0xE5, 0xFA, 0x2D, 0x0C, 0x70, 0x43, 0xF0, + 0x08, 0x01, 0x62, 0x21, 0x81, 0x65, 0x9F, 0x61, + 0xC6, 0x5A, 0x80, 0x64, 0x9D, 0x8E, 0xD7, 0x52, + 0xCF, 0xDC, 0x04, 0x50, 0x0A, 0x98, 0x5A, 0xF2, + 0x9F, 0x6A, 0xAF, 0xDA, 0x96, 0x35, 0x34, 0xF9, + 0xAB, 0x1E, 0x17, 0xC3, 0x18, 0x90, 0xFB, 0x07, + 0x5E, 0xA0, 0x02, 0x4C, 0x0C, 0xE1, 0xE9, 0x06, + 0x7F, 0x1F, 0xC1, 0xA2, 0x77, 0x63, 0xF0, 0x96, + 0xEE, 0x87, 0xC8, 0x28, 0x79, 0x17, 0x33, 0x2D, + 0x16, 0x43, 0x9A, 0x79, 0x32, 0xA9, 0x3D, 0x1F, + 0x35, 0x3D, + + 0xD1, 0x6C, 0xFF, 0x29, 0x4F, 0xC3, 0x29, 0xC5, + 0xC9, 0x5B, 0xDC, 0x81, 0xD1, 0xB3, 0x55, 0xA8, + 0x5E, 0xE2, 0xC9, 0xE3, 0xFC, 0x16, 0x30, 0x02, + 0xAB, 0x43, 0x26, 0x7E, 0xD1, 0xCD, 0x2B, 0x06, + 0xE8, 0x4E, 0xDA, 0xA3, 0xD3, 0xD3, 0x87, 0x05, + 0xB3, 0x05, 0x8C, 0xCF, 0xAE, 0xEF, 0x15, 0x33, + 0xCE, 0x72, 0x64, 0x52, 0x88, 0x78, 0x20, 0x1B, + 0xF1, 0x7E, 0xC9, 0x46, 0x13, 0xCF, 0xD9, 0xF2, + 0x4B, 0x1C, 0xA6, 0x96, 0xAF, 0x02, 0xAD, 0x6F, + 0xDB, 0xAD, 0x6F, 0x04, 0x55, 0xA2, 0x2C, 0x9C, + 0x56, 0xB6, 0x07, 0x8A, 0x87, 0x3F, 0xD6, 0x06, + 0x90, 0x4C, 0x6D, 0x5E, 0xE5, 0x16, 0x21, 0x46, + 0x00, 0x88, 0x77, 0x58, 0x0E, 0x9E, 0x89, 0xFE, + 0x3F, 0x20, 0x6A, 0x17, 0x64, 0x9C, 0x63, 0x71, + 0x3C, 0xDB, 0x36, 0xE3, 0x8A, 0xA6, 0x7A, 0xD5, + 0x1A, 0x27, 0x75, 0x4C, 0xD9, 0xF3, 0xF0, 0x02, + 0x2B, 0x3D, 0xE5, 0xF1, 0xDE, 0x98, 0x98, 0x62, + 0x18, 0x17, 0xAE, 0xD2, 0x80, 0xA7, 0xA3, 0x82, + 0xBF, 0x30, 0xC8, 0xC9, 0x68, 0x6A, 0x2F, 0x40, + 0x8A, 0x2F, 0x8A, 0x39, 0xB4, 0x60, 0x6F, 0xE1, + 0x0F, 0x19, 0xB1, 0x4C, 0x82, 0x9A, 0x11, 0xB4, + 0x98, 0x74, 0xE7, 0xAF, 0xD4, 0x21, 0x5E, 0xD8, + 0x30, 0xA1, 0x53, 0xF3, 0xD2, 0xDE, 0x02, 0x9F, + 0xA6, 0xA8, 0x4D, 0x03, 0x2A, 0x45, 0xE3, 0x49, + 0x98, 0xE2, 0xF7, 0x71, 0x9F, 0xBC, 0x93, 0xDE, + 0xF6, 0x7E, 0x12, 0xC1, 0x37, 0xB0, 0x93, 0x4E, + 0x89, 0x16, 0x39, 0x2B, 0xF6, 0x28, 0x30, 0x75, + 0xC0, 0x43, 0xA9, 0x3D, 0x1F, 0xD3, 0xFD, 0x56, + 0xF7, 0x65, 0xFC, 0x08, 0x3C, 0x9B, 0x1C, 0x33, + 0x57, 0x0B, 0xAB, 0x4B, 0xFE, 0xD4, 0x50, 0xFC, + 0x9D, 0x42, 0xF7, 0x8D, 0xB4, 0x50, 0xF5, 0xA9, + 0x54, 0x00, 0x74, 0x93, 0x59, 0x6B, 0x6F, 0x95, + 0x31, 0xEE, 0xF5, 0xC4, 0x4A, 0x9C, 0x33, 0x27, + 0x6E, 0x1D, 0x4A, + + 0xB5, 0xEE, 0x2C, 0xC7, 0x88, 0xD2, 0x63, 0x3E, + 0xF6, 0x8E, 0xC1, 0xA3, 0xD2, 0x39, 0x8E, 0xF6, + 0xD3, 0x44, 0x7C, 0xA6, 0x27, 0x6E, 0x67, 0x66, + 0x0F, 0x68, 0xF9, 0xE2, 0xE4, 0xA2, 0x9B, 0x59, + 0x6D, 0x26, 0xE2, 0x4B, 0xF1, 0x82, 0x5C, 0x67, + 0xE9, 0x55, 0xEE, 0xB6, 0xA0, 0xE3, 0x32, 0xEE, + 0x2A, 0x33, 0x2F, 0x6A, 0x2B, 0xBC, 0xE8, 0xB9, + 0x45, 0xCD, 0x0F, 0xF0, 0x84, 0xB6, 0x5D, 0xC5, + 0xAC, 0xD7, 0x45, 0x4B, 0x5A, 0xE4, 0xD5, 0x07, + 0x6D, 0x30, 0x0A, 0x9E, 0x73, 0x0E, 0x7D, 0x5F, + 0x8A, 0x2C, 0x7A, 0xE4, 0xD0, 0x1B, 0xE7, 0x02, + 0x93, 0x2E, 0xCE, 0x3C, 0xA1, 0xB1, 0x48, 0x5A, + 0xD6, 0xC0, 0x38, 0x0F, 0x13, 0xC7, 0x8B, 0x0F, + 0x4D, 0x90, 0xFC, 0x22, 0xC5, 0x74, 0xC6, 0xE0, + 0xFE, 0x1B, 0x2D, 0xEA, 0x3E, 0xDB, 0xC1, 0xCA, + 0x7F, 0x0D, 0xA0, 0xBB, 0x62, 0x0B, 0x51, 0x46, + 0xD4, 0xAB, 0x21, 0xE9, 0x6A, 0x13, 0x55, 0xEC, + 0x00, 0x16, 0xF5, 0xA3, 0xE8, 0x59, 0x90, 0xFB, + 0x56, 0xA5, 0x4B, 0x7F, 0x3F, 0xAA, 0x2E, 0x27, + 0x6F, 0xEC, 0x7B, 0xD1, 0xFA, 0x79, 0x36, 0x95, + 0x17, 0x84, 0xE0, 0xF1, 0xFB, 0xCA, 0xE2, 0x71, + 0x18, 0xAF, 0x49, 0x4D, 0x02, 0x51, 0xAB, 0x0C, + 0x56, 0x0A, 0xAF, 0x96, 0x0A, 0xD3, 0x57, 0x93, + 0xA1, 0x8E, 0xD1, 0x32, 0xD4, 0x1D, 0x62, 0xE1, + 0x1F, 0x4D, 0x00, 0xD4, 0x0B, 0x6F, 0xAE, 0x69, + 0x67, 0xAA, 0x2D, 0x75, 0x17, 0x0E, 0xE8, 0x72, + 0x91, 0x11, 0x05, 0xBB, 0x94, 0xBE, 0x0B, 0x2C, + 0x05, 0xF3, 0x09, 0x98, 0xAA, 0xA3, 0x77, 0xB9, + 0xAF, 0x75, 0x29, 0x57, 0xA0, 0x7F, 0x70, 0x53, + 0x4E, 0xEB, 0xD5, 0x15, 0x50, 0x60, 0x1D, 0x7B, + 0x3F, 0x3F, 0x65, 0x4E, 0xE0, 0x4A, 0x47, 0xEF, + 0xBA, 0x68, 0x01, 0xEB, 0xA5, 0x09, 0x4C, 0xE4, + 0xF6, 0xAA, 0xE0, 0x00, 0x43, 0x5B, 0x2E, 0x09, + 0xFE, 0xD0, 0x4E, 0xE8, + + 0x06, 0x49, 0x5B, 0x9A, 0xCF, 0x47, 0x2B, 0x04, + 0xBE, 0x1B, 0x98, 0x6A, 0xB5, 0x21, 0x6D, 0x0E, + 0x18, 0x9B, 0x87, 0xA4, 0x97, 0x13, 0xF5, 0x7E, + 0x94, 0x92, 0xB3, 0x69, 0xA1, 0xD5, 0x25, 0x46, + 0x26, 0x8E, 0x6B, 0x47, 0x0A, 0x77, 0x48, 0x51, + 0xB9, 0xAF, 0x64, 0x37, 0x70, 0x64, 0xBD, 0x98, + 0x16, 0x1A, 0x46, 0xAA, 0xFA, 0x0C, 0xB2, 0x3C, + 0x6F, 0x23, 0xA5, 0x6C, 0x81, 0x0B, 0x49, 0x7C, + 0x75, 0xE6, 0x0B, 0x47, 0x49, 0xDB, 0x70, 0xC5, + 0x26, 0x75, 0x20, 0x3E, 0xE2, 0x28, 0xD9, 0x1A, + 0xE2, 0x96, 0x9D, 0xAE, 0x29, 0x53, 0x9A, 0xE2, + 0xFE, 0xC9, 0xF5, 0x3B, 0x02, 0x40, 0x13, 0xF1, + 0x10, 0x27, 0x1A, 0x67, 0x97, 0x9C, 0xF6, 0xC5, + 0xBA, 0xE6, 0x3D, 0xA4, 0xA8, 0x67, 0xCF, 0xB6, + 0x35, 0xC7, 0x6B, 0xC6, 0x9C, 0x85, 0x25, 0x14, + 0x20, 0xC6, 0x48, 0x23, 0x26, 0x29, 0xE9, 0xBE, + 0x79, 0x89, 0xFA, 0x26, 0x2E, 0xB9, 0xC3, 0x54, + 0x28, 0x8B, 0xE2, 0xEF, 0xBC, 0xB2, 0x19, 0xC3, + 0x40, 0x85, 0x8A, 0x59, 0x06, 0x96, 0xDF, 0x39, + 0x03, 0x6E, 0xA0, 0xF8, 0x20, 0xD9, 0x3B, 0x72, + 0x80, 0xCC, 0x15, 0xBF, 0xB6, 0x2B, 0x15, 0x8A, + 0xC2, 0x71, 0x60, 0xEE, 0x51, 0x80, 0xCB, 0x61, + 0x7A, 0xDB, 0x17, 0x18, 0x80, 0xE5, 0x2F, 0xB9, + 0xB9, 0x36, 0xE3, 0xED, 0x7B, 0x7C, 0x23, 0xF7, + 0xBB, 0xBE, 0x61, 0xF1, 0xAF, 0x38, 0x5E, 0xAC, + 0x6E, 0x8F, 0x5A, 0x46, 0xB9, 0xD6, 0x4D, 0x51, + 0x5A, 0x7F, 0x3C, 0x34, 0xE5, 0x5E, 0x28, 0xB4, + 0x00, 0xD5, 0x76, 0xF6, 0x04, 0x94, 0x00, 0x36, + 0x23, 0xD1, 0x87, 0xA7, 0x0D, 0x55, 0xF4, 0x8A, + 0x89, 0x3A, 0x32, 0x9D, 0x08, 0xEB, 0xB6, 0x6F, + 0xED, 0xF0, 0xF8, 0x8F, 0x25, 0x3B, 0xAC, 0x6E, + 0xF5, 0x2B, 0x37, 0x4E, 0x4C, 0x28, 0x19, 0x69, + 0x66, 0x04, 0x40, 0x09, 0xE4, 0x1F, 0x82, 0x6F, + 0x5E, 0x40, 0x4C, 0x16, 0x4B, + + 0xBF, 0x12, 0xC4, 0xD2, 0xDD, 0xF1, 0x90, 0x50, + 0x38, 0x11, 0x8E, 0x5D, 0x20, 0x49, 0x64, 0xEB, + 0x08, 0xE0, 0x5F, 0xFF, 0x81, 0xC1, 0x23, 0x7F, + 0xA0, 0xBB, 0xB4, 0x28, 0x61, 0xA2, 0x99, 0xEB, + 0x44, 0x5A, 0x26, 0xF3, 0xF1, 0x76, 0x41, 0xF7, + 0x92, 0xFD, 0x6A, 0xB1, 0x72, 0x92, 0xBF, 0x62, + 0x92, 0x57, 0x46, 0x45, 0x0B, 0x5E, 0xA3, 0x33, + 0x64, 0x79, 0xE9, 0x3B, 0x50, 0x54, 0x62, 0xC1, + 0xB8, 0x5E, 0x45, 0x5A, 0x5F, 0xB4, 0xBB, 0x5F, + 0x6A, 0x01, 0x8D, 0x1B, 0x79, 0x76, 0x34, 0x08, + 0xF9, 0x42, 0xE4, 0xD6, 0x42, 0xDD, 0x16, 0x80, + 0xD4, 0x7D, 0x7D, 0xC4, 0x09, 0xAC, 0x96, 0xF8, + 0xB5, 0x8A, 0xF7, 0xBF, 0x92, 0xDB, 0x5D, 0xB7, + 0x15, 0x91, 0x6F, 0x96, 0xB5, 0x4C, 0x3E, 0x27, + 0xD8, 0xE2, 0xE1, 0x6F, 0x9D, 0x9B, 0xBB, 0x99, + 0x5D, 0xB5, 0x33, 0x55, 0xB3, 0x12, 0xFF, 0x64, + 0xBF, 0xB7, 0x58, 0xA0, 0x40, 0x9B, 0x6E, 0x35, + 0x26, 0x88, 0x13, 0x0B, 0x82, 0xA7, 0x2F, 0x10, + 0x70, 0x2B, 0xAF, 0x24, 0x1F, 0xAA, 0x62, 0xD2, + 0xBA, 0x0F, 0x3A, 0x29, 0x88, 0x48, 0xCB, 0xC9, + 0x60, 0x20, 0x73, 0x07, 0x46, 0x4D, 0x62, 0x2B, + 0x52, 0x2D, 0x39, 0xCB, 0x79, 0x63, 0x29, 0x54, + 0xA7, 0x4E, 0x3A, 0xD7, 0xD4, 0x51, 0x2D, 0xDD, + 0xBF, 0x6C, 0x16, 0x4E, 0xA7, 0x49, 0xEA, 0xE2, + 0x78, 0xBA, 0x84, 0x89, 0x7D, 0x5F, 0xA8, 0xFD, + 0x89, 0x2F, 0xA0, 0xE0, 0x1E, 0xE5, 0x51, 0x8D, + 0xE9, 0xE1, 0x73, 0x79, 0xE5, 0x28, 0x62, 0xFB, + 0x15, 0xD3, 0x44, 0xAF, 0xED, 0xCE, 0x1F, 0xB6, + 0x2D, 0x26, 0x5D, 0xDA, 0xED, 0x01, 0x30, 0x4D, + 0x72, 0x4F, 0x23, 0xF0, 0x5A, 0x1E, 0xC9, 0xAF, + 0xCF, 0x75, 0xA3, 0x15, 0xAE, 0x29, 0xF6, 0xD7, + 0xE4, 0xA9, 0x95, 0xF4, 0x39, 0x3E, 0xF6, 0x99, + 0xB5, 0xB3, 0x60, 0xDE, 0x7C, 0x26, 0xDD, 0xF0, + 0xD3, 0x04, 0x0A, 0xFC, 0xE9, 0xAE, + + 0xB0, 0x1B, 0x1C, 0xC2, 0xC4, 0x72, 0x71, 0xBF, + 0x61, 0x44, 0xD2, 0x9C, 0x4B, 0x14, 0x90, 0x14, + 0xC5, 0x89, 0x3D, 0xC7, 0x32, 0x07, 0xA7, 0xF5, + 0x64, 0xC1, 0xDD, 0x7D, 0x42, 0x2C, 0x3D, 0xDE, + 0x61, 0xDD, 0x78, 0x94, 0xB6, 0xB5, 0xF8, 0x47, + 0xEE, 0x5C, 0x2A, 0xA3, 0x32, 0xB5, 0x63, 0x3E, + 0x8C, 0xE6, 0x2F, 0x56, 0x1A, 0x24, 0xAA, 0xBD, + 0xA6, 0xAF, 0x30, 0x90, 0x7D, 0xF2, 0x73, 0x86, + 0x4D, 0x93, 0x74, 0xF1, 0xD8, 0x9B, 0x70, 0xDC, + 0xA5, 0xCC, 0xA8, 0xF9, 0x27, 0xBA, 0xA0, 0x3D, + 0x4D, 0x11, 0x19, 0xA5, 0x23, 0xE0, 0xC1, 0xC2, + 0xF7, 0x18, 0xDA, 0xCA, 0x23, 0x7E, 0x91, 0x56, + 0x72, 0xF7, 0xCE, 0xB4, 0xBF, 0x31, 0x2A, 0x61, + 0x9B, 0x7D, 0x82, 0xDF, 0xF2, 0xC7, 0x04, 0x74, + 0xD4, 0x2F, 0x14, 0x02, 0x4C, 0xC9, 0x12, 0x6D, + 0xF9, 0x67, 0x9C, 0xC5, 0x97, 0x3B, 0x9C, 0x54, + 0xA4, 0x45, 0xDA, 0xA5, 0xE8, 0xDB, 0xF7, 0x95, + 0x62, 0x0E, 0xE3, 0x25, 0x95, 0xC6, 0x68, 0xA1, + 0xBD, 0xC7, 0x78, 0xBD, 0x7E, 0xF8, 0x98, 0xDE, + 0xDA, 0x30, 0x75, 0xB6, 0xD0, 0xE1, 0x67, 0x42, + 0x6D, 0xE0, 0x26, 0x34, 0x7B, 0x47, 0x81, 0x03, + 0x96, 0x3C, 0x55, 0x8A, 0x6E, 0x73, 0x51, 0x88, + 0x1B, 0x05, 0x52, 0xDC, 0x8A, 0xA4, 0x07, 0x50, + 0x3C, 0x98, 0xC3, 0xFC, 0x58, 0xFA, 0xC8, 0x94, + 0x7D, 0x75, 0xE3, 0x4B, 0x6C, 0xCC, 0xB7, 0x9D, + 0x6F, 0xEA, 0x79, 0x4F, 0x5C, 0x77, 0xD3, 0x1B, + 0xC5, 0xB7, 0x97, 0xD7, 0xD4, 0xE9, 0x72, 0xD5, + 0x7E, 0xA3, 0xB5, 0xE9, 0xAC, 0xA0, 0x5D, 0xF8, + 0x38, 0xAC, 0x50, 0xA2, 0x47, 0x51, 0x96, 0x15, + 0x73, 0x74, 0x1B, 0x4E, 0xF2, 0x80, 0x59, 0xC6, + 0x58, 0x40, 0x3F, 0xB3, 0xE5, 0x4C, 0x62, 0x1F, + 0x65, 0xD9, 0x16, 0xBF, 0xD5, 0x45, 0x4A, 0x39, + 0xCA, 0x5A, 0x8F, 0xD2, 0x77, 0x5D, 0x96, 0x25, + 0x2E, 0xD4, 0xC3, 0x01, 0x25, 0xFB, 0x78 +}; diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testpoly1305.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testpoly1305.c new file mode 100644 index 0000000..3ecf1ca --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testpoly1305.c @@ -0,0 +1,102 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + + +#include "poly1305.h" + +#include "testutil.h" +#include "handy.h" +#include "cutest.h" + +static void check(const char *rstr, const char *sstr, + const char *msgstr, const char *tagstr) +{ + uint8_t r[16], s[16], tag[16]; + uint8_t msg[132], out[16]; + + unhex(r, sizeof r, rstr); + unhex(s, sizeof s, sstr); + size_t nmsg = unhex(msg, sizeof msg, msgstr); + unhex(tag, sizeof tag, tagstr); + + cf_poly1305 ctx; + cf_poly1305_init(&ctx, r, s); + cf_poly1305_update(&ctx, msg, nmsg); + cf_poly1305_finish(&ctx, out); + + TEST_CHECK(memcmp(out, tag, 16) == 0); +} + +static void test_poly1305(void) +{ + check("eea6a7251c1e72916d11c2cb214d3c25", + "2539121d8e234e652d651fa4c8cff880", + "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5", + "f3ffc7703f9400e52a7dfb4b3d3305d9"); + + check("851fc40c3467ac0be05cc20404f3f700", + "580b3b0f9447bb1e69d095b5928b6dbc", + "f3f6", + "f4c633c3044fc145f84f335cb81953de"); + + check("a0f3080000f46400d0c7e9076c834403", + "dd3fab2251f11ac759f0887129cc2ee7", + "", + "dd3fab2251f11ac759f0887129cc2ee7"); + + check("48443d0bb0d21109c89a100b5ce2c208", + "83149c69b561dd88298a1798b10716ef", + "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136", + "0ee1c16bb73f0f4fd19881753c01cdbe"); + + check("12976a08c4426d0ce8a82407c4f48207", + "80f8c20aa71202d1e29179cbcb555a57", + "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9", + "5154ad0d2cb26e01274fc51148491f1b"); + + /* extras from RFC7539 */ + check("02000000000000000000000000000000", + "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "03000000000000000000000000000000"); + check("02000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "02000000000000000000000000000000", + "03000000000000000000000000000000"); + check("01000000000000000000000000000000", + "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11000000000000000000000000000000", + "05000000000000000000000000000000"); + check("01000000000000000000000000000000", + "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE01010101010101010101010101010101", + "00000000000000000000000000000000"); + check("02000000000000000000000000000000", + "00000000000000000000000000000000", + "FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); + check("01000000000000000400000000000000", + "00000000000000000000000000000000", + "E33594D7505E43B900000000000000003394D7505E4379CD01000000000000000000000000000000000000000000000001000000000000000000000000000000", + "14000000000000005500000000000000"); + check("01000000000000000400000000000000", + "00000000000000000000000000000000", + "E33594D7505E43B900000000000000003394D7505E4379CD010000000000000000000000000000000000000000000000", + "13000000000000000000000000000000"); +} + +TEST_LIST = { + { "poly1305", test_poly1305 }, + { 0 } +}; diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsalsa20.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsalsa20.c new file mode 100644 index 0000000..9d50b93 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsalsa20.c @@ -0,0 +1,210 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "salsa20.h" + +#include "testutil.h" +#include "handy.h" +#include "cutest.h" + +static void test_salsa20_core(void) +{ + uint8_t k0[16], k1[16], nonce[16], sigma[16], out[64], expect[64]; + + /* From section 8. */ + memset(k0, 0, sizeof k0); + memset(k1, 0, sizeof k1); + memset(nonce, 0, sizeof nonce); + memset(sigma, 0, sizeof sigma); + + cf_salsa20_core(k0, k1, nonce, sigma, out); + + unhex(expect, 64, "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + TEST_CHECK(memcmp(expect, out, 64) == 0); + + /* + d39f0d73 + 4c3752b70375de25bfbbea8831edb330 + 016ab2db + afc7a6305610b3cf1ff0203f0f535da1 + 74933071 + ee37cc244fc9eb4f03519c2fcb1af4f3 + 58766836 + */ + unhex(k0, 16, "4c3752b70375de25bfbbea8831edb330"); + unhex(k1, 16, "ee37cc244fc9eb4f03519c2fcb1af4f3"); + unhex(nonce, 16, "afc7a6305610b3cf1ff0203f0f535da1"); + unhex(sigma, 16, "d39f0d73016ab2db7493307158766836"); + + cf_salsa20_core(k0, k1, nonce, sigma, out); + + unhex(expect, 64, "6d2ab2a89cf0f8eea8c4becb1a6eaa9a1d1d961a961eebf9bea3fb30459033397628989db4391b5e6b2aec231b6f7272dbece8876f9b6e1218e85f9eb31330ca"); + TEST_CHECK(memcmp(expect, out, 64) == 0); + + /* + 58766836 + 4fc9eb4f03519c2fcb1af4f3bfbbea88 + d39f0d73 + 4c3752b70375de255610b3cf31edb330 + 016ab2db + afc7a630ee37cc241ff0203f0f535da1 + 74933071 + */ + unhex(k0, 16, "4fc9eb4f03519c2fcb1af4f3bfbbea88"); + unhex(k1, 16, "afc7a630ee37cc241ff0203f0f535da1"); + unhex(nonce, 16, "4c3752b70375de255610b3cf31edb330"); + unhex(sigma, 16, "58766836d39f0d73016ab2db74933071"); + + cf_salsa20_core(k0, k1, nonce, sigma, out); + + unhex(expect, 64, "b31330cadbece8876f9b6e1218e85f9e1a6eaa9a6d2ab2a89cf0f8eea8c4becb459033391d1d961a961eebf9bea3fb301b6f72727628989db4391b5e6b2aec23"); + TEST_CHECK(memcmp(expect, out, 64) == 0); + + /* From section 9. */ + for (size_t i = 0; i < 16; i++) + { + k0[i] = 1 + i; + k1[i] = 201 + i; + nonce[i] = 101 + i; + } + + cf_salsa20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 64, "45254427290f6bc1ff8b7a06aae9d9625990b66a1533c841ef31de22d772287e68c507e1c5991f02664e4cb054f5f6b8b1a0858206489577c0c384ecea67f64a"); + TEST_CHECK(memcmp(expect, out, 64) == 0); + + cf_salsa20_core(k0, k0, nonce, (const uint8_t *) "expand 16-byte k", out); + + unhex(expect, 64, "27ad2ef81ec852113043feef25120df7f1c83d900a3732b9062ff6fd8f56bbe186556ef6a1a32bebe75eab3391d6701d0ee80510978cb78dab097ab568b6b1c1"); + TEST_CHECK(memcmp(expect, out, 64) == 0); +} + +static void test_salsa20(void) +{ + cf_salsa20_ctx ctx; + uint8_t key[32], nonce[8], cipher[64], expect[64]; + + unhex(key, 32, "0102030405060708090a0b0c0d0e0f10c9cacbcccdcecfd0d1d2d3d4d5d6d7d8"); + memset(nonce, 0, 8); + + cf_salsa20_init(&ctx, key, sizeof key, nonce); + unhex(ctx.nonce, 16, "65666768696a6b6c6d6e6f7071727374"); + memset(cipher, 0, 64); + cf_salsa20_cipher(&ctx, cipher, cipher, 64); + + unhex(expect, 64, "45254427290f6bc1ff8b7a06aae9d9625990b66a1533c841ef31de22d772287e68c507e1c5991f02664e4cb054f5f6b8b1a0858206489577c0c384ecea67f64a"); + TEST_CHECK(memcmp(expect, cipher, 64) == 0); + + cf_salsa20_init(&ctx, key, 16, nonce); + unhex(ctx.nonce, 16, "65666768696a6b6c6d6e6f7071727374"); + memset(cipher, 0, 64); + cf_salsa20_cipher(&ctx, cipher, cipher, 64); + + unhex(expect, 64, "27ad2ef81ec852113043feef25120df7f1c83d900a3732b9062ff6fd8f56bbe186556ef6a1a32bebe75eab3391d6701d0ee80510978cb78dab097ab568b6b1c1"); + TEST_CHECK(memcmp(expect, cipher, 64) == 0); +} + +static void test_chacha20_core(void) +{ + uint8_t k0[16], k1[16], nonce[16], out[64], expect[64]; + + /* From draft-agl-tls-chacha20poly1305-04 section 7. */ + + memset(k0, 0, sizeof k0); + memset(k1, 0, sizeof k1); + memset(nonce, 0, sizeof nonce); + + cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 60, "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669"); + TEST_CHECK(memcmp(expect, out, 60) == 0); + + k1[15] = 0x01; + cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 60, "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275"); + TEST_CHECK(memcmp(expect, out, 60) == 0); + + memset(k1, 0, sizeof k1); + nonce[15] = 0x01; + + cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 60, "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3"); + TEST_CHECK(memcmp(expect, out, 60) == 0); + + memset(nonce, 0, sizeof nonce); + nonce[8] = 0x01; + + cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 64, "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b"); + TEST_CHECK(memcmp(expect, out, 64) == 0); + + unhex(k0, 16, "000102030405060708090a0b0c0d0e0f"); + unhex(k1, 16, "101112131415161718191a1b1c1d1e1f"); + unhex(nonce, 16, "00000000000000000001020304050607"); + + cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 64, "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a"); + TEST_CHECK(memcmp(expect, out, 64) == 0); + + nonce[0]++; + cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 64, "38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c7"); + TEST_CHECK(memcmp(expect, out, 64) == 0); + + nonce[0]++; + cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 64, "9db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d7"); + TEST_CHECK(memcmp(expect, out, 64) == 0); + + nonce[0]++; + cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out); + + unhex(expect, 64, "0eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9"); + TEST_CHECK(memcmp(expect, out, 64) == 0); +} + +static void test_chacha20(void) +{ + uint8_t key[32], nonce[8], block[256], expect[256]; + + unhex(key, 32, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); + unhex(nonce, 8, "0001020304050607"); + unhex(expect, 256, "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9"); + memset(block, 0, 256); + + cf_chacha20_ctx ctx; + cf_chacha20_init(&ctx, key, sizeof key, nonce); + cf_chacha20_cipher(&ctx, block, block, sizeof block); + + TEST_CHECK(memcmp(expect, block, sizeof expect) == 0); + + /* Check 128-bit mode works. */ + cf_chacha20_init(&ctx, key, 16, nonce); + cf_chacha20_cipher(&ctx, block, block, sizeof block); +} + +TEST_LIST = { + { "salsa20-core", test_salsa20_core }, + { "chacha20-core", test_chacha20_core }, + { "salsa20", test_salsa20 }, + { "chacha20", test_chacha20 }, + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha.h new file mode 100644 index 0000000..70075f0 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha.h @@ -0,0 +1,213 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef TESTSHA_H +#define TESTSHA_H + +#include "hmac.h" + +/* Common functions for testing hash functions. + * You shouldn't use this file. */ + +static void vector(const cf_chash *hash, + const void *vmsg, size_t nmsg, + const char *expect, size_t nexpect) +{ + uint8_t digest[CF_MAXHASH]; + const uint8_t *msg = vmsg; + size_t orig_nmsg = nmsg; + + cf_chash_ctx ctx; + hash->init(&ctx); + + /* Input in carefully chosen chunk sizes to exercise blockwise code. */ + if (nmsg) + { + hash->update(&ctx, msg, 1); + nmsg--; + msg++; + } + + hash->update(&ctx, msg, nmsg); + hash->digest(&ctx, digest); + TEST_CHECK(nexpect == hash->hashsz); + TEST_CHECK(memcmp(digest, expect, nexpect) == 0); + + /* Now try with other arrangements. */ + msg = vmsg; + nmsg = orig_nmsg; + + hash->init(&ctx); + if (nmsg >= hash->blocksz) + { + hash->update(&ctx, msg, hash->blocksz - 1); + nmsg -= hash->blocksz - 1; + msg += hash->blocksz - 1; + } + + hash->update(&ctx, msg, nmsg); + hash->digest(&ctx, digest); + TEST_CHECK(memcmp(digest, expect, nexpect) == 0); +} + +/* These are shared between RFC2202 and RFC4231. */ +static inline void hmac_test(const cf_chash *hash, + const void *hi_there, + const void *jefe, + const void *aa_dd, + const void *counter_key) +{ + uint8_t sig[CF_MAXHASH]; + uint8_t key[25], message[50]; + + /* Key: 0x0b * 20 + * Message: "Hi There" + */ + memset(key, 0x0b, 20); + memcpy(message, "Hi There", 8); + cf_hmac(key, 20, message, 8, sig, hash); + + TEST_CHECK(memcmp(sig, hi_there, hash->hashsz) == 0); + + /* Key: "Jefe" + * Message: "what do ya want for nothing?" + */ + memcpy(key, "Jefe", 4); + memcpy(message, "what do ya want for nothing?", 28); + cf_hmac(key, 4, message, 28, sig, hash); + TEST_CHECK(memcmp(sig, jefe, hash->hashsz) == 0); + + /* Key: 0xaa * 20 + * Message: 0xdd * 50 + */ + memset(key, 0xaa, 20); + memset(message, 0xdd, 50); + cf_hmac(key, 20, message, 50, sig, hash); + TEST_CHECK(memcmp(sig, aa_dd, hash->hashsz) == 0); + + /* Key: 0x01..0x19 + * Message: 0xcd * 50 + */ + for (uint8_t i = 1; i < 26; i++) + key[i - 1] = i; + memset(message, 0xcd, 50); + cf_hmac(key, 25, message, 50, sig, hash); + TEST_CHECK(memcmp(sig, counter_key, hash->hashsz) == 0); +} + +/* These are specific to RFC4231. */ +static inline void hmac_test_sha2(const cf_chash *hash, + const char *long_key, + const char *long_message) +{ + uint8_t sig[CF_MAXHASH]; + uint8_t key[131], message[152]; + + /* Key: 0xaa * 131 + * Message: "Test Using Larger Than Block-Size Key - Hash Key First" + */ + memset(key, 0xaa, 131); + memcpy(message, "Test Using Larger Than Block-Size Key - Hash Key First", 54); + cf_hmac(key, 131, message, 54, sig, hash); + TEST_CHECK(memcmp(sig, long_key, hash->hashsz) == 0); + + /* Key: 0xaa * 131 + * Message: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm." + */ + memset(key, 0xaa, 131); + memcpy(message, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", 152); + cf_hmac(key, 131, message, 152, sig, hash); + TEST_CHECK(memcmp(sig, long_message, hash->hashsz) == 0); +} + +/* This is as hmac_test_sha2, except the sizes are specific to + * a 512-bit block. This is from RFC2202. */ +static inline void hmac_test_sha1(const cf_chash *hash, + const char *long_key, + const char *long_message) +{ + uint8_t sig[CF_MAXHASH]; + uint8_t key[80], message[73]; + + /* Key: 0xaa * 80 + * Message: "Test Using Larger Than Block-Size Key - Hash Key First" + */ + memset(key, 0xaa, 80); + memcpy(message, "Test Using Larger Than Block-Size Key - Hash Key First", 54); + cf_hmac(key, 80, message, 54, sig, hash); + TEST_CHECK(memcmp(sig, long_key, hash->hashsz) == 0); + + /* Key: 0xaa * 80 + * Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + */ + memset(key, 0xaa, 80); + memcpy(message, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73); + cf_hmac(key, 80, message, 73, sig, hash); + TEST_CHECK(memcmp(sig, long_message, hash->hashsz) == 0); +} + +typedef void (*final_fn)(void *ctx, uint8_t *out); + +/* Check incremental interface works, and final function likewise. */ +static void vector_abc_final(const cf_chash *hash, const void *vfinal_fn, + const void *expect, size_t nexpect) +{ + uint8_t digest[CF_MAXHASH]; + + final_fn final = vfinal_fn; + cf_chash_ctx ctx; + hash->init(&ctx); + hash->update(&ctx, "a", 1); + hash->digest(&ctx, digest); + hash->update(&ctx, "b", 1); + hash->digest(&ctx, digest); + hash->update(&ctx, "c", 1); + final(&ctx, digest); + + TEST_CHECK(hash->hashsz == nexpect); + TEST_CHECK(memcmp(expect, digest, nexpect) == 0); +} + +/* Check length-checking vectors work (generated by programs in ../extra_vecs) */ +static inline void vector_length(const cf_chash *h, + size_t max, + const void *expect, size_t nexpect) +{ + cf_chash_ctx outer, inner; + uint8_t digest[CF_MAXHASH]; + + h->init(&outer); + + for (size_t n = 0; n < max; n++) + { + h->init(&inner); + + for (size_t i = 0; i < n; i++) + { + uint8_t byte = (uint8_t) n & 0xff; + h->update(&inner, &byte, 1); + } + + h->digest(&inner, digest); + + h->update(&outer, digest, h->hashsz); + } + + h->digest(&outer, digest); + + TEST_CHECK(h->hashsz == nexpect); + TEST_CHECK(memcmp(expect, digest, nexpect) == 0); +} + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha1.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha1.c new file mode 100644 index 0000000..c7adc8a --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha1.c @@ -0,0 +1,55 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "sha1.h" +#include "hmac.h" +#include "handy.h" +#include "cutest.h" +#include "testutil.h" + +#include "testsha.h" + +static void test_sha1(void) +{ + const cf_chash *h = &cf_sha1; + vector(h, "", 0, "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09", 20); + vector(h, "abc", 3, "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", 20); + vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1", 20); + vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\xa4\x9b\x24\x46\xa0\x2c\x64\x5b\xf4\x19\xf9\x95\xb6\x70\x91\x25\x3a\x04\xa2\x59", 20); + + vector_abc_final(h, cf_sha1_digest_final, "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", 20); + + vector_length(h, 1024, "\x15\x53\x65\xcf\x77\xee\xd4\x8f\x46\xe2\x55\xc7\xdd\xdf\xfd\x0a\xf6\x99\x88\xbe", 20); +} + +static void test_hmac_sha1(void) +{ + hmac_test(&cf_sha1, + "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00", + "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79", + "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3", + "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"); + hmac_test_sha1(&cf_sha1, + "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12", + "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"); +} + +TEST_LIST = { + { "sha1", test_sha1}, + { "hmac-sha1", test_hmac_sha1}, + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha2.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha2.c new file mode 100644 index 0000000..fc0ab6c --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha2.c @@ -0,0 +1,224 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "sha2.h" +#include "hmac.h" +#include "pbkdf2.h" +#include "handy.h" +#include "cutest.h" +#include "testutil.h" + +#include "testsha.h" + +#undef REALLY_SLOW_TEST + +static void test_sha224(void) +{ + const cf_chash *h = &cf_sha224; + vector(h, "", 0, "\xd1\x4a\x02\x8c\x2a\x3a\x2b\xc9\x47\x61\x02\xbb\x28\x82\x34\xc4\x15\xa2\xb0\x1f\x82\x8e\xa6\x2a\xc5\xb3\xe4\x2f", 28); + vector(h, "abc", 3, "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7", 28); + vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25", 28); + vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\xc9\x7c\xa9\xa5\x59\x85\x0c\xe9\x7a\x04\xa9\x6d\xef\x6d\x99\xa9\xe0\xe0\xe2\xab\x14\xe6\xb8\xdf\x26\x5f\xc0\xb3", 28); + + /* Check that incremental interface produces correct results. */ + vector_abc_final(h, cf_sha224_digest_final, "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7", 28); + + vector_length(h, 1024, "\x08\x2c\x80\x5b\x6f\x85\xde\x0e\xdf\xa8\x51\xa0\x1f\xe6\x4f\x64\x85\x16\x48\xae\xfc\xc1\xd4\x52\x4e\xf8\x36\xe7", 28); +} + +static void test_hmac_sha224(void) +{ + hmac_test(&cf_sha224, + "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22", + "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44", + "\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea", + "\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a"); + hmac_test_sha2(&cf_sha224, + "\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e", + "\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1"); +} + +static void test_sha256(void) +{ + const cf_chash *h = &cf_sha256; + vector(h, "", 0, "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55", 32); + vector(h, "abc", 3, "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32); + vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1", 32); + vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\xcf\x5b\x16\xa7\x78\xaf\x83\x80\x03\x6c\xe5\x9e\x7b\x04\x92\x37\x0b\x24\x9b\x11\xe8\xf0\x7a\x51\xaf\xac\x45\x03\x7a\xfe\xe9\xd1", 32); + + vector_abc_final(h, cf_sha256_digest_final, "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32); + + vector_length(h, 1024, "\x55\x7b\xfd\xd5\xef\xda\xfd\x63\x06\x5e\xb7\x98\x87\xde\x86\xdb\x54\xc3\xfe\xdf\x7b\xcc\xcb\x97\x08\xfa\x87\xf0\x11\x87\x61\xdc", 32); +} + +static void test_hmac_sha256(void) +{ + hmac_test(&cf_sha256, + "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7", + "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43", + "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe", + "\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b"); + hmac_test_sha2(&cf_sha256, + "\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54", + "\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2"); +} + +static void test_sha384(void) +{ + const cf_chash *h = &cf_sha384; + vector(h, "", 0, "\x38\xb0\x60\xa7\x51\xac\x96\x38\x4c\xd9\x32\x7e\xb1\xb1\xe3\x6a\x21\xfd\xb7\x11\x14\xbe\x07\x43\x4c\x0c\xc7\xbf\x63\xf6\xe1\xda\x27\x4e\xde\xbf\xe7\x6f\x65\xfb\xd5\x1a\xd2\xf1\x48\x98\xb9\x5b", 48); + vector(h, "abc", 3, "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48); + vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x33\x91\xfd\xdd\xfc\x8d\xc7\x39\x37\x07\xa6\x5b\x1b\x47\x09\x39\x7c\xf8\xb1\xd1\x62\xaf\x05\xab\xfe\x8f\x45\x0d\xe5\xf3\x6b\xc6\xb0\x45\x5a\x85\x20\xbc\x4e\x6f\x5f\xe9\x5b\x1f\xe3\xc8\x45\x2b", 48); + vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91\x74\x60\x39", 48); + + vector_abc_final(h, cf_sha384_digest_final, "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48); + + vector_length(h, 1024, "\xae\xe7\xf1\x43\xef\x69\x7b\xa2\xe1\xfd\x39\x9f\xd7\xe6\x28\x9c\x19\xaf\x3c\xc1\xbd\xda\xbd\x3f\x07\xae\xc2\xea\x40\x55\x37\x27\x5f\x41\x49\x50\x3f\xcc\xaf\xa0\xc5\x95\xf7\x62\x9b\xff\x50\x32", 48); +} + +static void test_hmac_sha384(void) +{ + hmac_test(&cf_sha384, + "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6", + "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49", + "\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27", + "\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb"); + hmac_test_sha2(&cf_sha384, + "\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52", + "\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e"); +} + +static void test_sha512(void) +{ + const cf_chash *h = &cf_sha512; + vector(h, "", 0, "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e", 64); + vector(h, "abc", 3, "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f", 64); + vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45", 64); + vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09", 64); + + vector_abc_final(h, cf_sha512_digest_final, "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f", 64); + + vector_length(h, 1024, "\x61\x20\x81\x2e\xd5\x0c\xc3\x11\x67\x04\x3f\x1f\x06\x9d\xcd\x4a\xd8\x83\x23\xd9\x96\x53\xd9\x67\x38\x2c\xc3\x44\x25\x69\x53\x1c\xd0\x3d\xe4\x79\x0a\x71\xde\x88\x45\x44\x66\x80\xb8\xc5\x90\xb3\x07\xc8\xae\x52\x57\x67\xf9\x28\xf8\xda\x9e\x9e\x80\xc9\x35\x5e", 64); +} + +static void test_hmac_sha512(void) +{ + hmac_test(&cf_sha512, + "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54", + "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37", + "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb", + "\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd"); + hmac_test_sha2(&cf_sha512, + "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98", + "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58"); +} + +#ifdef REALLY_SLOW_TEST +static void test_sha256_long(void) +{ + uint8_t digest[32]; + cf_sha256_context ctx; + cf_sha256_init(&ctx); + + for (size_t i = 0; i < 0x1000000; i++) + cf_sha256_update(&ctx, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno", 64); + cf_sha256_digest_final(&ctx, digest); + + uint8_t expect[32]; + unhex(expect, sizeof expect, "\x50\xe7\x2a\x0e\x26\x44\x2f\xe2\x55\x2d\xc3\x93\x8a\xc5\x86\x58\x22\x8c\x0c\xbf\xb1\xd2\xca\x87\x2a\xe4\x35\x26\x6f\xcd\x05\x5e", 32); + TEST_CHECK(memcmp(expect, digest, sizeof digest) == 0); +} +#endif + +static void check_pkbdf2_sha256(const void *pw, size_t npw, + const void *salt, size_t nsalt, + uint32_t iters, + const void *expect, size_t nexpect) +{ + uint8_t output[64]; + + cf_pbkdf2_hmac((const void *) pw, npw, + (const void *) salt, nsalt, + iters, + output, nexpect, + &cf_sha256); + + TEST_CHECK(memcmp(expect, output, nexpect) == 0); +} + +static void test_pbkdf2_sha256(void) +{ + check_pkbdf2_sha256("password", 8, + "salt", 4, + 1, + "\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52\x56\xc4\xf8\x37\xa8\x65\x48\xc9\x2c\xcc\x35\x48\x08\x05\x98\x7c\xb7\x0b\xe1\x7b", 32); + + check_pkbdf2_sha256("password", 8, + "salt", 4, + 2, + "\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e\xf3\xc2\x51\xdf\xd6\xe2\xd8\x5a\x95\x47\x4c\x43", 32); + + check_pkbdf2_sha256("password", 8, + "salt", 4, + 4096, + "\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6\x84\x5c\x4c\x8d\x96\x28\x93\xa0\x01\xce\x4e\x11\xa4\x96\x38\x73\xaa\x98\x13\x4a", 32); + + check_pkbdf2_sha256("passwordPASSWORDpassword", 24, + "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, + 4096, + "\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11\x6e\x84\xcf\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c\x4e\x2a\x1f\xb8\xdd\x53\xe1\xc6\x35\x51\x8c\x7d\xac\x47\xe9", 40); + + check_pkbdf2_sha256("", 0, + "salt", 4, + 1024, + "\x9e\x83\xf2\x79\xc0\x40\xf2\xa1\x1a\xa4\xa0\x2b\x24\xc4\x18\xf2\xd3\xcb\x39\x56\x0c\x96\x27\xfa\x4f\x47\xe3\xbc\xc2\x89\x7c\x3d", 32); + + check_pkbdf2_sha256("password", 8, + "", 0, + 1024, + "\xea\x58\x08\x41\x1e\xb0\xc7\xe8\x30\xde\xab\x55\x09\x6c\xee\x58\x27\x61\xe2\x2a\x9b\xc0\x34\xe3\xec\xe9\x25\x22\x5b\x07\xbf\x46", 32); + + check_pkbdf2_sha256("\x70\x61\x73\x73\x00\x77\x6f\x72\x64", 9, + "\x73\x61\x00\x6c\x74", 5, + 4096, + "\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26\x65\x0a\x86\x87", 16); +} + +TEST_LIST = { + { "sha224", test_sha224}, + { "sha256", test_sha256 }, + { "sha384", test_sha384 }, + { "sha512", test_sha512 }, + + { "hmac-sha224", test_hmac_sha224 }, + { "hmac-sha256", test_hmac_sha256 }, + { "hmac-sha384", test_hmac_sha384 }, + { "hmac-sha512", test_hmac_sha512 }, + + { "pbkdf2-sha256", test_pbkdf2_sha256 }, + +#ifdef REALLY_SLOW_TEST + { "sha256-long", test_sha256_long }, +#endif + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha3.c b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha3.c new file mode 100644 index 0000000..92ab9cf --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testsha3.c @@ -0,0 +1,104 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "sha3.h" +#include "handy.h" +#include "cutest.h" +#include "testutil.h" +#include "testsha.h" + +static void test_sha3_224(void) +{ + const cf_chash *H = &cf_sha3_224; + vector(H, "", 0, + "\x6b\x4e\x03\x42\x36\x67\xdb\xb7\x3b\x6e\x15\x45\x4f\x0e\xb1\xab\xd4\x59\x7f\x9a\x1b\x07\x8e\x3f\x5b\x5a\x6b\xc7", 28); + vector(H, "abc", 3, + "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf", 28); + vector(H, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x8a\x24\x10\x8b\x15\x4a\xda\x21\xc9\xfd\x55\x74\x49\x44\x79\xba\x5c\x7e\x7a\xb7\x6e\xf2\x64\xea\xd0\xfc\xce\x33", 28); + vector(H, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc", 28); + + /* Artificial exercise for len(msg) = rate_bytes - 1 codepath */ + vector(H, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 143, + "\x73\xb1\xb2\x2b\x54\xf5\x15\xf6\x26\xa6\xab\xdd\xe6\xaf\x25\xcd\x48\x01\xdc\x6e\x9d\xc7\xfa\x3f\x77\xe1\xc1\x22", 28); + + vector_abc_final(H, cf_sha3_224_digest_final, + "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf", 28); + + vector_length(H, 1024, "\xf2\x54\xf3\x67\x6d\xc6\xc0\x0f\x2f\xee\x50\x59\x07\x62\x8b\x0d\x5b\x9e\xdf\xf8\xe8\xc2\x9e\x9b\xa7\xd6\x05\xdd", 28); +} + +static void test_sha3_256(void) +{ + const cf_chash *H = &cf_sha3_256; + vector(H, "", 0, + "\xa7\xff\xc6\xf8\xbf\x1e\xd7\x66\x51\xc1\x47\x56\xa0\x61\xd6\x62\xf5\x80\xff\x4d\xe4\x3b\x49\xfa\x82\xd8\x0a\x4b\x80\xf8\x43\x4a", 32); + vector(H, "abc", 3, + "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32", 32); + vector(H, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x41\xc0\xdb\xa2\xa9\xd6\x24\x08\x49\x10\x03\x76\xa8\x23\x5e\x2c\x82\xe1\xb9\x99\x8a\x99\x9e\x21\xdb\x32\xdd\x97\x49\x6d\x33\x76", 32); + vector(H, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf\xdb\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18", 32); + + vector_abc_final(H, cf_sha3_256_digest_final, + "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32", 32); + + vector_length(H, 1024, "\xf7\xed\xf7\x2b\x34\x8c\xb4\xab\x5e\xe7\x4f\x6c\xae\xaf\x11\xad\xe2\x2f\x04\x65\x84\x8e\x5c\xaa\x14\x38\x7f\xd4\xeb\xdb\x9d\x70", 32); +} + +static void test_sha3_384(void) +{ + const cf_chash *H = &cf_sha3_384; + vector(H, "", 0, + "\x0c\x63\xa7\x5b\x84\x5e\x4f\x7d\x01\x10\x7d\x85\x2e\x4c\x24\x85\xc5\x1a\x50\xaa\xaa\x94\xfc\x61\x99\x5e\x71\xbb\xee\x98\x3a\x2a\xc3\x71\x38\x31\x26\x4a\xdb\x47\xfb\x6b\xd1\xe0\x58\xd5\xf0\x04", 48); + vector(H, "abc", 3, + "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25", 48); + vector(H, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x99\x1c\x66\x57\x55\xeb\x3a\x4b\x6b\xbd\xfb\x75\xc7\x8a\x49\x2e\x8c\x56\xa2\x2c\x5c\x4d\x7e\x42\x9b\xfd\xbc\x32\xb9\xd4\xad\x5a\xa0\x4a\x1f\x07\x6e\x62\xfe\xa1\x9e\xef\x51\xac\xd0\x65\x7c\x22", 48); + vector(H, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7", 48); + + vector_abc_final(H, cf_sha3_384_digest_final, + "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25", 48); + + vector_length(H, 1024, "\xc2\x16\x48\x6a\x00\x32\xb1\xe1\x98\xf8\x72\x52\x01\x87\xba\xd4\xcf\x39\x13\x9c\x54\x21\x6d\x78\x86\x93\x88\xf9\x75\x03\xc1\x11\xcc\x7f\x5a\xc3\x21\x00\x3f\xc8\xa1\xf7\xfa\x10\x75\x60\xdb\xb1", 48); +} + +static void test_sha3_512(void) +{ + const cf_chash *H = &cf_sha3_512; + vector(H, "", 0, + "\xa6\x9f\x73\xcc\xa2\x3a\x9a\xc5\xc8\xb5\x67\xdc\x18\x5a\x75\x6e\x97\xc9\x82\x16\x4f\xe2\x58\x59\xe0\xd1\xdc\xc1\x47\x5c\x80\xa6\x15\xb2\x12\x3a\xf1\xf5\xf9\x4c\x11\xe3\xe9\x40\x2c\x3a\xc5\x58\xf5\x00\x19\x9d\x95\xb6\xd3\xe3\x01\x75\x85\x86\x28\x1d\xcd\x26", 64); + vector(H, "abc", 3, + "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0", 64); + vector(H, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x04\xa3\x71\xe8\x4e\xcf\xb5\xb8\xb7\x7c\xb4\x86\x10\xfc\xa8\x18\x2d\xd4\x57\xce\x6f\x32\x6a\x0f\xd3\xd7\xec\x2f\x1e\x91\x63\x6d\xee\x69\x1f\xbe\x0c\x98\x53\x02\xba\x1b\x0d\x8d\xc7\x8c\x08\x63\x46\xb5\x33\xb4\x9c\x03\x0d\x99\xa2\x7d\xaf\x11\x39\xd6\xe7\x5e", 64); + vector(H, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85", 64); + + vector_abc_final(H, cf_sha3_512_digest_final, + "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0", 64); + + vector_length(H, 1024, "\x3a\x98\x11\x17\xbc\x2f\xa3\x3b\x00\x51\x71\xf8\x80\x86\x33\x7f\x4f\x6c\xe9\xd1\x5c\xb7\x38\xc0\x9b\xe2\x8a\xb6\xd5\x38\xba\xbf\x7b\xc5\x4e\xbf\x3d\xdb\x53\x4a\x9c\x3c\x10\x85\xe7\x18\x3d\x46\xa5\x8c\xbc\xb0\x15\xb0\xdf\x50\x7a\xad\x0e\xdf\xf3\x54\x8e\xfd", 64); +} + +TEST_LIST = { + { "sha3-224", test_sha3_224 }, + { "sha3-256", test_sha3_256 }, + { "sha3-384", test_sha3_384 }, + { "sha3-512", test_sha3_512 }, + { 0 } +}; + diff --git a/debian/vendor-h2o/deps/picotls/deps/cifra/src/testutil.h b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testutil.h new file mode 100644 index 0000000..b9a52b3 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/cifra/src/testutil.h @@ -0,0 +1,61 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#ifndef TESTUTIL_H +#define TESTUTIL_H + +#include <assert.h> +#include <string.h> +#include <stdio.h> + +static inline uint8_t unhex_chr(char a) +{ + if (a >= '0' && a <= '9') + return a - '0'; + else if (a >= 'a' && a <= 'f') + return a - 'a' + 10; + else if (a >= 'A' && a <= 'F') + return a - 'A' + 10; + return 0; +} + +static inline size_t unhex(uint8_t *buf, size_t len, const char *str) +{ + size_t used = 0; + + assert(strlen(str) % 2 == 0); + assert(strlen(str) / 2 <= len); + + while (*str) + { + assert(len); + *buf = unhex_chr(str[0]) << 4 | unhex_chr(str[1]); + buf++; + used++; + str += 2; + len--; + } + + return used; +} + +static inline void dump(const char *label, const uint8_t *buf, size_t len) +{ + printf("%s: ", label); + for (size_t i = 0; i < len; i++) + printf("%02x", buf[i]); + printf("\n"); +} + +#endif diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/LICENSE.txt b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/LICENSE.txt new file mode 100644 index 0000000..ab099ae --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) 2014, Kenneth MacKay +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/README.md b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/README.md new file mode 100644 index 0000000..01926e3 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/README.md @@ -0,0 +1,41 @@ +micro-ecc +========== + +A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors. + +The static version of micro-ecc (ie, where the curve was selected at compile-time) can be found in the "static" branch. + +Features +-------- + + * Resistant to known side-channel attacks. + * Written in C, with optional GCC inline assembly for AVR, ARM and Thumb platforms. + * Supports 8, 32, and 64-bit architectures. + * Small code size. + * No dynamic memory allocation. + * Support for 5 standard curves: secp160r1, secp192r1, secp224r1, secp256r1, and secp256k1. + * BSD 2-clause license. + +Usage Notes +----------- +### Point Representation ### +Compressed points are represented in the standard format as defined in http://www.secg.org/collateral/sec1_final.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_compress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations. + +Private keys are represented in the standard format. + +### Using the Code ### + +I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions. + +For use with Arduino, you can just create a symlink to the `uECC` directory in your Arduino `libraries` directory. You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu). + +See uECC.h for documentation for each function. + +### Compilation Notes ### + + * Should compile with any C/C++ compiler that supports stdint.h (this includes Visual Studio 2013). + * If you want to change the defaults for any of the uECC compile-time options (such as `uECC_OPTIMIZATION_LEVEL`), you must change them in your Makefile or similar so that uECC.c is compiled with the desired values (ie, compile uECC.c with `-DuECC_OPTIMIZATION_LEVEL=3` or whatever). + * When compiling for a Thumb-1 platform, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher). + * When compiling for an ARM/Thumb-2 platform with `uECC_OPTIMIZATION_LEVEL` >= 3, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher). + * When compiling for AVR, you must have optimizations enabled (compile with `-O1` or higher). + * When building for Windows, you will need to link in the `advapi32.lib` system library. diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm.inc b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm.inc new file mode 100644 index 0000000..688fdc7 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm.inc @@ -0,0 +1,820 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_ARM_H_ +#define _UECC_ASM_ARM_H_ + +#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #define uECC_MIN_WORDS 8 +#endif +#if uECC_SUPPORTS_secp224r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 7 +#endif +#if uECC_SUPPORTS_secp192r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 6 +#endif +#if uECC_SUPPORTS_secp160r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 5 +#endif + +#if (uECC_PLATFORM == uECC_arm_thumb) + #define REG_RW "+l" + #define REG_WRITE "=l" +#else + #define REG_RW "+r" + #define REG_WRITE "=r" +#endif + +#if (uECC_PLATFORM == uECC_arm_thumb || uECC_PLATFORM == uECC_arm_thumb2) + #define REG_RW_LO "+l" + #define REG_WRITE_LO "=l" +#else + #define REG_RW_LO "+r" + #define REG_WRITE_LO "=r" +#endif + +#if (uECC_PLATFORM == uECC_arm_thumb2) + #define RESUME_SYNTAX +#else + #define RESUME_SYNTAX ".syntax divided \n\t" +#endif + +#if (uECC_OPTIMIZATION_LEVEL >= 2) + +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { +#if (uECC_MAX_WORDS != uECC_MIN_WORDS) + #if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2) + uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1; + #else /* ARM */ + uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4; + #endif +#endif + uint32_t carry; + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + ".syntax unified \n\t" + "movs %[carry], #0 \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "adr %[left], 1f \n\t" + ".align 4 \n\t" + "adds %[jump], %[left] \n\t" + #endif + + "ldmia %[lptr]!, {%[left]} \n\t" + "ldmia %[rptr]!, {%[right]} \n\t" + "adds %[left], %[right] \n\t" + "stmia %[dptr]!, {%[left]} \n\t" + + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "bx %[jump] \n\t" + #endif + "1: \n\t" + REPEAT(DEC(uECC_MAX_WORDS), + "ldmia %[lptr]!, {%[left]} \n\t" + "ldmia %[rptr]!, {%[right]} \n\t" + "adcs %[left], %[right] \n\t" + "stmia %[dptr]!, {%[left]} \n\t") + + "adcs %[carry], %[carry] \n\t" + RESUME_SYNTAX + : [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right), + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + [jump] REG_RW_LO (jump), + #endif + [carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word), + [right] REG_WRITE_LO (right_word) + : + : "cc", "memory" + ); + return carry; +} +#define asm_add 1 + +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { +#if (uECC_MAX_WORDS != uECC_MIN_WORDS) + #if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2) + uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1; + #else /* ARM */ + uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4; + #endif +#endif + uint32_t carry; + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + ".syntax unified \n\t" + "movs %[carry], #0 \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "adr %[left], 1f \n\t" + ".align 4 \n\t" + "adds %[jump], %[left] \n\t" + #endif + + "ldmia %[lptr]!, {%[left]} \n\t" + "ldmia %[rptr]!, {%[right]} \n\t" + "subs %[left], %[right] \n\t" + "stmia %[dptr]!, {%[left]} \n\t" + + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "bx %[jump] \n\t" + #endif + "1: \n\t" + REPEAT(DEC(uECC_MAX_WORDS), + "ldmia %[lptr]!, {%[left]} \n\t" + "ldmia %[rptr]!, {%[right]} \n\t" + "sbcs %[left], %[right] \n\t" + "stmia %[dptr]!, {%[left]} \n\t") + + "adcs %[carry], %[carry] \n\t" + RESUME_SYNTAX + : [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right), + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + [jump] REG_RW_LO (jump), + #endif + [carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word), + [right] REG_WRITE_LO (right_word) + : + : "cc", "memory" + ); + return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting + (for some reason...) */ +} +#define asm_sub 1 + +#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */ + +#if (uECC_OPTIMIZATION_LEVEL >= 3) + +#if (uECC_PLATFORM != uECC_arm_thumb) + +#if uECC_ARM_USE_UMAAL + #include "asm_arm_mult_square_umaal.inc" +#else + #include "asm_arm_mult_square.inc" +#endif + +#if (uECC_OPTIMIZATION_LEVEL == 3) + +uECC_VLI_API void uECC_vli_mult(uint32_t *result, + const uint32_t *left, + const uint32_t *right, + wordcount_t num_words) { + register uint32_t *r0 __asm__("r0") = result; + register const uint32_t *r1 __asm__("r1") = left; + register const uint32_t *r2 __asm__("r2") = right; + register uint32_t r3 __asm__("r3") = num_words; + + __asm__ volatile ( + ".syntax unified \n\t" +#if (uECC_MIN_WORDS == 5) + FAST_MULT_ASM_5 + #if (uECC_MAX_WORDS > 5) + FAST_MULT_ASM_5_TO_6 + #endif + #if (uECC_MAX_WORDS > 6) + FAST_MULT_ASM_6_TO_7 + #endif + #if (uECC_MAX_WORDS > 7) + FAST_MULT_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 6) + FAST_MULT_ASM_6 + #if (uECC_MAX_WORDS > 6) + FAST_MULT_ASM_6_TO_7 + #endif + #if (uECC_MAX_WORDS > 7) + FAST_MULT_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 7) + FAST_MULT_ASM_7 + #if (uECC_MAX_WORDS > 7) + FAST_MULT_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 8) + FAST_MULT_ASM_8 +#endif + "1: \n\t" + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); +} +#define asm_mult 1 + +#if uECC_SQUARE_FUNC +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + register uint32_t *r0 __asm__("r0") = result; + register const uint32_t *r1 __asm__("r1") = left; + register uint32_t r2 __asm__("r2") = num_words; + + __asm__ volatile ( + ".syntax unified \n\t" +#if (uECC_MIN_WORDS == 5) + FAST_SQUARE_ASM_5 + #if (uECC_MAX_WORDS > 5) + FAST_SQUARE_ASM_5_TO_6 + #endif + #if (uECC_MAX_WORDS > 6) + FAST_SQUARE_ASM_6_TO_7 + #endif + #if (uECC_MAX_WORDS > 7) + FAST_SQUARE_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 6) + FAST_SQUARE_ASM_6 + #if (uECC_MAX_WORDS > 6) + FAST_SQUARE_ASM_6_TO_7 + #endif + #if (uECC_MAX_WORDS > 7) + FAST_SQUARE_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 7) + FAST_SQUARE_ASM_7 + #if (uECC_MAX_WORDS > 7) + FAST_SQUARE_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 8) + FAST_SQUARE_ASM_8 +#endif + + "1: \n\t" + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); +} +#define asm_square 1 +#endif /* uECC_SQUARE_FUNC */ + +#else /* (uECC_OPTIMIZATION_LEVEL > 3) */ + +uECC_VLI_API void uECC_vli_mult(uint32_t *result, + const uint32_t *left, + const uint32_t *right, + wordcount_t num_words) { + register uint32_t *r0 __asm__("r0") = result; + register const uint32_t *r1 __asm__("r1") = left; + register const uint32_t *r2 __asm__("r2") = right; + register uint32_t r3 __asm__("r3") = num_words; + +#if uECC_SUPPORTS_secp160r1 + if (num_words == 5) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_MULT_ASM_5 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if uECC_SUPPORTS_secp192r1 + if (num_words == 6) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_MULT_ASM_6 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if uECC_SUPPORTS_secp224r1 + if (num_words == 7) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_MULT_ASM_7 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + if (num_words == 8) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_MULT_ASM_8 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +} +#define asm_mult 1 + +#if uECC_SQUARE_FUNC +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + register uint32_t *r0 __asm__("r0") = result; + register const uint32_t *r1 __asm__("r1") = left; + register uint32_t r2 __asm__("r2") = num_words; + +#if uECC_SUPPORTS_secp160r1 + if (num_words == 5) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_SQUARE_ASM_5 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if uECC_SUPPORTS_secp192r1 + if (num_words == 6) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_SQUARE_ASM_6 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if uECC_SUPPORTS_secp224r1 + if (num_words == 7) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_SQUARE_ASM_7 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + if (num_words == 8) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_SQUARE_ASM_8 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +} +#define asm_square 1 +#endif /* uECC_SQUARE_FUNC */ + +#endif /* (uECC_OPTIMIZATION_LEVEL > 3) */ + +#endif /* uECC_PLATFORM != uECC_arm_thumb */ + +#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */ + +/* ---- "Small" implementations ---- */ + +#if !asm_add +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uint32_t carry = 0; + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + ".syntax unified \n\t" + "1: \n\t" + "ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */ + "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */ + "lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */ + "adcs %[left], %[left], %[right] \n\t" /* Add with carry. */ + "adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */ + "stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */ + "subs %[ctr], #1 \n\t" /* Decrement counter. */ + "bne 1b \n\t" /* Loop until counter == 0. */ + RESUME_SYNTAX + : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right), + [ctr] REG_RW (num_words), [carry] REG_RW (carry), + [left] REG_WRITE (left_word), [right] REG_WRITE (right_word) + : + : "cc", "memory" + ); + return carry; +} +#define asm_add 1 +#endif + +#if !asm_sub +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */ + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + ".syntax unified \n\t" + "1: \n\t" + "ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */ + "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */ + "lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */ + "sbcs %[left], %[left], %[right] \n\t" /* Subtract with borrow. */ + "adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */ + "stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */ + "subs %[ctr], #1 \n\t" /* Decrement counter. */ + "bne 1b \n\t" /* Loop until counter == 0. */ + RESUME_SYNTAX + : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right), + [ctr] REG_RW (num_words), [carry] REG_RW (carry), + [left] REG_WRITE (left_word), [right] REG_WRITE (right_word) + : + : "cc", "memory" + ); + return !carry; +} +#define asm_sub 1 +#endif + +#if !asm_mult +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { +#if (uECC_PLATFORM != uECC_arm_thumb) + uint32_t c0 = 0; + uint32_t c1 = 0; + uint32_t c2 = 0; + uint32_t k = 0; + uint32_t i; + uint32_t t0, t1; + + __asm__ volatile ( + ".syntax unified \n\t" + + "1: \n\t" /* outer loop (k < num_words) */ + "movs %[i], #0 \n\t" /* i = 0 */ + "b 3f \n\t" + + "2: \n\t" /* outer loop (k >= num_words) */ + "movs %[i], %[k] \n\t" /* i = k */ + "subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */ + + "3: \n\t" /* inner loop */ + "subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */ + + "ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = right[k - i] */ + "ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */ + + "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */ + + "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */ + "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */ + "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */ + + "adds %[i], #4 \n\t" /* i += 4 */ + "cmp %[i], %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */ + "bgt 4f \n\t" /* if so, exit the loop */ + "cmp %[i], %[k] \n\t" /* i <= k? */ + "ble 3b \n\t" /* if so, continue looping */ + + "4: \n\t" /* end inner loop */ + + "str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */ + "mov %[c0], %[c1] \n\t" /* c0 = c1 */ + "mov %[c1], %[c2] \n\t" /* c1 = c2 */ + "movs %[c2], #0 \n\t" /* c2 = 0 */ + "adds %[k], #4 \n\t" /* k += 4 */ + "cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */ + "ble 1b \n\t" /* if so, loop back, start with i = 0 */ + "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */ + "ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */ + /* end outer loop */ + + "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */ + RESUME_SYNTAX + : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2), + [k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1) + : [result] "r" (result), [left] "r" (left), [right] "r" (right), + [last_word] "r" ((num_words - 1) * 4) + : "cc", "memory" + ); + +#else /* Thumb-1 */ + uint32_t r4, r5, r6, r7; + + __asm__ volatile ( + ".syntax unified \n\t" + "subs %[r3], #1 \n\t" /* r3 = num_words - 1 */ + "lsls %[r3], #2 \n\t" /* r3 = (num_words - 1) * 4 */ + "mov r8, %[r3] \n\t" /* r8 = (num_words - 1) * 4 */ + "lsls %[r3], #1 \n\t" /* r3 = (num_words - 1) * 8 */ + "mov r9, %[r3] \n\t" /* r9 = (num_words - 1) * 8 */ + "movs %[r3], #0 \n\t" /* c0 = 0 */ + "movs %[r4], #0 \n\t" /* c1 = 0 */ + "movs %[r5], #0 \n\t" /* c2 = 0 */ + "movs %[r6], #0 \n\t" /* k = 0 */ + + "push {%[r0]} \n\t" /* keep result on the stack */ + + "1: \n\t" /* outer loop (k < num_words) */ + "movs %[r7], #0 \n\t" /* r7 = i = 0 */ + "b 3f \n\t" + + "2: \n\t" /* outer loop (k >= num_words) */ + "movs %[r7], %[r6] \n\t" /* r7 = k */ + "mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */ + "subs %[r7], %[r0] \n\t" /* r7 = i = k - (num_words - 1) (times 4) */ + + "3: \n\t" /* inner loop */ + "mov r10, %[r3] \n\t" + "mov r11, %[r4] \n\t" + "mov r12, %[r5] \n\t" + "mov r14, %[r6] \n\t" + "subs %[r0], %[r6], %[r7] \n\t" /* r0 = k - i */ + + "ldr %[r4], [%[r2], %[r0]] \n\t" /* r4 = right[k - i] */ + "ldr %[r0], [%[r1], %[r7]] \n\t" /* r0 = left[i] */ + + "lsrs %[r3], %[r0], #16 \n\t" /* r3 = a1 */ + "uxth %[r0], %[r0] \n\t" /* r0 = a0 */ + + "lsrs %[r5], %[r4], #16 \n\t" /* r5 = b1 */ + "uxth %[r4], %[r4] \n\t" /* r4 = b0 */ + + "movs %[r6], %[r3] \n\t" /* r6 = a1 */ + "muls %[r6], %[r5], %[r6] \n\t" /* r6 = a1 * b1 */ + "muls %[r3], %[r4], %[r3] \n\t" /* r3 = b0 * a1 */ + "muls %[r5], %[r0], %[r5] \n\t" /* r5 = a0 * b1 */ + "muls %[r0], %[r4], %[r0] \n\t" /* r0 = a0 * b0 */ + + /* Add middle terms */ + "lsls %[r4], %[r3], #16 \n\t" + "lsrs %[r3], %[r3], #16 \n\t" + "adds %[r0], %[r4] \n\t" + "adcs %[r6], %[r3] \n\t" + + "lsls %[r4], %[r5], #16 \n\t" + "lsrs %[r5], %[r5], #16 \n\t" + "adds %[r0], %[r4] \n\t" + "adcs %[r6], %[r5] \n\t" + + "mov %[r3], r10\n\t" + "mov %[r4], r11\n\t" + "mov %[r5], r12\n\t" + "adds %[r3], %[r0] \n\t" /* add low word to c0 */ + "adcs %[r4], %[r6] \n\t" /* add high word to c1, including carry */ + "movs %[r0], #0 \n\t" /* r0 = 0 (does not affect carry bit) */ + "adcs %[r5], %[r0] \n\t" /* add carry to c2 */ + + "mov %[r6], r14\n\t" /* r6 = k */ + + "adds %[r7], #4 \n\t" /* i += 4 */ + "cmp %[r7], r8 \n\t" /* i > (num_words - 1) (times 4)? */ + "bgt 4f \n\t" /* if so, exit the loop */ + "cmp %[r7], %[r6] \n\t" /* i <= k? */ + "ble 3b \n\t" /* if so, continue looping */ + + "4: \n\t" /* end inner loop */ + + "ldr %[r0], [sp, #0] \n\t" /* r0 = result */ + + "str %[r3], [%[r0], %[r6]] \n\t" /* result[k] = c0 */ + "mov %[r3], %[r4] \n\t" /* c0 = c1 */ + "mov %[r4], %[r5] \n\t" /* c1 = c2 */ + "movs %[r5], #0 \n\t" /* c2 = 0 */ + "adds %[r6], #4 \n\t" /* k += 4 */ + "cmp %[r6], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */ + "ble 1b \n\t" /* if so, loop back, start with i = 0 */ + "cmp %[r6], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */ + "ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */ + /* end outer loop */ + + "str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */ + "pop {%[r0]} \n\t" /* pop result off the stack */ + + ".syntax divided \n\t" + : [r3] "+l" (num_words), [r4] "=&l" (r4), + [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7) + : [r0] "l" (result), [r1] "l" (left), [r2] "l" (right) + : "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); +#endif +} +#define asm_mult 1 +#endif + +#if uECC_SQUARE_FUNC +#if !asm_square +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { +#if (uECC_PLATFORM != uECC_arm_thumb) + uint32_t c0 = 0; + uint32_t c1 = 0; + uint32_t c2 = 0; + uint32_t k = 0; + uint32_t i, tt; + uint32_t t0, t1; + + __asm__ volatile ( + ".syntax unified \n\t" + + "1: \n\t" /* outer loop (k < num_words) */ + "movs %[i], #0 \n\t" /* i = 0 */ + "b 3f \n\t" + + "2: \n\t" /* outer loop (k >= num_words) */ + "movs %[i], %[k] \n\t" /* i = k */ + "subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */ + + "3: \n\t" /* inner loop */ + "subs %[tt], %[k], %[i] \n\t" /* tt = k-i */ + + "ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = left[k - i] */ + "ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */ + + "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */ + + "cmp %[i], %[tt] \n\t" /* (i < k - i) ? */ + "bge 4f \n\t" /* if i >= k - i, skip */ + "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */ + "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */ + "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */ + + "4: \n\t" + "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */ + "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */ + "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */ + + "adds %[i], #4 \n\t" /* i += 4 */ + "cmp %[i], %[k] \n\t" /* i >= k? */ + "bge 5f \n\t" /* if so, exit the loop */ + "subs %[tt], %[k], %[i] \n\t" /* tt = k - i */ + "cmp %[i], %[tt] \n\t" /* i <= k - i? */ + "ble 3b \n\t" /* if so, continue looping */ + + "5: \n\t" /* end inner loop */ + + "str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */ + "mov %[c0], %[c1] \n\t" /* c0 = c1 */ + "mov %[c1], %[c2] \n\t" /* c1 = c2 */ + "movs %[c2], #0 \n\t" /* c2 = 0 */ + "adds %[k], #4 \n\t" /* k += 4 */ + "cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */ + "ble 1b \n\t" /* if so, loop back, start with i = 0 */ + "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */ + "ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */ + /* end outer loop */ + + "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */ + RESUME_SYNTAX + : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2), + [k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1) + : [result] "r" (result), [left] "r" (left), [last_word] "r" ((num_words - 1) * 4) + : "cc", "memory" + ); + +#else + uint32_t r3, r4, r5, r6, r7; + + __asm__ volatile ( + ".syntax unified \n\t" + "subs %[r2], #1 \n\t" /* r2 = num_words - 1 */ + "lsls %[r2], #2 \n\t" /* r2 = (num_words - 1) * 4 */ + "mov r8, %[r2] \n\t" /* r8 = (num_words - 1) * 4 */ + "lsls %[r2], #1 \n\t" /* r2 = (num_words - 1) * 8 */ + "mov r9, %[r2] \n\t" /* r9 = (num_words - 1) * 8 */ + "movs %[r2], #0 \n\t" /* c0 = 0 */ + "movs %[r3], #0 \n\t" /* c1 = 0 */ + "movs %[r4], #0 \n\t" /* c2 = 0 */ + "movs %[r5], #0 \n\t" /* k = 0 */ + + "push {%[r0]} \n\t" /* keep result on the stack */ + + "1: \n\t" /* outer loop (k < num_words) */ + "movs %[r6], #0 \n\t" /* r6 = i = 0 */ + "b 3f \n\t" + + "2: \n\t" /* outer loop (k >= num_words) */ + "movs %[r6], %[r5] \n\t" /* r6 = k */ + "mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */ + "subs %[r6], %[r0] \n\t" /* r6 = i = k - (num_words - 1) (times 4) */ + + "3: \n\t" /* inner loop */ + "mov r10, %[r2] \n\t" + "mov r11, %[r3] \n\t" + "mov r12, %[r4] \n\t" + "mov r14, %[r5] \n\t" + "subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */ + + "ldr %[r3], [%[r1], %[r7]] \n\t" /* r3 = left[k - i] */ + "ldr %[r0], [%[r1], %[r6]] \n\t" /* r0 = left[i] */ + + "lsrs %[r2], %[r0], #16 \n\t" /* r2 = a1 */ + "uxth %[r0], %[r0] \n\t" /* r0 = a0 */ + + "lsrs %[r4], %[r3], #16 \n\t" /* r4 = b1 */ + "uxth %[r3], %[r3] \n\t" /* r3 = b0 */ + + "movs %[r5], %[r2] \n\t" /* r5 = a1 */ + "muls %[r5], %[r4], %[r5] \n\t" /* r5 = a1 * b1 */ + "muls %[r2], %[r3], %[r2] \n\t" /* r2 = b0 * a1 */ + "muls %[r4], %[r0], %[r4] \n\t" /* r4 = a0 * b1 */ + "muls %[r0], %[r3], %[r0] \n\t" /* r0 = a0 * b0 */ + + /* Add middle terms */ + "lsls %[r3], %[r2], #16 \n\t" + "lsrs %[r2], %[r2], #16 \n\t" + "adds %[r0], %[r3] \n\t" + "adcs %[r5], %[r2] \n\t" + + "lsls %[r3], %[r4], #16 \n\t" + "lsrs %[r4], %[r4], #16 \n\t" + "adds %[r0], %[r3] \n\t" + "adcs %[r5], %[r4] \n\t" + + /* Add to acc, doubling if necessary */ + "mov %[r2], r10\n\t" + "mov %[r3], r11\n\t" + "mov %[r4], r12\n\t" + + "cmp %[r6], %[r7] \n\t" /* (i < k - i) ? */ + "bge 4f \n\t" /* if i >= k - i, skip */ + "movs %[r7], #0 \n\t" /* r7 = 0 */ + "adds %[r2], %[r0] \n\t" /* add low word to c0 */ + "adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */ + "adcs %[r4], %[r7] \n\t" /* add carry to c2 */ + "4: \n\t" + "movs %[r7], #0 \n\t" /* r7 = 0 */ + "adds %[r2], %[r0] \n\t" /* add low word to c0 */ + "adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */ + "adcs %[r4], %[r7] \n\t" /* add carry to c2 */ + + "mov %[r5], r14\n\t" /* r5 = k */ + + "adds %[r6], #4 \n\t" /* i += 4 */ + "cmp %[r6], %[r5] \n\t" /* i >= k? */ + "bge 5f \n\t" /* if so, exit the loop */ + "subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */ + "cmp %[r6], %[r7] \n\t" /* i <= k - i? */ + "ble 3b \n\t" /* if so, continue looping */ + + "5: \n\t" /* end inner loop */ + + "ldr %[r0], [sp, #0] \n\t" /* r0 = result */ + + "str %[r2], [%[r0], %[r5]] \n\t" /* result[k] = c0 */ + "mov %[r2], %[r3] \n\t" /* c0 = c1 */ + "mov %[r3], %[r4] \n\t" /* c1 = c2 */ + "movs %[r4], #0 \n\t" /* c2 = 0 */ + "adds %[r5], #4 \n\t" /* k += 4 */ + "cmp %[r5], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */ + "ble 1b \n\t" /* if so, loop back, start with i = 0 */ + "cmp %[r5], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */ + "ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */ + /* end outer loop */ + + "str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */ + "pop {%[r0]} \n\t" /* pop result off the stack */ + + ".syntax divided \n\t" + : [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4), + [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7) + : [r0] "l" (result), [r1] "l" (left) + : "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); +#endif +} +#define asm_square 1 +#endif +#endif /* uECC_SQUARE_FUNC */ + +#endif /* _UECC_ASM_ARM_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square.inc b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square.inc new file mode 100644 index 0000000..8907fc1 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square.inc @@ -0,0 +1,2311 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_ARM_MULT_SQUARE_H_ +#define _UECC_ASM_ARM_MULT_SQUARE_H_ + +#define FAST_MULT_ASM_5 \ + "push {r3} \n\t" \ + "add r0, 12 \n\t" \ + "add r2, 12 \n\t" \ + "ldmia r1!, {r3,r4} \n\t" \ + "ldmia r2!, {r6,r7} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adc r10, r10, r14 \n\t" \ + "stmia r0!, {r9, r10} \n\t" \ + \ + "sub r0, 28 \n\t" \ + "sub r2, 20 \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + "ldmia r1!, {r5} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adc r11, r11, r9 \n\t" \ + "stmia r0!, {r10, r11} \n\t" \ + "pop {r3} \n\t" + +#define FAST_MULT_ASM_5_TO_6 \ + "cmp r3, #5 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high, r5 = right high */ \ + "ldr r4, [r1] \n\t" \ + "ldr r5, [r2] \n\t" \ + \ + "sub r0, #20 \n\t" \ + "sub r1, #20 \n\t" \ + "sub r2, #20 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + /* skip past already-loaded (r4, r5) */ \ + "ldr r7, [r1], #8 \n\t" \ + "ldr r8, [r2], #8 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "umull r11, r12, r4, r5 \n\t" \ + "adds r11, r11, r14 \n\t" \ + "adc r12, r12, r9 \n\t" \ + "stmia r0!, {r11, r12} \n\t" + +#define FAST_MULT_ASM_6 \ + "push {r3} \n\t" \ + "add r0, 12 \n\t" \ + "add r2, 12 \n\t" \ + "ldmia r1!, {r3,r4,r5} \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adc r12, r12, r10 \n\t" \ + "stmia r0!, {r11, r12} \n\t" \ + \ + "sub r0, 36 \n\t" \ + "sub r2, 24 \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r1!, {r5} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r2!, {r8} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r3, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r5, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "umull r10, r11, r5, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adc r14, r14, r11 \n\t" \ + "stmia r0!, {r12, r14} \n\t" \ + "pop {r3} \n\t" + +#define FAST_MULT_ASM_6_TO_7 \ + "cmp r3, #6 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high, r5 = right high */ \ + "ldr r4, [r1] \n\t" \ + "ldr r5, [r2] \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + "sub r2, #24 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + /* skip past already-loaded (r4, r5) */ \ + "ldr r7, [r1], #8 \n\t" \ + "ldr r8, [r2], #8 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "umull r11, r12, r4, r5 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adc r12, r12, r10 \n\t" \ + "stmia r0!, {r11, r12} \n\t" + +#define FAST_MULT_ASM_7 \ + "push {r3} \n\t" \ + "add r0, 24 \n\t" \ + "add r2, 24 \n\t" \ + "ldmia r1!, {r3} \n\t" \ + "ldmia r2!, {r6} \n\t" \ + \ + "umull r9, r10, r3, r6 \n\t" \ + "stmia r0!, {r9, r10} \n\t" \ + \ + "sub r0, 20 \n\t" \ + "sub r2, 16 \n\t" \ + "ldmia r2!, {r6, r7, r8} \n\t" \ + "ldmia r1!, {r4, r5} \n\t" \ + \ + "umull r9, r10, r3, r6 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umull r9, r12, r3, r7 \n\t" \ + "adds r10, r10, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r9, r11, r4, r6 \n\t" \ + "adds r10, r10, r9 \n\t" \ + "adcs r12, r12, r11 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r5, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "umull r9, r10, r3, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adc r12, r12, r10 \n\t" \ + "stmia r0!, {r11, r12} \n\t" \ + \ + "sub r0, 44 \n\t" \ + "sub r1, 16 \n\t" \ + "sub r2, 28 \n\t" \ + "ldmia r1!, {r3,r4,r5} \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + \ + "umull r9, r10, r3, r6 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umull r9, r12, r3, r7 \n\t" \ + "adds r10, r10, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r9, r11, r4, r6 \n\t" \ + "adds r10, r10, r9 \n\t" \ + "adcs r12, r12, r11 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r5, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r5} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r3, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r5, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r4, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r3, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r2!, {r8} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r4, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "umull r10, r11, r3, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adc r14, r14, r11 \n\t" \ + "stmia r0!, {r12, r14} \n\t" \ + "pop {r3} \n\t" + +#define FAST_MULT_ASM_7_TO_8 \ + "cmp r3, #7 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high, r5 = right high */ \ + "ldr r4, [r1] \n\t" \ + "ldr r5, [r2] \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + "sub r2, #28 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + /* skip past already-loaded (r4, r5) */ \ + "ldr r7, [r1], #8 \n\t" \ + "ldr r8, [r2], #8 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "umull r11, r12, r4, r5 \n\t" \ + "adds r11, r11, r10 \n\t" \ + "adc r12, r12, r14 \n\t" \ + "stmia r0!, {r11, r12} \n\t" + +#define FAST_MULT_ASM_8 \ + "push {r3} \n\t" \ + "add r0, 24 \n\t" \ + "add r2, 24 \n\t" \ + "ldmia r1!, {r3,r4} \n\t" \ + "ldmia r2!, {r6,r7} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adc r10, r10, r14 \n\t" \ + "stmia r0!, {r9, r10} \n\t" \ + \ + "sub r0, 28 \n\t" \ + "sub r2, 20 \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + "ldmia r1!, {r5} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adc r11, r11, r9 \n\t" \ + "stmia r0!, {r10, r11} \n\t" \ + \ + "sub r0, 52 \n\t" \ + "sub r1, 20 \n\t" \ + "sub r2, 32 \n\t" \ + "ldmia r1!, {r3,r4,r5} \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r1!, {r5} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r5, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r5, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r2!, {r8} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r5, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r3, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r5, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r4, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r5, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r3, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r4, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "umull r9, r10, r4, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adc r12, r12, r10 \n\t" \ + "stmia r0!, {r11, r12} \n\t" \ + "pop {r3} \n\t" + +#define FAST_SQUARE_ASM_5 \ + "push {r2} \n\t" \ + "ldmia r1!, {r2,r3,r4,r5,r6} \n\t" \ + "push {r1} \n\t" \ + \ + "umull r11, r12, r2, r2 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r2, r3 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r11, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r8, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r2, r4 \n\t" \ + "adds r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r3 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r5 \n\t" \ + "umull r1, r14, r3, r4 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r2, r6 \n\t" \ + "umull r1, r14, r3, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "umull r1, r14, r4, r4 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r3, r6 \n\t" \ + "umull r1, r14, r4, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r8, #0 \n\t" \ + "umull r1, r10, r4, r6 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "umull r1, r10, r5, r5 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r1, r10, r5, r6 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "adds r12, r12, r1 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r1, r10, r6, r6 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "stmia r0!, {r8, r11} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_5_TO_6 \ + "cmp r2, #5 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #20 \n\t" \ + "sub r1, #20 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r6,r7,r8,r9,r10,r11} \n\t" \ + "umull r3, r4, r6, r11 \n\t" \ + "umull r6, r5, r7, r11 \n\t" \ + "adds r4, r4, r6 \n\t" \ + "umull r7, r6, r8, r11 \n\t" \ + "adcs r5, r5, r7 \n\t" \ + "umull r8, r7, r9, r11 \n\t" \ + "adcs r6, r6, r8 \n\t" \ + "umull r9, r8, r10, r11 \n\t" \ + "adcs r7, r7, r9 \n\t" \ + "adcs r8, r8, #0 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r9, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r14, [r0], #4 \n\t" \ + "adds r3, r3, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r4, r4, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r5, r5, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r6, r6, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r7, r7, r14 \n\t" \ + "adcs r8, r8, #0 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "sub r0, #20 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r8, r9, r11, r11 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9} \n\t" + +#define FAST_SQUARE_ASM_6 \ + "push {r2} \n\t" \ + "ldmia r1!, {r2,r3,r4,r5,r6,r7} \n\t" \ + "push {r1} \n\t" \ + \ + "umull r11, r12, r2, r2 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r2, r3 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r11, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r8, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r2, r4 \n\t" \ + "adds r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r3 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r5 \n\t" \ + "umull r1, r14, r3, r4 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r2, r6 \n\t" \ + "umull r1, r14, r3, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "umull r1, r14, r4, r4 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r7 \n\t" \ + "umull r1, r14, r3, r6 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r1, r14, r4, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r3, r7 \n\t" \ + "umull r1, r14, r4, r6 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "umull r1, r14, r5, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r4, r7 \n\t" \ + "umull r1, r14, r5, r6 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r8, #0 \n\t" \ + "umull r1, r10, r5, r7 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "umull r1, r10, r6, r6 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r1, r10, r6, r7 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "adds r12, r12, r1 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r1, r10, r7, r7 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "stmia r0!, {r8, r11} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_6_TO_7 \ + "cmp r2, #6 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r6,r7,r8,r9,r10,r11,r12} \n\t" \ + "umull r3, r4, r6, r12 \n\t" \ + "umull r6, r5, r7, r12 \n\t" \ + "adds r4, r4, r6 \n\t" \ + "umull r7, r6, r8, r12 \n\t" \ + "adcs r5, r5, r7 \n\t" \ + "umull r8, r7, r9, r12 \n\t" \ + "adcs r6, r6, r8 \n\t" \ + "umull r9, r8, r10, r12 \n\t" \ + "adcs r7, r7, r9 \n\t" \ + "umull r10, r9, r11, r12 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r10, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r14, [r0], #4 \n\t" \ + "adds r3, r3, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r4, r4, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r5, r5, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r6, r6, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r7, r7, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r8, r8, r14 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "sub r0, #24 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r9, r10, r12, r12 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10} \n\t" + +#define FAST_SQUARE_ASM_7 \ + "push {r2} \n\t" \ + "ldmia r1!, {r2, r3, r4, r5, r6, r7, r8} \n\t" \ + "push {r1} \n\t" \ + "sub r1, 4 \n\t" \ + \ + "add r0, 24 \n\t" \ + "umull r9, r10, r2, r8 \n\t" \ + "stmia r0!, {r9, r10} \n\t" \ + "sub r0, 32 \n\t" \ + \ + "umull r11, r12, r2, r2 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r2, r3 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r11, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r8, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r2, r4 \n\t" \ + "adds r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r3 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r5 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r3, r4 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r2, r6 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r3, r5 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r4, r4 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r7 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r3, r6 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r4, r5 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "ldmia r1!, {r2} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r3, r7 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r4, r6 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r5, r5 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r3, r2 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r4, r7 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r5, r6 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r4, r2 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r5, r7 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r6, r6 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r5, r2 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r6, r7 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r8, #0 \n\t" \ + "umull r1, r10, r6, r2 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "umull r1, r10, r7, r7 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r1, r10, r7, r2 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "adds r12, r12, r1 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r1, r10, r2, r2 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "stmia r0!, {r8, r11} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_7_TO_8 \ + "cmp r2, #7 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r6,r7,r8,r9,r10,r11,r12,r14} \n\t" \ + "umull r3, r4, r6, r14 \n\t" \ + "umull r6, r5, r7, r14 \n\t" \ + "adds r4, r4, r6 \n\t" \ + "umull r7, r6, r8, r14 \n\t" \ + "adcs r5, r5, r7 \n\t" \ + "umull r8, r7, r9, r14 \n\t" \ + "adcs r6, r6, r8 \n\t" \ + "umull r9, r8, r10, r14 \n\t" \ + "adcs r7, r7, r9 \n\t" \ + "umull r10, r9, r11, r14 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "umull r11, r10, r12, r14 \n\t" \ + "adcs r9, r9, r11 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r11, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r12, [r0], #4 \n\t" \ + "adds r3, r3, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r4, r4, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r5, r5, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r6, r6, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r7, r7, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r8, r8, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "sub r0, #28 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r10, r11, r14, r14 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10,r11} \n\t" + +#define FAST_SQUARE_ASM_8 \ + "push {r2} \n\t" \ + "ldmia r1!, {r2,r3,r4,r5,r6,r7,r8,r9} \n\t" \ + "push {r1} \n\t" \ + "sub r1, 8 \n\t" \ + \ + "add r0, 24 \n\t" \ + "umull r10, r11, r2, r8 \n\t" \ + "umull r12, r14, r2, r9 \n\t" \ + "umull r8, r9, r3, r9 \n\t" \ + "adds r11, r11, r12 \n\t" \ + "adcs r12, r14, r8 \n\t" \ + "adcs r14, r9, #0 \n\t" \ + "stmia r0!, {r10, r11, r12, r14} \n\t" \ + "sub r0, 40 \n\t" \ + \ + "umull r11, r12, r2, r2 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r2, r3 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r11, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r8, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r2, r4 \n\t" \ + "adds r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r3 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r5 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r3, r4 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r2, r6 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r3, r5 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r4, r4 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r7 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r3, r6 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r4, r5 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "ldmia r1!, {r2} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r3, r7 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r4, r6 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r5, r5 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r3, r2 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r4, r7 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r5, r6 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r4, r2 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r5, r7 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r6, r6 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r4, r3 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r5, r2 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r6, r7 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r5, r3 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r6, r2 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r7, r7 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r6, r3 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r7, r2 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r8, #0 \n\t" \ + "umull r1, r10, r7, r3 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "umull r1, r10, r2, r2 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r1, r10, r2, r3 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "adds r12, r12, r1 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r1, r10, r3, r3 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "stmia r0!, {r8, r11} \n\t" \ + "pop {r1, r2} \n\t" + +#endif /* _UECC_ASM_ARM_MULT_SQUARE_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square_umaal.inc b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square_umaal.inc new file mode 100644 index 0000000..c554d20 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square_umaal.inc @@ -0,0 +1,1202 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_ARM_MULT_SQUARE_H_ +#define _UECC_ASM_ARM_MULT_SQUARE_H_ + +#define FAST_MULT_ASM_5 \ + "push {r3} \n\t" \ + "ldmia r2!, {r3, r4, r5, r6, r7} \n\t" \ + "push {r2} \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "umull r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "mov r14, #0 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + "str r12, [r0], #4 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "pop {r2, r3} \n\t" + +#define FAST_MULT_ASM_5_TO_6 \ + "cmp r3, #5 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high */ \ + "ldr r4, [r1] \n\t" \ + \ + "sub r0, #20 \n\t" \ + "sub r1, #20 \n\t" \ + "sub r2, #20 \n\t" \ + \ + /* Do right side */ \ + "ldr r14, [r2], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r0], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r7, [r0], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r8, [r0], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r9, [r0], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r10, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "sub r0, #20 \n\t" \ + \ + /* r4 = right high */ \ + "ldr r4, [r2], #4 \n\t" \ + \ + /* Do left side */ \ + "ldr r14, [r1], #4 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r12, r5, r4, r14 \n\t" \ + "str r12, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "str r5, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "str r6, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "str r7, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "stmia r0!, {r9, r10} \n\t" + +#define FAST_MULT_ASM_6 \ + "ldmia r2!, {r4, r5, r6} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umull r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + "ldmia r2!, {r4, r5, r6} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" + +#define FAST_MULT_ASM_6_TO_7 \ + "cmp r3, #6 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high */ \ + "ldr r4, [r1] \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + "sub r2, #24 \n\t" \ + \ + /* Do right side */ \ + "ldr r14, [r2], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r0], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r7, [r0], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r8, [r0], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r9, [r0], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r10, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r11, [r0], #4 \n\t" \ + "umaal r10, r11, r4, r14 \n\t" \ + "sub r0, #24 \n\t" \ + \ + /* r4 = right high */ \ + "ldr r4, [r2], #4 \n\t" \ + \ + /* Do left side */ \ + "ldr r14, [r1], #4 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r12, r5, r4, r14 \n\t" \ + "str r12, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "str r5, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "str r6, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "str r7, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r10, r11, r4, r14 \n\t" \ + "stmia r0!, {r10, r11} \n\t" + +#define FAST_MULT_ASM_7 \ + "ldmia r2!, {r4, r5, r6, r7} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umull r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + "str r12, [r0], #4 \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + "ldmia r2!, {r4, r5, r6} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" + +#define FAST_MULT_ASM_7_TO_8 \ + "cmp r3, #7 \n\t" \ + "beq 1f \n\t" \ + "push {r3} \n\t" \ + \ + /* r4 = left high */ \ + "ldr r4, [r1] \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + "sub r2, #28 \n\t" \ + \ + /* Do right side */ \ + "ldr r14, [r2], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r0], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r7, [r0], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r8, [r0], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r9, [r0], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r10, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r11, [r0], #4 \n\t" \ + "umaal r10, r11, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "umaal r11, r12, r4, r14 \n\t" \ + "sub r0, #28 \n\t" \ + \ + /* r4 = right high */ \ + "ldr r4, [r2], #4 \n\t" \ + \ + /* Do left side */ \ + "ldr r14, [r1], #4 \n\t" \ + "mov r3, #0 \n\t" \ + "umaal r3, r5, r4, r14 \n\t" \ + "str r3, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "str r5, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "str r6, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "str r7, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "str r9, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r10, r11, r4, r14 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r11, r12, r4, r14 \n\t" \ + "stmia r0!, {r11, r12} \n\t" \ + "pop {r3} \n\t" + +#define FAST_MULT_ASM_8 \ + "ldmia r2!, {r4, r5, r6, r7} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umull r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + "str r12, [r0], #4 \n\t" \ + \ + "sub r0, #32 \n\t" \ + "sub r1, #32 \n\t" \ + "ldmia r2!, {r4, r5, r6, r7} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + "str r12, [r0], #4 \n\t" + +#define FAST_SQUARE_ASM_5 \ + "ldmia r1!, {r9,r10,r11,r12,r14} \n\t" \ + "push {r1, r2} \n\t" \ + \ + "umull r1, r2, r10, r9 \n\t" \ + "mov r3, #0 \n\t" \ + "umaal r2, r3, r11, r9 \n\t" \ + "mov r4, #0 \n\t" \ + "umaal r3, r4, r12, r9 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r14, r9 \n\t" \ + \ + "mov r6, #0 \n\t" \ + "umaal r6, r3, r11, r10 \n\t" \ + "umaal r3, r4, r12, r10 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + \ + "umull r7, r8, r9, r9 \n\t" \ + /* Store carry in r9 */ \ + "mov r9, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "stmia r0!, {r7,r8} \n\t" \ + \ + "umull r7, r8, r10, r10 \n\t" \ + "adcs r7, r7, r2 \n\t" \ + "adcs r8, r8, r6 \n\t" \ + "stmia r0!, {r7,r8} \n\t" \ + \ + "umaal r4, r5, r14, r10 \n\t" \ + /* Store carry in r10 */ \ + "mov r10, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + \ + "mov r1, #0 \n\t" \ + "umaal r1, r4, r12, r11 \n\t" \ + "umaal r4, r5, r14, r11 \n\t" \ + \ + "mov r2, #0 \n\t" \ + "umaal r2, r5, r14, r12 \n\t" \ + /* Load carry from r9 */ \ + "lsrs r9, #1 \n\t" \ + "adcs r1, r1, r1 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + /* r9 is 0 now */ \ + "adc r9, r9, #0 \n\t" \ + \ + /* Use carry from r10 */ \ + "umaal r3, r10, r11, r11 \n\t" \ + "adds r10, r10, r1 \n\t" \ + "stmia r0!, {r3,r10} \n\t" \ + \ + "umull r6, r10, r12, r12 \n\t" \ + "adcs r6, r6, r4 \n\t" \ + "adcs r10, r10, r2 \n\t" \ + "stmia r0!, {r6,r10} \n\t" \ + \ + "umull r6, r10, r14, r14 \n\t" \ + "adcs r6, r6, r5 \n\t" \ + "adcs r10, r10, r9 \n\t" \ + "stmia r0!, {r6,r10} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_5_TO_6 \ + "cmp r2, #5 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #20 \n\t" \ + "sub r1, #20 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r5,r6,r7,r8,r9,r14} \n\t" \ + "umull r3, r4, r5, r14 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r6, r14 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r7, r14 \n\t" \ + "mov r7, #0 \n\t" \ + "umaal r6, r7, r8, r14 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r7, r8, r9, r14 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r9, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r12, [r0], #4 \n\t" \ + "adds r3, r3, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r4, r4, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r5, r5, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r6, r6, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r7, r7, r12 \n\t" \ + "adcs r8, r8, #0 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "sub r0, #20 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r8, r9, r14, r14 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9} \n\t" + +#define FAST_SQUARE_ASM_6 \ + "ldmia r1!, {r8,r9,r10,r11,r12,r14} \n\t" \ + "push {r1, r2} \n\t" \ + \ + "umull r1, r2, r9, r8 \n\t" \ + "mov r3, #0 \n\t" \ + "umaal r2, r3, r10, r8 \n\t" \ + "mov r4, #0 \n\t" \ + "umaal r3, r4, r11, r8 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r12, r8 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r14, r8 \n\t" \ + \ + "mov r7, #0 \n\t" \ + "umaal r7, r3, r10, r9 \n\t" \ + "umaal r3, r4, r11, r9 \n\t" \ + "umaal r4, r5, r12, r9 \n\t" \ + "push {r4, r5} \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + \ + "umull r4, r5, r8, r8 \n\t" \ + /* Store carry in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r5, r5, r1 \n\t" \ + "stmia r0!, {r4,r5} \n\t" \ + \ + "umull r4, r5, r9, r9 \n\t" \ + "adcs r4, r4, r2 \n\t" \ + "adcs r5, r5, r7 \n\t" \ + "stmia r0!, {r4,r5} \n\t" \ + \ + "pop {r4, r5} \n\t" \ + "umaal r5, r6, r14, r9 \n\t" \ + /* Store carry in r9 */ \ + "mov r9, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + \ + "mov r1, #0 \n\t" \ + "umaal r1, r4, r11, r10 \n\t" \ + "umaal r4, r5, r12, r10 \n\t" \ + "umaal r5, r6, r14, r10 \n\t" \ + \ + "mov r2, #0 \n\t" \ + "umaal r2, r5, r12, r11 \n\t" \ + "umaal r5, r6, r14, r11 \n\t" \ + \ + "mov r7, #0 \n\t" \ + "umaal r7, r6, r14, r12 \n\t" \ + \ + /* Load carry from r8 */ \ + "lsrs r8, #1 \n\t" \ + "adcs r1, r1, r1 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + /* Use carry from r9 */ \ + "umaal r3, r9, r10, r10 \n\t" \ + "adds r9, r9, r1 \n\t" \ + "stmia r0!, {r3,r9} \n\t" \ + \ + "umull r9, r10, r11, r11 \n\t" \ + "adcs r9, r9, r4 \n\t" \ + "adcs r10, r10, r2 \n\t" \ + "stmia r0!, {r9,r10} \n\t" \ + \ + "umull r9, r10, r12, r12 \n\t" \ + "adcs r9, r9, r5 \n\t" \ + "adcs r10, r10, r7 \n\t" \ + "stmia r0!, {r9,r10} \n\t" \ + \ + "umull r9, r10, r14, r14 \n\t" \ + "adcs r9, r9, r6 \n\t" \ + "adcs r10, r10, r8 \n\t" \ + "stmia r0!, {r9,r10} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_6_TO_7 \ + "cmp r2, #6 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r5,r6,r7,r8,r9,r10,r14} \n\t" \ + "umull r3, r4, r5, r14 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r6, r14 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r7, r14 \n\t" \ + "mov r7, #0 \n\t" \ + "umaal r6, r7, r8, r14 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r7, r8, r9, r14 \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r10, r14 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r10, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r12, [r0], #4 \n\t" \ + "adds r3, r3, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r4, r4, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r5, r5, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r6, r6, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r7, r7, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r8, r8, r12 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "sub r0, #24 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r9, r10, r14, r14 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10} \n\t" + +#define FAST_SQUARE_ASM_7 \ + "ldmia r1!, {r9,r10,r11,r12} \n\t" \ + "push {r2} \n\t" \ + \ + "umull r14, r2, r10, r9 \n\t" \ + "mov r3, #0 \n\t" \ + "umaal r2, r3, r11, r9 \n\t" \ + "mov r4, #0 \n\t" \ + "umaal r3, r4, r12, r9 \n\t" \ + \ + "mov r5, #0 \n\t" \ + "umaal r5, r3, r11, r10 \n\t" \ + "adds r14, r14, r14 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + /* Store carry in r7 */ \ + "mov r7, #0 \n\t" \ + "adc r7, r7, #0 \n\t" \ + \ + "umull r6, r8, r9, r9 \n\t" \ + "adds r8, r8, r14 \n\t" \ + "stmia r0!, {r6,r8} \n\t" \ + \ + "umull r6, r8, r10, r10 \n\t" \ + "adcs r6, r6, r2 \n\t" \ + "adcs r8, r8, r5 \n\t" \ + "stmia r0!, {r6,r8} \n\t" \ + /* Store carry in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "ldmia r1!, {r2, r6, r14} \n\t" \ + "push {r1} \n\t" \ + "umaal r3, r4, r2, r9 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r6, r9 \n\t" \ + "mov r1, #0 \n\t" \ + "umaal r5, r1, r14, r9 \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umaal r3, r9, r12, r10 \n\t" \ + "umaal r9, r4, r2, r10 \n\t" \ + "umaal r4, r5, r6, r10 \n\t" \ + "umaal r5, r1, r14, r10 \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umaal r10, r9, r12, r11 \n\t" \ + "umaal r9, r4, r2, r11 \n\t" \ + "umaal r4, r5, r6, r11 \n\t" \ + "umaal r5, r1, r14, r11 \n\t" \ + \ + /* Load carry from r7 */ \ + "lsrs r7, #1 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + /* Store carry back in r7 */ \ + "adc r7, r7, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r3, r8, r11, r11 \n\t" \ + "adds r8, r8, r10 \n\t" \ + "stmia r0!, {r3,r8} \n\t" \ + /* Store carry back in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "mov r3, #0 \n\t" \ + "umaal r3, r4, r2, r12 \n\t" \ + "umaal r4, r5, r6, r12 \n\t" \ + "umaal r5, r1, r14, r12 \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umaal r10, r5, r6, r2 \n\t" \ + "umaal r5, r1, r14, r2 \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umaal r11, r1, r14, r6 \n\t" \ + \ + /* Load carry from r7 */ \ + "lsrs r7, #1 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adcs r1, r1, r1 \n\t" \ + "adc r7, r7, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r8, r9, r12, r12 \n\t" \ + "adds r9, r9, r3 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + \ + "umull r8, r9, r2, r2 \n\t" \ + "adcs r8, r8, r4 \n\t" \ + "adcs r9, r9, r10 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + \ + "umull r8, r9, r6, r6 \n\t" \ + "adcs r8, r8, r5 \n\t" \ + "adcs r9, r9, r11 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + \ + "umull r8, r9, r14, r14 \n\t" \ + "adcs r8, r8, r1 \n\t" \ + "adcs r9, r9, r7 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_7_TO_8 \ + "cmp r2, #7 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r5,r6,r7,r8,r9,r10,r11,r14} \n\t" \ + "umull r3, r4, r5, r14 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r6, r14 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r7, r14 \n\t" \ + "mov r7, #0 \n\t" \ + "umaal r6, r7, r8, r14 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r7, r8, r9, r14 \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r10, r14 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r11, r14 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r11, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r12, [r0], #4 \n\t" \ + "adds r3, r3, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r4, r4, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r5, r5, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r6, r6, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r7, r7, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r8, r8, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "sub r0, #28 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r10, r11, r14, r14 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10,r11} \n\t" + +#define FAST_SQUARE_ASM_8 \ + "ldmia r1!, {r10,r11,r12,r14} \n\t" \ + "push {r2} \n\t" \ + \ + "umull r2, r3, r11, r10 \n\t" \ + "mov r4, #0 \n\t" \ + "umaal r3, r4, r12, r10 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r14, r10 \n\t" \ + \ + "mov r6, #0 \n\t" \ + "umaal r6, r4, r12, r11 \n\t" \ + "adds r2, r2, r2 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + /* Store carry in r7 */ \ + "mov r7, #0 \n\t" \ + "adc r7, r7, #0 \n\t" \ + \ + "umull r8, r9, r10, r10 \n\t" \ + "adds r9, r9, r2 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + \ + "umull r8, r9, r11, r11 \n\t" \ + "adcs r8, r8, r3 \n\t" \ + "adcs r9, r9, r6 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + /* Store carry in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "ldmia r1!, {r2, r3} \n\t" \ + "push {r1} \n\t" \ + "umaal r4, r5, r2, r10 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r3, r10 \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umaal r9, r4, r14, r11 \n\t" \ + "umaal r4, r5, r2, r11 \n\t" \ + \ + "mov r1, #0 \n\t" \ + "umaal r1, r4, r14, r12 \n\t" \ + \ + /* Load carry from r7 */ \ + "lsrs r7, #1 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r1, r1, r1 \n\t" \ + /* Store carry back in r7 */ \ + "adc r7, r7, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r8, r9, r12, r12 \n\t" \ + "adds r9, r9, r1 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + /* Store carry back in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "pop {r1} \n\t" \ + /* TODO could fix up r1 value on stack here */ \ + /* and leave the value on the stack (rather */ \ + /* than popping) if supporting curves > 256 bits */ \ + "ldr r9, [r1], #4 \n\t" \ + "ldr r1, [r1] \n\t" \ + \ + "push {r7} \n\t" \ + "umaal r5, r6, r9, r10 \n\t" \ + "mov r7, #0 \n\t" \ + "umaal r6, r7, r1, r10 \n\t" \ + /* Carry now stored in r10 */ \ + "pop {r10} \n\t" \ + \ + "umaal r4, r5, r3, r11 \n\t" \ + "umaal r5, r6, r9, r11 \n\t" \ + "umaal r6, r7, r1, r11 \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umaal r11, r4, r2, r12 \n\t" \ + "umaal r4, r5, r3, r12 \n\t" \ + "umaal r5, r6, r9, r12 \n\t" \ + "umaal r6, r7, r1, r12 \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umaal r12, r4, r2, r14 \n\t" \ + "umaal r4, r5, r3, r14 \n\t" \ + "umaal r5, r6, r9, r14 \n\t" \ + "umaal r6, r7, r1, r14 \n\t" \ + \ + /* Load carry from r10 */ \ + "lsrs r10, #1 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r8, r11, r14, r14 \n\t" \ + "adds r11, r11, r12 \n\t" \ + "stmia r0!, {r8,r11} \n\t" \ + /* Store carry back in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umaal r11, r5, r3, r2 \n\t" \ + "umaal r5, r6, r9, r2 \n\t" \ + "umaal r6, r7, r1, r2 \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umaal r12, r6, r9, r3 \n\t" \ + "umaal r6, r7, r1, r3 \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umaal r14, r7, r1, r9 \n\t" \ + \ + /* Load carry from r10 */ \ + "lsrs r10, #1 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r14, r14, r14 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adc r10, r10, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r4, r8, r2, r2 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "stmia r0!, {r4,r8} \n\t" \ + \ + "umull r4, r8, r3, r3 \n\t" \ + "adcs r4, r4, r5 \n\t" \ + "adcs r8, r8, r12 \n\t" \ + "stmia r0!, {r4,r8} \n\t" \ + \ + "umull r4, r8, r9, r9 \n\t" \ + "adcs r4, r4, r6 \n\t" \ + "adcs r8, r8, r14 \n\t" \ + "stmia r0!, {r4,r8} \n\t" \ + \ + "umull r4, r8, r1, r1 \n\t" \ + "adcs r4, r4, r7 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "stmia r0!, {r4,r8} \n\t" \ + /* TODO pop {r1, r2} if supporting curves > 256 bits */ \ + "pop {r2} \n\t" + +#endif /* _UECC_ASM_ARM_MULT_SQUARE_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_avr.inc b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_avr.inc new file mode 100644 index 0000000..c988040 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_avr.inc @@ -0,0 +1,1089 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_AVR_H_ +#define _UECC_ASM_AVR_H_ + +#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #define uECC_MIN_WORDS 32 +#endif +#if uECC_SUPPORTS_secp224r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 28 +#endif +#if uECC_SUPPORTS_secp192r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 24 +#endif +#if uECC_SUPPORTS_secp160r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 20 +#endif + +#if __AVR_HAVE_EIJMP_EICALL__ + #define IJMP "eijmp \n\t" +#else + #define IJMP "ijmp \n\t" +#endif + +#if (uECC_OPTIMIZATION_LEVEL >= 2) + +uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { + volatile uECC_word_t *v = vli; + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(1f) \n\t" + "ldi r31, pm_hi8(1f) \n\t" + "sub r30, %[num] \n\t" + "sbc r31, __zero_reg__ \n\t" + IJMP + #endif + + REPEAT(uECC_MAX_WORDS, "st x+, __zero_reg__ \n\t") + "1: \n\t" + : "+x" (v) + : [num] "r" (num_words) + : + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "r30", "r31", "cc" + #endif + ); +} +#define asm_clear 1 + +uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) { + volatile uECC_word_t *d = dest; + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(1f) \n\t" + "ldi r31, pm_hi8(1f) \n\t" + "sub r30, %[num] \n\t" + "sbc r31, __zero_reg__ \n\t" + IJMP + #endif + + REPEAT(uECC_MAX_WORDS, + "ld r0, y+ \n\t" + "st x+, r0 \n\t") + "1: \n\t" + : "+x" (d), "+y" (src) + : [num] "r" ((uint8_t)(num_words * 2)) + : "r0", + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "r30", "r31", "cc" + #endif + ); +} +#define asm_set 1 + +uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { + volatile uECC_word_t *v = vli; + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(1f) \n\t" + "ldi r31, pm_hi8(1f) \n\t" + "sub r30, %[jump] \n\t" + "sbc r31, __zero_reg__ \n\t" + #endif + + "add r26, %[num] \n\t" + "adc r27, __zero_reg__ \n\t" + "ld r0, -x \n\t" + "lsr r0 \n\t" + "st x, r0 \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + IJMP + #endif + + REPEAT(DEC(uECC_MAX_WORDS), + "ld r0, -x \n\t" + "ror r0 \n\t" + "st x, r0 \n\t") + "1: \n\t" + : "+x" (v) + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + : [num] "r" (num_words), [jump] "r" ((uint8_t)(3 * (num_words - 1))) + : "r0", "r30", "r31", "cc" + #else + : [num] "r" (num_words) + : "r0", "cc" + #endif + ); +} +#define asm_rshift1 1 + +#define ADD_RJPM_TABLE(N) \ + "movw r30, %A[result] \n\t" \ + "rjmp add_%=_" #N " \n\t" + +#define ADD_RJPM_DEST(N) \ + "add_%=_" #N ":" \ + "ld %[clb], x+ \n\t" \ + "ld %[rb], y+ \n\t" \ + "adc %[clb], %[rb] \n\t" \ + "st z+, %[clb] \n\t" + +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t carry; + uint8_t right_byte; + + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(add_%=_" STR(uECC_MAX_WORDS) ") \n\t" + "ldi r31, pm_hi8(add_%=_" STR(uECC_MAX_WORDS) ") \n\t" + "sub r30, %[num] \n\t" + "sbc r31, __zero_reg__ \n\t" + #endif + + "clc \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + IJMP + REPEATM(uECC_MAX_WORDS, ADD_RJPM_TABLE) + #endif + + REPEATM(uECC_MAX_WORDS, ADD_RJPM_DEST) + + "mov %[clb], __zero_reg__ \n\t" + "adc %[clb], %[clb] \n\t" /* Store carry bit. */ + + : "+x" (left), "+y" (right), + [clb] "=&r" (carry), [rb] "=&r" (right_byte) + : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2)) + : "r30", "r31", "cc" + ); + return carry; +} +#define asm_add 1 + +#define SUB_RJPM_TABLE(N) \ + "movw r30, %A[result] \n\t" \ + "rjmp sub_%=_" #N " \n\t" + +#define SUB_RJPM_DEST(N) \ + "sub_%=_" #N ":" \ + "ld %[clb], x+ \n\t" \ + "ld %[rb], y+ \n\t" \ + "sbc %[clb], %[rb] \n\t" \ + "st z+, %[clb] \n\t" + +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t carry; + uint8_t right_byte; + + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(sub_%=_" STR(uECC_MAX_WORDS) ") \n\t" + "ldi r31, pm_hi8(sub_%=_" STR(uECC_MAX_WORDS) ") \n\t" + "sub r30, %[num] \n\t" + "sbc r31, __zero_reg__ \n\t" + #endif + + "clc \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + IJMP + REPEATM(uECC_MAX_WORDS, SUB_RJPM_TABLE) + #endif + + REPEATM(uECC_MAX_WORDS, SUB_RJPM_DEST) + + "mov %[clb], __zero_reg__ \n\t" + "adc %[clb], %[clb] \n\t" /* Store carry bit. */ + + : "+x" (left), "+y" (right), + [clb] "=&r" (carry), [rb] "=&r" (right_byte) + : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2)) + : "r30", "r31", "cc" + ); + return carry; +} +#define asm_sub 1 + +#if (uECC_OPTIMIZATION_LEVEL >= 3) + +#include "asm_avr_mult_square.inc" + +__attribute((noinline)) +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + /* num_words should already be in r18. */ + register wordcount_t r18 __asm__("r18") = num_words; + + __asm__ volatile ( + "push r18 \n\t" +#if (uECC_MIN_WORDS == 20) + FAST_MULT_ASM_20 + "pop r18 \n\t" + #if (uECC_MAX_WORDS > 20) + FAST_MULT_ASM_20_TO_24 + #endif + #if (uECC_MAX_WORDS > 24) + FAST_MULT_ASM_24_TO_28 + #endif + #if (uECC_MAX_WORDS > 28) + FAST_MULT_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 24) + FAST_MULT_ASM_24 + "pop r18 \n\t" + #if (uECC_MAX_WORDS > 24) + FAST_MULT_ASM_24_TO_28 + #endif + #if (uECC_MAX_WORDS > 28) + FAST_MULT_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 28) + FAST_MULT_ASM_28 + "pop r18 \n\t" + #if (uECC_MAX_WORDS > 28) + FAST_MULT_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 32) + FAST_MULT_ASM_32 + "pop r18 \n\t" +#endif + "2: \n\t" + "eor r1, r1 \n\t" + : "+x" (left), "+y" (right), "+z" (result) + : "r" (r18) + : "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r19", "r20", + "r21", "r22", "r23", "r24", "r25", "cc" + ); +} +#define asm_mult 1 + +#if uECC_SQUARE_FUNC +__attribute((noinline)) +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + /* num_words should already be in r20. */ + register wordcount_t r20 __asm__("r20") = num_words; + + __asm__ volatile ( + "push r20 \n\t" +#if (uECC_MIN_WORDS == 20) + FAST_SQUARE_ASM_20 + "pop r20 \n\t" + #if (uECC_MAX_WORDS > 20) + FAST_SQUARE_ASM_20_TO_24 + #endif + #if (uECC_MAX_WORDS > 24) + FAST_SQUARE_ASM_24_TO_28 + #endif + #if (uECC_MAX_WORDS > 28) + FAST_SQUARE_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 24) + FAST_SQUARE_ASM_24 + "pop r20 \n\t" + #if (uECC_MAX_WORDS > 24) + FAST_SQUARE_ASM_24_TO_28 + #endif + #if (uECC_MAX_WORDS > 28) + FAST_SQUARE_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 28) + FAST_SQUARE_ASM_28 + "pop r20 \n\t" + #if (uECC_MAX_WORDS > 28) + FAST_SQUARE_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 32) + FAST_SQUARE_ASM_32 + "pop r20 \n\t" +#endif + "2: \n\t" + "eor r1, r1 \n\t" + : "+x" (left), "+z" (result) + : "r" (r20) + : "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", + "r21", "r22", "r23", "r24", "r25", "r28", "r29", "cc" + ); +} +#define asm_square 1 +#endif /* uECC_SQUARE_FUNC */ + +#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */ + +#if uECC_SUPPORTS_secp160r1 +static const struct uECC_Curve_t curve_secp160r1; +static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { + uint8_t carry = 0; + __asm__ volatile ( + "in r30, __SP_L__ \n\t" + "in r31, __SP_H__ \n\t" + "sbiw r30, 24 \n\t" + "in r0, __SREG__ \n\t" + "cli \n\t" + "out __SP_H__, r31 \n\t" + "out __SREG__, r0 \n\t" + "out __SP_L__, r30 \n\t" + + "adiw r30, 25 \n\t" /* we are shifting by 31 bits, so shift over 4 bytes + (+ 1 since z initially points below the stack) */ + "adiw r26, 40 \n\t" /* end of product */ + "ld r18, -x \n\t" /* Load word. */ + "lsr r18 \n\t" /* Shift. */ + "st -z, r18 \n\t" /* Store the first result word. */ + + /* Now we just do the remaining words with the carry bit (using ROR) */ + REPEAT(19, + "ld r18, -x \n\t" + "ror r18 \n\t" + "st -z, r18 \n\t") + + "eor r18, r18 \n\t" /* r18 = 0 */ + "ror r18 \n\t" /* get last bit */ + "st -z, r18 \n\t" /* store it */ + + "sbiw r30, 3 \n\t" /* move z back to point at tmp */ + /* now we add right */ + "ld r18, x+ \n\t" + "st z+, r18 \n\t" /* the first 3 bytes do not need to be added */ + "ld r18, x+ \n\t" + "st z+, r18 \n\t" + "ld r18, x+ \n\t" + "st z+, r18 \n\t" + + "ld r18, x+ \n\t" + "ld r19, z \n\t" + "add r18, r19 \n\t" + "st z+, r18 \n\t" + + /* Now we just do the remaining words with the carry bit (using ADC) */ + REPEAT(16, + "ld r18, x+ \n\t" + "ld r19, z \n\t" + "adc r18, r19 \n\t" + "st z+, r18 \n\t") + + /* Propagate over the remaining bytes of result */ + "ld r18, z \n\t" + "adc r18, r1 \n\t" + "st z+, r18 \n\t" + + "ld r18, z \n\t" + "adc r18, r1 \n\t" + "st z+, r18 \n\t" + + "ld r18, z \n\t" + "adc r18, r1 \n\t" + "st z+, r18 \n\t" + + "ld r18, z \n\t" + "adc r18, r1 \n\t" + "st z+, r18 \n\t" + + "sbiw r30, 24 \n\t" /* move z back to point at tmp */ + "sbiw r26, 40 \n\t" /* move x back to point at product */ + + /* add low bytes of tmp to product, storing in result */ + "ld r18, z+ \n\t" + "ld r19, x+ \n\t" + "add r18, r19 \n\t" + "st y+, r18 \n\t" + REPEAT(19, + "ld r18, z+ \n\t" + "ld r19, x+ \n\t" + "adc r18, r19 \n\t" + "st y+, r18 \n\t") + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ + /* at this point x is at the end of product, y is at the end of result, + z is 20 bytes into tmp */ + "sbiw r28, 20 \n\t" /* move y back to point at result */ + "adiw r30, 4 \n\t" /* move z to point to the end of tmp */ + + /* do omega_mult again with the 4 relevant bytes */ + /* z points to the end of tmp, x points to the end of product */ + "ld r18, -z \n\t" /* Load word. */ + "lsr r18 \n\t" /* Shift. */ + "st -x, r18 \n\t" /* Store the first result word. */ + + "ld r18, -z \n\t" + "ror r18 \n\t" + "st -x, r18 \n\t" + "ld r18, -z \n\t" + "ror r18 \n\t" + "st -x, r18 \n\t" + "ld r18, -z \n\t" + "ror r18 \n\t" + "st -x, r18 \n\t" + + "eor r18, r18 \n\t" /* r18 = 0 */ + "ror r18 \n\t" /* get last bit */ + "st -x, r18 \n\t" /* store it */ + + "sbiw r26, 3 \n\t" /* move x back to point at beginning */ + /* now we add a copy of the 4 bytes */ + "ld r18, z+ \n\t" + "st x+, r18 \n\t" /* the first 3 bytes do not need to be added */ + "ld r18, z+ \n\t" + "st x+, r18 \n\t" + "ld r18, z+ \n\t" + "st x+, r18 \n\t" + + "ld r18, z+ \n\t" + "ld r19, x \n\t" + "add r18, r19 \n\t" + "st x+, r18 \n\t" + + /* Propagate over the remaining bytes */ + "ld r18, x \n\t" + "adc r18, r1 \n\t" + "st x+, r18 \n\t" + + "ld r18, x \n\t" + "adc r18, r1 \n\t" + "st x+, r18 \n\t" + + "ld r18, x \n\t" + "adc r18, r1 \n\t" + "st x+, r18 \n\t" + + "ld r18, x \n\t" + "adc r18, r1 \n\t" + "st x+, r18 \n\t" + + /* now z points to the end of tmp, x points to the end of product + (y still points at result) */ + "sbiw r26, 8 \n\t" /* move x back to point at beginning of actual data */ + /* add into result */ + "ld r18, x+ \n\t" + "ld r19, y \n\t" + "add r18, r19 \n\t" + "st y+, r18 \n\t" + REPEAT(7, + "ld r18, x+ \n\t" + "ld r19, y \n\t" + "adc r18, r19 \n\t" + "st y+, r18 \n\t") + + /* Done adding, now propagate carry bit */ + REPEAT(12, + "ld r18, y \n\t" + "adc r18, __zero_reg__ \n\t" + "st y+, r18 \n\t") + + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ + "sbiw r28, 20 \n\t" /* move y back to point at result */ + + "sbiw r30, 1 \n\t" /* fix stack pointer */ + "in r0, __SREG__ \n\t" + "cli \n\t" + "out __SP_H__, r31 \n\t" + "out __SREG__, r0 \n\t" + "out __SP_L__, r30 \n\t" + + : "+x" (product), [carry] "+r" (carry) + : "y" (result) + : "r0", "r18", "r19", "r30", "r31", "cc" + ); + + if (carry > 0) { + --carry; + uECC_vli_sub(result, result, curve_secp160r1.p, 20); + } + if (carry > 0) { + uECC_vli_sub(result, result, curve_secp160r1.p, 20); + } + if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, 20) > 0) { + uECC_vli_sub(result, result, curve_secp160r1.p, 20); + } +} +#define asm_mmod_fast_secp160r1 1 +#endif /* uECC_SUPPORTS_secp160r1 */ + +#if uECC_SUPPORTS_secp256k1 +static const struct uECC_Curve_t curve_secp256k1; +static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { + uint8_t carry = 0; + __asm__ volatile ( + "in r30, __SP_L__ \n\t" + "in r31, __SP_H__ \n\t" + "sbiw r30, 37 \n\t" + "in r0, __SREG__ \n\t" + "cli \n\t" + "out __SP_H__, r31 \n\t" + "out __SREG__, r0 \n\t" + "out __SP_L__, r30 \n\t" + + "adiw r30, 1 \n\t" /* add 1 since z initially points below the stack */ + "adiw r26, 32 \n\t" /* product + uECC_WORDS */ + "ldi r25, 0x03 \n\t" + "ldi r24, 0xD1 \n\t" + "ld r18, x+ \n\t" + "ld r19, x+ \n\t" + "ld r20, x+ \n\t" + "ld r21, x+ \n\t" + + "mul r24, r18 \n\t" + "st z+, r0 \n\t" + "mov r22, r1 \n\t" + "ldi r23, 0 \n\t" + + "mul r24, r19 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" /* can't overflow */ + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" /* can't overflow */ + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + "mul r24, r20 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r19 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "mul r24, r21 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r20 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + /* now we start adding the 2^32 part as well */ + "add r23, r18 \n\t" // 28 + "adc r22, r22 \n\t" + "ld r18, x+ \n\t" + "mul r24, r18 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r21 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r19 \n\t" // 27 + "adc r23, r23 \n\t" + "ld r19, x+ \n\t" + "mul r24, r19 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + REPEAT(6, // 26 - 3 + "add r23, r20 \n\t" + "adc r22, r22 \n\t" + "ld r20, x+ \n\t" + "mul r24, r20 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r19 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r21 \n\t" + "adc r23, r23 \n\t" + "ld r21, x+ \n\t" + "mul r24, r21 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r20 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r18 \n\t" + "adc r22, r22 \n\t" + "ld r18, x+ \n\t" + "mul r24, r18 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r21 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r19 \n\t" + "adc r23, r23 \n\t" + "ld r19, x+ \n\t" + "mul r24, r19 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t") + + "add r23, r20 \n\t" // 2 + "adc r22, r22 \n\t" + "ld r20, x+ \n\t" + "mul r24, r20 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r19 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r21 \n\t" // 1 + "adc r23, r23 \n\t" + "ld r21, x+ \n\t" + "mul r24, r21 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r20 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + /* Now finish the carries etc */ + "add r23, r18 \n\t" + "adc r22, r22 \n\t" + "mul r25, r21 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r19 \n\t" + "adc r23, r23 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r20 \n\t" + "adc r22, r22 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r21 \n\t" + "adc r23, r23 \n\t" + "st z+, r22 \n\t" + "st z+, r23 \n\t" + "eor r1, r1 \n\t" /* make r1 be 0 again */ + + "sbiw r30, 37 \n\t" /* move z back to point at tmp */ + "subi r26, 64 \n\t" /* move x back to point at product */ + "sbc r27, __zero_reg__ \n\t" + + /* add low bytes of tmp to product, storing in result */ + "ld r18, z+ \n\t" + "ld r19, x+ \n\t" + "add r18, r19 \n\t" + "st y+, r18 \n\t" + REPEAT(31, + "ld r18, z+ \n\t" + "ld r19, x+ \n\t" + "adc r18, r19 \n\t" + "st y+, r18 \n\t") + + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ + /* at this point x is at the end of product, y is at the end of result, + z is 32 bytes into tmp */ + "sbiw r28, 32 \n\t" /* move y back to point at result */ + + /* do omega_mult again with the 5 relevant bytes */ + /* z points to tmp + uECC_WORDS, x points to the end of product */ + "sbiw r26, 32 \n\t" /* shift x back to point into the product buffer + (we can overwrite it now) */ + "ld r18, z+ \n\t" + "ld r19, z+ \n\t" + "ld r20, z+ \n\t" + "ld r21, z+ \n\t" + + "mul r24, r18 \n\t" + "st x+, r0 \n\t" + "mov r22, r1 \n\t" + "ldi r23, 0 \n\t" + + "mul r24, r19 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" /* can't overflow */ + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" /* can't overflow */ + "st x+, r22 \n\t" + "ldi r22, 0 \n\t" + + "mul r24, r20 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r19 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st x+, r23 \n\t" + "ldi r23, 0 \n\t" + + "mul r24, r21 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r20 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st x+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r18 \n\t" + "adc r22, r22 \n\t" + "ld r18, z+ \n\t" + "mul r24, r18 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r21 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st x+, r23 \n\t" + "ldi r23, 0 \n\t" + + /* Now finish the carries etc */ + "add r22, r19 \n\t" + "adc r23, r23 \n\t" + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st x+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r20 \n\t" + "adc r22, r22 \n\t" + "st x+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r21 \n\t" + "adc r23, r23 \n\t" + "st x+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r18 \n\t" + "adc r22, r22 \n\t" + "st x+, r23 \n\t" + "st x+, r22 \n\t" + "eor r1, r1 \n\t" /* make r1 be 0 again */ + + /* now z points to the end of tmp, x points to the end of product + (y still points at result) */ + "sbiw r26, 10 \n\t" /* move x back to point at beginning of actual data */ + /* add into result */ + "ld r18, x+ \n\t" + "ld r19, y \n\t" + "add r18, r19 \n\t" + "st y+, r18 \n\t" + REPEAT(9, + "ld r18, x+ \n\t" + "ld r19, y \n\t" + "adc r18, r19 \n\t" + "st y+, r18 \n\t") + + /* Done adding, now propagate carry bit */ + REPEAT(22, + "ld r18, y \n\t" + "adc r18, __zero_reg__ \n\t" + "st y+, r18 \n\t") + + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ + "sbiw r28, 32 \n\t" /* move y back to point at result */ + + "sbiw r30, 1 \n\t" /* fix stack pointer */ + "in r0, __SREG__ \n\t" + "cli \n\t" + "out __SP_H__, r31 \n\t" + "out __SREG__, r0 \n\t" + "out __SP_L__, r30 \n\t" + + : "+x" (product), [carry] "+r" (carry) + : "y" (result) + : "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc" + ); + + if (carry > 0) { + --carry; + uECC_vli_sub(result, result, curve_secp256k1.p, 32); + } + if (carry > 0) { + uECC_vli_sub(result, result, curve_secp256k1.p, 32); + } + if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, 32) > 0) { + uECC_vli_sub(result, result, curve_secp256k1.p, 32); + } +} +#define asm_mmod_fast_secp256k1 1 +#endif /* uECC_SUPPORTS_secp256k1 */ + +#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */ + +/* ---- "Small" implementations ---- */ + +#if !asm_add +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t carry = 0; + uint8_t left_byte; + uint8_t right_byte; + + __asm__ volatile ( + "clc \n\t" + + "1: \n\t" + "ld %[left], x+ \n\t" /* Load left byte. */ + "ld %[right], y+ \n\t" /* Load right byte. */ + "adc %[left], %[right] \n\t" /* Add. */ + "st z+, %[left] \n\t" /* Store the result. */ + "dec %[i] \n\t" + "brne 1b \n\t" + + "adc %[carry], %[carry] \n\t" /* Store carry bit. */ + + : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), + [carry] "+r" (carry), [left] "=&r" (left_byte), [right] "=&r" (right_byte) + : + : "cc" + ); + return carry; +} +#define asm_add 1 +#endif + +#if !asm_sub +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t borrow = 0; + uint8_t left_byte; + uint8_t right_byte; + + __asm__ volatile ( + "clc \n\t" + + "1: \n\t" + "ld %[left], x+ \n\t" /* Load left byte. */ + "ld %[right], y+ \n\t" /* Load right byte. */ + "sbc %[left], %[right] \n\t" /* Subtract. */ + "st z+, %[left] \n\t" /* Store the result. */ + "dec %[i] \n\t" + "brne 1b \n\t" + + "adc %[borrow], %[borrow] \n\t" /* Store carry bit in borrow. */ + + : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (i), + [borrow] "+r" (borrow), [left] "=&r" (left_byte), [right] "=&r" (right_byte) + : + : "cc" + ); + return borrow; +} +#define asm_sub 1 +#endif + +#if !asm_mult +__attribute((noinline)) +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t r0 = 0; + uint8_t r1 = 0; + uint8_t r2 = 0; + uint8_t zero = 0; + uint8_t k, i; + + __asm__ volatile ( + "ldi %[k], 1 \n\t" /* k = 1; k < num_words; ++k */ + + "1: \n\t" + "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */ + + "add r28, %[k] \n\t" /* pre-add right ptr */ + "adc r29, %[zero] \n\t" + + "2: \n\t" + "ld r0, x+ \n\t" + "ld r1, -y \n\t" + "mul r0, r1 \n\t" + + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + + "inc %[i] \n\t" + "cp %[i], %[k] \n\t" + "brlo 2b \n\t" /* loop if i < k */ + + "sub r26, %[k] \n\t" /* fix up left ptr */ + "sbc r27, %[zero] \n\t" + + "st z+, %[r0] \n\t" /* Store the result. */ + "mov %[r0], %[r1] \n\t" + "mov %[r1], %[r2] \n\t" + "mov %[r2], %[zero] \n\t" + + "inc %[k] \n\t" + "cp %[k], %[num] \n\t" + "brlo 1b \n\t" /* loop if k < num_words */ + + /* second half */ + "mov %[k], %[num] \n\t" /* k = num_words; k > 0; --k */ + "add r28, %[num] \n\t" /* move right ptr to point at the end of right */ + "adc r29, %[zero] \n\t" + + "1: \n\t" + "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */ + + "2: \n\t" + "ld r0, x+ \n\t" + "ld r1, -y \n\t" + "mul r0, r1 \n\t" + + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + + "inc %[i] \n\t" + "cp %[i], %[k] \n\t" + "brlo 2b \n\t" /* loop if i < k */ + + "add r28, %[k] \n\t" /* fix up right ptr */ + "adc r29, %[zero] \n\t" + + "st z+, %[r0] \n\t" /* Store the result. */ + "mov %[r0], %[r1] \n\t" + "mov %[r1], %[r2] \n\t" + "mov %[r2], %[zero] \n\t" + + "dec %[k] \n\t" + "sub r26, %[k] \n\t" /* fix up left ptr (after k is decremented, so next time + we start 1 higher) */ + "sbc r27, %[zero] \n\t" + + "cp %[k], %[zero] \n\t" + "brne 1b \n\t" /* loop if k > 0 */ + + "st z+, %[r0] \n\t" /* Store last result byte. */ + "eor r1, r1 \n\t" /* fix r1 to be 0 again */ + + : "+z" (result), "+x" (left), "+y" (right), + [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), + [zero] "+r" (zero), [num] "+r" (num_words), + [k] "=&r" (k), [i] "=&r" (i) + : + : "r0", "cc" + ); +} +#define asm_mult 1 +#endif + +#if (uECC_SQUARE_FUNC && !asm_square) +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t r0 = 0; + uint8_t r1 = 0; + uint8_t r2 = 0; + uint8_t zero = 0; + uint8_t k; + + __asm__ volatile ( + "ldi %[k], 1 \n\t" /* k = 1; k < num_words * 2; ++k */ + + "1: \n\t" + + "movw r26, %[orig] \n\t" /* copy orig ptr to 'left' ptr */ + "movw r30, %[orig] \n\t" /* copy orig ptr to 'right' ptr */ + "cp %[k], %[num] \n\t" + "brlo 2f \n\t" + "breq 2f \n\t" + + /* when k > num_words, we start from (k - num_words) on the 'left' ptr */ + "add r26, %[k] \n\t" + "adc r27, %[zero] \n\t" + "sub r26, %[num] \n\t" + "sbc r27, %[zero] \n\t" + "add r30, %[num] \n\t" /* move right ptr to point at the end */ + "adc r31, %[zero] \n\t" + "rjmp 3f \n\t" + + "2: \n\t" /* when k <= num_words, we add k to the 'right' ptr */ + "add r30, %[k] \n\t" /* pre-add 'right' ptr */ + "adc r31, %[zero] \n\t" + + "3: \n\t" + "ld r0, x+ \n\t" + "cp r26, r30 \n\t" /* if left == right here, then we are done after this mult + (and we don't need to double) */ + "breq 4f \n\t" + "ld r1, -z \n\t" + "mul r0, r1 \n\t" + + /* add twice since it costs the same as doubling */ + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + + "cpse r26, r30 \n\t" /* if left == right here, then we are done */ + "rjmp 3b \n\t" + "rjmp 5f \n\t" /* skip code for non-doubled mult */ + + "4: \n\t" + "ld r1, -z \n\t" + "mul r0, r1 \n\t" + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + + "5: \n\t" + "movw r30, %[result] \n\t" /* make z point to result */ + "st z+, %[r0] \n\t" /* Store the result. */ + "movw %[result], r30 \n\t" /* update result ptr*/ + "mov %[r0], %[r1] \n\t" + "mov %[r1], %[r2] \n\t" + "mov %[r2], %[zero] \n\t" + + "inc %[k] \n\t" + "cp %[k], %[max] \n\t" + "brlo 1b \n\t" /* loop if k < num_words * 2 */ + + "movw r30, %[result] \n\t" /* make z point to result */ + "st z+, %[r0] \n\t" /* Store last result byte. */ + "eor r1, r1 \n\t" /* fix r1 to be 0 again */ + + : [result] "+r" (r), + [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero), + [k] "=&a" (k) + : [orig] "r" (left), [max] "r" ((uint8_t)(2 * num_words)), + [num] "r" (num_words) + : "r0", "r26", "r27", "r30", "r31", "cc" + ); +} +#define asm_square 1 +#endif /* uECC_SQUARE_FUNC && !asm_square */ + +#endif /* _UECC_ASM_AVR_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_avr_mult_square.inc b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_avr_mult_square.inc new file mode 100644 index 0000000..7ae08bc --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/asm_avr_mult_square.inc @@ -0,0 +1,26311 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_AVR_MULT_SQUARE_H_ +#define _UECC_ASM_AVR_MULT_SQUARE_H_ + +#define FAST_MULT_ASM_20 \ + "adiw r30, 10 \n\t" \ + "adiw r28, 10 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" \ + \ + "sbiw r30, 30 \n\t" \ + "sbiw r28, 20 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" + +#define FAST_MULT_ASM_20_TO_24 \ + "cpi r18, 20 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r6, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r7, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r8, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r9, y+ \n\t" \ + "sbiw r26, 24 \n\t" \ + "sbiw r28, 24 \n\t" \ + "sbiw r30, 20 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + \ + "mul r2, r14 \n\t" \ + "mov r19, r0 \n\t" \ + "mov r20, r1 \n\t" \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r12, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r12, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r13, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r13, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r3, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r4, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "st z+, r21 \n\t" \ + "st z+, r19 \n\t" \ + "adiw r26, 4 \n\t" \ + "adiw r28, 4 \n\t" + +#define FAST_MULT_ASM_24 \ + "adiw r30, 20 \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" \ + \ + "sbiw r30, 18 \n\t" \ + "sbiw r28, 14 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + \ + "sbiw r30, 38 \n\t" \ + "sbiw r28, 24 \n\t" \ + "sbiw r26, 14 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" + +#define FAST_MULT_ASM_24_TO_28 \ + "cpi r18, 24 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r6, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r7, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r8, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r9, y+ \n\t" \ + "sbiw r26, 28 \n\t" \ + "sbiw r28, 28 \n\t" \ + "sbiw r30, 24 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + \ + "mul r2, r14 \n\t" \ + "mov r19, r0 \n\t" \ + "mov r20, r1 \n\t" \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r12, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r12, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r13, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r13, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r3, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r4, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "mul r5, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "st z+, r19 \n\t" \ + "st z+, r20 \n\t" \ + "adiw r26, 4 \n\t" \ + "adiw r28, 4 \n\t" + +#define FAST_MULT_ASM_28 \ + "adiw r30, 20 \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + \ + "sbiw r30, 26 \n\t" \ + "sbiw r28, 18 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + \ + "sbiw r30, 46 \n\t" \ + "sbiw r28, 28 \n\t" \ + "sbiw r26, 18 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" + +#define FAST_MULT_ASM_28_TO_32 \ + "cpi r18, 28 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r6, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r7, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r8, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r9, y+ \n\t" \ + "sbiw r26, 32 \n\t" \ + "sbiw r28, 32 \n\t" \ + "sbiw r30, 28 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + \ + "mul r2, r14 \n\t" \ + "mov r19, r0 \n\t" \ + "mov r20, r1 \n\t" \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r12, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r12, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r13, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r13, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r3, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "mul r5, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "st z+, r20 \n\t" \ + "st z+, r21 \n\t" + /* Not necessary to move ptrs since we don't support sizes > 32 */ + +#define FAST_MULT_ASM_32 \ + "adiw r30, 30 \n\t" \ + "adiw r28, 30 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + \ + "sbiw r30, 14 \n\t" \ + "sbiw r28, 12 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + \ + "sbiw r30, 34 \n\t" \ + "sbiw r28, 22 \n\t" \ + "sbiw r26, 12 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" \ + \ + "sbiw r30, 54 \n\t" \ + "sbiw r28, 32 \n\t" \ + "sbiw r26, 22 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" + +#define FAST_SQUARE_ASM_20 \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r14, x+ \n\t" \ + "ld r15, x+ \n\t" \ + "ld r16, x+ \n\t" \ + "ld r17, x+ \n\t" \ + "ld r18, x+ \n\t" \ + "ld r19, x+ \n\t" \ + "ld r20, x+ \n\t" \ + "ld r21, x+ \n\t" \ + "push r26 \n\t" \ + "push r27 \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r2 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r3 \n\t" \ + "lsl r0 \n\t" \ + "rol r1 \n\t" \ + "adc r24, r25 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r4 \n\t" \ + "lsl r0 \n\t" \ + "rol r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r12, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r12, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r12, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r13, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r14, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r12, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r13, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r14, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r15, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r12, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r13, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r14, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r15, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r12, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r16, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r12, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r13, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r14, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r15, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r16, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r13, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r14, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r17, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r14, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r15, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r16, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r17, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r15, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r16, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r18, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r16, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r17, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r18, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r17, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r18, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r19, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r18, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r19, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r19, r21 \n\t" \ + "lsl r0 \n\t" \ + "rol r1 \n\t" \ + "adc r23, r25 \n\t" \ + "add r27, r0 \n\t" \ + "adc r26, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r20, r20 \n\t" \ + "add r27, r0 \n\t" \ + "adc r26, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r27 \n\t" \ + \ + "ldi r27, 0 \n\t" \ + "mul r20, r21 \n\t" \ + "lsl r0 \n\t" \ + "rol r1 \n\t" \ + "adc r27, r25 \n\t" \ + "add r26, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r27, r25 \n\t" \ + "st z+, r26 \n\t" \ + \ + "mul r21, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r27 \n\t" \ + "pop r27 \n\t" \ + "pop r26 \n\t" + +#define FAST_SQUARE_ASM_20_TO_24 \ + "cpi r20, 20 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "sbiw r26, 24 \n\t" \ + "sbiw r30, 20 \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + \ + "mul r2, r6 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "mov r12, r25 \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r22, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r23, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r24, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r28, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + \ + "lsl r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "rol r22 \n\t" \ + "rol r23 \n\t" \ + "rol r24 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "ld r0, z \n\t" \ + "add r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "ld r0, z \n\t" \ + "adc r18, r0 \n\t" \ + "st z+, r18 \n\t" \ + "ld r0, z \n\t" \ + "adc r19, r0 \n\t" \ + "st z+, r19 \n\t" \ + "ld r0, z \n\t" \ + "adc r21, r0 \n\t" \ + "st z+, r21 \n\t" \ + "ld r0, z \n\t" \ + "adc r22, r0 \n\t" \ + "st z+, r22 \n\t" \ + "ld r0, z \n\t" \ + "adc r23, r0 \n\t" \ + "st z+, r23 \n\t" \ + "ld r0, z \n\t" \ + "adc r24, r0 \n\t" \ + "st z+, r24 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "bst r28, 0 \n\t" \ + "lsr r29 \n\t" \ + "ror r28 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r10, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r11, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r12, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "lsl r28 \n\t" \ + "bld r28, 0 \n\t" \ + "rol r29 \n\t" \ + "rol r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "ld r0, z \n\t" \ + "add r28, r0 \n\t" \ + "st z+, r28 \n\t" \ + "ld r0, z \n\t" \ + "adc r29, r0 \n\t" \ + "st z+, r29 \n\t" \ + "ld r0, z \n\t" \ + "adc r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "adc r14, r25 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "mul r2, r2 \n\t" \ + "mov r16, r0 \n\t" \ + "mov r17, r1 \n\t" \ + "mul r3, r3 \n\t" \ + "mov r18, r0 \n\t" \ + "mov r19, r1 \n\t" \ + "mul r4, r4 \n\t" \ + "mov r21, r0 \n\t" \ + "mov r22, r1 \n\t" \ + "mul r5, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "add r16, r14 \n\t" \ + "adc r17, r15 \n\t" \ + "adc r18, r25 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "mul r7, r5 \n\t" \ + "mov r14, r0 \n\t" \ + "mov r15, r1 \n\t" \ + "mov r28, r25 \n\t" \ + "mul r8, r4 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mov r29, r25 \n\t" \ + "mul r8, r5 \n\t" \ + "add r15, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r15, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r15, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mov r10, r25 \n\t" \ + "mul r9, r5 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mov r11, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mov r12, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + \ + "lsl r14 \n\t" \ + "rol r15 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "rol r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "adc r24, r25 \n\t" \ + "add r16, r14 \n\t" \ + "adc r17, r15 \n\t" \ + "adc r18, r28 \n\t" \ + "adc r19, r29 \n\t" \ + "adc r21, r10 \n\t" \ + "adc r22, r11 \n\t" \ + "adc r23, r12 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "st z+, r16 \n\t" \ + "st z+, r17 \n\t" \ + "st z+, r18 \n\t" \ + "st z+, r19 \n\t" \ + "st z+, r21 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + "adiw r26, 4 \n\t" + +#define FAST_SQUARE_ASM_24 \ + "ldi r25, 0 \n\t" \ + "movw r28, r26 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "adiw r30, 20 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul 2, 12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" \ + \ + "sbiw r26, 4 \n\t" \ + "sbiw r30, 28 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r14, x+ \n\t" \ + "ld r15, x+ \n\t" \ + "ld r16, x+ \n\t" \ + "ld r17, x+ \n\t" \ + "ld r18, x+ \n\t" \ + "ld r19, x+ \n\t" \ + "ld r20, x+ \n\t" \ + "ld r21, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r2 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r3 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r12, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r3, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r5, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r14, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r5, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r6, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r7, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r15, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r16, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r8, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r9, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r17, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r10, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r11, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r12, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r18, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r12, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r13, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r13, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r14, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r19, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r14, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r15, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r15, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r16, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r20, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r16, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r17, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r17, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r18, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r21, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r18, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r19, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r19, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r20, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r2, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r20, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r21, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r21, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r5 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r4 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r28 \n\t" \ + \ + "ldi r28, 0 \n\t" \ + "mul r4, r5 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "st z+, r29 \n\t" \ + \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r28 \n\t" + +#define FAST_SQUARE_ASM_24_TO_28 \ + "cpi r20, 24 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "sbiw r26, 28 \n\t" \ + "sbiw r30, 24 \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + \ + "mul r2, r6 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "mov r12, r25 \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r22, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r23, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r24, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r28, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + \ + "lsl r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "rol r22 \n\t" \ + "rol r23 \n\t" \ + "rol r24 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "ld r0, z \n\t" \ + "add r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "ld r0, z \n\t" \ + "adc r18, r0 \n\t" \ + "st z+, r18 \n\t" \ + "ld r0, z \n\t" \ + "adc r19, r0 \n\t" \ + "st z+, r19 \n\t" \ + "ld r0, z \n\t" \ + "adc r21, r0 \n\t" \ + "st z+, r21 \n\t" \ + "ld r0, z \n\t" \ + "adc r22, r0 \n\t" \ + "st z+, r22 \n\t" \ + "ld r0, z \n\t" \ + "adc r23, r0 \n\t" \ + "st z+, r23 \n\t" \ + "ld r0, z \n\t" \ + "adc r24, r0 \n\t" \ + "st z+, r24 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "bst r28, 0 \n\t" \ + "lsr r29 \n\t" \ + "ror r28 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r10, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r11, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r12, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "lsl r28 \n\t" \ + "bld r28, 0 \n\t" \ + "rol r29 \n\t" \ + "rol r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "ld r0, z \n\t" \ + "add r28, r0 \n\t" \ + "st z+, r28 \n\t" \ + "ld r0, z \n\t" \ + "adc r29, r0 \n\t" \ + "st z+, r29 \n\t" \ + "ld r0, z \n\t" \ + "adc r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "adc r18, r25 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "mul r2, r2 \n\t" \ + "mov r21, r0 \n\t" \ + "mov r22, r1 \n\t" \ + "mul r3, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r4 \n\t" \ + "mov r28, r0 \n\t" \ + "mov r29, r1 \n\t" \ + "mul r5, r5 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "add r21, r18 \n\t" \ + "adc r22, r19 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "mul r7, r5 \n\t" \ + "mov r18, r0 \n\t" \ + "mov r19, r1 \n\t" \ + "mov r12, r25 \n\t" \ + "mul r8, r4 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mov r13, r25 \n\t" \ + "mul r8, r5 \n\t" \ + "add r19, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r19, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r19, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mov r14, r25 \n\t" \ + "mul r9, r5 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mov r15, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mov r16, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + \ + "lsl r18 \n\t" \ + "rol r19 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "adc r11, r25 \n\t" \ + "add r21, r18 \n\t" \ + "adc r22, r19 \n\t" \ + "adc r23, r12 \n\t" \ + "adc r24, r13 \n\t" \ + "adc r28, r14 \n\t" \ + "adc r29, r15 \n\t" \ + "adc r10, r16 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "st z+, r21 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r28 \n\t" \ + "st z+, r29 \n\t" \ + "st z+, r10 \n\t" \ + "st z+, r11 \n\t" \ + "adiw r26, 4 \n\t" + +#define FAST_SQUARE_ASM_28 \ + "ldi r25, 0 \n\t" \ + "movw r28, r26 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "adiw r30, 20 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul 2, 12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + \ + "sbiw r26, 8 \n\t" \ + "sbiw r30, 36 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r14, x+ \n\t" \ + "ld r15, x+ \n\t" \ + "ld r16, x+ \n\t" \ + "ld r17, x+ \n\t" \ + "ld r18, x+ \n\t" \ + "ld r19, x+ \n\t" \ + "ld r20, x+ \n\t" \ + "ld r21, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r2 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r3 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r12, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r3, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r5, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r14, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r5, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r6, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r7, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r15, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r16, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r7, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r8, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r8, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r9, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r17, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r8, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r9, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r9, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r18, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r9, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r10, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r11, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r19, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r10, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r11, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r12, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r20, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r12, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r13, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r13, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r14, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r21, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r14, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r15, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r15, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r16, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r2, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r16, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r17, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r17, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r18, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r18, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r19, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r19, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r20, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r20, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r21, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r21, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r2, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r7, r9 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r8 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r28 \n\t" \ + \ + "ldi r28, 0 \n\t" \ + "mul r8, r9 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "st z+, r29 \n\t" \ + \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r28 \n\t" + +#define FAST_SQUARE_ASM_28_TO_32 \ + "cpi r20, 28 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "sbiw r26, 32 \n\t" \ + "sbiw r30, 28 \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + \ + "mul r2, r6 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "mov r12, r25 \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r22, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r23, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r24, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r28, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + \ + "lsl r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "rol r22 \n\t" \ + "rol r23 \n\t" \ + "rol r24 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "ld r0, z \n\t" \ + "add r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "ld r0, z \n\t" \ + "adc r18, r0 \n\t" \ + "st z+, r18 \n\t" \ + "ld r0, z \n\t" \ + "adc r19, r0 \n\t" \ + "st z+, r19 \n\t" \ + "ld r0, z \n\t" \ + "adc r21, r0 \n\t" \ + "st z+, r21 \n\t" \ + "ld r0, z \n\t" \ + "adc r22, r0 \n\t" \ + "st z+, r22 \n\t" \ + "ld r0, z \n\t" \ + "adc r23, r0 \n\t" \ + "st z+, r23 \n\t" \ + "ld r0, z \n\t" \ + "adc r24, r0 \n\t" \ + "st z+, r24 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "bst r28, 0 \n\t" \ + "lsr r29 \n\t" \ + "ror r28 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r10, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r11, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r12, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r22, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r23, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r24, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "lsl r28 \n\t" \ + "bld r28, 0 \n\t" \ + "rol r29 \n\t" \ + "rol r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "rol r22 \n\t" \ + "rol r23 \n\t" \ + "rol r24 \n\t" \ + "ld r0, z \n\t" \ + "add r28, r0 \n\t" \ + "st z+, r28 \n\t" \ + "ld r0, z \n\t" \ + "adc r29, r0 \n\t" \ + "st z+, r29 \n\t" \ + "ld r0, z \n\t" \ + "adc r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "ld r0, z \n\t" \ + "adc r18, r0 \n\t" \ + "st z+, r18 \n\t" \ + "ld r0, z \n\t" \ + "adc r19, r0 \n\t" \ + "st z+, r19 \n\t" \ + "ld r0, z \n\t" \ + "adc r21, r0 \n\t" \ + "st z+, r21 \n\t" \ + "ld r0, z \n\t" \ + "adc r22, r0 \n\t" \ + "st z+, r22 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "mul r2, r2 \n\t" \ + "mov r28, r0 \n\t" \ + "mov r29, r1 \n\t" \ + "mul r3, r3 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "mul r4, r4 \n\t" \ + "mov r12, r0 \n\t" \ + "mov r13, r1 \n\t" \ + "mul r5, r5 \n\t" \ + "mov r14, r0 \n\t" \ + "mov r15, r1 \n\t" \ + "add r28, r23 \n\t" \ + "adc r29, r24 \n\t" \ + "adc r10, r25 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "mul r7, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mov r16, r25 \n\t" \ + "mul r8, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mov r17, r25 \n\t" \ + "mul r8, r5 \n\t" \ + "add r24, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r24, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r24, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mov r18, r25 \n\t" \ + "mul r9, r5 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mov r21, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "adc r15, r25 \n\t" \ + "add r28, r23 \n\t" \ + "adc r29, r24 \n\t" \ + "adc r10, r16 \n\t" \ + "adc r11, r17 \n\t" \ + "adc r12, r18 \n\t" \ + "adc r13, r19 \n\t" \ + "adc r14, r21 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "st z+, r28 \n\t" \ + "st z+, r29 \n\t" \ + "st z+, r10 \n\t" \ + "st z+, r11 \n\t" \ + "st z+, r12 \n\t" \ + "st z+, r13 \n\t" \ + "st z+, r14 \n\t" \ + "st z+, r15 \n\t" \ + "adiw r26, 4 \n\t" + +#define FAST_SQUARE_ASM_32 \ + "ldi r25, 0 \n\t" \ + "movw r28, r26 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "adiw r30, 20 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul 2, 12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + \ + "sbiw r26, 12 \n\t" \ + "sbiw r30, 44 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r14, x+ \n\t" \ + "ld r15, x+ \n\t" \ + "ld r16, x+ \n\t" \ + "ld r17, x+ \n\t" \ + "ld r18, x+ \n\t" \ + "ld r19, x+ \n\t" \ + "ld r20, x+ \n\t" \ + "ld r21, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r2 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r3 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r12, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r3, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r5, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r14, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r5, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r6, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r7, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r15, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r16, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r7, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r8, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r8, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r9, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r17, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r8, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r9, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r9, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r18, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r9, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r10, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r11, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r19, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r10, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r11, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r12, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r20, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r11, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r12, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r12, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r13, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r21, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r12, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r13, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r13, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r14, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r2, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r13, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r14, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r14, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r15, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r14, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r15, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r15, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r16, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r16, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r17, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r17, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r18, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r18, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r19, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r19, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r20, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r20, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r21, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r21, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r8, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r11, r13 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r12, r12 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r28 \n\t" \ + \ + "ldi r28, 0 \n\t" \ + "mul r12, r13 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "st z+, r29 \n\t" \ + \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r28 \n\t" + +#endif /* _UECC_ASM_AVR_MULT_SQUARE_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/curve-specific.inc b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/curve-specific.inc new file mode 100644 index 0000000..0453b21 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/curve-specific.inc @@ -0,0 +1,1248 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_CURVE_SPECIFIC_H_ +#define _UECC_CURVE_SPECIFIC_H_ + +#define num_bytes_secp160r1 20 +#define num_bytes_secp192r1 24 +#define num_bytes_secp224r1 28 +#define num_bytes_secp256r1 32 +#define num_bytes_secp256k1 32 + +#if (uECC_WORD_SIZE == 1) + +#define num_words_secp160r1 20 +#define num_words_secp192r1 24 +#define num_words_secp224r1 28 +#define num_words_secp256r1 32 +#define num_words_secp256k1 32 + +#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) \ + 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##a, 0x##b, 0x##c, 0x##d + +#elif (uECC_WORD_SIZE == 4) + +#define num_words_secp160r1 5 +#define num_words_secp192r1 6 +#define num_words_secp224r1 7 +#define num_words_secp256r1 8 +#define num_words_secp256k1 8 + +#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a + +#elif (uECC_WORD_SIZE == 8) + +#define num_words_secp160r1 3 +#define num_words_secp192r1 3 +#define num_words_secp224r1 4 +#define num_words_secp256r1 4 +#define num_words_secp256k1 4 + +#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##h##g##f##e##d##c##b##a##ull +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a##ull + +#endif /* uECC_WORD_SIZE */ + +#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ + uECC_SUPPORTS_secp224r1 || uECC_SUPPORTS_secp256r1 +static void double_jacobian_default(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve) { + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[uECC_MAX_WORDS]; + uECC_word_t t5[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + if (uECC_vli_isZero(Z1, num_words)) { + return; + } + + uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */ + uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ + uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */ + uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ + uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */ + + uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ + uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ + uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ + uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */ + + uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ + uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ + if (uECC_vli_testBit(X1, 0)) { + uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words); + uECC_vli_rshift1(X1, num_words); + X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); + } else { + uECC_vli_rshift1(X1, num_words); + } + /* t1 = 3/2*(x1^2 - z1^4) = B */ + + uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */ + uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ + uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ + uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ + uECC_vli_modSub(t4, X1, t4, curve->p, num_words); /* t4 = B * (A - x3) - y1^4 = y3 */ + + uECC_vli_set(X1, Z1, num_words); + uECC_vli_set(Z1, Y1, num_words); + uECC_vli_set(Y1, t4, num_words); +} + +/* Computes result = x^3 + ax + b. result must not overlap x. */ +static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) { + uECC_word_t _3[uECC_MAX_WORDS] = {3}; /* -a = 3 */ + wordcount_t num_words = curve->num_words; + + uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ + uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ + uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ + uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); /* r = x^3 - 3x + b */ +} +#endif /* uECC_SUPPORTS_secp... */ + +#if uECC_SUPPORT_COMPRESSED_POINT +#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ + uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1 +/* Compute a = sqrt(a) (mod curve_p). */ +static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { + bitcount_t i; + uECC_word_t p1[uECC_MAX_WORDS] = {1}; + uECC_word_t l_result[uECC_MAX_WORDS] = {1}; + wordcount_t num_words = curve->num_words; + + /* When curve->p == 3 (mod 4), we can compute + sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */ + uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */ + for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) { + uECC_vli_modSquare_fast(l_result, l_result, curve); + if (uECC_vli_testBit(p1, i)) { + uECC_vli_modMult_fast(l_result, l_result, a, curve); + } + } + uECC_vli_set(a, l_result, num_words); +} +#endif /* uECC_SUPPORTS_secp... */ +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +#if uECC_SUPPORTS_secp160r1 + +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp160r1 = { + num_words_secp160r1, + num_bytes_secp160r1, + 161, /* num_n_bits */ + { BYTES_TO_WORDS_8(FF, FF, FF, 7F, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_4(FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(57, 22, 75, CA, D3, AE, 27, F9), + BYTES_TO_WORDS_8(C8, F4, 01, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 01, 00, 00, 00) }, + { BYTES_TO_WORDS_8(82, FC, CB, 13, B9, 8B, C3, 68), + BYTES_TO_WORDS_8(89, 69, 64, 46, 28, 73, F5, 8E), + BYTES_TO_WORDS_4(68, B5, 96, 4A), + + BYTES_TO_WORDS_8(32, FB, C5, 7A, 37, 51, 23, 04), + BYTES_TO_WORDS_8(12, C9, DC, 59, 7D, 94, 68, 31), + BYTES_TO_WORDS_4(55, 28, A6, 23) }, + { BYTES_TO_WORDS_8(45, FA, 65, C5, AD, D4, D4, 81), + BYTES_TO_WORDS_8(9F, F8, AC, 65, 8B, 7A, BD, 54), + BYTES_TO_WORDS_4(FC, BE, 97, 1C) }, + &double_jacobian_default, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_default, +#endif + &x_side_default, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp160r1 +#endif +}; + +uECC_Curve uECC_secp160r1(void) { return &curve_secp160r1; } + +#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) +/* Computes result = product % curve_p + see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354 + + Note that this only works if log2(omega) < log2(p) / 2 */ +static void omega_mult_secp160r1(uECC_word_t *result, const uECC_word_t *right); +#if uECC_WORD_SIZE == 8 +static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { + uECC_word_t tmp[2 * num_words_secp160r1]; + uECC_word_t copy; + + uECC_vli_clear(tmp, num_words_secp160r1); + uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1); + + omega_mult_secp160r1(tmp, product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */ + + product[num_words_secp160r1 - 1] &= 0xffffffff; + copy = tmp[num_words_secp160r1 - 1]; + tmp[num_words_secp160r1 - 1] &= 0xffffffff; + uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */ + uECC_vli_clear(product, num_words_secp160r1); + tmp[num_words_secp160r1 - 1] = copy; + omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */ + uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */ + + while (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) { + uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); + } +} + +static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) { + uint32_t carry; + unsigned i; + + /* Multiply by (2^31 + 1). */ + carry = 0; + for (i = 0; i < num_words_secp160r1; ++i) { + uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32); + result[i] = (tmp << 31) + tmp + carry; + carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp)); + } + result[i] = carry; +} +#else +static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { + uECC_word_t tmp[2 * num_words_secp160r1]; + uECC_word_t carry; + + uECC_vli_clear(tmp, num_words_secp160r1); + uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1); + + omega_mult_secp160r1(tmp, product + num_words_secp160r1); /* (Rq, q) = q * c */ + + carry = uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */ + uECC_vli_clear(product, num_words_secp160r1); + omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */ + carry += uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */ + + while (carry > 0) { + --carry; + uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); + } + if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) { + uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); + } +} +#endif + +#if uECC_WORD_SIZE == 1 +static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) { + uint8_t carry; + uint8_t i; + + /* Multiply by (2^31 + 1). */ + uECC_vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */ + uECC_vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */ + result[3] = right[0] << 7; /* get last bit from shift */ + + carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */ + for (i = num_words_secp160r1; carry; ++i) { + uint16_t sum = (uint16_t)result[i] + carry; + result[i] = (uint8_t)sum; + carry = sum >> 8; + } +} +#elif uECC_WORD_SIZE == 4 +static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) { + uint32_t carry; + unsigned i; + + /* Multiply by (2^31 + 1). */ + uECC_vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */ + uECC_vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */ + result[0] = right[0] << 31; /* get last bit from shift */ + + carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */ + for (i = num_words_secp160r1; carry; ++i) { + uint64_t sum = (uint64_t)result[i] + carry; + result[i] = (uint32_t)sum; + carry = sum >> 32; + } +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) */ + +#endif /* uECC_SUPPORTS_secp160r1 */ + +#if uECC_SUPPORTS_secp192r1 + +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp192r1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp192r1 = { + num_words_secp192r1, + num_bytes_secp192r1, + 192, /* num_n_bits */ + { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(31, 28, D2, B4, B1, C9, 6B, 14), + BYTES_TO_WORDS_8(36, F8, DE, 99, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(12, 10, FF, 82, FD, 0A, FF, F4), + BYTES_TO_WORDS_8(00, 88, A1, 43, EB, 20, BF, 7C), + BYTES_TO_WORDS_8(F6, 90, 30, B0, 0E, A8, 8D, 18), + + BYTES_TO_WORDS_8(11, 48, 79, 1E, A1, 77, F9, 73), + BYTES_TO_WORDS_8(D5, CD, 24, 6B, ED, 11, 10, 63), + BYTES_TO_WORDS_8(78, DA, C8, FF, 95, 2B, 19, 07) }, + { BYTES_TO_WORDS_8(B1, B9, 46, C1, EC, DE, B8, FE), + BYTES_TO_WORDS_8(49, 30, 24, 72, AB, E9, A7, 0F), + BYTES_TO_WORDS_8(E7, 80, 9C, E5, 19, 05, 21, 64) }, + &double_jacobian_default, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_default, +#endif + &x_side_default, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp192r1 +#endif +}; + +uECC_Curve uECC_secp192r1(void) { return &curve_secp192r1; } + +#if (uECC_OPTIMIZATION_LEVEL > 0) +/* Computes result = product % curve_p. + See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */ +#if uECC_WORD_SIZE == 1 +static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) { + uint8_t tmp[num_words_secp192r1]; + uint8_t carry; + + uECC_vli_set(result, product, num_words_secp192r1); + + uECC_vli_set(tmp, &product[24], num_words_secp192r1); + carry = uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; + tmp[8] = product[24]; tmp[9] = product[25]; tmp[10] = product[26]; tmp[11] = product[27]; + tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31]; + tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35]; + tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39]; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[8] = product[40]; + tmp[1] = tmp[9] = product[41]; + tmp[2] = tmp[10] = product[42]; + tmp[3] = tmp[11] = product[43]; + tmp[4] = tmp[12] = product[44]; + tmp[5] = tmp[13] = product[45]; + tmp[6] = tmp[14] = product[46]; + tmp[7] = tmp[15] = product[47]; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); + } +} +#elif uECC_WORD_SIZE == 4 +static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) { + uint32_t tmp[num_words_secp192r1]; + int carry; + + uECC_vli_set(result, product, num_words_secp192r1); + + uECC_vli_set(tmp, &product[6], num_words_secp192r1); + carry = uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[1] = 0; + tmp[2] = product[6]; + tmp[3] = product[7]; + tmp[4] = product[8]; + tmp[5] = product[9]; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[2] = product[10]; + tmp[1] = tmp[3] = product[11]; + tmp[4] = tmp[5] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); + } +} +#else +static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) { + uint64_t tmp[num_words_secp192r1]; + int carry; + + uECC_vli_set(result, product, num_words_secp192r1); + + uECC_vli_set(tmp, &product[3], num_words_secp192r1); + carry = (int)uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = 0; + tmp[1] = product[3]; + tmp[2] = product[4]; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[1] = product[5]; + tmp[2] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); + } +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */ + +#endif /* uECC_SUPPORTS_secp192r1 */ + +#if uECC_SUPPORTS_secp224r1 + +#if uECC_SUPPORT_COMPRESSED_POINT +static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve); +#endif +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp224r1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp224r1 = { + num_words_secp224r1, + num_bytes_secp224r1, + 224, /* num_n_bits */ + { BYTES_TO_WORDS_8(01, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_4(FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(3D, 2A, 5C, 5C, 45, 29, DD, 13), + BYTES_TO_WORDS_8(3E, F0, B8, E0, A2, 16, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_4(FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(21, 1D, 5C, 11, D6, 80, 32, 34), + BYTES_TO_WORDS_8(22, 11, C2, 56, D3, C1, 03, 4A), + BYTES_TO_WORDS_8(B9, 90, 13, 32, 7F, BF, B4, 6B), + BYTES_TO_WORDS_4(BD, 0C, 0E, B7), + + BYTES_TO_WORDS_8(34, 7E, 00, 85, 99, 81, D5, 44), + BYTES_TO_WORDS_8(64, 47, 07, 5A, A0, 75, 43, CD), + BYTES_TO_WORDS_8(E6, DF, 22, 4C, FB, 23, F7, B5), + BYTES_TO_WORDS_4(88, 63, 37, BD) }, + { BYTES_TO_WORDS_8(B4, FF, 55, 23, 43, 39, 0B, 27), + BYTES_TO_WORDS_8(BA, D8, BF, D7, B7, B0, 44, 50), + BYTES_TO_WORDS_8(56, 32, 41, F5, AB, B3, 04, 0C), + BYTES_TO_WORDS_4(85, 0A, 05, B4) }, + &double_jacobian_default, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_secp224r1, +#endif + &x_side_default, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp224r1 +#endif +}; + +uECC_Curve uECC_secp224r1(void) { return &curve_secp224r1; } + + +#if uECC_SUPPORT_COMPRESSED_POINT +/* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1_rs(uECC_word_t *d1, + uECC_word_t *e1, + uECC_word_t *f1, + const uECC_word_t *d0, + const uECC_word_t *e0, + const uECC_word_t *f0) { + uECC_word_t t[num_words_secp224r1]; + + uECC_vli_modSquare_fast(t, d0, &curve_secp224r1); /* t <-- d0 ^ 2 */ + uECC_vli_modMult_fast(e1, d0, e0, &curve_secp224r1); /* e1 <-- d0 * e0 */ + uECC_vli_modAdd(d1, t, f0, curve_secp224r1.p, num_words_secp224r1); /* d1 <-- t + f0 */ + uECC_vli_modAdd(e1, e1, e1, curve_secp224r1.p, num_words_secp224r1); /* e1 <-- e1 + e1 */ + uECC_vli_modMult_fast(f1, t, f0, &curve_secp224r1); /* f1 <-- t * f0 */ + uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */ + uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */ +} + +/* Routine 3.2.5 RSS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1_rss(uECC_word_t *d1, + uECC_word_t *e1, + uECC_word_t *f1, + const uECC_word_t *d0, + const uECC_word_t *e0, + const uECC_word_t *f0, + const bitcount_t j) { + bitcount_t i; + + uECC_vli_set(d1, d0, num_words_secp224r1); /* d1 <-- d0 */ + uECC_vli_set(e1, e0, num_words_secp224r1); /* e1 <-- e0 */ + uECC_vli_set(f1, f0, num_words_secp224r1); /* f1 <-- f0 */ + for (i = 1; i <= j; i++) { + mod_sqrt_secp224r1_rs(d1, e1, f1, d1, e1, f1); /* RS (d1,e1,f1,d1,e1,f1) */ + } +} + +/* Routine 3.2.6 RM; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1_rm(uECC_word_t *d2, + uECC_word_t *e2, + uECC_word_t *f2, + const uECC_word_t *c, + const uECC_word_t *d0, + const uECC_word_t *e0, + const uECC_word_t *d1, + const uECC_word_t *e1) { + uECC_word_t t1[num_words_secp224r1]; + uECC_word_t t2[num_words_secp224r1]; + + uECC_vli_modMult_fast(t1, e0, e1, &curve_secp224r1); /* t1 <-- e0 * e1 */ + uECC_vli_modMult_fast(t1, t1, c, &curve_secp224r1); /* t1 <-- t1 * c */ + /* t1 <-- p - t1 */ + uECC_vli_modSub(t1, curve_secp224r1.p, t1, curve_secp224r1.p, num_words_secp224r1); + uECC_vli_modMult_fast(t2, d0, d1, &curve_secp224r1); /* t2 <-- d0 * d1 */ + uECC_vli_modAdd(t2, t2, t1, curve_secp224r1.p, num_words_secp224r1); /* t2 <-- t2 + t1 */ + uECC_vli_modMult_fast(t1, d0, e1, &curve_secp224r1); /* t1 <-- d0 * e1 */ + uECC_vli_modMult_fast(e2, d1, e0, &curve_secp224r1); /* e2 <-- d1 * e0 */ + uECC_vli_modAdd(e2, e2, t1, curve_secp224r1.p, num_words_secp224r1); /* e2 <-- e2 + t1 */ + uECC_vli_modSquare_fast(f2, e2, &curve_secp224r1); /* f2 <-- e2^2 */ + uECC_vli_modMult_fast(f2, f2, c, &curve_secp224r1); /* f2 <-- f2 * c */ + /* f2 <-- p - f2 */ + uECC_vli_modSub(f2, curve_secp224r1.p, f2, curve_secp224r1.p, num_words_secp224r1); + uECC_vli_set(d2, t2, num_words_secp224r1); /* d2 <-- t2 */ +} + +/* Routine 3.2.7 RP; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1_rp(uECC_word_t *d1, + uECC_word_t *e1, + uECC_word_t *f1, + const uECC_word_t *c, + const uECC_word_t *r) { + wordcount_t i; + wordcount_t pow2i = 1; + uECC_word_t d0[num_words_secp224r1]; + uECC_word_t e0[num_words_secp224r1] = {1}; /* e0 <-- 1 */ + uECC_word_t f0[num_words_secp224r1]; + + uECC_vli_set(d0, r, num_words_secp224r1); /* d0 <-- r */ + /* f0 <-- p - c */ + uECC_vli_modSub(f0, curve_secp224r1.p, c, curve_secp224r1.p, num_words_secp224r1); + for (i = 0; i <= 6; i++) { + mod_sqrt_secp224r1_rss(d1, e1, f1, d0, e0, f0, pow2i); /* RSS (d1,e1,f1,d0,e0,f0,2^i) */ + mod_sqrt_secp224r1_rm(d1, e1, f1, c, d1, e1, d0, e0); /* RM (d1,e1,f1,c,d1,e1,d0,e0) */ + uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */ + uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */ + uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */ + pow2i *= 2; + } +} + +/* Compute a = sqrt(a) (mod curve_p). */ +/* Routine 3.2.8 mp_mod_sqrt_224; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) { + bitcount_t i; + uECC_word_t e1[num_words_secp224r1]; + uECC_word_t f1[num_words_secp224r1]; + uECC_word_t d0[num_words_secp224r1]; + uECC_word_t e0[num_words_secp224r1]; + uECC_word_t f0[num_words_secp224r1]; + uECC_word_t d1[num_words_secp224r1]; + + /* s = a; using constant instead of random value */ + mod_sqrt_secp224r1_rp(d0, e0, f0, a, a); /* RP (d0, e0, f0, c, s) */ + mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */ + for (i = 1; i <= 95; i++) { + uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */ + uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */ + uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */ + mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */ + if (uECC_vli_isZero(d1, num_words_secp224r1)) { /* if d1 == 0 */ + break; + } + } + uECC_vli_modInv(f1, e0, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- 1 / e0 */ + uECC_vli_modMult_fast(a, d0, f1, &curve_secp224r1); /* a <-- d0 / e0 */ +} +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +#if (uECC_OPTIMIZATION_LEVEL > 0) +/* Computes result = product % curve_p + from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +#if uECC_WORD_SIZE == 1 +static void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) { + uint8_t tmp[num_words_secp224r1]; + int8_t carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp224r1); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; + tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; + tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; + tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31]; + tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35]; + tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39]; + tmp[24] = product[40]; tmp[25] = product[41]; tmp[26] = product[42]; tmp[27] = product[43]; + carry = uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* s2 */ + tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47]; + tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51]; + tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55]; + tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* d1 */ + tmp[0] = product[28]; tmp[1] = product[29]; tmp[2] = product[30]; tmp[3] = product[31]; + tmp[4] = product[32]; tmp[5] = product[33]; tmp[6] = product[34]; tmp[7] = product[35]; + tmp[8] = product[36]; tmp[9] = product[37]; tmp[10] = product[38]; tmp[11] = product[39]; + tmp[12] = product[40]; tmp[13] = product[41]; tmp[14] = product[42]; tmp[15] = product[43]; + tmp[16] = product[44]; tmp[17] = product[45]; tmp[18] = product[46]; tmp[19] = product[47]; + tmp[20] = product[48]; tmp[21] = product[49]; tmp[22] = product[50]; tmp[23] = product[51]; + tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + /* d2 */ + tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47]; + tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51]; + tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55]; + tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; + tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); + } + } +} +#elif uECC_WORD_SIZE == 4 +static void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product) +{ + uint32_t tmp[num_words_secp224r1]; + int carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp224r1); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = 0; + tmp[3] = product[7]; + tmp[4] = product[8]; + tmp[5] = product[9]; + tmp[6] = product[10]; + carry = uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* s2 */ + tmp[3] = product[11]; + tmp[4] = product[12]; + tmp[5] = product[13]; + tmp[6] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* d1 */ + tmp[0] = product[7]; + tmp[1] = product[8]; + tmp[2] = product[9]; + tmp[3] = product[10]; + tmp[4] = product[11]; + tmp[5] = product[12]; + tmp[6] = product[13]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + /* d2 */ + tmp[0] = product[11]; + tmp[1] = product[12]; + tmp[2] = product[13]; + tmp[3] = tmp[4] = tmp[5] = tmp[6] = 0; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); + } + } +} +#else +static void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product) +{ + uint64_t tmp[num_words_secp224r1]; + int carry = 0; + + /* t */ + uECC_vli_set(result, product, num_words_secp224r1); + result[num_words_secp224r1 - 1] &= 0xffffffff; + + /* s1 */ + tmp[0] = 0; + tmp[1] = product[3] & 0xffffffff00000000ull; + tmp[2] = product[4]; + tmp[3] = product[5] & 0xffffffff; + uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* s2 */ + tmp[1] = product[5] & 0xffffffff00000000ull; + tmp[2] = product[6]; + tmp[3] = 0; + uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* d1 */ + tmp[0] = (product[3] >> 32) | (product[4] << 32); + tmp[1] = (product[4] >> 32) | (product[5] << 32); + tmp[2] = (product[5] >> 32) | (product[6] << 32); + tmp[3] = product[6] >> 32; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + /* d2 */ + tmp[0] = (product[5] >> 32) | (product[6] << 32); + tmp[1] = product[6] >> 32; + tmp[2] = tmp[3] = 0; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); + } while (carry < 0); + } else { + while (uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { + uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); + } + } +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */ + +#endif /* uECC_SUPPORTS_secp224r1 */ + +#if uECC_SUPPORTS_secp256r1 + +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp256r1 = { + num_words_secp256r1, + num_bytes_secp256r1, + 256, /* num_n_bits */ + { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), + BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), + BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), + BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), + BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), + + BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), + BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), + BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), + BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) }, + { BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), + BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), + BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), + BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) }, + &double_jacobian_default, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_default, +#endif + &x_side_default, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp256r1 +#endif +}; + +uECC_Curve uECC_secp256r1(void) { return &curve_secp256r1; } + + +#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) +/* Computes result = product % curve_p + from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +#if uECC_WORD_SIZE == 1 +static void vli_mmod_fast_secp256r1(uint8_t *result, uint8_t *product) { + uint8_t tmp[num_words_secp256r1]; + int8_t carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp256r1); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; + tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; + tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; + tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47]; + tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51]; + tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55]; + tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59]; + tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63]; + carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s2 */ + tmp[12] = product[48]; tmp[13] = product[49]; tmp[14] = product[50]; tmp[15] = product[51]; + tmp[16] = product[52]; tmp[17] = product[53]; tmp[18] = product[54]; tmp[19] = product[55]; + tmp[20] = product[56]; tmp[21] = product[57]; tmp[22] = product[58]; tmp[23] = product[59]; + tmp[24] = product[60]; tmp[25] = product[61]; tmp[26] = product[62]; tmp[27] = product[63]; + tmp[28] = tmp[29] = tmp[30] = tmp[31] = 0; + carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s3 */ + tmp[0] = product[32]; tmp[1] = product[33]; tmp[2] = product[34]; tmp[3] = product[35]; + tmp[4] = product[36]; tmp[5] = product[37]; tmp[6] = product[38]; tmp[7] = product[39]; + tmp[8] = product[40]; tmp[9] = product[41]; tmp[10] = product[42]; tmp[11] = product[43]; + tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; + tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59]; + tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s4 */ + tmp[0] = product[36]; tmp[1] = product[37]; tmp[2] = product[38]; tmp[3] = product[39]; + tmp[4] = product[40]; tmp[5] = product[41]; tmp[6] = product[42]; tmp[7] = product[43]; + tmp[8] = product[44]; tmp[9] = product[45]; tmp[10] = product[46]; tmp[11] = product[47]; + tmp[12] = product[52]; tmp[13] = product[53]; tmp[14] = product[54]; tmp[15] = product[55]; + tmp[16] = product[56]; tmp[17] = product[57]; tmp[18] = product[58]; tmp[19] = product[59]; + tmp[20] = product[60]; tmp[21] = product[61]; tmp[22] = product[62]; tmp[23] = product[63]; + tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55]; + tmp[28] = product[32]; tmp[29] = product[33]; tmp[30] = product[34]; tmp[31] = product[35]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* d1 */ + tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47]; + tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51]; + tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55]; + tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; + tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + tmp[24] = product[32]; tmp[25] = product[33]; tmp[26] = product[34]; tmp[27] = product[35]; + tmp[28] = product[40]; tmp[29] = product[41]; tmp[30] = product[42]; tmp[31] = product[43]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d2 */ + tmp[0] = product[48]; tmp[1] = product[49]; tmp[2] = product[50]; tmp[3] = product[51]; + tmp[4] = product[52]; tmp[5] = product[53]; tmp[6] = product[54]; tmp[7] = product[55]; + tmp[8] = product[56]; tmp[9] = product[57]; tmp[10] = product[58]; tmp[11] = product[59]; + tmp[12] = product[60]; tmp[13] = product[61]; tmp[14] = product[62]; tmp[15] = product[63]; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; + tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + tmp[24] = product[36]; tmp[25] = product[37]; tmp[26] = product[38]; tmp[27] = product[39]; + tmp[28] = product[44]; tmp[29] = product[45]; tmp[30] = product[46]; tmp[31] = product[47]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d3 */ + tmp[0] = product[52]; tmp[1] = product[53]; tmp[2] = product[54]; tmp[3] = product[55]; + tmp[4] = product[56]; tmp[5] = product[57]; tmp[6] = product[58]; tmp[7] = product[59]; + tmp[8] = product[60]; tmp[9] = product[61]; tmp[10] = product[62]; tmp[11] = product[63]; + tmp[12] = product[32]; tmp[13] = product[33]; tmp[14] = product[34]; tmp[15] = product[35]; + tmp[16] = product[36]; tmp[17] = product[37]; tmp[18] = product[38]; tmp[19] = product[39]; + tmp[20] = product[40]; tmp[21] = product[41]; tmp[22] = product[42]; tmp[23] = product[43]; + tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; + tmp[28] = product[48]; tmp[29] = product[49]; tmp[30] = product[50]; tmp[31] = product[51]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d4 */ + tmp[0] = product[56]; tmp[1] = product[57]; tmp[2] = product[58]; tmp[3] = product[59]; + tmp[4] = product[60]; tmp[5] = product[61]; tmp[6] = product[62]; tmp[7] = product[63]; + tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; + tmp[12] = product[36]; tmp[13] = product[37]; tmp[14] = product[38]; tmp[15] = product[39]; + tmp[16] = product[40]; tmp[17] = product[41]; tmp[18] = product[42]; tmp[19] = product[43]; + tmp[20] = product[44]; tmp[21] = product[45]; tmp[22] = product[46]; tmp[23] = product[47]; + tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; + tmp[28] = product[52]; tmp[29] = product[53]; tmp[30] = product[54]; tmp[31] = product[55]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); + } + } +} +#elif uECC_WORD_SIZE == 4 +static void vli_mmod_fast_secp256r1(uint32_t *result, uint32_t *product) { + uint32_t tmp[num_words_secp256r1]; + int carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp256r1); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = 0; + tmp[3] = product[11]; + tmp[4] = product[12]; + tmp[5] = product[13]; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s2 */ + tmp[3] = product[12]; + tmp[4] = product[13]; + tmp[5] = product[14]; + tmp[6] = product[15]; + tmp[7] = 0; + carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s3 */ + tmp[0] = product[8]; + tmp[1] = product[9]; + tmp[2] = product[10]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s4 */ + tmp[0] = product[9]; + tmp[1] = product[10]; + tmp[2] = product[11]; + tmp[3] = product[13]; + tmp[4] = product[14]; + tmp[5] = product[15]; + tmp[6] = product[13]; + tmp[7] = product[8]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* d1 */ + tmp[0] = product[11]; + tmp[1] = product[12]; + tmp[2] = product[13]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[8]; + tmp[7] = product[10]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d2 */ + tmp[0] = product[12]; + tmp[1] = product[13]; + tmp[2] = product[14]; + tmp[3] = product[15]; + tmp[4] = tmp[5] = 0; + tmp[6] = product[9]; + tmp[7] = product[11]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d3 */ + tmp[0] = product[13]; + tmp[1] = product[14]; + tmp[2] = product[15]; + tmp[3] = product[8]; + tmp[4] = product[9]; + tmp[5] = product[10]; + tmp[6] = 0; + tmp[7] = product[12]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d4 */ + tmp[0] = product[14]; + tmp[1] = product[15]; + tmp[2] = 0; + tmp[3] = product[9]; + tmp[4] = product[10]; + tmp[5] = product[11]; + tmp[6] = 0; + tmp[7] = product[13]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); + } + } +} +#else +static void vli_mmod_fast_secp256r1(uint64_t *result, uint64_t *product) { + uint64_t tmp[num_words_secp256r1]; + int carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp256r1); + + /* s1 */ + tmp[0] = 0; + tmp[1] = product[5] & 0xffffffff00000000ull; + tmp[2] = product[6]; + tmp[3] = product[7]; + carry = (int)uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s2 */ + tmp[1] = product[6] << 32; + tmp[2] = (product[6] >> 32) | (product[7] << 32); + tmp[3] = product[7] >> 32; + carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s3 */ + tmp[0] = product[4]; + tmp[1] = product[5] & 0xffffffff; + tmp[2] = 0; + tmp[3] = product[7]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s4 */ + tmp[0] = (product[4] >> 32) | (product[5] << 32); + tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull); + tmp[2] = product[7]; + tmp[3] = (product[6] >> 32) | (product[4] << 32); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* d1 */ + tmp[0] = (product[5] >> 32) | (product[6] << 32); + tmp[1] = (product[6] >> 32); + tmp[2] = 0; + tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32); + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d2 */ + tmp[0] = product[6]; + tmp[1] = product[7]; + tmp[2] = 0; + tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull); + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d3 */ + tmp[0] = (product[6] >> 32) | (product[7] << 32); + tmp[1] = (product[7] >> 32) | (product[4] << 32); + tmp[2] = (product[4] >> 32) | (product[5] << 32); + tmp[3] = (product[6] << 32); + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d4 */ + tmp[0] = product[7]; + tmp[1] = product[4] & 0xffffffff00000000ull; + tmp[2] = product[5]; + tmp[3] = product[6] & 0xffffffff00000000ull; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); + } + } +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) */ + +#endif /* uECC_SUPPORTS_secp256r1 */ + +#if uECC_SUPPORTS_secp256k1 + +static void double_jacobian_secp256k1(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve); +static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp256k1 = { + num_words_secp256k1, + num_bytes_secp256k1, + 256, /* num_n_bits */ + { BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF), + BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA), + BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59), + BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02), + BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55), + BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79), + + BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C), + BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD), + BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D), + BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48) }, + { BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00) }, + &double_jacobian_secp256k1, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_default, +#endif + &x_side_secp256k1, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp256k1 +#endif +}; + +uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; } + + +/* Double in place */ +static void double_jacobian_secp256k1(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve) { + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[num_words_secp256k1]; + uECC_word_t t5[num_words_secp256k1]; + + if (uECC_vli_isZero(Z1, num_words_secp256k1)) { + return; + } + + uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */ + uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */ + uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */ + uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */ + + uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */ + uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */ + if (uECC_vli_testBit(Y1, 0)) { + uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1); + uECC_vli_rshift1(Y1, num_words_secp256k1); + Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1); + } else { + uECC_vli_rshift1(Y1, num_words_secp256k1); + } + /* t2 = 3/2*(x1^2) = B */ + + uECC_vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */ + uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */ + uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */ + + uECC_vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */ + uECC_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */ + uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */ +} + +/* Computes result = x^3 + b. result must not overlap x. */ +static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) { + uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ + uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 */ + uECC_vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */ +} + +#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256k1) +static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right); +static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { + uECC_word_t tmp[2 * num_words_secp256k1]; + uECC_word_t carry; + + uECC_vli_clear(tmp, num_words_secp256k1); + uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1); + + omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */ + + carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q */ + uECC_vli_clear(product, num_words_secp256k1); + omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */ + carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */ + + while (carry > 0) { + --carry; + uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); + } + if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) > 0) { + uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); + } +} + +#if uECC_WORD_SIZE == 1 +static void omega_mult_secp256k1(uint8_t * result, const uint8_t * right) { + /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + wordcount_t k; + + /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + muladd(0xD1, right[0], &r0, &r1, &r2); + result[0] = r0; + r0 = r1; + r1 = r2; + /* r2 is still 0 */ + + for (k = 1; k < num_words_secp256k1; ++k) { + muladd(0x03, right[k - 1], &r0, &r1, &r2); + muladd(0xD1, right[k], &r0, &r1, &r2); + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + muladd(0x03, right[num_words_secp256k1 - 1], &r0, &r1, &r2); + result[num_words_secp256k1] = r0; + result[num_words_secp256k1 + 1] = r1; + /* add the 2^32 multiple */ + result[4 + num_words_secp256k1] = + uECC_vli_add(result + 4, result + 4, right, num_words_secp256k1); +} +#elif uECC_WORD_SIZE == 4 +static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) { + /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + uint32_t carry = 0; + wordcount_t k; + + for (k = 0; k < num_words_secp256k1; ++k) { + uint64_t p = (uint64_t)0x3D1 * right[k] + carry; + result[k] = (uint32_t) p; + carry = p >> 32; + } + result[num_words_secp256k1] = carry; + /* add the 2^32 multiple */ + result[1 + num_words_secp256k1] = + uECC_vli_add(result + 1, result + 1, right, num_words_secp256k1); +} +#else +static void omega_mult_secp256k1(uint64_t * result, const uint64_t * right) { + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + wordcount_t k; + + /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + for (k = 0; k < num_words_secp256k1; ++k) { + muladd(0x1000003D1ull, right[k], &r0, &r1, &r2); + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + result[num_words_secp256k1] = r0; +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && && !asm_mmod_fast_secp256k1) */ + +#endif /* uECC_SUPPORTS_secp256k1 */ + +#endif /* _UECC_CURVE_SPECIFIC_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/emk_project.py b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/emk_project.py new file mode 100644 index 0000000..940fadc --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/emk_project.py @@ -0,0 +1,127 @@ +import os + +c, link, asm, utils = emk.module("c", "link", "asm", "utils") + +default_compile_flags = ["-fvisibility=hidden", "-Wall", "-Wextra", "-Wshadow", "-Werror", "-Wno-missing-field-initializers", "-Wno-unused-parameter", \ + "-Wno-comment", "-Wno-unused", "-Wno-unknown-pragmas"] +default_link_flags = [] +opt_flags = {"dbg":["-g"], "std":["-O2"], "max":["-O3"], "small":["-Os"]} +opt_link_flags = {"dbg":[], "std":[], "max":[], "small":[]} +c_flags = ["-std=c99"] +cxx_flags = ["-std=c++11", "-Wno-reorder", "-fno-rtti", "-fno-exceptions"] +c_link_flags = [] +cxx_link_flags = ["-fno-rtti", "-fno-exceptions"] + +def setup_build_dir(): + build_arch = None + if "arch" in emk.options: + build_arch = emk.options["arch"] + elif not emk.cleaning: + build_arch = "osx" + emk.options["arch"] = build_arch + + opt_level = None + if "opt" in emk.options: + level = emk.options["opt"] + if level in opt_flags: + opt_level = level + else: + emk.log.warning("Unknown optimization level '%s'" % (level)) + elif not emk.cleaning: + opt_level = "dbg" + emk.options["opt"] = opt_level + + dirs = ["__build__"] + if build_arch: + dirs.append(build_arch) + if opt_level: + dirs.append(opt_level) + emk.build_dir = os.path.join(*dirs) + +def setup_osx(): + global c + global link + + flags = [("-arch", "x86_64"), "-fno-common", "-Wnewline-eof"] + c.flags.extend(flags) + c.cxx.flags += ["-stdlib=libc++"] + link.cxx.flags += ["-stdlib=libc++"] + + link_flags = [("-arch", "x86_64")] + link.local_flags.extend(link_flags) + +def setup_avr(): + global c + global link + + c.compiler = c.GccCompiler("/Projects/avr-tools/bin/avr-") + c.flags += ["-mmcu=atmega256rfr2", "-ffunction-sections", "-fdata-sections"] + link.linker = link.GccLinker("/Projects/avr-tools/bin/avr-") + link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"] + link.strip = True + +def setup_arm_thumb(): + global c + global link + global asm + global utils + + asm.assembler = asm.GccAssembler("/cross/arm_cortex/bin/arm-none-eabi-") + c.compiler = c.GccCompiler("/cross/arm_cortex/bin/arm-none-eabi-") + link.linker = link.GccLinker("/cross/arm_cortex/bin/arm-none-eabi-") + + c.flags.extend(["-mcpu=cortex-m0", "-mthumb", "-ffunction-sections", "-fdata-sections", "-fno-builtin-fprintf", "-fno-builtin-printf"]) + c.defines["LPC11XX"] = 1 + + link.local_flags.extend(["-mcpu=cortex-m0", "-mthumb", "-nostartfiles", "-nostdlib", "-Wl,--gc-sections"]) + link.local_flags.extend(["-Tflash.lds", "-L/Projects/lpc11xx/core", "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"]) + link.local_syslibs += ["gcc"] + link.depdirs += ["/Projects/lpc11xx/stdlib"] + + def do_objcopy(produces, requires): + utils.call("/cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0]) + + def handle_exe(path): + emk.depend(path, "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o") + emk.rule(do_objcopy, path + ".bin", path, cwd_safe=True, ex_safe=True) + emk.autobuild(path + ".bin") + + link.exe_funcs.append(handle_exe) + link.strip = True + + emk.recurse("/Projects/lpc11xx/core") + +def setup_linux_rpi(): + global c + global link + + c.compiler = c.GccCompiler("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-") + link.linker = link.GccLinker("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-") + + c.flags.extend(["-fomit-frame-pointer"]) + +setup_build_dir() + +setup_funcs = {"osx":setup_osx, "avr":setup_avr, "arm_thumb":setup_arm_thumb, "rpi": setup_linux_rpi} + +if not emk.cleaning: + build_arch = emk.options["arch"] + opt_level = emk.options["opt"] + + c.flags.extend(default_compile_flags) + c.flags.extend(opt_flags[opt_level]) + c.c.flags.extend(c_flags) + c.cxx.flags.extend(cxx_flags) + link.local_flags.extend(default_link_flags) + link.local_flags.extend(opt_link_flags[opt_level]) + link.c.local_flags.extend(c_link_flags) + link.cxx.local_flags.extend(cxx_link_flags) + + c.include_dirs.append("$:proj:$") + + if build_arch in setup_funcs: + setup_funcs[build_arch]() + else: + raise emk.BuildError("Unknown target arch '%s'" % (build_arch)) + + c.defines["TARGET_ARCH_" + build_arch.upper()] = 1 diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/emk_rules.py b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/emk_rules.py new file mode 100644 index 0000000..b1d76c8 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/emk_rules.py @@ -0,0 +1,3 @@ +c, link = emk.module("c", "link") + +emk.subdir("test") diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/platform-specific.inc b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/platform-specific.inc new file mode 100644 index 0000000..1bb595a --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/platform-specific.inc @@ -0,0 +1,67 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_PLATFORM_SPECIFIC_H_ +#define _UECC_PLATFORM_SPECIFIC_H_ + +#include "types.h" + +#if (defined(_WIN32) || defined(_WIN64)) +/* Windows */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <wincrypt.h> + +static int default_RNG(uint8_t *dest, unsigned size) { + HCRYPTPROV prov; + if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + return 0; + } + + CryptGenRandom(prov, size, (BYTE *)dest); + CryptReleaseContext(prov, 0); + return 1; +} +#define default_RNG_defined 1 + +#elif defined(unix) || defined(__linux__) || defined(__unix__) || defined(__unix) || \ + (defined(__APPLE__) && defined(__MACH__)) || defined(uECC_POSIX) + +/* Some POSIX-like system with /dev/urandom or /dev/random. */ +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef O_CLOEXEC + #define O_CLOEXEC 0 +#endif + +static int default_RNG(uint8_t *dest, unsigned size) { + int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + fd = open("/dev/random", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + return 0; + } + } + + char *ptr = (char *)dest; + size_t left = size; + while (left > 0) { + ssize_t bytes_read = read(fd, ptr, left); + if (bytes_read <= 0) { // read failed + close(fd); + return 0; + } + left -= bytes_read; + ptr += bytes_read; + } + + close(fd); + return 1; +} +#define default_RNG_defined 1 + +#endif /* platform */ + +#endif /* _UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_arm.py b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_arm.py new file mode 100755 index 0000000..402ace1 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_arm.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in 32-bit words" + sys.exit(1) + +size = int(sys.argv[1]) + +full_rows = size // 3 +init_size = size % 3 + +if init_size == 0: + full_rows = full_rows - 1 + init_size = 3 + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +rx = [3, 4, 5] +ry = [6, 7, 8] + +#### set up registers +emit("add r0, %s", (size - init_size) * 4) # move z +emit("add r2, %s", (size - init_size) * 4) # move y + +emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size)])) +emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(init_size)])) + +print "" +if init_size == 1: + emit("umull r9, r10, r3, r6") + emit("stmia r0!, {r9, r10}") +else: + #### first two multiplications of initial block + emit("umull r11, r12, r3, r6") + emit("stmia r0!, {r11}") + print "" + emit("mov r10, #0") + emit("umull r11, r9, r3, r7") + emit("adds r12, r12, r11") + emit("adc r9, r9, #0") + emit("umull r11, r14, r4, r6") + emit("adds r12, r12, r11") + emit("adcs r9, r9, r14") + emit("adc r10, r10, #0") + emit("stmia r0!, {r12}") + print "" + + #### rest of initial block, with moving accumulator registers + acc = [9, 10, 11, 12, 14] + if init_size == 3: + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 3): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 2): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i + 1], ry[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[init_size-1], ry[init_size-1]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("stmia r0!, {r%s}", acc[0]) + emit("stmia r0!, {r%s}", acc[1]) +print "" + +#### reset y and z pointers +emit("sub r0, %s", (2 * init_size + 3) * 4) +emit("sub r2, %s", (init_size + 3) * 4) + +#### load y registers +emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(3)])) + +#### load additional x registers +if init_size != 3: + emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size, 3)])) +print "" + +prev_size = init_size +for row in xrange(full_rows): + emit("umull r11, r12, r3, r6") + emit("stmia r0!, {r11}") + print "" + emit("mov r10, #0") + emit("umull r11, r9, r3, r7") + emit("adds r12, r12, r11") + emit("adc r9, r9, #0") + emit("umull r11, r14, r4, r6") + emit("adds r12, r12, r11") + emit("adcs r9, r9, r14") + emit("adc r10, r10, #0") + emit("stmia r0!, {r12}") + print "" + + acc = [9, 10, 11, 12, 14] + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 3): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + #### now we need to start shifting x and loading from z + x_regs = [3, 4, 5] + for r in xrange(0, prev_size): + x_regs = x_regs[1:] + x_regs[:1] + emit("ldmia r1!, {r%s}", x_regs[2]) + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 3): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], ry[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, #0", acc[1], acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + # done shifting x, start shifting y + y_regs = [6, 7, 8] + for r in xrange(0, prev_size): + y_regs = y_regs[1:] + y_regs[:1] + emit("ldmia r2!, {r%s}", y_regs[2]) + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 3): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], y_regs[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, #0", acc[1], acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + # done both shifts, do remaining corner + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 2): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i + 1], y_regs[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[2], y_regs[2]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("stmia r0!, {r%s}", acc[0]) + emit("stmia r0!, {r%s}", acc[1]) + print "" + + prev_size = prev_size + 3 + if row < full_rows - 1: + #### reset x, y and z pointers + emit("sub r0, %s", (2 * prev_size + 3) * 4) + emit("sub r1, %s", prev_size * 4) + emit("sub r2, %s", (prev_size + 3) * 4) + + #### load x and y registers + emit("ldmia r1!, {%s}", ",".join(["r%s" % (rx[i]) for i in xrange(3)])) + emit("ldmia r2!, {%s}", ",".join(["r%s" % (ry[i]) for i in xrange(3)])) + + print "" diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_avr.py b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_avr.py new file mode 100755 index 0000000..d40e4c2 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_avr.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in bytes" + sys.exit(1) + +size = int(sys.argv[1]) + +full_rows = size // 10 +init_size = size % 10 + +if init_size == 0: + full_rows = full_rows - 1 + init_size = 10 + +def rx(i): + return i + 2 + +def ry(i): + return i + 12 + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +#### set up registers +emit("adiw r30, %s", size - init_size) # move z +emit("adiw r28, %s", size - init_size) # move y + +for i in xrange(init_size): + emit("ld r%s, x+", rx(i)) +for i in xrange(init_size): + emit("ld r%s, y+", ry(i)) + +emit("ldi r25, 0") +print "" +if init_size == 1: + emit("mul r2, r12") + emit("st z+, r0") + emit("st z+, r1") +else: + #### first two multiplications of initial block + emit("ldi r23, 0") + emit("mul r2, r12") + emit("st z+, r0") + emit("mov r22, r1") + print "" + emit("ldi r24, 0") + emit("mul r2, r13") + emit("add r22, r0") + emit("adc r23, r1") + emit("mul r3, r12") + emit("add r22, r0") + emit("adc r23, r1") + emit("adc r24, r25") + emit("st z+, r22") + print "" + + #### rest of initial block, with moving accumulator registers + acc = [23, 24, 22] + for r in xrange(2, init_size): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, r+1): + emit("mul r%s, r%s", rx(i), ry(r - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + for r in xrange(1, init_size-1): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, init_size-r): + emit("mul r%s, r%s", rx(r+i), ry((init_size-1) - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + emit("mul r%s, r%s", rx(init_size-1), ry(init_size-1)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("st z+, r%s", acc[0]) + emit("st z+, r%s", acc[1]) +print "" + +#### reset y and z pointers +emit("sbiw r30, %s", 2 * init_size + 10) +emit("sbiw r28, %s", init_size + 10) + +#### load y registers +for i in xrange(10): + emit("ld r%s, y+", ry(i)) + +#### load additional x registers +for i in xrange(init_size, 10): + emit("ld r%s, x+", rx(i)) +print "" + +prev_size = init_size +for row in xrange(full_rows): + #### do x = 0-9, y = 0-9 multiplications + emit("ldi r23, 0") + emit("mul r2, r12") + emit("st z+, r0") + emit("mov r22, r1") + print "" + emit("ldi r24, 0") + emit("mul r2, r13") + emit("add r22, r0") + emit("adc r23, r1") + emit("mul r3, r12") + emit("add r22, r0") + emit("adc r23, r1") + emit("adc r24, r25") + emit("st z+, r22") + print "" + + acc = [23, 24, 22] + for r in xrange(2, 10): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, r+1): + emit("mul r%s, r%s", rx(i), ry(r - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + #### now we need to start shifting x and loading from z + x_regs = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] + for r in xrange(0, prev_size): + x_regs = x_regs[1:] + x_regs[:1] + emit("ld r%s, x+", x_regs[9]) # load next byte of left + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, 10): + emit("mul r%s, r%s", x_regs[i], ry(9 - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r25", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) # store next byte (z increments) + print "" + acc = acc[1:] + acc[:1] + + # done shifting x, start shifting y + y_regs = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21] + for r in xrange(0, prev_size): + y_regs = y_regs[1:] + y_regs[:1] + emit("ld r%s, y+", y_regs[9]) # load next byte of right + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, 10): + emit("mul r%s, r%s", x_regs[i], y_regs[9 -i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r25", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) # store next byte (z increments) + print "" + acc = acc[1:] + acc[:1] + + # done both shifts, do remaining corner + for r in xrange(1, 9): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, 10-r): + emit("mul r%s, r%s", x_regs[r+i], y_regs[9 - i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + emit("mul r%s, r%s", x_regs[9], y_regs[9]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("st z+, r%s", acc[0]) + emit("st z+, r%s", acc[1]) + print "" + + prev_size = prev_size + 10 + if row < full_rows - 1: + #### reset x, y and z pointers + emit("sbiw r30, %s", 2 * prev_size + 10) + emit("sbiw r28, %s", prev_size + 10) + emit("sbiw r26, %s", prev_size) + + #### load x and y registers + for i in xrange(10): + emit("ld r%s, x+", rx(i)) + emit("ld r%s, y+", ry(i)) + print "" + +emit("eor r1, r1") diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_avr_extra.py b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_avr_extra.py new file mode 100755 index 0000000..f6e654f --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/mult_avr_extra.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in bytes" + sys.exit(1) + +size = int(sys.argv[1]) + +def lhi(i): + return i + 2 + +def rhi(i): + return i + 6 + +left_lo = [10, 11, 12, 13] +right_lo = [14, 15, 16, 17] + +def llo(i): + return left_lo[i] + +def rlo(i): + return right_lo[i] + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +def update_low(): + global left_lo + global right_lo + left_lo = left_lo[1:] + left_lo[:1] + right_lo = right_lo[1:] + right_lo[:1] + emit("ld r%s, x+", left_lo[3]) + emit("ld r%s, y+", right_lo[3]) + +accum = [19, 20, 21] + +def acc(i): + return accum[i] + +def rotate_acc(): + global accum + accum = accum[1:] + accum[:1] + +# Load high values +for i in xrange(4): + emit("ld r%s, x+", lhi(i)) + emit("ld r%s, y+", rhi(i)) + +emit("sbiw r26, %s", size + 4) +emit("sbiw r28, %s", size + 4) +emit("sbiw r30, %s", size) + +# Load low values +for i in xrange(4): + emit("ld r%s, x+", llo(i)) + emit("ld r%s, y+", rlo(i)) +print "" + +# Compute initial triangles +emit("mul r%s, r%s", lhi(0), rlo(0)) +emit("mov r%s, r0", acc(0)) +emit("mov r%s, r1", acc(1)) +emit("ldi r%s, 0", acc(2)) +emit("ld r0, z") +emit("add r%s, r0", acc(0)) +emit("adc r%s, r25", acc(1)) +emit("mul r%s, r%s", rhi(0), llo(0)) +emit("add r%s, r0", acc(0)) +emit("adc r%s, r1", acc(1)) +emit("adc r%s, r25", acc(2)) +emit("st z+, r%s", acc(0)) +print "" +rotate_acc() + +for i in xrange(1, 4): + emit("ldi r%s, 0", acc(2)) + emit("ld r0, z") + emit("add r%s, r0", acc(0)) + emit("adc r%s, r25", acc(1)) + for j in xrange(i + 1): + emit("mul r%s, r%s", lhi(j), rlo(i-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("mul r%s, r%s", rhi(j), llo(i-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("st z+, r%s", acc(0)) + print "" + rotate_acc() + +# Compute rows overlapping old block +for i in xrange(4, size): + emit("ldi r%s, 0", acc(2)) + emit("ld r0, z") + emit("add r%s, r0", acc(0)) + emit("adc r%s, r25", acc(1)) + update_low() + for j in xrange(4): + emit("mul r%s, r%s", lhi(j), rlo(3-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("mul r%s, r%s", rhi(j), llo(3-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("st z+, r%s", acc(0)) + print "" + rotate_acc() + +# Compute new triangle +left_combined = [llo(1), llo(2), llo(3), lhi(0), lhi(1), lhi(2), lhi(3)] +right_combined = [rlo(1), rlo(2), rlo(3), rhi(0), rhi(1), rhi(2), rhi(3)] + +def left(i): + return left_combined[i] + +def right(i): + return right_combined[i] + +for i in xrange(6): + emit("ldi r%s, 0", acc(2)) + for j in xrange(7 - i): + emit("mul r%s, r%s", left(i+j), right(6-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("st z+, r%s", acc(0)) + print "" + rotate_acc() + +emit("mul r%s, r%s", left(6), right(6)) +emit("add r%s, r0", acc(0)) +emit("adc r%s, r1", acc(1)) +emit("st z+, r%s", acc(0)) +emit("st z+, r%s", acc(1)) +emit("adiw r26, 4") +emit("adiw r28, 4") diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/square_arm.py b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/square_arm.py new file mode 100755 index 0000000..5330c7e --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/square_arm.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in 32-bit words" + sys.exit(1) + +size = int(sys.argv[1]) + +if size > 8: + print "This script doesn't work with integer size %s due to laziness" % (size) + sys.exit(1) + +init_size = 0 +if size > 6: + init_size = size - 6 + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +def mulacc(acc, r1, r2): + if size <= 6: + emit("umull r1, r14, r%s, r%s", r1, r2) + emit("adds r%s, r%s, r1", acc[0], acc[0]) + emit("adcs r%s, r%s, r14", acc[1], acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + else: + emit("mov r14, r%s", acc[1]) + emit("umlal r%s, r%s, r%s, r%s", acc[0], acc[1], r1, r2) + emit("cmp r14, r%s", acc[1]) + emit("it hi") + emit("adchi r%s, r%s, #0", acc[2], acc[2]) + +r = [2, 3, 4, 5, 6, 7] + +s = size - init_size + +if init_size == 1: + emit("ldmia r1!, {r2}") + emit("add r1, %s", (size - init_size * 2) * 4) + emit("ldmia r1!, {r5}") + + emit("add r0, %s", (size - init_size) * 4) + emit("umull r8, r9, r2, r5") + emit("stmia r0!, {r8, r9}") + + emit("sub r0, %s", (size + init_size) * 4) + emit("sub r1, %s", (size) * 4) + print "" +elif init_size == 2: + emit("ldmia r1!, {r2, r3}") + emit("add r1, %s", (size - init_size * 2) * 4) + emit("ldmia r1!, {r5, r6}") + + emit("add r0, %s", (size - init_size) * 4) + print "" + + emit("umull r8, r9, r2, r5") + emit("stmia r0!, {r8}") + print "" + + emit("umull r12, r10, r2, r6") + emit("adds r9, r9, r12") + emit("adc r10, r10, #0") + emit("stmia r0!, {r9}") + print "" + + emit("umull r8, r9, r3, r6") + emit("adds r10, r10, r8") + emit("adc r11, r9, #0") + emit("stmia r0!, {r10, r11}") + print "" + + emit("sub r0, %s", (size + init_size) * 4) + emit("sub r1, %s", (size) * 4) + +# load input words +emit("ldmia r1!, {%s}", ", ".join(["r%s" % (r[i]) for i in xrange(s)])) +print "" + +emit("umull r11, r12, r2, r2") +emit("stmia r0!, {r11}") +print "" +emit("mov r9, #0") +emit("umull r10, r11, r2, r3") +emit("adds r12, r12, r10") +emit("adcs r8, r11, #0") +emit("adc r9, r9, #0") +emit("adds r12, r12, r10") +emit("adcs r8, r8, r11") +emit("adc r9, r9, #0") +emit("stmia r0!, {r12}") +print "" +emit("mov r10, #0") +emit("umull r11, r12, r2, r4") +emit("adds r11, r11, r11") +emit("adcs r12, r12, r12") +emit("adc r10, r10, #0") +emit("adds r8, r8, r11") +emit("adcs r9, r9, r12") +emit("adc r10, r10, #0") +emit("umull r11, r12, r3, r3") +emit("adds r8, r8, r11") +emit("adcs r9, r9, r12") +emit("adc r10, r10, #0") +emit("stmia r0!, {r8}") +print "" + +acc = [8, 9, 10] +old_acc = [11, 12] +for i in xrange(3, s): + emit("mov r%s, #0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], r[0], r[i]) + for j in xrange(1, (i+1)//2): + mulacc(acc, r[j], r[i-j]) + # multiply by 2 + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1]) + emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2]) + + # add equal word (if any) + if ((i+1) % 2) != 0: + mulacc(acc, r[i//2], r[i//2]) + + # add old accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + + # store + emit("stmia r0!, {r%s}", acc[0]) + print "" + +regs = list(r) +for i in xrange(init_size): + regs = regs[1:] + regs[:1] + emit("ldmia r1!, {r%s}", regs[5]) + + for limit in [4, 5]: + emit("mov r%s, #0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], regs[0], regs[limit]) + for j in xrange(1, (limit+1)//2): + mulacc(acc, regs[j], regs[limit-j]) + + emit("ldr r14, [r0]") # load stored value from initial block, and add to accumulator + emit("adds r%s, r%s, r14", acc[0], acc[0]) + emit("adcs r%s, r%s, #0", acc[1], acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + + # multiply by 2 + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1]) + emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2]) + + # add equal word + if limit == 4: + mulacc(acc, regs[2], regs[2]) + + # add old accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + + # store + emit("stmia r0!, {r%s}", acc[0]) + print "" + +for i in xrange(1, s-3): + emit("mov r%s, #0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], regs[i], regs[s - 1]) + for j in xrange(1, (s-i)//2): + mulacc(acc, regs[i+j], regs[s - 1 - j]) + + # multiply by 2 + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1]) + emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2]) + + # add equal word (if any) + if ((s-i) % 2) != 0: + mulacc(acc, regs[i + (s-i)//2], regs[i + (s-i)//2]) + + # add old accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + + # store + emit("stmia r0!, {r%s}", acc[0]) + print "" + +acc = acc[1:] + acc[:1] +emit("mov r%s, #0", acc[2]) +emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 3], regs[s - 1]) +emit("adds r1, r1, r1") +emit("adcs r%s, r%s, r%s", old_acc[1], old_acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("adds r%s, r%s, r1", acc[0], acc[0]) +emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 2], regs[s - 2]) +emit("adds r%s, r%s, r1", acc[0], acc[0]) +emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("stmia r0!, {r%s}", acc[0]) +print "" + +acc = acc[1:] + acc[:1] +emit("mov r%s, #0", acc[2]) +emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 2], regs[s - 1]) +emit("adds r1, r1, r1") +emit("adcs r%s, r%s, r%s", old_acc[1], old_acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("adds r%s, r%s, r1", acc[0], acc[0]) +emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("stmia r0!, {r%s}", acc[0]) +print "" + +acc = acc[1:] + acc[:1] +emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 1], regs[s - 1]) +emit("adds r%s, r%s, r1", acc[0], acc[0]) +emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) +emit("stmia r0!, {r%s}", acc[0]) +emit("stmia r0!, {r%s}", acc[1]) diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/square_avr.py b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/square_avr.py new file mode 100755 index 0000000..6571c3b --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/scripts/square_avr.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in bytes" + sys.exit(1) + +size = int(sys.argv[1]) + +if size > 40: + print "This script doesn't work with integer size %s due to laziness" % (size) + sys.exit(1) + +init_size = size - 20 +if size < 20: + init_size = 0 + +def rg(i): + return i + 2 + +def lo(i): + return i + 2 + +def hi(i): + return i + 12 + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +#### set up registers +zero = "r25" +emit("ldi %s, 0", zero) # zero register + +if init_size > 0: + emit("movw r28, r26") # y = x + h = (init_size + 1)//2 + + for i in xrange(h): + emit("ld r%s, x+", lo(i)) + emit("adiw r28, %s", size - init_size) # move y to other end + for i in xrange(h): + emit("ld r%s, y+", hi(i)) + + emit("adiw r30, %s", size - init_size) # move z + + if init_size == 1: + emit("mul %s, %s", lo(0), hi(0)) + emit("st z+, r0") + emit("st z+, r1") + else: + #### first one + print "" + emit("ldi r23, 0") + emit("mul %s, %s", lo(0), hi(0)) + emit("st z+, r0") + emit("mov r22, r1") + print "" + + #### rest of initial block, with moving accumulator registers + acc = [22, 23, 24] + for r in xrange(1, h): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, (r+2)//2): + emit("mul r%s, r%s", lo(i), hi(r - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + lo_r = range(2, 2 + h) + hi_r = range(12, 12 + h) + + # now we need to start loading more from the high end + for r in xrange(h, init_size): + hi_r = hi_r[1:] + hi_r[:1] + emit("ld r%s, y+", hi_r[h-1]) + + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, (r+2)//2): + emit("mul r%s, r%s", lo(i), hi_r[h - 1 - i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + # loaded all of the high end bytes; now need to start loading the rest of the low end + for r in xrange(1, init_size-h): + lo_r = lo_r[1:] + lo_r[:1] + emit("ld r%s, x+", lo_r[h-1]) + + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, (init_size+1 - r)//2): + emit("mul r%s, r%s", lo_r[i], hi_r[h - 1 - i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + lo_r = lo_r[1:] + lo_r[:1] + emit("ld r%s, x+", lo_r[h-1]) + + # now we have loaded everything, and we just need to finish the last corner + for r in xrange(init_size-h, init_size-1): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, (init_size+1 - r)//2): + emit("mul r%s, r%s", lo_r[i], hi_r[h - 1 - i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + lo_r = lo_r[1:] + lo_r[:1] # make the indexing easy + + emit("mul r%s, r%s", lo_r[0], hi_r[h - 1]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("st z+, r%s", acc[0]) + emit("st z+, r%s", acc[1]) + print "" + emit("sbiw r26, %s", init_size) # reset x + emit("sbiw r30, %s", size + init_size) # reset z + +# TODO you could do more rows of size 20 here if your integers are larger than 40 bytes + +s = size - init_size + +for i in xrange(s): + emit("ld r%s, x+", rg(i)) + +#### first few columns +# NOTE: this is only valid if size >= 3 +print "" +emit("ldi r23, 0") +emit("mul r%s, r%s", rg(0), rg(0)) +emit("st z+, r0") +emit("mov r22, r1") +print "" +emit("ldi r24, 0") +emit("mul r%s, r%s", rg(0), rg(1)) +emit("add r22, r0") +emit("adc r23, r1") +emit("adc r24, %s", zero) +emit("add r22, r0") +emit("adc r23, r1") +emit("adc r24, %s", zero) +emit("st z+, r22") +print "" +emit("ldi r22, 0") +emit("mul r%s, r%s", rg(0), rg(2)) +emit("add r23, r0") +emit("adc r24, r1") +emit("adc r22, %s", zero) +emit("add r23, r0") +emit("adc r24, r1") +emit("adc r22, %s", zero) +emit("mul r%s, r%s", rg(1), rg(1)) +emit("add r23, r0") +emit("adc r24, r1") +emit("adc r22, %s", zero) +emit("st z+, r23") +print "" + +acc = [23, 24, 22] +old_acc = [28, 29] +for i in xrange(3, s): + emit("ldi r%s, 0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("mul r%s, r%s", rg(0), rg(i)) + emit("mov r%s, r0", acc[0]) + emit("mov r%s, r1", acc[1]) + for j in xrange(1, (i+1)//2): + emit("mul r%s, r%s", rg(j), rg(i-j)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + # multiply by 2 + emit("lsl r%s", acc[0]) + emit("rol r%s", acc[1]) + emit("rol r%s", acc[2]) + + # add equal word (if any) + if ((i+1) % 2) != 0: + emit("mul r%s, r%s", rg(i//2), rg(i//2)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # add old accumulator + emit("add r%s, r%s", acc[0], old_acc[0]) + emit("adc r%s, r%s", acc[1], old_acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # store + emit("st z+, r%s", acc[0]) + print "" + +regs = range(2, 22) +for i in xrange(init_size): + regs = regs[1:] + regs[:1] + emit("ld r%s, x+", regs[19]) + + for limit in [18, 19]: + emit("ldi r%s, 0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("mul r%s, r%s", regs[0], regs[limit]) + emit("mov r%s, r0", acc[0]) + emit("mov r%s, r1", acc[1]) + for j in xrange(1, (limit+1)//2): + emit("mul r%s, r%s", regs[j], regs[limit-j]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + + emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r25", acc[1]) + emit("adc r%s, r25", acc[2]) + + # multiply by 2 + emit("lsl r%s", acc[0]) + emit("rol r%s", acc[1]) + emit("rol r%s", acc[2]) + + # add equal word + if limit == 18: + emit("mul r%s, r%s", regs[9], regs[9]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # add old accumulator + emit("add r%s, r%s", acc[0], old_acc[0]) + emit("adc r%s, r%s", acc[1], old_acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # store + emit("st z+, r%s", acc[0]) + print "" + +for i in xrange(1, s-3): + emit("ldi r%s, 0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("mul r%s, r%s", regs[i], regs[s - 1]) + emit("mov r%s, r0", acc[0]) + emit("mov r%s, r1", acc[1]) + for j in xrange(1, (s-i)//2): + emit("mul r%s, r%s", regs[i+j], regs[s - 1 - j]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + # multiply by 2 + emit("lsl r%s", acc[0]) + emit("rol r%s", acc[1]) + emit("rol r%s", acc[2]) + + # add equal word (if any) + if ((s-i) % 2) != 0: + emit("mul r%s, r%s", regs[i + (s-i)//2], regs[i + (s-i)//2]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # add old accumulator + emit("add r%s, r%s", acc[0], old_acc[0]) + emit("adc r%s, r%s", acc[1], old_acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # store + emit("st z+, r%s", acc[0]) + print "" + +acc = acc[1:] + acc[:1] +emit("ldi r%s, 0", acc[2]) +emit("mul r%s, r%s", regs[17], regs[19]) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("mul r%s, r%s", regs[18], regs[18]) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("st z+, r%s", acc[0]) +print "" + +acc = acc[1:] + acc[:1] +emit("ldi r%s, 0", acc[2]) +emit("mul r%s, r%s", regs[18], regs[19]) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("st z+, r%s", acc[0]) +print "" + +emit("mul r%s, r%s", regs[19], regs[19]) +emit("add r%s, r0", acc[1]) +emit("adc r%s, r1", acc[2]) +emit("st z+, r%s", acc[1]) + +emit("st z+, r%s", acc[2]) +emit("eor r1, r1") diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/ecc_test/ecc_test.ino b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/ecc_test/ecc_test.ino new file mode 100644 index 0000000..c3c8900 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/ecc_test/ecc_test.ino @@ -0,0 +1,85 @@ +#include <uECC.h> + +extern "C" { + +static int RNG(uint8_t *dest, unsigned size) { + // Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of + // random noise). This can take a long time to generate random data if the result of analogRead(0) + // doesn't change very frequently. + while (size) { + uint8_t val = 0; + for (unsigned i = 0; i < 8; ++i) { + int init = analogRead(0); + int count = 0; + while (analogRead(0) == init) { + ++count; + } + + if (count == 0) { + val = (val << 1) | (init & 0x01); + } else { + val = (val << 1) | (count & 0x01); + } + } + *dest = val; + ++dest; + --size; + } + // NOTE: it would be a good idea to hash the resulting random data using SHA-256 or similar. + return 1; +} + +} // extern "C" + +void setup() { + Serial.begin(115200); + Serial.print("Testing ecc\n"); + uECC_set_rng(&RNG); +} + +void loop() { + const struct uECC_Curve_t * curve = uECC_secp160r1(); + uint8_t private1[21]; + uint8_t private2[21]; + + uint8_t public1[40]; + uint8_t public2[40]; + + uint8_t secret1[20]; + uint8_t secret2[20]; + + unsigned long a = millis(); + uECC_make_key(public1, private1, curve); + unsigned long b = millis(); + + Serial.print("Made key 1 in "); Serial.println(b-a); + a = millis(); + uECC_make_key(public2, private2, curve); + b = millis(); + Serial.print("Made key 2 in "); Serial.println(b-a); + + a = millis(); + int r = uECC_shared_secret(public2, private1, secret1, curve); + b = millis(); + Serial.print("Shared secret 1 in "); Serial.println(b-a); + if (!r) { + Serial.print("shared_secret() failed (1)\n"); + return; + } + + a = millis(); + r = uECC_shared_secret(public1, private2, secret2, curve); + b = millis(); + Serial.print("Shared secret 2 in "); Serial.println(b-a); + if (!r) { + Serial.print("shared_secret() failed (2)\n"); + return; + } + + if (memcmp(secret1, secret2, 20) != 0) { + Serial.print("Shared secrets are not identical!\n"); + } else { + Serial.print("Shared secrets are identical\n"); + } +} + diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/emk_rules.py b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/emk_rules.py new file mode 100644 index 0000000..956ccf5 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/emk_rules.py @@ -0,0 +1,4 @@ +c, link = emk.module("c", "link") +link.depdirs += [ + "$:proj:$" +] diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_compress.c b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_compress.c new file mode 100644 index 0000000..aef374c --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_compress.c @@ -0,0 +1,79 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include <stdio.h> +#include <string.h> + +#ifndef uECC_TEST_NUMBER_OF_ITERATIONS +#define uECC_TEST_NUMBER_OF_ITERATIONS 256 +#endif + +void vli_print(char *str, uint8_t *vli, unsigned int size) { + printf("%s ", str); + for(unsigned i=0; i<size; ++i) { + printf("%02X ", (unsigned)vli[i]); + } + printf("\n"); +} + +int main() { + uint8_t public[64]; + uint8_t private[32]; + uint8_t compressed_point[33]; + uint8_t decompressed_point[64]; + + int i; + int c; + + const struct uECC_Curve_t * curves[5]; + int num_curves = 0; +#if uECC_SUPPORTS_secp160r1 + curves[num_curves++] = uECC_secp160r1(); +#endif +#if uECC_SUPPORTS_secp192r1 + curves[num_curves++] = uECC_secp192r1(); +#endif +#if uECC_SUPPORTS_secp224r1 + curves[num_curves++] = uECC_secp224r1(); +#endif +#if uECC_SUPPORTS_secp256r1 + curves[num_curves++] = uECC_secp256r1(); +#endif +#if uECC_SUPPORTS_secp256k1 + curves[num_curves++] = uECC_secp256k1(); +#endif + + printf("Testing compression and decompression of %d random EC points\n", + uECC_TEST_NUMBER_OF_ITERATIONS); + + for (c = 0; c < num_curves; ++c) { + for (i = 0; i < uECC_TEST_NUMBER_OF_ITERATIONS; ++i) { + printf("."); + fflush(stdout); + + memset(public, 0, sizeof(public)); + memset(decompressed_point, 0, sizeof(decompressed_point)); + + /* Generate arbitrary EC point (public) on Curve */ + if (!uECC_make_key(public, private, curves[c])) { + printf("uECC_make_key() failed\n"); + continue; + } + + /* compress and decompress point */ + uECC_compress(public, compressed_point, curves[c]); + uECC_decompress(compressed_point, decompressed_point, curves[c]); + + if (memcmp(public, decompressed_point, sizeof(public)) != 0) { + printf("Original and decompressed points are not identical!\n"); + vli_print("Original point = ", public, sizeof(public)); + vli_print("Compressed point = ", compressed_point, sizeof(compressed_point)); + vli_print("Decompressed point = ", decompressed_point, sizeof(decompressed_point)); + } + } + printf("\n"); + } + + return 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_compute.c b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_compute.c new file mode 100644 index 0000000..7b936d8 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_compute.c @@ -0,0 +1,81 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include <stdio.h> +#include <string.h> + +void vli_print(char *str, uint8_t *vli, unsigned int size) { + printf("%s ", str); + for(unsigned i=0; i<size; ++i) { + printf("%02X ", (unsigned)vli[i]); + } + printf("\n"); +} + +int main() { + int i; + int success; + uint8_t private[32]; + uint8_t public[64]; + uint8_t public_computed[64]; + + int c; + + const struct uECC_Curve_t * curves[5]; + int num_curves = 0; +#if uECC_SUPPORTS_secp160r1 + curves[num_curves++] = uECC_secp160r1(); +#endif +#if uECC_SUPPORTS_secp192r1 + curves[num_curves++] = uECC_secp192r1(); +#endif +#if uECC_SUPPORTS_secp224r1 + curves[num_curves++] = uECC_secp224r1(); +#endif +#if uECC_SUPPORTS_secp256r1 + curves[num_curves++] = uECC_secp256r1(); +#endif +#if uECC_SUPPORTS_secp256k1 + curves[num_curves++] = uECC_secp256k1(); +#endif + + printf("Testing 256 random private key pairs\n"); + for (c = 0; c < num_curves; ++c) { + for (i = 0; i < 256; ++i) { + printf("."); + fflush(stdout); + + memset(public, 0, sizeof(public)); + memset(public_computed, 0, sizeof(public_computed)); + + if (!uECC_make_key(public, private, curves[c])) { + printf("uECC_make_key() failed\n"); + continue; + } + + if (!uECC_compute_public_key(private, public_computed, curves[c])) { + printf("uECC_compute_public_key() failed\n"); + } + + if (memcmp(public, public_computed, sizeof(public)) != 0) { + printf("Computed and provided public keys are not identical!\n"); + vli_print("Computed public key = ", public_computed, sizeof(public_computed)); + vli_print("Provided public key = ", public, sizeof(public)); + vli_print("Private key = ", private, sizeof(private)); + } + } + + printf("\n"); + printf("Testing private key = 0\n"); + + memset(private, 0, sizeof(private)); + success = uECC_compute_public_key(private, public_computed, curves[c]); + if (success) { + printf("uECC_compute_public_key() should have failed\n"); + } + printf("\n"); + } + + return 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdh.c b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdh.c new file mode 100644 index 0000000..7315b75 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdh.c @@ -0,0 +1,90 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include <stdio.h> +#include <string.h> + +void vli_print(uint8_t *vli, unsigned int size) { + for(unsigned i=0; i<size; ++i) { + printf("%02X ", (unsigned)vli[i]); + } +} + +int main() { + int i, c; + uint8_t private1[32] = {0}; + uint8_t private2[32] = {0}; + uint8_t public1[64] = {0}; + uint8_t public2[64] = {0}; + uint8_t secret1[32] = {0}; + uint8_t secret2[32] = {0}; + + const struct uECC_Curve_t * curves[5]; + int num_curves = 0; +#if uECC_SUPPORTS_secp160r1 + curves[num_curves++] = uECC_secp160r1(); +#endif +#if uECC_SUPPORTS_secp192r1 + curves[num_curves++] = uECC_secp192r1(); +#endif +#if uECC_SUPPORTS_secp224r1 + curves[num_curves++] = uECC_secp224r1(); +#endif +#if uECC_SUPPORTS_secp256r1 + curves[num_curves++] = uECC_secp256r1(); +#endif +#if uECC_SUPPORTS_secp256k1 + curves[num_curves++] = uECC_secp256k1(); +#endif + + printf("Testing 256 random private key pairs\n"); + + for (c = 0; c < num_curves; ++c) { + for (i = 0; i < 256; ++i) { + printf("."); + fflush(stdout); + + if (!uECC_make_key(public1, private1, curves[c]) || + !uECC_make_key(public2, private2, curves[c])) { + printf("uECC_make_key() failed\n"); + return 1; + } + + if (!uECC_shared_secret(public2, private1, secret1, curves[c])) { + printf("shared_secret() failed (1)\n"); + return 1; + } + + if (!uECC_shared_secret(public1, private2, secret2, curves[c])) { + printf("shared_secret() failed (2)\n"); + return 1; + } + + if (memcmp(secret1, secret2, sizeof(secret1)) != 0) { + printf("Shared secrets are not identical!\n"); + printf("Private key 1 = "); + vli_print(private1, 32); + printf("\n"); + printf("Private key 2 = "); + vli_print(private2, 32); + printf("\n"); + printf("Public key 1 = "); + vli_print(public1, 64); + printf("\n"); + printf("Public key 2 = "); + vli_print(public2, 64); + printf("\n"); + printf("Shared secret 1 = "); + vli_print(secret1, 32); + printf("\n"); + printf("Shared secret 2 = "); + vli_print(secret2, 32); + printf("\n"); + } + } + printf("\n"); + } + + return 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdsa.c b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdsa.c new file mode 100644 index 0000000..8699794 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdsa.c @@ -0,0 +1,59 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include <stdio.h> +#include <string.h> + +int main() { + int i, c; + uint8_t private[32] = {0}; + uint8_t public[64] = {0}; + uint8_t hash[32] = {0}; + uint8_t sig[64] = {0}; + + const struct uECC_Curve_t * curves[5]; + int num_curves = 0; +#if uECC_SUPPORTS_secp160r1 + curves[num_curves++] = uECC_secp160r1(); +#endif +#if uECC_SUPPORTS_secp192r1 + curves[num_curves++] = uECC_secp192r1(); +#endif +#if uECC_SUPPORTS_secp224r1 + curves[num_curves++] = uECC_secp224r1(); +#endif +#if uECC_SUPPORTS_secp256r1 + curves[num_curves++] = uECC_secp256r1(); +#endif +#if uECC_SUPPORTS_secp256k1 + curves[num_curves++] = uECC_secp256k1(); +#endif + + printf("Testing 256 signatures\n"); + for (c = 0; c < num_curves; ++c) { + for (i = 0; i < 256; ++i) { + printf("."); + fflush(stdout); + + if (!uECC_make_key(public, private, curves[c])) { + printf("uECC_make_key() failed\n"); + return 1; + } + memcpy(hash, public, sizeof(hash)); + + if (!uECC_sign(private, hash, sizeof(hash), sig, curves[c])) { + printf("uECC_sign() failed\n"); + return 1; + } + + if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) { + printf("uECC_verify() failed\n"); + return 1; + } + } + printf("\n"); + } + + return 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdsa_deterministic.c.example b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdsa_deterministic.c.example new file mode 100644 index 0000000..df9aa10 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/test/test_ecdsa_deterministic.c.example @@ -0,0 +1,93 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include <stdio.h> +#include <string.h> + +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 + +typedef struct SHA256_CTX { + uint32_t state[8]; + uint64_t bitcount; + uint8_t buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; + +extern void SHA256_Init(SHA256_CTX *ctx); +extern void SHA256_Update(SHA256_CTX *ctx, const uint8_t *message, size_t message_size); +extern void SHA256_Final(uint8_t digest[SHA256_DIGEST_LENGTH], SHA256_CTX *ctx); + +typedef struct SHA256_HashContext { + uECC_HashContext uECC; + SHA256_CTX ctx; +} SHA256_HashContext; + +static void init_SHA256(const uECC_HashContext *base) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Init(&context->ctx); +} + +static void update_SHA256(const uECC_HashContext *base, + const uint8_t *message, + unsigned message_size) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Update(&context->ctx, message, message_size); +} + +static void finish_SHA256(const uECC_HashContext *base, uint8_t *hash_result) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Final(hash_result, &context->ctx); +} + +int main() { + int i, c; + uint8_t private[32] = {0}; + uint8_t public[64] = {0}; + uint8_t hash[32] = {0}; + uint8_t sig[64] = {0}; + + uint8_t tmp[2 * SHA256_DIGEST_LENGTH + SHA256_BLOCK_LENGTH]; + SHA256_HashContext ctx = {{ + &init_SHA256, + &update_SHA256, + &finish_SHA256, + SHA256_BLOCK_LENGTH, + SHA256_DIGEST_LENGTH, + tmp + }}; + + const struct uECC_Curve_t * curves[5]; + curves[0] = uECC_secp160r1(); + curves[1] = uECC_secp192r1(); + curves[2] = uECC_secp224r1(); + curves[3] = uECC_secp256r1(); + curves[4] = uECC_secp256k1(); + + printf("Testing 256 signatures\n"); + for (c = 0; c < 5; ++c) { + for (i = 0; i < 256; ++i) { + printf("."); + fflush(stdout); + + if (!uECC_make_key(public, private, curves[c])) { + printf("uECC_make_key() failed\n"); + return 1; + } + memcpy(hash, public, sizeof(hash)); + + if (!uECC_sign_deterministic(private, hash, sizeof(hash), &ctx.uECC, sig, curves[c])) { + printf("uECC_sign() failed\n"); + return 1; + } + + if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) { + printf("uECC_verify() failed\n"); + return 1; + } + } + printf("\n"); + } + + return 0; +} diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/types.h b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/types.h new file mode 100644 index 0000000..9ee8143 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/types.h @@ -0,0 +1,108 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_TYPES_H_ +#define _UECC_TYPES_H_ + +#ifndef uECC_PLATFORM + #if __AVR__ + #define uECC_PLATFORM uECC_avr + #elif defined(__thumb2__) || defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */ + #define uECC_PLATFORM uECC_arm_thumb2 + #elif defined(__thumb__) + #define uECC_PLATFORM uECC_arm_thumb + #elif defined(__arm__) || defined(_M_ARM) + #define uECC_PLATFORM uECC_arm + #elif defined(__aarch64__) + #define uECC_PLATFORM uECC_arm64 + #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__) + #define uECC_PLATFORM uECC_x86 + #elif defined(__amd64__) || defined(_M_X64) + #define uECC_PLATFORM uECC_x86_64 + #else + #define uECC_PLATFORM uECC_arch_other + #endif +#endif + +#ifndef uECC_ARM_USE_UMAAL + #if (uECC_PLATFORM == uECC_arm) && (__ARM_ARCH >= 6) + #define uECC_ARM_USE_UMAAL 1 + #elif (uECC_PLATFORM == uECC_arm_thumb2) && (__ARM_ARCH >= 6) && !__ARM_ARCH_7M__ + #define uECC_ARM_USE_UMAAL 1 + #else + #define uECC_ARM_USE_UMAAL 0 + #endif +#endif + +#ifndef uECC_WORD_SIZE + #if uECC_PLATFORM == uECC_avr + #define uECC_WORD_SIZE 1 + #elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64) + #define uECC_WORD_SIZE 8 + #else + #define uECC_WORD_SIZE 4 + #endif +#endif + +#if (uECC_WORD_SIZE != 1) && (uECC_WORD_SIZE != 4) && (uECC_WORD_SIZE != 8) + #error "Unsupported value for uECC_WORD_SIZE" +#endif + +#if ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1)) + #pragma message ("uECC_WORD_SIZE must be 1 for AVR") + #undef uECC_WORD_SIZE + #define uECC_WORD_SIZE 1 +#endif + +#if ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \ + uECC_PLATFORM == uECC_arm_thumb2) && \ + (uECC_WORD_SIZE != 4)) + #pragma message ("uECC_WORD_SIZE must be 4 for ARM") + #undef uECC_WORD_SIZE + #define uECC_WORD_SIZE 4 +#endif + +#if defined(__SIZEOF_INT128__) || ((__clang_major__ * 100 + __clang_minor__) >= 302) + #define SUPPORTS_INT128 1 +#else + #define SUPPORTS_INT128 0 +#endif + +typedef int8_t wordcount_t; +typedef int16_t bitcount_t; +typedef int8_t cmpresult_t; + +#if (uECC_WORD_SIZE == 1) + +typedef uint8_t uECC_word_t; +typedef uint16_t uECC_dword_t; + +#define HIGH_BIT_SET 0x80 +#define uECC_WORD_BITS 8 +#define uECC_WORD_BITS_SHIFT 3 +#define uECC_WORD_BITS_MASK 0x07 + +#elif (uECC_WORD_SIZE == 4) + +typedef uint32_t uECC_word_t; +typedef uint64_t uECC_dword_t; + +#define HIGH_BIT_SET 0x80000000 +#define uECC_WORD_BITS 32 +#define uECC_WORD_BITS_SHIFT 5 +#define uECC_WORD_BITS_MASK 0x01F + +#elif (uECC_WORD_SIZE == 8) + +typedef uint64_t uECC_word_t; +#if SUPPORTS_INT128 +typedef unsigned __int128 uECC_dword_t; +#endif + +#define HIGH_BIT_SET 0x8000000000000000ull +#define uECC_WORD_BITS 64 +#define uECC_WORD_BITS_SHIFT 6 +#define uECC_WORD_BITS_MASK 0x03F + +#endif /* uECC_WORD_SIZE */ + +#endif /* _UECC_TYPES_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC.c b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC.c new file mode 100644 index 0000000..daa144a --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC.c @@ -0,0 +1,1634 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" +#include "uECC_vli.h" + +#ifndef uECC_RNG_MAX_TRIES + #define uECC_RNG_MAX_TRIES 64 +#endif + +#if uECC_ENABLE_VLI_API + #define uECC_VLI_API +#else + #define uECC_VLI_API static +#endif + +#define CONCATX(a, ...) a ## __VA_ARGS__ +#define CONCAT(a, ...) CONCATX(a, __VA_ARGS__) + +#define STRX(a) #a +#define STR(a) STRX(a) + +#define EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__)))) +#define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__)))) +#define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__)))) +#define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__)))) +#define EVAL4(...) __VA_ARGS__ + +#define DEC_1 0 +#define DEC_2 1 +#define DEC_3 2 +#define DEC_4 3 +#define DEC_5 4 +#define DEC_6 5 +#define DEC_7 6 +#define DEC_8 7 +#define DEC_9 8 +#define DEC_10 9 +#define DEC_11 10 +#define DEC_12 11 +#define DEC_13 12 +#define DEC_14 13 +#define DEC_15 14 +#define DEC_16 15 +#define DEC_17 16 +#define DEC_18 17 +#define DEC_19 18 +#define DEC_20 19 +#define DEC_21 20 +#define DEC_22 21 +#define DEC_23 22 +#define DEC_24 23 +#define DEC_25 24 +#define DEC_26 25 +#define DEC_27 26 +#define DEC_28 27 +#define DEC_29 28 +#define DEC_30 29 +#define DEC_31 30 +#define DEC_32 31 + +#define DEC(N) CONCAT(DEC_, N) + +#define SECOND_ARG(_, val, ...) val +#define SOME_CHECK_0 ~, 0 +#define GET_SECOND_ARG(...) SECOND_ARG(__VA_ARGS__, SOME,) +#define SOME_OR_0(N) GET_SECOND_ARG(CONCAT(SOME_CHECK_, N)) + +#define EMPTY(...) +#define DEFER(...) __VA_ARGS__ EMPTY() + +#define REPEAT_NAME_0() REPEAT_0 +#define REPEAT_NAME_SOME() REPEAT_SOME +#define REPEAT_0(...) +#define REPEAT_SOME(N, stuff) DEFER(CONCAT(REPEAT_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), stuff) stuff +#define REPEAT(N, stuff) EVAL(REPEAT_SOME(N, stuff)) + +#define REPEATM_NAME_0() REPEATM_0 +#define REPEATM_NAME_SOME() REPEATM_SOME +#define REPEATM_0(...) +#define REPEATM_SOME(N, macro) macro(N) \ + DEFER(CONCAT(REPEATM_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), macro) +#define REPEATM(N, macro) EVAL(REPEATM_SOME(N, macro)) + +#include "platform-specific.inc" + +#if (uECC_WORD_SIZE == 1) + #if uECC_SUPPORTS_secp160r1 + #define uECC_MAX_WORDS 21 /* Due to the size of curve_n. */ + #endif + #if uECC_SUPPORTS_secp192r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 24 + #endif + #if uECC_SUPPORTS_secp224r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 28 + #endif + #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 32 + #endif +#elif (uECC_WORD_SIZE == 4) + #if uECC_SUPPORTS_secp160r1 + #define uECC_MAX_WORDS 6 /* Due to the size of curve_n. */ + #endif + #if uECC_SUPPORTS_secp192r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 6 + #endif + #if uECC_SUPPORTS_secp224r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 7 + #endif + #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 8 + #endif +#elif (uECC_WORD_SIZE == 8) + #if uECC_SUPPORTS_secp160r1 + #define uECC_MAX_WORDS 3 + #endif + #if uECC_SUPPORTS_secp192r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 3 + #endif + #if uECC_SUPPORTS_secp224r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 4 + #endif + #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 4 + #endif +#endif /* uECC_WORD_SIZE */ + +#define BITS_TO_WORDS(num_bits) ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8)) +#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8) + +struct uECC_Curve_t { + wordcount_t num_words; + wordcount_t num_bytes; + bitcount_t num_n_bits; + uECC_word_t p[uECC_MAX_WORDS]; + uECC_word_t n[uECC_MAX_WORDS]; + uECC_word_t G[uECC_MAX_WORDS * 2]; + uECC_word_t b[uECC_MAX_WORDS]; + void (*double_jacobian)(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve); +#if uECC_SUPPORT_COMPRESSED_POINT + void (*mod_sqrt)(uECC_word_t *a, uECC_Curve curve); +#endif + void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); +#if (uECC_OPTIMIZATION_LEVEL > 0) + void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product); +#endif +}; + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN +static void bcopy(uint8_t *dst, + const uint8_t *src, + unsigned num_bytes) { + while (0 != num_bytes) { + num_bytes--; + dst[num_bytes] = src[num_bytes]; + } +} +#endif + +static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +#if (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \ + uECC_PLATFORM == uECC_arm_thumb2) + #include "asm_arm.inc" +#endif + +#if (uECC_PLATFORM == uECC_avr) + #include "asm_avr.inc" +#endif + +#if default_RNG_defined +static uECC_RNG_Function g_rng_function = &default_RNG; +#else +static uECC_RNG_Function g_rng_function = 0; +#endif + +void uECC_set_rng(uECC_RNG_Function rng_function) { + g_rng_function = rng_function; +} + +uECC_RNG_Function uECC_get_rng(void) { + return g_rng_function; +} + +int uECC_curve_private_key_size(uECC_Curve curve) { + return BITS_TO_BYTES(curve->num_n_bits); +} + +int uECC_curve_public_key_size(uECC_Curve curve) { + return 2 * curve->num_bytes; +} + +#if !asm_clear +uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { + wordcount_t i; + for (i = 0; i < num_words; ++i) { + vli[i] = 0; + } +} +#endif /* !asm_clear */ + +/* Constant-time comparison to zero - secure way to compare long integers */ +/* Returns 1 if vli == 0, 0 otherwise. */ +uECC_VLI_API uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) { + uECC_word_t bits = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + bits |= vli[i]; + } + return (bits == 0); +} + +/* Returns nonzero if bit 'bit' of vli is set. */ +uECC_VLI_API uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) { + return (vli[bit >> uECC_WORD_BITS_SHIFT] & ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); +} + +/* Counts the number of words in vli. */ +static wordcount_t vli_numDigits(const uECC_word_t *vli, const wordcount_t max_words) { + wordcount_t i; + /* Search from the end until we find a non-zero digit. + We do it in reverse because we expect that most digits will be nonzero. */ + for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { + } + + return (i + 1); +} + +/* Counts the number of bits required to represent vli. */ +uECC_VLI_API bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words) { + uECC_word_t i; + uECC_word_t digit; + + wordcount_t num_digits = vli_numDigits(vli, max_words); + if (num_digits == 0) { + return 0; + } + + digit = vli[num_digits - 1]; + for (i = 0; digit; ++i) { + digit >>= 1; + } + + return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); +} + +/* Sets dest = src. */ +#if !asm_set +uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) { + wordcount_t i; + for (i = 0; i < num_words; ++i) { + dest[i] = src[i]; + } +} +#endif /* !asm_set */ + +/* Returns sign of left - right. */ +static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + if (left[i] > right[i]) { + return 1; + } else if (left[i] < right[i]) { + return -1; + } + } + return 0; +} + +/* Constant-time comparison function - secure way to compare long integers */ +/* Returns one if left == right, zero otherwise. */ +uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t diff = 0; + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + diff |= (left[i] ^ right[i]); + } + return (diff == 0); +} + +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Returns sign of left - right, in constant time. */ +uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + return (!equal - 2 * neg); +} + +/* Computes vli = vli >> 1. */ +#if !asm_rshift1 +uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { + uECC_word_t *end = vli; + uECC_word_t carry = 0; + + vli += num_words; + while (vli-- > end) { + uECC_word_t temp = *vli; + *vli = (temp >> 1) | carry; + carry = temp << (uECC_WORD_BITS - 1); + } +} +#endif /* !asm_rshift1 */ + +/* Computes result = left + right, returning carry. Can modify in place. */ +#if !asm_add +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t carry = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + uECC_word_t sum = left[i] + right[i] + carry; + if (sum != left[i]) { + carry = (sum < left[i]); + } + result[i] = sum; + } + return carry; +} +#endif /* !asm_add */ + +/* Computes result = left - right, returning borrow. Can modify in place. */ +#if !asm_sub +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + uECC_word_t diff = left[i] - right[i] - borrow; + if (diff != left[i]) { + borrow = (diff > left[i]); + } + result[i] = diff; + } + return borrow; +} +#endif /* !asm_sub */ + +#if !asm_mult || (uECC_SQUARE_FUNC && !asm_square) || \ + (uECC_SUPPORTS_secp256k1 && (uECC_OPTIMIZATION_LEVEL > 0) && \ + ((uECC_WORD_SIZE == 1) || (uECC_WORD_SIZE == 8))) +static void muladd(uECC_word_t a, + uECC_word_t b, + uECC_word_t *r0, + uECC_word_t *r1, + uECC_word_t *r2) { +#if uECC_WORD_SIZE == 8 && !SUPPORTS_INT128 + uint64_t a0 = a & 0xffffffffull; + uint64_t a1 = a >> 32; + uint64_t b0 = b & 0xffffffffull; + uint64_t b1 = b >> 32; + + uint64_t i0 = a0 * b0; + uint64_t i1 = a0 * b1; + uint64_t i2 = a1 * b0; + uint64_t i3 = a1 * b1; + + uint64_t p0, p1; + + i2 += (i0 >> 32); + i2 += i1; + if (i2 < i1) { /* overflow */ + i3 += 0x100000000ull; + } + + p0 = (i0 & 0xffffffffull) | (i2 << 32); + p1 = i3 + (i2 >> 32); + + *r0 += p0; + *r1 += (p1 + (*r0 < p0)); + *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0)); +#else + uECC_dword_t p = (uECC_dword_t)a * b; + uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0; + r01 += p; + *r2 += (r01 < p); + *r1 = r01 >> uECC_WORD_BITS; + *r0 = (uECC_word_t)r01; +#endif +} +#endif /* muladd needed */ + +#if !asm_mult +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + wordcount_t i, k; + + /* Compute each digit of result in sequence, maintaining the carries. */ + for (k = 0; k < num_words; ++k) { + for (i = 0; i <= k; ++i) { + muladd(left[i], right[k - i], &r0, &r1, &r2); + } + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + for (k = num_words; k < num_words * 2 - 1; ++k) { + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], &r0, &r1, &r2); + } + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + result[num_words * 2 - 1] = r0; +} +#endif /* !asm_mult */ + +#if uECC_SQUARE_FUNC + +#if !asm_square +static void mul2add(uECC_word_t a, + uECC_word_t b, + uECC_word_t *r0, + uECC_word_t *r1, + uECC_word_t *r2) { +#if uECC_WORD_SIZE == 8 && !SUPPORTS_INT128 + uint64_t a0 = a & 0xffffffffull; + uint64_t a1 = a >> 32; + uint64_t b0 = b & 0xffffffffull; + uint64_t b1 = b >> 32; + + uint64_t i0 = a0 * b0; + uint64_t i1 = a0 * b1; + uint64_t i2 = a1 * b0; + uint64_t i3 = a1 * b1; + + uint64_t p0, p1; + + i2 += (i0 >> 32); + i2 += i1; + if (i2 < i1) + { /* overflow */ + i3 += 0x100000000ull; + } + + p0 = (i0 & 0xffffffffull) | (i2 << 32); + p1 = i3 + (i2 >> 32); + + *r2 += (p1 >> 63); + p1 = (p1 << 1) | (p0 >> 63); + p0 <<= 1; + + *r0 += p0; + *r1 += (p1 + (*r0 < p0)); + *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0)); +#else + uECC_dword_t p = (uECC_dword_t)a * b; + uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0; + *r2 += (p >> (uECC_WORD_BITS * 2 - 1)); + p *= 2; + r01 += p; + *r2 += (r01 < p); + *r1 = r01 >> uECC_WORD_BITS; + *r0 = (uECC_word_t)r01; +#endif +} + +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + + wordcount_t i, k; + + for (k = 0; k < num_words * 2 - 1; ++k) { + uECC_word_t min = (k < num_words ? 0 : (k + 1) - num_words); + for (i = min; i <= k && i <= k - i; ++i) { + if (i < k-i) { + mul2add(left[i], left[k - i], &r0, &r1, &r2); + } else { + muladd(left[i], left[k - i], &r0, &r1, &r2); + } + } + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + + result[num_words * 2 - 1] = r0; +} +#endif /* !asm_square */ + +#else /* uECC_SQUARE_FUNC */ + +#if uECC_ENABLE_VLI_API +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + uECC_vli_mult(result, left, left, num_words); +} +#endif /* uECC_ENABLE_VLI_API */ + +#endif /* uECC_SQUARE_FUNC */ + +/* Computes result = (left + right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +uECC_VLI_API void uECC_vli_modAdd(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t carry = uECC_vli_add(result, left, right, num_words); + if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { + /* result > mod (result = mod + remainder), so subtract mod to get remainder. */ + uECC_vli_sub(result, result, mod, num_words); + } +} + +/* Computes result = (left - right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +uECC_VLI_API void uECC_vli_modSub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); + if (l_borrow) { + /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, + we can get the correct result from result + mod (with overflow). */ + uECC_vli_add(result, result, mod, num_words); + } +} + +/* Computes result = product % mod, where product is 2N words long. */ +/* Currently only designed to work for curve_p or curve_n. */ +uECC_VLI_API void uECC_vli_mmod(uECC_word_t *result, + uECC_word_t *product, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t mod_multiple[2 * uECC_MAX_WORDS]; + uECC_word_t tmp[2 * uECC_MAX_WORDS]; + uECC_word_t *v[2] = {tmp, product}; + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words); + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple, word_shift); + if (bit_shift > 0) { + for(index = 0; index < (uECC_word_t)num_words; ++index) { + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod, num_words); + } + + for (index = 1; shift >= 0; --shift) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + uECC_vli_rshift1(mod_multiple + num_words, num_words); + } + uECC_vli_set(result, v[index], num_words); +} + +/* Computes result = (left * right) % mod. */ +uECC_VLI_API void uECC_vli_modMult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_mult(product, left, right, num_words); + uECC_vli_mmod(result, product, mod, num_words); +} + +uECC_VLI_API void uECC_vli_modMult_fast(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + uECC_Curve curve) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_mult(product, left, right, curve->num_words); +#if (uECC_OPTIMIZATION_LEVEL > 0) + curve->mmod_fast(result, product); +#else + uECC_vli_mmod(result, product, curve->p, curve->num_words); +#endif +} + +#if uECC_SQUARE_FUNC + +#if uECC_ENABLE_VLI_API +/* Computes result = left^2 % mod. */ +uECC_VLI_API void uECC_vli_modSquare(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_square(product, left, num_words); + uECC_vli_mmod(result, product, mod, num_words); +} +#endif /* uECC_ENABLE_VLI_API */ + +uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result, + const uECC_word_t *left, + uECC_Curve curve) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_square(product, left, curve->num_words); +#if (uECC_OPTIMIZATION_LEVEL > 0) + curve->mmod_fast(result, product); +#else + uECC_vli_mmod(result, product, curve->p, curve->num_words); +#endif +} + +#else /* uECC_SQUARE_FUNC */ + +#if uECC_ENABLE_VLI_API +uECC_VLI_API void uECC_vli_modSquare(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_vli_modMult(result, left, left, mod, num_words); +} +#endif /* uECC_ENABLE_VLI_API */ + +uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result, + const uECC_word_t *left, + uECC_Curve curve) { + uECC_vli_modMult_fast(result, left, left, curve); +} + +#endif /* uECC_SQUARE_FUNC */ + +#define EVEN(vli) (!(vli[0] & 1)) +static void vli_modInv_update(uECC_word_t *uv, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t carry = 0; + if (!EVEN(uv)) { + carry = uECC_vli_add(uv, uv, mod, num_words); + } + uECC_vli_rshift1(uv, num_words); + if (carry) { + uv[num_words - 1] |= HIGH_BIT_SET; + } +} + +/* Computes result = (1 / input) % mod. All VLIs are the same size. + See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */ +uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result, + const uECC_word_t *input, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS]; + cmpresult_t cmpResult; + + if (uECC_vli_isZero(input, num_words)) { + uECC_vli_clear(result, num_words); + return; + } + + uECC_vli_set(a, input, num_words); + uECC_vli_set(b, mod, num_words); + uECC_vli_clear(u, num_words); + u[0] = 1; + uECC_vli_clear(v, num_words); + while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { + if (EVEN(a)) { + uECC_vli_rshift1(a, num_words); + vli_modInv_update(u, mod, num_words); + } else if (EVEN(b)) { + uECC_vli_rshift1(b, num_words); + vli_modInv_update(v, mod, num_words); + } else if (cmpResult > 0) { + uECC_vli_sub(a, a, b, num_words); + uECC_vli_rshift1(a, num_words); + if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { + uECC_vli_add(u, u, mod, num_words); + } + uECC_vli_sub(u, u, v, num_words); + vli_modInv_update(u, mod, num_words); + } else { + uECC_vli_sub(b, b, a, num_words); + uECC_vli_rshift1(b, num_words); + if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { + uECC_vli_add(v, v, mod, num_words); + } + uECC_vli_sub(v, v, u, num_words); + vli_modInv_update(v, mod, num_words); + } + } + uECC_vli_set(result, u, num_words); +} + +/* ------ Point operations ------ */ + +#include "curve-specific.inc" + +/* Returns 1 if 'point' is the point at infinity, 0 otherwise. */ +#define EccPoint_isZero(point, curve) uECC_vli_isZero((point), (curve)->num_words * 2) + +/* Point multiplication algorithm using Montgomery's ladder with co-Z coordinates. +From http://eprint.iacr.org/2011/338.pdf +*/ + +/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */ +static void apply_z(uECC_word_t * X1, + uECC_word_t * Y1, + const uECC_word_t * const Z, + uECC_Curve curve) { + uECC_word_t t1[uECC_MAX_WORDS]; + + uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */ + uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ + uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ + uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ +} + +/* P = (x1, y1) => 2P, (x2, y2) => P' */ +static void XYcZ_initial_double(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + const uECC_word_t * const initial_Z, + uECC_Curve curve) { + uECC_word_t z[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + if (initial_Z) { + uECC_vli_set(z, initial_Z, num_words); + } else { + uECC_vli_clear(z, num_words); + z[0] = 1; + } + + uECC_vli_set(X2, X1, num_words); + uECC_vli_set(Y2, Y1, num_words); + + apply_z(X1, Y1, z, curve); + curve->double_jacobian(X1, Y1, z, curve); + apply_z(X2, Y2, z, curve); +} + +/* Input P = (x1, y1, Z), Q = (x2, y2, Z) + Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) + or P => P', Q => P + Q +*/ +static void XYcZ_add(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + uECC_Curve curve) { + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ + + uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ + uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ + uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ + uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ + + uECC_vli_set(X2, t5, num_words); +} + +/* Input P = (x1, y1, Z), Q = (x2, y2, Z) + Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) + or P => P - Q, Q => P + Q +*/ +static void XYcZ_addC(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + uECC_Curve curve) { + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[uECC_MAX_WORDS]; + uECC_word_t t6[uECC_MAX_WORDS]; + uECC_word_t t7[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + + uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */ + uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ + uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */ + uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ + + uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = (y2 - y1)*(B - x3) - E = y3 */ + + uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */ + uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ + uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ + uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */ + uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); /* t2 = (y2+y1)*(x3' - B) - E = y3' */ + + uECC_vli_set(X1, t7, num_words); +} + +/* result may overlap point. */ +static void EccPoint_mult(uECC_word_t * result, + const uECC_word_t * point, + const uECC_word_t * scalar, + const uECC_word_t * initial_Z, + bitcount_t num_bits, + uECC_Curve curve) { + /* R0 and R1 */ + uECC_word_t Rx[2][uECC_MAX_WORDS]; + uECC_word_t Ry[2][uECC_MAX_WORDS]; + uECC_word_t z[uECC_MAX_WORDS]; + bitcount_t i; + uECC_word_t nb; + wordcount_t num_words = curve->num_words; + + uECC_vli_set(Rx[1], point, num_words); + uECC_vli_set(Ry[1], point + num_words, num_words); + + XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); + + for (i = num_bits - 2; i > 0; --i) { + nb = !uECC_vli_testBit(scalar, i); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + } + + nb = !uECC_vli_testBit(scalar, 0); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + + /* Find final 1/Z value. */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ + uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */ + uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */ + uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0)) */ + /* yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, point + num_words, curve); + uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); /* Xb * yP / (xP * Yb * (X1 - X0)) */ + /* End 1/Z calculation */ + + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + apply_z(Rx[0], Ry[0], z, curve); + + uECC_vli_set(result, Rx[0], num_words); + uECC_vli_set(result + num_words, Ry[0], num_words); +} + +static uECC_word_t regularize_k(const uECC_word_t * const k, + uECC_word_t *k0, + uECC_word_t *k1, + uECC_Curve curve) { + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && + uECC_vli_testBit(k0, num_n_bits)); + uECC_vli_add(k1, k0, curve->n, num_n_words); + return carry; +} + +static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private_key, + uECC_Curve curve) { + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {tmp1, tmp2}; + uECC_word_t carry; + + /* Regularize the bitcount for the private key so that attackers cannot use a side channel + attack to learn the number of leading zeros. */ + carry = regularize_k(private_key, tmp1, tmp2, curve); + + EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); + + if (EccPoint_isZero(result, curve)) { + return 0; + } + return 1; +} + +#if uECC_WORD_SIZE == 1 + +uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, + int num_bytes, + const uint8_t *native) { + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + bytes[i] = native[(num_bytes - 1) - i]; + } +} + +uECC_VLI_API void uECC_vli_bytesToNative(uint8_t *native, + const uint8_t *bytes, + int num_bytes) { + uECC_vli_nativeToBytes(native, num_bytes, bytes); +} + +#else + +uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, + int num_bytes, + const uECC_word_t *native) { + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); + } +} + +uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, + const uint8_t *bytes, + int num_bytes) { + wordcount_t i; + uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + native[b / uECC_WORD_SIZE] |= + (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); + } +} + +#endif /* uECC_WORD_SIZE */ + +/* Generates a random integer in the range 0 < random < top. + Both random and top have num_words words. */ +uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random, + const uECC_word_t *top, + wordcount_t num_words) { + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top, num_words); + + if (!g_rng_function) { + return 0; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + return 0; + } + random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random, num_words) && + uECC_vli_cmp(top, random, num_words) == 1) { + return 1; + } + } + return 0; +} + +int uECC_make_key(uint8_t *public_key, + uint8_t *private_key, + uECC_Curve curve) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *_private = (uECC_word_t *)private_key; + uECC_word_t *_public = (uECC_word_t *)public_key; +#else + uECC_word_t _private[uECC_MAX_WORDS]; + uECC_word_t _public[uECC_MAX_WORDS * 2]; +#endif + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!uECC_generate_random_int(_private, curve->n, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (EccPoint_compute_public_key(_public, _private, curve)) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(curve->num_n_bits), _private); + uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public); + uECC_vli_nativeToBytes( + public_key + curve->num_bytes, curve->num_bytes, _public + curve->num_words); +#endif + return 1; + } + } + return 0; +} + +int uECC_shared_secret(const uint8_t *public_key, + const uint8_t *private_key, + uint8_t *secret, + uECC_Curve curve) { + uECC_word_t _public[uECC_MAX_WORDS * 2]; + uECC_word_t _private[uECC_MAX_WORDS]; + + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {_private, tmp}; + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_bytes = curve->num_bytes; + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) _private, private_key, num_bytes); + bcopy((uint8_t *) _public, public_key, num_bytes*2); +#else + uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + uECC_vli_bytesToNative(_public, public_key, num_bytes); + uECC_vli_bytesToNative(_public + num_words, public_key + num_bytes, num_bytes); +#endif + + /* Regularize the bitcount for the private key so that attackers cannot use a side channel + attack to learn the number of leading zeros. */ + carry = regularize_k(_private, _private, tmp, curve); + + /* If an RNG function was specified, try to get a random initial Z value to improve + protection against side-channel attacks. */ + if (g_rng_function) { + if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) { + return 0; + } + initial_Z = p2[carry]; + } + + EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, curve); +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) secret, (uint8_t *) _public, num_bytes); +#else + uECC_vli_nativeToBytes(secret, num_bytes, _public); +#endif + return !EccPoint_isZero(_public, curve); +} + +#if uECC_SUPPORT_COMPRESSED_POINT +void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve) { + wordcount_t i; + for (i = 0; i < curve->num_bytes; ++i) { + compressed[i+1] = public_key[i]; + } +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + compressed[0] = 2 + (public_key[curve->num_bytes] & 0x01); +#else + compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01); +#endif +} + +void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *point = (uECC_word_t *)public_key; +#else + uECC_word_t point[uECC_MAX_WORDS * 2]; +#endif + uECC_word_t *y = point + curve->num_words; +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy(public_key, compressed+1, curve->num_bytes); +#else + uECC_vli_bytesToNative(point, compressed + 1, curve->num_bytes); +#endif + curve->x_side(y, point, curve); + curve->mod_sqrt(y, curve); + + if ((y[0] & 0x01) != (compressed[0] & 0x01)) { + uECC_vli_sub(y, curve->p, y, curve->num_words); + } + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_nativeToBytes(public_key, curve->num_bytes, point); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y); +#endif +} +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + return 0; + } + + /* x and y must be smaller than p. */ + if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || + uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { + return 0; + } + + uECC_vli_modSquare_fast(tmp1, point + num_words, curve); + curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ + + /* Make sure that y^2 == x^3 + ax + b */ + return (int)(uECC_vli_equal(tmp1, tmp2, num_words)); +} + +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *_public = (uECC_word_t *)public_key; +#else + uECC_word_t _public[uECC_MAX_WORDS * 2]; +#endif + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); + uECC_vli_bytesToNative( + _public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes); +#endif + return uECC_valid_point(_public, curve); +} + +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *_private = (uECC_word_t *)private_key; + uECC_word_t *_public = (uECC_word_t *)public_key; +#else + uECC_word_t _private[uECC_MAX_WORDS]; + uECC_word_t _public[uECC_MAX_WORDS * 2]; +#endif + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(curve->num_n_bits)); +#endif + + /* Make sure the private key is in the range [1, n-1]. */ + if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) { + return 0; + } + + /* Compute public key. */ + if (!EccPoint_compute_public_key(_public, _private, curve)) { + return 0; + } + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public); + uECC_vli_nativeToBytes( + public_key + curve->num_bytes, curve->num_bytes, _public + curve->num_words); +#endif + return 1; +} + + +/* -------- ECDSA code -------- */ + +static void bits2int(uECC_word_t *native, + const uint8_t *bits, + unsigned bits_size, + uECC_Curve curve) { + unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); + unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits); + int shift; + uECC_word_t carry; + uECC_word_t *ptr; + + if (bits_size > num_n_bytes) { + bits_size = num_n_bytes; + } + + uECC_vli_clear(native, num_n_words); +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) native, bits, bits_size); +#else + uECC_vli_bytesToNative(native, bits, bits_size); +#endif + if (bits_size * 8 <= (unsigned)curve->num_n_bits) { + return; + } + shift = bits_size * 8 - curve->num_n_bits; + carry = 0; + ptr = native + num_n_words; + while (ptr-- > native) { + uECC_word_t temp = *ptr; + *ptr = (temp >> shift) | carry; + carry = temp << (uECC_WORD_BITS - shift); + } + + /* Reduce mod curve_n */ + if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) { + uECC_vli_sub(native, native, curve->n, num_n_words); + } +} + +static int uECC_sign_with_k(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + uECC_word_t *k, + uint8_t *signature, + uECC_Curve curve) { + + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t s[uECC_MAX_WORDS]; + uECC_word_t *k2[2] = {tmp, s}; +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *p = (uECC_word_t *)signature; +#else + uECC_word_t p[uECC_MAX_WORDS * 2]; +#endif + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + + /* Make sure 0 < k < curve_n */ + if (uECC_vli_isZero(k, num_words) || uECC_vli_cmp(curve->n, k, num_n_words) != 1) { + return 0; + } + + carry = regularize_k(k, tmp, s, curve); + EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve); + if (uECC_vli_isZero(p, num_words)) { + return 0; + } + + /* If an RNG function was specified, get a random number + to prevent side channel analysis of k. */ + if (!g_rng_function) { + uECC_vli_clear(tmp, num_n_words); + tmp[0] = 1; + } else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) { + return 0; + } + + /* Prevent side channel analysis of uECC_vli_modInv() to determine + bits of k / the private key by premultiplying by a random number */ + uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */ + uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */ + uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */ + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */ +#endif + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); +#else + uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); /* tmp = d */ +#endif + + s[num_n_words - 1] = 0; + uECC_vli_set(s, p, num_words); + uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ + + bits2int(tmp, message_hash, hash_size, curve); + uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */ + uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */ + if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) { + return 0; + } +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s, curve->num_bytes); +#else + uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s); +#endif + return 1; +} + +int uECC_sign(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + uint8_t *signature, + uECC_Curve curve) { + uECC_word_t k[uECC_MAX_WORDS]; + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!uECC_generate_random_int(k, curve->n, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, curve)) { + return 1; + } + } + return 0; +} + +/* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always + the same size as the hash result size. */ +static void HMAC_init(const uECC_HashContext *hash_context, const uint8_t *K) { + uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size; + unsigned i; + for (i = 0; i < hash_context->result_size; ++i) + pad[i] = K[i] ^ 0x36; + for (; i < hash_context->block_size; ++i) + pad[i] = 0x36; + + hash_context->init_hash(hash_context); + hash_context->update_hash(hash_context, pad, hash_context->block_size); +} + +static void HMAC_update(const uECC_HashContext *hash_context, + const uint8_t *message, + unsigned message_size) { + hash_context->update_hash(hash_context, message, message_size); +} + +static void HMAC_finish(const uECC_HashContext *hash_context, + const uint8_t *K, + uint8_t *result) { + uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size; + unsigned i; + for (i = 0; i < hash_context->result_size; ++i) + pad[i] = K[i] ^ 0x5c; + for (; i < hash_context->block_size; ++i) + pad[i] = 0x5c; + + hash_context->finish_hash(hash_context, result); + + hash_context->init_hash(hash_context); + hash_context->update_hash(hash_context, pad, hash_context->block_size); + hash_context->update_hash(hash_context, result, hash_context->result_size); + hash_context->finish_hash(hash_context, result); +} + +/* V = HMAC_K(V) */ +static void update_V(const uECC_HashContext *hash_context, uint8_t *K, uint8_t *V) { + HMAC_init(hash_context, K); + HMAC_update(hash_context, V, hash_context->result_size); + HMAC_finish(hash_context, K, V); +} + +/* Deterministic signing, similar to RFC 6979. Differences are: + * We just use H(m) directly rather than bits2octets(H(m)) + (it is not reduced modulo curve_n). + * We generate a value for k (aka T) directly rather than converting endianness. + + Layout of hash_context->tmp: <K> | <V> | (1 byte overlapped 0x00 or 0x01) / <HMAC pad> */ +int uECC_sign_deterministic(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uECC_HashContext *hash_context, + uint8_t *signature, + uECC_Curve curve) { + uint8_t *K = hash_context->tmp; + uint8_t *V = K + hash_context->result_size; + wordcount_t num_bytes = curve->num_bytes; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t tries; + unsigned i; + for (i = 0; i < hash_context->result_size; ++i) { + V[i] = 0x01; + K[i] = 0; + } + + /* K = HMAC_K(V || 0x00 || int2octets(x) || h(m)) */ + HMAC_init(hash_context, K); + V[hash_context->result_size] = 0x00; + HMAC_update(hash_context, V, hash_context->result_size + 1); + HMAC_update(hash_context, private_key, num_bytes); + HMAC_update(hash_context, message_hash, hash_size); + HMAC_finish(hash_context, K, K); + + update_V(hash_context, K, V); + + /* K = HMAC_K(V || 0x01 || int2octets(x) || h(m)) */ + HMAC_init(hash_context, K); + V[hash_context->result_size] = 0x01; + HMAC_update(hash_context, V, hash_context->result_size + 1); + HMAC_update(hash_context, private_key, num_bytes); + HMAC_update(hash_context, message_hash, hash_size); + HMAC_finish(hash_context, K, K); + + update_V(hash_context, K, V); + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + uECC_word_t T[uECC_MAX_WORDS]; + uint8_t *T_ptr = (uint8_t *)T; + wordcount_t T_bytes = 0; + for (;;) { + update_V(hash_context, K, V); + for (i = 0; i < hash_context->result_size; ++i) { + T_ptr[T_bytes++] = V[i]; + if (T_bytes >= num_n_words * uECC_WORD_SIZE) { + goto filled; + } + } + } + filled: + if ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8 > num_n_bits) { + uECC_word_t mask = (uECC_word_t)-1; + T[num_n_words - 1] &= + mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits)); + } + + if (uECC_sign_with_k(private_key, message_hash, hash_size, T, signature, curve)) { + return 1; + } + + /* K = HMAC_K(V || 0x00) */ + HMAC_init(hash_context, K); + V[hash_context->result_size] = 0x00; + HMAC_update(hash_context, V, hash_context->result_size + 1); + HMAC_finish(hash_context, K, K); + + update_V(hash_context, K, V); + } + return 0; +} + +static bitcount_t smax(bitcount_t a, bitcount_t b) { + return (a > b ? a : b); +} + +int uECC_verify(const uint8_t *public_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *signature, + uECC_Curve curve) { + uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS]; + uECC_word_t z[uECC_MAX_WORDS]; + uECC_word_t sum[uECC_MAX_WORDS * 2]; + uECC_word_t rx[uECC_MAX_WORDS]; + uECC_word_t ry[uECC_MAX_WORDS]; + uECC_word_t tx[uECC_MAX_WORDS]; + uECC_word_t ty[uECC_MAX_WORDS]; + uECC_word_t tz[uECC_MAX_WORDS]; + const uECC_word_t *points[4]; + const uECC_word_t *point; + bitcount_t num_bits; + bitcount_t i; +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *_public = (uECC_word_t *)public_key; +#else + uECC_word_t _public[uECC_MAX_WORDS * 2]; +#endif + uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) r, signature, curve->num_bytes); + bcopy((uint8_t *) s, signature + curve->num_bytes, curve->num_bytes); +#else + uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); + uECC_vli_bytesToNative( + _public + num_words, public_key + curve->num_bytes, curve->num_bytes); + uECC_vli_bytesToNative(r, signature, curve->num_bytes); + uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); +#endif + + /* r, s must not be 0. */ + if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { + return 0; + } + + /* r, s must be < n. */ + if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || + uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { + return 0; + } + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + u1[num_n_words - 1] = 0; + bits2int(u1, message_hash, hash_size, curve); + uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */ + uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ + + /* Calculate sum = G + Q. */ + uECC_vli_set(sum, _public, num_words); + uECC_vli_set(sum + num_words, _public + num_words, num_words); + uECC_vli_set(tx, curve->G, num_words); + uECC_vli_set(ty, curve->G + num_words, num_words); + uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ + XYcZ_add(tx, ty, sum, sum + num_words, curve); + uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ + apply_z(sum, sum + num_words, z, curve); + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + points[1] = curve->G; + points[2] = _public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point, num_words); + uECC_vli_set(ry, point + num_words, num_words); + uECC_vli_clear(z, num_words); + z[0] = 1; + + for (i = num_bits - 2; i >= 0; --i) { + uECC_word_t index; + curve->double_jacobian(rx, ry, z, curve); + + index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); + point = points[index]; + if (point) { + uECC_vli_set(tx, point, num_words); + uECC_vli_set(ty, point + num_words, num_words); + apply_z(tx, ty, z, curve); + uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ + XYcZ_add(tx, ty, rx, ry, curve); + uECC_vli_modMult_fast(z, z, tz, curve); + } + } + + uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ + apply_z(rx, ry, z, curve); + + /* v = x1 (mod n) */ + if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { + uECC_vli_sub(rx, rx, curve->n, num_n_words); + } + + /* Accept only if v == r. */ + return (int)(uECC_vli_equal(rx, r, num_words)); +} + +#if uECC_ENABLE_VLI_API + +unsigned uECC_curve_num_words(uECC_Curve curve) { + return curve->num_words; +} + +unsigned uECC_curve_num_bytes(uECC_Curve curve) { + return curve->num_bytes; +} + +unsigned uECC_curve_num_bits(uECC_Curve curve) { + return curve->num_bytes * 8; +} + +unsigned uECC_curve_num_n_words(uECC_Curve curve) { + return BITS_TO_WORDS(curve->num_n_bits); +} + +unsigned uECC_curve_num_n_bytes(uECC_Curve curve) { + return BITS_TO_BYTES(curve->num_n_bits); +} + +unsigned uECC_curve_num_n_bits(uECC_Curve curve) { + return curve->num_n_bits; +} + +const uECC_word_t *uECC_curve_p(uECC_Curve curve) { + return curve->p; +} + +const uECC_word_t *uECC_curve_n(uECC_Curve curve) { + return curve->n; +} + +const uECC_word_t *uECC_curve_G(uECC_Curve curve) { + return curve->G; +} + +const uECC_word_t *uECC_curve_b(uECC_Curve curve) { + return curve->b; +} + +#if uECC_SUPPORT_COMPRESSED_POINT +void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve) { + curve->mod_sqrt(a, curve); +} +#endif + +void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve) { +#if (uECC_OPTIMIZATION_LEVEL > 0) + curve->mmod_fast(result, product); +#else + uECC_vli_mmod(result, product, curve->p, curve->num_words); +#endif +} + +void uECC_point_mult(uECC_word_t *result, + const uECC_word_t *point, + const uECC_word_t *scalar, + uECC_Curve curve) { + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {tmp1, tmp2}; + uECC_word_t carry = regularize_k(scalar, tmp1, tmp2, curve); + + EccPoint_mult(result, point, p2[!carry], 0, curve->num_n_bits + 1, curve); +} + +#endif /* uECC_ENABLE_VLI_API */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC.h b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC.h new file mode 100644 index 0000000..9911763 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC.h @@ -0,0 +1,362 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_H_ +#define _UECC_H_ + +#include <stdint.h> + +/* Platform selection options. +If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros. +Possible values for uECC_PLATFORM are defined below: */ +#define uECC_arch_other 0 +#define uECC_x86 1 +#define uECC_x86_64 2 +#define uECC_arm 3 +#define uECC_arm_thumb 4 +#define uECC_arm_thumb2 5 +#define uECC_arm64 6 +#define uECC_avr 7 + +/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes). +If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your +platform. */ + +/* Optimization level; trade speed for code size. + Larger values produce code that is faster but larger. + Currently supported values are 0 - 4; 0 is unusably slow for most applications. + Optimization level 4 currently only has an effect ARM platforms where more than one + curve is enabled. */ +#ifndef uECC_OPTIMIZATION_LEVEL + #define uECC_OPTIMIZATION_LEVEL 2 +#endif + +/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be +used for (scalar) squaring instead of the generic multiplication function. This can make things +faster somewhat faster, but increases the code size. */ +#ifndef uECC_SQUARE_FUNC + #define uECC_SQUARE_FUNC 0 +#endif + +/* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native +little-endian format for *all* arrays passed in and out of the public API. This includes public +and private keys, shared secrets, signatures and message hashes. +Using this switch reduces the amount of call stack memory used by uECC, since less intermediate +translations are required. +Note that this will *only* work on native little-endian processors and it will treat the uint8_t +arrays passed into the public API as word arrays, therefore requiring the provided byte arrays +to be word aligned on architectures that do not support unaligned accesses. */ +#ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN + #define uECC_VLI_NATIVE_LITTLE_ENDIAN 0 +#endif + +/* Curve support selection. Set to 0 to remove that curve. */ +#ifndef uECC_SUPPORTS_secp160r1 + #define uECC_SUPPORTS_secp160r1 1 +#endif +#ifndef uECC_SUPPORTS_secp192r1 + #define uECC_SUPPORTS_secp192r1 1 +#endif +#ifndef uECC_SUPPORTS_secp224r1 + #define uECC_SUPPORTS_secp224r1 1 +#endif +#ifndef uECC_SUPPORTS_secp256r1 + #define uECC_SUPPORTS_secp256r1 1 +#endif +#ifndef uECC_SUPPORTS_secp256k1 + #define uECC_SUPPORTS_secp256k1 1 +#endif + +/* Specifies whether compressed point format is supported. + Set to 0 to disable point compression/decompression functions. */ +#ifndef uECC_SUPPORT_COMPRESSED_POINT + #define uECC_SUPPORT_COMPRESSED_POINT 1 +#endif + +struct uECC_Curve_t; +typedef const struct uECC_Curve_t * uECC_Curve; + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if uECC_SUPPORTS_secp160r1 +uECC_Curve uECC_secp160r1(void); +#endif +#if uECC_SUPPORTS_secp192r1 +uECC_Curve uECC_secp192r1(void); +#endif +#if uECC_SUPPORTS_secp224r1 +uECC_Curve uECC_secp224r1(void); +#endif +#if uECC_SUPPORTS_secp256r1 +uECC_Curve uECC_secp256r1(void); +#endif +#if uECC_SUPPORTS_secp256k1 +uECC_Curve uECC_secp256k1(void); +#endif + +/* uECC_RNG_Function type +The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if +'dest' was filled with random data, or 0 if the random data could not be generated. +The filled-in values should be either truly random, or from a cryptographically-secure PRNG. + +A correctly functioning RNG function must be set (using uECC_set_rng()) before calling +uECC_make_key() or uECC_sign(). + +Setting a correctly functioning RNG function improves the resistance to side-channel attacks +for uECC_shared_secret() and uECC_sign_deterministic(). + +A correct RNG function is set by default when building for Windows, Linux, or OS X. +If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom, +you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined +RNG function; you must provide your own. +*/ +typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size); + +/* uECC_set_rng() function. +Set the function that will be used to generate random bytes. The RNG function should +return 1 if the random data was generated, or 0 if the random data could not be generated. + +On platforms where there is no predefined RNG function (eg embedded platforms), this must +be called before uECC_make_key() or uECC_sign() are used. + +Inputs: + rng_function - The function that will be used to generate random bytes. +*/ +void uECC_set_rng(uECC_RNG_Function rng_function); + +/* uECC_get_rng() function. + +Returns the function that will be used to generate random bytes. +*/ +uECC_RNG_Function uECC_get_rng(void); + +/* uECC_curve_private_key_size() function. + +Returns the size of a private key for the curve in bytes. +*/ +int uECC_curve_private_key_size(uECC_Curve curve); + +/* uECC_curve_public_key_size() function. + +Returns the size of a public key for the curve in bytes. +*/ +int uECC_curve_public_key_size(uECC_Curve curve); + +/* uECC_make_key() function. +Create a public/private key pair. + +Outputs: + public_key - Will be filled in with the public key. Must be at least 2 * the curve size + (in bytes) long. For example, if the curve is secp256r1, public_key must be 64 + bytes long. + private_key - Will be filled in with the private key. Must be as long as the curve order; this + is typically the same as the curve size, except for secp160r1. For example, if the + curve is secp256r1, private_key must be 32 bytes long. + + For secp160r1, private_key must be 21 bytes long! Note that the first byte will + almost always be 0 (there is about a 1 in 2^80 chance of it being non-zero). + +Returns 1 if the key pair was generated successfully, 0 if an error occurred. +*/ +int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve); + +/* uECC_shared_secret() function. +Compute a shared secret given your secret key and someone else's public key. +Note: It is recommended that you hash the result of uECC_shared_secret() before using it for +symmetric encryption or HMAC. + +Inputs: + public_key - The public key of the remote party. + private_key - Your private key. + +Outputs: + secret - Will be filled in with the shared secret value. Must be the same size as the + curve size; for example, if the curve is secp256r1, secret must be 32 bytes long. + +Returns 1 if the shared secret was generated successfully, 0 if an error occurred. +*/ +int uECC_shared_secret(const uint8_t *public_key, + const uint8_t *private_key, + uint8_t *secret, + uECC_Curve curve); + +#if uECC_SUPPORT_COMPRESSED_POINT +/* uECC_compress() function. +Compress a public key. + +Inputs: + public_key - The public key to compress. + +Outputs: + compressed - Will be filled in with the compressed public key. Must be at least + (curve size + 1) bytes long; for example, if the curve is secp256r1, + compressed must be 33 bytes long. +*/ +void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve); + +/* uECC_decompress() function. +Decompress a compressed public key. + +Inputs: + compressed - The compressed public key. + +Outputs: + public_key - Will be filled in with the decompressed public key. +*/ +void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve); +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +/* uECC_valid_public_key() function. +Check to see if a public key is valid. + +Note that you are not required to check for a valid public key before using any other uECC +functions. However, you may wish to avoid spending CPU time computing a shared secret or +verifying a signature using an invalid public key. + +Inputs: + public_key - The public key to check. + +Returns 1 if the public key is valid, 0 if it is invalid. +*/ +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve); + +/* uECC_compute_public_key() function. +Compute the corresponding public key for a private key. + +Inputs: + private_key - The private key to compute the public key for + +Outputs: + public_key - Will be filled in with the corresponding public key + +Returns 1 if the key was computed successfully, 0 if an error occurred. +*/ +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve); + +/* uECC_sign() function. +Generate an ECDSA signature for a given hash value. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to +this function along with your private key. + +Inputs: + private_key - Your private key. + message_hash - The hash of the message to sign. + hash_size - The size of message_hash in bytes. + +Outputs: + signature - Will be filled in with the signature value. Must be at least 2 * curve size long. + For example, if the curve is secp256r1, signature must be 64 bytes long. + +Returns 1 if the signature generated successfully, 0 if an error occurred. +*/ +int uECC_sign(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + uint8_t *signature, + uECC_Curve curve); + +/* uECC_HashContext structure. +This is used to pass in an arbitrary hash function to uECC_sign_deterministic(). +The structure will be used for multiple hash computations; each time a new hash +is computed, init_hash() will be called, followed by one or more calls to +update_hash(), and finally a call to finish_hash() to produce the resulting hash. + +The intention is that you will create a structure that includes uECC_HashContext +followed by any hash-specific data. For example: + +typedef struct SHA256_HashContext { + uECC_HashContext uECC; + SHA256_CTX ctx; +} SHA256_HashContext; + +void init_SHA256(uECC_HashContext *base) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Init(&context->ctx); +} + +void update_SHA256(uECC_HashContext *base, + const uint8_t *message, + unsigned message_size) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Update(&context->ctx, message, message_size); +} + +void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Final(hash_result, &context->ctx); +} + +... when signing ... +{ + uint8_t tmp[32 + 32 + 64]; + SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}}; + uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature); +} +*/ +typedef struct uECC_HashContext { + void (*init_hash)(const struct uECC_HashContext *context); + void (*update_hash)(const struct uECC_HashContext *context, + const uint8_t *message, + unsigned message_size); + void (*finish_hash)(const struct uECC_HashContext *context, uint8_t *hash_result); + unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */ + unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */ + uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */ +} uECC_HashContext; + +/* uECC_sign_deterministic() function. +Generate an ECDSA signature for a given hash value, using a deterministic algorithm +(see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling +this function; however, if the RNG is defined it will improve resistance to side-channel +attacks. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it to +this function along with your private key and a hash context. Note that the message_hash +does not need to be computed with the same hash function used by hash_context. + +Inputs: + private_key - Your private key. + message_hash - The hash of the message to sign. + hash_size - The size of message_hash in bytes. + hash_context - A hash context to use. + +Outputs: + signature - Will be filled in with the signature value. + +Returns 1 if the signature generated successfully, 0 if an error occurred. +*/ +int uECC_sign_deterministic(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uECC_HashContext *hash_context, + uint8_t *signature, + uECC_Curve curve); + +/* uECC_verify() function. +Verify an ECDSA signature. + +Usage: Compute the hash of the signed data using the same hash as the signer and +pass it to this function along with the signer's public key and the signature values (r and s). + +Inputs: + public_key - The signer's public key. + message_hash - The hash of the signed data. + hash_size - The size of message_hash in bytes. + signature - The signature value. + +Returns 1 if the signature is valid, 0 if it is invalid. +*/ +int uECC_verify(const uint8_t *public_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *signature, + uECC_Curve curve); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _UECC_H_ */ diff --git a/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC_vli.h b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC_vli.h new file mode 100644 index 0000000..864cc33 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/deps/micro-ecc/uECC_vli.h @@ -0,0 +1,172 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_VLI_H_ +#define _UECC_VLI_H_ + +#include "uECC.h" +#include "types.h" + +/* Functions for raw large-integer manipulation. These are only available + if uECC.c is compiled with uECC_ENABLE_VLI_API defined to 1. */ +#ifndef uECC_ENABLE_VLI_API + #define uECC_ENABLE_VLI_API 0 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if uECC_ENABLE_VLI_API + +void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words); + +/* Constant-time comparison to zero - secure way to compare long integers */ +/* Returns 1 if vli == 0, 0 otherwise. */ +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words); + +/* Returns nonzero if bit 'bit' of vli is set. */ +uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); + +/* Counts the number of bits required to represent vli. */ +bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words); + +/* Sets dest = src. */ +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words); + +/* Constant-time comparison function - secure way to compare long integers */ +/* Returns one if left == right, zero otherwise */ +uECC_word_t uECC_vli_equal(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Constant-time comparison function - secure way to compare long integers */ +/* Returns sign of left - right, in constant time. */ +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, wordcount_t num_words); + +/* Computes vli = vli >> 1. */ +void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words); + +/* Computes result = left + right, returning carry. Can modify in place. */ +uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Computes result = left - right, returning borrow. Can modify in place. */ +uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Computes result = left * right. Result must be 2 * num_words long. */ +void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Computes result = left^2. Result must be 2 * num_words long. */ +void uECC_vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words); + +/* Computes result = (left + right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +void uECC_vli_modAdd(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Computes result = (left - right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +void uECC_vli_modSub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Computes result = product % mod, where product is 2N words long. + Currently only designed to work for mod == curve->p or curve_n. */ +void uECC_vli_mmod(uECC_word_t *result, + uECC_word_t *product, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Calculates result = product (mod curve->p), where product is up to + 2 * curve->num_words long. */ +void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve); + +/* Computes result = (left * right) % mod. + Currently only designed to work for mod == curve->p or curve_n. */ +void uECC_vli_modMult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Computes result = (left * right) % curve->p. */ +void uECC_vli_modMult_fast(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + uECC_Curve curve); + +/* Computes result = left^2 % mod. + Currently only designed to work for mod == curve->p or curve_n. */ +void uECC_vli_modSquare(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Computes result = left^2 % curve->p. */ +void uECC_vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left, uECC_Curve curve); + +/* Computes result = (1 / input) % mod.*/ +void uECC_vli_modInv(uECC_word_t *result, + const uECC_word_t *input, + const uECC_word_t *mod, + wordcount_t num_words); + +#if uECC_SUPPORT_COMPRESSED_POINT +/* Calculates a = sqrt(a) (mod curve->p) */ +void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve); +#endif + +/* Converts an integer in uECC native format to big-endian bytes. */ +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const uECC_word_t *native); +/* Converts big-endian bytes to an integer in uECC native format. */ +void uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes, int num_bytes); + +unsigned uECC_curve_num_words(uECC_Curve curve); +unsigned uECC_curve_num_bytes(uECC_Curve curve); +unsigned uECC_curve_num_bits(uECC_Curve curve); +unsigned uECC_curve_num_n_words(uECC_Curve curve); +unsigned uECC_curve_num_n_bytes(uECC_Curve curve); +unsigned uECC_curve_num_n_bits(uECC_Curve curve); + +const uECC_word_t *uECC_curve_p(uECC_Curve curve); +const uECC_word_t *uECC_curve_n(uECC_Curve curve); +const uECC_word_t *uECC_curve_G(uECC_Curve curve); +const uECC_word_t *uECC_curve_b(uECC_Curve curve); + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve); + +/* Multiplies a point by a scalar. Points are represented by the X coordinate followed by + the Y coordinate in the same array, both coordinates are curve->num_words long. Note + that scalar must be curve->num_n_words long (NOT curve->num_words). */ +void uECC_point_mult(uECC_word_t *result, + const uECC_word_t *point, + const uECC_word_t *scalar, + uECC_Curve curve); + +/* Generates a random integer in the range 0 < random < top. + Both random and top have num_words words. */ +int uECC_generate_random_int(uECC_word_t *random, + const uECC_word_t *top, + wordcount_t num_words); + +#endif /* uECC_ENABLE_VLI_API */ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _UECC_VLI_H_ */ |