[
  {
    "path": ".gitignore",
    "content": "bak\nbak/*\ntest\ntest/*\ntest.*\ncarl\nmpw\nmpw/*\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## 2.2\n\n- \"Crypto Ancienne Meets the Hooded Fang\"\n\n- New ports to classic MacOS/MPW and AmigaOS, and contributed ports for SCO Unix 4.2 (SCO ODT) and SerenityOS.\n\n- `carl` now can automatically fallback to TLS 1.2 contexts for sites that don't have ciphers in common with TLS 1.3 (except BeOS, which is always TLS 1.2 currently), along with a `-3` option to prevent fallback for testing and higher security. The `-2` option, conversely, forces TLS 1.2 and is intended for debugging only.\n\n- Use `NO_FUNNY_ALIGNMENT` by default on SPARC, HP PA-RISC, MIPS and SuperH, which avoids crashes and performance-draining trips to the system alignment handler (Alpha on Tru64 still requires `-misalign`).\n\n- Allow wrapped records in TLS 1.3 before changing ciphers.\n\n- Support Fred Fish `egcs` on BeOS/PowerPC.\n\n- Minor local and upstream fixes.\n\n## 2.0\n\n- Support for TLS 1.3 on all supported platforms except classic BeOS\n  (which still has support for TLS 1.2).\n\n- ChaCha20Poly1305 now available on all big-endian architectures too.\n\n- New official support for macOS on Apple silicon, with contributed support\n  for SCO OpenServer 6 on `i386`, Solaris 9 and 10 on SPARC v9, HP-UX 11.31\n  on Itanium, and HP-UX 10.20 and 11.11+ on PA-RISC.\n\n- Multiple crash and early-termination bugs on classic BeOS wallpapered, at\n  least with Metrowerks `cc` on PowerPC hardware (see changed build\n  instructions).\n\n- Support for RSA-PSS-RSAE-SHA-family signatures.\n\n- Endian detection is now canonicalized and displayed at compile-time.\n\n- Various upstream signature algorithm and verification fixes.\n\n- Minimal `User-Agent` header added to `carl` on the command line to counter\n  `HTTP 500` errors from some nginx servers.\n\n- Added a simple TLS hello packet debugger in Perl for development purposes.\n\n## 1.5\n\n- New official support for BeOS R5, Tru64 5.1B, SunOS 4.1 and IRIX 6.5,\n  with contributed support for the Mac OS X Public Beta, Cheetah and Puma,\n  NeXTSTEP 3.3 on 68K, Professional MachTen 2.3 on 68K, IRIX 6.5 with gcc\n  and Haiku R1.\n\n- Fixed test failures on A/UX and Power MachTen.\n\n- Compile-time options for reducing issues with unaligned pointers and\n  local variable size.\n\n- Converts all comments to `/* */` for better compiler compatibility.\n\n- Improves RFC 8422 compliance, fixing some server incompatibilities.\n\n- Using secp521r1 due to issues with internal curve25519 implementation\n  (to be fixed).\n\n- Adds `-N` option to `carl` and expands exit statuses.\n\n## 1.0\n\n- Initial release on Mac OS X 10.2+, Rhapsody/Mac OS Server, NeXTSTEP 3.3\n  on PA-RISC, macOS, Linux, NetBSD, A/UX 3.1, AIX 4+ and Power MachTen 4.1.4.\n"
  },
  {
    "path": "README.md",
    "content": "# Crypto Ancienne: TLS for the Internet of Old Things\n\nCopyright (C) 2020-3 Cameron Kaiser and Contributors. All rights reserved.\n\nCrypto Ancienne, or Cryanc for short, is a TLS library with an aim for compatibility with pre-C99 C compilers and geriatric architectures. The [TLS apocalypse](http://tenfourfox.blogspot.com/2018/02/the-tls-apocalypse-reaches-power-macs.html) may have knocked these hulking beasts out of the running for awhile, but now it's time for the Great Old Computing Ones to reclaim the Earth. That old server in your closet? It's only been sleeping, and now it's ready to take back the Web on the Web's own terms. 1997 just called and it's *ticked*.\n\nCryanc is intended as a *client* library. Although it can facilitate acting as a server, this is probably more efficiently and safely accomplished with a separate reverse proxy to which the encryption can be offloaded.\n\n**The use of this library does not make your application cryptographically secure, and certain systems may entirely lack any technological means to make that possible. Its functionality and security should be regarded as, at best, \"good enough to shoot yourself in the foot with.\"**\n\n## Before you file an issue\n\n- If you are filing an issue for a modern system, you should be using one of the upstream libraries, not this one. If you don't know what the upstreams are, you should read the next section before you do *anything else*.\n- If you have not tested your issue against upstream, you should do that first. If it's an upstream bug, don't file it here.\n- If you use this for something mission-critical, you are stupid. It may work, but you're still stupid.\n- Issues without patches or PRs may or may not be addressed. Ever.\n\n## Supported features\n\n- TLS 1.3 with SNI (on most ports; based on [TLSe](https://github.com/eduardsui/tlse) with local improvements)\n- Most standard crypto algorithms (from [`libtomcrypt`](https://github.com/libtom/libtomcrypt))\n- Built-in PRNG (`arc4random` from OpenBSD, allegedly, they tell me), with facultative seeding from `/dev/urandom` if present\n\nIn addition, `carl`, the included `curl`-like utility and the Cryanc example application, also has:\n\n- SOCKSv4 client support (keep your Old Ones behind a firewall, they tend to cause mental derangement in weaker humans)\n- HTTP and HTTPS proxy feature with similarly ancient browsers that do not insist on using `CONNECT` (requires `inetd` or `inetd`-like connecting piece such as [`micro_inetd`](https://acme.com/software/micro_inetd/))\n  - Browsers known to work: NCSA X-Mosaic 2.7b\\* and [Mosaic-CK](http://www.floodgap.com/retrotech/machten/mosaic/) on Un*xy things, Lynx and [MacLynx](http://www.floodgap.com/retrotech/mac/lynx/) 2.7 and possibly some early versions of 2.8, OmniWeb before 4.2, [Classilla 9.3.4b](http://www.floodgap.com/software/classilla/carl.html), [BeOS NetPositive+](https://oldvcr.blogspot.com/2022/10/going-where-beos-netpositive-hasnt-gone.html) (_not_ regular NetPositive), Magic Cap [Web Browser 3.5.1+](https://oldvcr.blogspot.com/2023/01/bringing-tls-to-magic-cap-datarover.html). Also see [this post](https://oldvcr.blogspot.com/2020/11/fun-with-crypto-ancienne-tls-for.html) and [this post](http://oldvcr.blogspot.com/2022/07/crypto-ancienne-20-now-brings-tls-13-to.html).\n\nSee the `carl` manual page in this repo for more (in `man` and Markdown format).\n\n## Not yet supported but coming soon\n\n**Don't file issues about these.** If you do, they will be closed as \"user doesn't read documentation\" and offenders will be ravenously eaten.\n\n- No 0-RTT or session resumption.\n- No ECDSA support. As a result, although certificate validation is available in the library, it is not presently enabled in `carl` as it can't yet validate ECDSA certificates.\n\nThese are all acknowledged limitations in TLSe and should improve as upstream does (or our time to work on it).\n\n- Support for other, possibly better (C)PRNGs or the old `prngd`/`egd` protocol.\n\n## Known differences\n\n- kTLS is not presently enabled, even on systems that offer this support (define `WITH_KTLS` if you want it) and even though TLSe supports it: most platforms that need Crypto Ancienne won't have kTLS or a sufficiently new enough implementation and thus this will likely never be the default.\n\n## Working configurations\n\nThese are tested using `carl`, which is the included example, and should \"just work.\" Most configurations can build simply with `gcc -O3 -o carl carl.c`. The magic for operating system support is almost all in `cryanc.c`.\n\n- Linux (`gcc`). This is tested on `ppc64le` but pretty much any architecture should be compatible (though see notes below about `NO_FUNNY_ALIGNMENT` if you are using a \"classic\" RISC CPU).\n- NetBSD (`gcc`). Ditto with 32-bit PowerPC, 68K and little-endian MIPS, and probably works on most other BSDs. If someone wants to give this a whack on 4.4BSD or Ultrix I would be highly amused.\n\n- Mach family (OpenSTEP 4.0 probably also works given that these all do):\n\n  - Mac OS X 10.2 through at least 12 (PowerPC, `i386`, `x86_64`, Apple silicon; Xcode `gcc` 3.3+ or `clang`)\n  - Mac OS X Server v1.2/Rhapsody 5.6 (PowerPC; `cc` (actually `gcc` 2.7.2.1))\n  - Tru64 5.1B (Alpha; `cc` (actually Compaq C V6.5)). Must compile with `-misalign`.\n  - NeXTSTEP 3.3 (HP PA-RISC; `cc` (actually `gcc` 2.5))\n  - Power MachTen 4.1.4 (PowerPC; `gcc` 2.8.1; `setstackspace 1048576 /usr/bin/cpp` and `setstackspace 4194304 /usr/bin/as`)\n\n- AmigaOS 3.9 (68K; `gcc` 2.95.3 with `ixemul.library` and `ixnet.library`; `-mstackextend` strongly advised). Using library version 63.1; may work on earlier versions and earlier OSes. The [Aminet ADE package](http://aminet.net/package/dev/gcc/ADE) is most convenient for building this. Note that stack usage may be considerable -- my test script uses a stack of 132K minimum.\n- IRIX 6.5.30 (SGI MIPS; `cc` (actually MIPSPro 7.4.4m)). For 6.5.22, you may need to use `c99` (older MIPSPro versions may also work with `c99`).\n- AIX 4+ (PowerPC, Power ISA; `gcc` 2.7.2.2 and 4.8). This is tested on 4.1.5 and 6.1, and should \"just work\" on 5L and 7.\n- A/UX 3.1 (68K; `gcc` 2.7.2.2, requires `-lbsd` or linking with `/lib/libbsd.a`)\n- SunOS 4.1 (SPARC; `gcc` 2.95.2). Binary compatible with Solbourne OS/MP. Tested on OS/MP 4.1C (SunOS 4.1.3).\n\n## Working contributed configurations\n\nThese are attested to be working but are maintained by others. Some \"just work\" and others have specific support in the code base.\n\n- Mac OS X Public Beta through 10.1 (PowerPC; Apple `cc` 912+ (actually `gcc` 2.95.2))\n- NeXTSTEP 3.3 (68K; `cc` (actually `gcc` 2.5))\n- Professional MachTen 2.3 (68K; `gcc` 2.7.2.f.1)\n- IRIX 6.5 (SGI MIPS; `gcc` 9.2.0)\n- Haiku R1/beta2 (`x86_64`; `gcc` 8.3.0, requires `-lnetwork`)\n- Solaris 9 and 10 (SPARC v9; `gcc` 2.95.3+, requires `-lsocket -lnsl`)\n- SCO UNIX 4.2 OpenDesktop (SCO ODT) (`i386`; `gcc` 2.5.8+)\n- OpenServer 6 (`i386`; `gcc` 7.3.0, requires `-lsocket`)\n- HP-UX 11.31 (Itanium; `cc` A.06.26 and `gcc` 4.7.4)\n- HP-UX 11.11+ (HP PA-RISC; `gcc` 4.7.1)\n- HP-UX 10.20 (HP PA-RISC; `gcc` 2.95.3, requires `-Doldhpux`)\n- SerenityOS (`x86_64`, `gcc` 12+ and `clang` 13+)\n\n## Partially working configurations\n\nThese platforms do _not_ \"just work.\" It is possible due to various compiler or OS limitations that they may never work completely.\n\n- BeOS R5 (PowerPC BeBox and Power Macintosh; `cc` (actually Metrowerks CodeWarrior `mwcc` 2.2) or Fred Fish Geek Gadgets `gcc` 2.90.27 (`egcs-1.0.2`)). **This port is very fragile:**\n  - Must compile **without optimization** (i.e., `cc -o carl carl.c`, not even `-O`), and you may need to use `carl` with the `-t` option to disable timeouts or long transactions may not complete. For `gcc`, use something like ```\ngcc -I`echo $BEINCLUDES | sed 's/;/ -I/g'` -o carl carl.c\n```. However, CodeWarrior seems to produce a faster binary than `gcc` even though `gcc` can make a stable binary at `-O3`.\n  - TLS 1.3 is _not_ currently supported due to limited system resources; all requests are TLS 1.2.\n  - Due to differences in the way BeOS treats standard input, reading proxy requests from the TTY doesn't currently work (it does from files).\n  - Should work with `x86`; not tested with Dano, ZETA or BONE. These versions may not require these limitations. Submit your patch, you can help! (If you're using Haiku, you can just compile Cryanc normally.)\n\n- Classic MacOS (PowerPC; MPW `MrC` 4.1.0f1c1 or better). This generates an MPW tool version of `carl` that runs within the MPW Shell or ToolServer. MacOS being MacOS, it has its own weir-dass build instructions:\n  - Install MPW and the [GUSI library distribution](https://sourceforge.net/projects/gusi/files/) if you haven't already, making sure you run the installation scripts or your setup won't have all the necessary headers. We use GUSI's latest version 2.2.3 but earlier versions may work. You also need to ensure that `${GUSI}` is set to your installation folder, which the installation should do for you (e.g., `Set -e \"Macintosh HD:GUSI_223:\"`).\n  - UnStuff `carl_mpw.sit.hqx`; you should get a folder named `mpw`. Open the `Makefile` inside it (it should start the MPW Shell) and ensure your working directory is that `mpw` folder, not the `cryanc` folder it's within.\n  - Press Command-B to build, and enter the target `carl`. The `Makefile` will fix up the type and creator of the source files and generate a tool `carl` in the same `mpw` folder.\n  - To run `carl` from the MPW Shell, just enter `carl` or `carl -options \"URL\"` (the URL must be quoted since slashes can be salient to MPW). `carl` will cooperatively multitask with MPW and other applications while running, even if a host does not respond (press Command-. to cancel a request). However, due to differences in the way the Shell treats standard input, reading proxy requests directly from the keyboard doesn't currently work (it does from files and pipes).\n  - **`MrC` generates verifiably incorrect code.** To reduce this risk, we disable optimization and spot-enable it only for certain critical or likely-safe functions. It is possible it has other bugs that cause miscompiles or crashes, or those functions aren't actually as safe as we think they are. Because most of the code is not optimized, you may need to use `carl` with the `-t` option to disable timeouts or long transactions may not complete.\n  - Because of high stack demands, if you experience crashes you may need to expand the MPW Shell's default stack allotment for tools. The `HEXA` 128 resource contains the default stack space as a 32-bit integer; a value of `0008 0000` would be 512K, for example.\n  - To use the `carl` MPW tool as a proxy requires a Mac `inetd` clone. The GUSI docs talk about \"David Petersons `inetd`\" [sic] but we can't find this (can you help?). We are exploring whether [ToolDaemon](https://github.com/fblondiau/ToolDaemon) can be hacked to serve this purpose, since the source code is available. In the meantime, if you need to run it as a proxy for Classilla or MacLynx, your best bet right now is to compile and run `carl` under Power MachTen -- and it will probably be more stable, too.\n\n## Not tested or not working but might in the future\n\n- Classic Mac OS (68K `SC` with GUSI; or PowerPC MPW `gcc` 2.5 with GUSI; or Metrowerks CodeWarrior on 68K or PowerPC with GUSI and SIOUX). The `gcc` MPW requires that the source files be converted to CR instead of CRLF and has other odd quirks, but should avoid `MrC`'s code generation problems. The same may apply for CodeWarrior. As for 68K Macs, the existing code may already work with Symantec C under MPW but I haven't tried, and unfortunately most 68K Macs will not be fast enough for many sites (see notes below about systems slower than 40MHz).\n- It should be possible to port to Win32 with something like `mxe`; there are hooks for it in TLSe already.\n- Solaris 2+ should work now that SunOS 4 does.\n- HP-UX on 68K. We have one locally.\n- Would be nice to eliminate the `ixemul` and `ixnet` dependencies for AmigaOS, but it was the easiest way of getting the port launched. Would also consider `libnix`-based code.\n- The people demand a VMS port! Need to check the license for that C compiler on our VAXstation ...\n\n## Porting it to your favourite geriatric platform\n\nMost other platforms with `gcc` 2.5 or higher, support for 64-bit ints (usually `long long`) and `stdarg.h` should \"just work.\"\n\nIf your system lacks `stdint.h`, you can try using `-DNOT_POSIX=1` to use the built-in definitions. You may also need to add `-include stdarg.h` and other headers. Consider compiling with `-DDEBUG` if you get crashes so you can see where it dies (it's also a neat way to see TLS under the hood).\n\nA few architectures, especially old RISC, may not like the liberties taken with unaligned pointers and memory access. For these systems try `-DNO_FUNNY_ALIGNMENT`, which is the default for SPARC, HP PA-RISC, MIPS and SuperH. However, it seems we may not have smoked all of them out (for example, it's not good enough for DEC Alpha on Tru64, the king of alignment-finicky configurations, and we still have to use `-misalign` with the Compaq C compiler).\n\nLarge local stack allocations are occasionally used for buffering efficiency. If your compiler doesn't like this (Metrowerks comes to mind) or you get crashes when `carl` terminates, try `-DBIG_STRING_SIZE=xx`, substituting a smaller buffer size like 16384 or 4096.\n\nOnce you figure out the secret sauce, we encourage you to put some additional blocks into `cryanc.c` to get the right header files and compiler flags loaded. PRs accepted for these as long as no presently working configuration is regressed. Similarly, we would love to further expand our compiler support, though we now support quite a few.\n\nSome systems may be too slow for present-day server expectations and thus will appear not to function even if the library otherwise works correctly. In our testing this starts to become a problem for CPUs slower than 40MHz or so, regardless of architecture. Even built with `-O3`, our little NetBSD Macintosh IIci with a 25MHz 68030 and no L2 card took 22 seconds\n(give `carl` the `-t` option to disable timeouts) for a single short TLS 1.2 transaction to a local test server; a number of Internet hosts we tested it with simply cut the connection instead of waiting. Rude!\n\n## Using it in your application\n\nA simple `#include \"cryanc.c\"` is sufficient (add both `cryanc.c` and `cryanc.h` to your source code). `cryanc.h` serves to document the more or less public interface and can be used if you turn Cryanc into a library instead of simply merging it into your source.\n\n`carl` demonstrates the basic notion:\n\n- open a TCP socket\n- `tls_create_context` creates the TLS context (`TLS_V12` or `TLS_V13`)\n- `tls_sni_set` sets the SNI hostname for the context\n- `tls_client_connect` initializes the connection\n\nYour application then needs to service reads and writes. The loop at the end of `carl` is a complete example, using `select(3)` to determine when data has arrived, and using an additional interior read loop to satisfy some servers that demand the socket be serviced promptly.\n\nAs data accumulates from the TLS hello and calls to `tls_write`,\nit should check `tls_get_write_buffer` and send this data down the socket. `carl` has a helper function called `https_send_pending` which it calls periodically to do this. Once the context write buffer is serviced, it clears the context buffer with `tls_buffer_clear`.\n\nLikewise, as data is read from the socket, it is sent to `tls_consume_stream`. When the secure connection is established, `tls_established` will become true for the context and you can read data from `tls_read`.\n\nIf a TLS alert occurs, it can be fetched from `context->error_code`.\n\n## Language pedantry note\n\nHere, \"crypto\" is short for *la cryptographie* and therefore the use of the feminine singular *ancienne*, so there.\n\n## Licenses and copyrights\n\nCrypto Ancienne is released under the BSD license.\n\nCopyright (C) 2020-3 Cameron Kaiser and Contributors. All rights reserved.\n\nBased on TLSe. Copyright (C) 2016-2023 Eduard Suica. All rights reserved.\n\nBased on Adam Langley's implementation of Curve25519. Copyright (C) 2008 Google, Inc. All rights reserved.\n\nBased on OpenBSD's `arc4random` (allegedly). Copyright (C) 1996 David Mazieres. All rights reserved.\n\nBased on `libtomcrypt` by Tom St Denis and contributors. Unlicense.\n\nBased on public domain works by D. J. Bernstein.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. 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.\n\nTHIS 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.\n"
  },
  {
    "path": "carl.1",
    "content": ".TH carl 1 \"Crypto Ancienne\"\n\n.SH NAME\ncarl \\- Crypto Ancienne Resource Loader\n\n.SH SYNOPSIS\n.B carl\n.RI [ options ]\n\\fIurl\\fR\n\n.SH DESCRIPTION\n.B carl\nis both a demonstration application for the Crypto Ancienne TLS library and a utility reminiscent of the much more comprehensive\n.BR curl (1),\nof which its name is a desperate pun. It may also be more suitable as a\n.BR curl (1)\nsubstitute for the older systems that Crypto Ancienne caters to, since\nit has no prerequisites other than a compatible C compiler.\n.LP\nLike its inspiration,\n.B carl\nfetches URLs, emitting them to standard output. However,\n.B carl\nonly supports HTTP and HTTPS (and only HTTP/0.9, HTTP/1.0 and HTTP/1.1), although it will also parse SOCKS URLs and use them as proxies (see\n.BR ENVIRONMENT ).\n.LP\n.B carl\ncan also accept complete\nHTTP and HTTPS requests over standard input (see\n.B PROXY\n.BR MODE ).\nIf connected to\n.BR inetd (8)\nor a similar utility, this can act as a complete proxy solution, including for some browsers which may not speak HTTPS or\ncurrent TLS versions themselves but can be trained or tricked to send requests for\n.B https://\nURLs to it.\n\n.SH OPTIONS\nIn general, options do not match\n.BR curl (1)'s.\n.LP\n.TP\n.B \\-q\nQuiet mode; no verbose errors are displayed (see\n.B EXIT\n.BR STATUS ).\n.TP\n.B \\-t\nDisable timeouts. Otherwise, transactions that take longer than 10 seconds are aborted. Necessary for slower systems that may not negotiate TLS quickly enough. Given that Crypto Ancienne specifically caters to such systems, this option may become the default in future versions.\n.TP\n.B \\-H\nUse\n.B HEAD\nas the request method instead of\n.BR GET .\nIn this mode, HTTP(S) headers are displayed automatically, along with any residual message body that may be transmitted by some servers. Other methods such as\n.B POST\nmust be specified as proxy requests (i.e., sent over standard input when\n.B \\-p\nis specified).\n.TP\n.B \\-i\nDump both headers and body, even if\n.B \\-H\nisn't specified. Irrelevant in proxy mode (when\n.B \\-p\nis specified).\n.TP\n.B \\-N\nIgnore the\n.B ALL_PROXY\nenvironment variable, if it exists (see\n.BR ENVIRONMENT ).\n.TP\n.B \\-u\nTreat all HTTP URLs as HTTPS, even if they are specified as HTTP. This includes URLs received in proxy mode (when\n.B \\-p\nis specified).\n.TP\n.B \\-s\nDowngrade HTTP/1.1 replies to HTTP/1.0 for consumers or clients which are intolerant. Irrelevant if headers are not displayed (i.e., without\n.BR \\-H ,\n.BR \\-p\nor\n.BR \\-i ).\n.TP\n.B \\-2\nMaximally negotiate TLS 1.2 instead of TLS 1.3. This is primarily for analysing handshake failures; under typical circumstances requiring this option to access a site should be considered a bug.\n.TP\n.B \\-3\nConversely, do not allow fallbacks to a TLS 1.2 context if negotiating a TLS 1.3 context fails. By default\n.B carl\nwill retry such connections to account for those hosts that genuinely support TLS 1.2 but not any of the ciphers that TLS 1.2 and TLS 1.3 would have in common. These sites are getting fewer and fewer, and thus this option may become the default in future versions.\n.TP\n.B \\-p\nEnables proxy mode (see\n.B PROXY\n.BR MODE ).\n.BR \\-i ,\n.BR \\-q ,\nand\n.BR \\-H ,\nif they are specified, are ignored. If a URL is provided, it may only be a\n.B socks://\nor\n.B socks5://\nURL, which is used as a SOCKS proxy for\n.B carl\nto relay through (see the\n.B ALL_PROXY\nenvironment variable in\n.BR ENVIRONMENT ).\n.TP\n.B \\-v\nDisplay version string (the same as the main library).\n.TP\n.B \\-h\nDisplay a synopsis of these options.\n\n.SH \"PROXY MODE\"\nIf the\n.B \\-p\noption is specified,\n.B carl\nwill accept a full proxy client request for an\n.B http://\nor\n.B https://\nURL from standard input. It must be formatted as a standard HTTP proxy request with method\nand fully-specified URL minimally compliant to RFC 7230, though\n.B carl\nis tolerant, and will quietly adjust client requests as needed or requested (see also the\n.B \\-u\nand\n.B \\-s\noptions). A full HTTP reply with all remote headers will be sent in response.\n.LP\nThe request must be delimited by the standard two-CRLF separator. If the method is intended to send data to the server, such as\n.BR POST ,\nthe payload may trail the request headers after it.\n.B carl\ndoes no encoding of this data; your application must do that itself.\n.LP\nIn proxy mode, the \\fIurl\\fR argument may only be used to specify a SOCKS proxy through which the request will be forwarded. If the\n.B ALL_PROXY\nenvironment variable exists, specifying a SOCKS URL on the command line will override it (or use\n.B -N\nto ignore it; see\n.BR ENVIRONMENT ).\nOtherwise,\n.B carl\nwill connect directly.\n.LP\nThe\n.B CONNECT\nmethod is intentionally not implemented.\n.LP\n.B carl\ndoes not bind any server port itself. However, because this mode accepts data on standard input, any\n.BR inetd (8)\nor\n.BR inetd (8)-like\nsuperserver environment such as\n.BR xinetd (8)\nor\n.BR micro_inetd (1)\ncan be used to make it accessible on the network. \\fICareful: if you bind an external interface, you've just made your computer into an open HTTP proxy!\\fR\n.B carl\nimplements no access controls or authentication, so check your superserver's documentation on how to only bind an internal interface or the loopback.\n.SH ENVIRONMENT\n.TP\n.B ALL_PROXY\n.B carl\nhas built-in SOCKSv4 client support. If a SOCKS URL (either\n.B socks://\nor\n.BR socks5:// ,\nwhich is treated as a synonym) is specified in this environment variable, all requests will be forwarded through it.\nIf a port number is not specified in the URL, it is assumed to be 1080. Any provided path or arguments are ignored.\n.B carl\ndoes not support authentication or SOCKSv5 features, and requires your DNS be able to resolve hostnames.\n.IP\nThis variable is ignored if\n.B \\-N\nis specified on the command line, and it is overridden in proxy mode\n.RB ( \\-p )\nif a SOCKS URL is specified on the command line.\n.LP\n.B NO_PROXY\nis not currently implemented.\n.SH \"EXIT STATUS\"\nA possibly helpful message may also appear unless it is suppressed by\n.BR \\-q .\nThese exit return codes may be expanded in future versions.\n.TP\n.B 0\nNo error.\n.TP\n.B 1\nThe request is pathological (nonsense, inappropriate or incomplete). This can also occur when a non-SOCKS proxy is provided\n.RB ( carl\ndoes not talk to other HTTP proxies; they are vapid and uninteresting at parties).\n.TP\n.B 2\nThe host or proxy host could not be resolved.\n.TP\n.B 3\nThe host resolved to an IPv6 address, but\n.B carl\ndoesn't support those yet.\n.TP\n.B 4\nThe connection to the SOCKS proxy failed.\n.TP\n.B 5\nThe connection to the HTTP(S) server failed.\n.TP\n.B 6\nThe TLS response from the HTTPS server could not be processed.\n.TP\n.B 253\nNo data was received.\n.TP\n.B 254\nTimeout. Consider using\n.B \\-t\nif the system is slower and the request should have worked.\n.TP\n.B 255\nGeneral failure.\n\n.SH NOTES\n.B carl\ndoes not currently evaluate certificates for validity, so its encryption support is best considered opportunistic and it\nshould not be used for high-security environments.\n\n.SH \"SEE ALSO\"\n.BR curl (1)\n\n.SH \"HOME PAGE\"\nhttps://github.com/classilla/cryanc\n\n.SH AUTHOR\n(C)2020-3 Cameron Kaiser and Contributors. All rights reserved. Additional copyrights apply; see the home page for full credits. BSD license.\n"
  },
  {
    "path": "carl.c",
    "content": "/*\n * Crypto Ancienne Resource Loader \"carl\" (and example application)\n * Copyright 2020-3 Cameron Kaiser and contributors. All rights reserved.\n * BSD license (see README.md)\n */\n\n#include <stdio.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#if defined (M_XENIX) && !defined(M_UNIX)\n#include <sys/types.tcp.h>\n#endif\n#include <sys/socket.h>\n#if !defined (M_XENIX) || defined(_SCO_DS) /* On SCO Unix the next line crashes gcc, but on OpenServer it might work/be needed? */\n#if !defined(__AUX__) && !defined(__AMIGA__) && (!defined(NS_TARGET_MAJOR) || (NS_TARGET_MAJOR > 3)) && !defined(__MACHTEN_68K__) && !defined(__sun) && !defined(__BEOS__) && (!defined(__hppa) && !defined(__hpux)) && !defined(macintosh)\n#include <sys/select.h>\n#endif\n#endif\n\n#if defined(macintosh)\n#include <ioctl.h>\n#include <sys/filio.h>\n#endif\n\n#include <netinet/in.h>\n#include <netdb.h> \n\n#ifndef STDIN_FILENO\n#define STDIN_FILENO 0\n#endif\n#ifndef STDOUT_FILENO\n#define STDOUT_FILENO 1\n#endif\n\n/* stdint or equivalent set here */\n#include \"cryanc.c\"\n\nint quiet = 0;\nint proxy = 0;\nint http09 = 0;\n\nvoid error(char *msg, int code) {\n    if (proxy) {\n        if (!http09)\n            fprintf(stdout, \"HTTP/1.0 502 Proxy Error\\r\\n\"\n                            \"Content-type: text/html\\r\\n\\r\\n\");\n        fprintf(stdout, \"%s\\n\", msg);\n        exit(code);\n    }\n\n    if (!quiet) {\n        if (errno > 0) perror(msg); else fprintf(stdout, \"%s\\n\", msg);\n    }\n    exit(code);\n}\n\nvoid timeout() { /* portable enough */\n    error(\"Timeout\", 254);\n}\n\n/* The BeOS port is bound by unusual constraints, partially by Metrowerks\n   cc, partially by the operating system. Some of the code here is\n   bizarre, but it's here because it works and passes tests. */\n#if defined(__BEOS__)\n#include <fcntl.h>\n#if defined(BONE_VERSION)\n#warning not tested with BONE\n#endif\n\n/* ping-pong interval for semi-busy wait */\n#define TIMESLICE 1000\n/* BeOS is \"special\" with stdin, and select() doesn't work with it. */\nint stdin_pending() {\n    int i, j;\n    char c;\n\n    /* hack: don't check if we're not in proxy mode, we don't use it. */\n    if (!proxy) return 0;\n\n    /* check tty ioctl first */\n    i = ioctl(0, 'ichr', &j);\n    if (i >= 0 && j > 0) return 1;\n\n    /* \"peek\" at stdin (must already be non-blocking) */\n    return (read(STDIN_FILENO, &c, 0) >= 0);\n}\n#else\n#if defined(macintosh)\n/* The MacOS port is also bound by unusual constraints because it's MacOS. */\n\n/* GUSI stdio isn't very std, so also check only in proxy mode. */\n#define stdin_pending() (proxy && FD_ISSET(STDIN_FILENO, &fdset))\n\n/* In a cooperative world connect() must be non-blocking. */\nvoid mac_connect(int sockfd, struct sockaddr *s, int ssize, char *err, int code) {\n    long m=1;\n    fd_set fdset;\n\n    (void)ioctl(sockfd, FIONBIO, &m);\n    m = connect(sockfd, s, ssize);\n    if (m < 0) {\n        /* GUSI might return any of these values for an in-progress socket */\n        if (errno != EISCONN && /* connected already? */\n                errno != EINPROGRESS &&\n                errno != EALREADY)\n            error(err, code);\n    }\n    /* wait for it to become writeable. GUSI calls WaitNextEvent for us,\n       so make the socket blocking again to preserve other semantics. */\n    m=0; (void)ioctl(sockfd, FIONBIO, &m);\n    FD_ZERO(&fdset);\n    FD_SET(sockfd, &fdset);\n    (void)select(sockfd + 1, NULL, &fdset, NULL, NULL);\n}\n#else\n#define stdin_pending() (FD_ISSET(STDIN_FILENO, &fdset))\n#endif\n#endif\n\nint https_send_pending(int client_sock, struct TLSContext *context) {\n    unsigned int out_buffer_len = 0;\n    unsigned int out_buffer_index = 0;\n    int send_res = 0;\n    const unsigned char *out_buffer = tls_get_write_buffer(context, &out_buffer_len);\n    while ((out_buffer) && (out_buffer_len > 0)) {\n        int res = send(client_sock, (char *)&out_buffer[out_buffer_index], out_buffer_len, 0);\n        if (res <= 0) {\n            send_res = res;\n            break;\n        }\n        out_buffer_len -= res;\n        out_buffer_index += res;\n    }\n    tls_buffer_clear(context);\n    return send_res;\n}\n\n/* NYI */\nint validate_certificate(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len) {\n    int i;\n    if (certificate_chain) {\n        for (i = 0; i < len; i++) {\n            struct TLSCertificate *certificate = certificate_chain[i];\n            /* check certificate ... */\n        }\n    }\n    /* return certificate_expired;\n    // return certificate_revoked;\n    // return certificate_unknown; */\n    return no_error;\n}\n\nint scheme_is(char *url, char *scheme) {\n    if (strlen(url) <= strlen(scheme)) return 0;\n    return (strstr(url, scheme) == url);\n}\n\n/* given a URL string, set hostname, port and protocol (identified by well\n   known service port number) and return where in the string the path\n   starts (or NULL if it didn't parse correctly). */\nchar *parse_url(char *url, char *hostname, size_t *port, size_t *proto) {\n    char *h, *p, *pn;\n    unsigned int i;\n\n    if (scheme_is(url, \"socks://\")) {\n        *proto = 1080;\n    } else if (scheme_is(url, \"socks5://\")) {\n        *proto = 1080;\n    } else if (scheme_is(url, \"http://\")) {\n        *proto = 80;\n    } else if (scheme_is(url, \"https://\")) {\n        *proto = 443;\n    } else\n        return NULL; /* we don't know this protocol */\n\n    /* find the second slash: that's where the hostname starts. */\n    for (h=url,i=0;*h && i!=2;h++) if(*h=='/') i++;\n    if (i != 2) return NULL; /* ran off the end of the string */\n\n    /* find the third slash: that's where the selector starts. */\n    for (p=h;*p && i!=3;p++) if(*p=='/') i++;\n    /* if there is no third slash, treat as a zero-length path */\n    if (i == 3) p--;\n\n    /* hostname:port must be at least 1 character long. */\n    if ((p - h) < 1) return NULL;\n\n    if ((pn = strchr(h, ':')) && pn < p) {\n        /* automatic null termination */\n        char sport[6] = { 0, 0, 0, 0, 0, 0 };\n\n        /* check hostname and port lengths */\n        if (pn == h || (pn - h) > 255 || (p - pn) < 2 || (p - pn) > 6)\n            return NULL;\n\n        memcpy((void *)hostname, (void *)h, (pn - h));\n        *(hostname + (pn - h)) = '\\0';\n        memcpy((void *)&sport, (void *)++pn,  (p - pn));\n\n        *port = atoi(sport);\n        if (*port < 1 || *port > 65535) return NULL;\n\n        /* atoi will allow something like :3aa but we shouldn't */\n        if (*port < 10    && (p - pn) != 1) return NULL;\n        if (*port > 9     && *port < 100   && (p - pn) != 2) return NULL;\n        if (*port > 99    && *port < 1000  && (p - pn) != 3) return NULL;\n        if (*port > 999   && *port < 10000 && (p - pn) != 4) return NULL;\n    } else {\n        if ((p - h) > 255) return NULL;\n\n        memcpy((void *)hostname, (void *)h, (p - h));\n        *(hostname + (p - h)) = '\\0';\n        *port = *proto;\n    }\n\n    /* we don't support authority information currently */\n    if (strchr(hostname, '@')) return NULL;\n\n    return p;\n}\n\nvoid help(int longdesc, char *me) {\n    fprintf(stderr, \"Crypto Ancienne Resource Loader v2.2\\n\");\n    if (!longdesc) return;\n\n    fprintf(stderr,\n\"Copyright (C)2020-3 Cameron Kaiser and Contributors. All rights reserved.\\n\"\n\"usage: %s [option] [url (optional if -p)]\\n\\n\"\n\"protocols: http https\\n\\n\"\n\"-h This message\\n\"\n\"-v Version string\\n\"\n\"-p Proxy mode (accepts HTTP client request on stdin, ignores -i -q -H)\\n\"\n\"   If url is also specified, it may be a socks:// URL only\\n\"\n\"-H HEAD request (default is GET)\\n\"\n\"-N Ignore ALL_PROXY environment variable\\n\"\n\"-q Emit no errors, only status code\\n\"\n\"-i Dump both headers and body (default is body only, irrelevant if -H or -p)\\n\"\n\"-t No timeout (default is 10s)\\n\"\n\"-u Upgrade HTTP requests to HTTPS transparently\\n\"\n\"-s Spoof HTTP/1.1 replies as HTTP/1.0 (irrelevant without -H, -p or -i)\\n\"\n#if !defined(__BEOS__)\n/* Accepted but ignored, being limited to TLS 1.2. */\n\"-3 Do not retry as TLS 1.2\\n\"\n\"-2 Negotiate TLS 1.2 instead of 1.3\\n\"\n#endif\n    , me);\n}\n\nint main(int argc, char *argv[]) {\n    int sockfd, n, proxycon = 0, forever = 0, spoof10 = 0, stdindone = 0;\n    size_t portno, socksport, proto, socksproto, numcrs = 0, bytesread = 0;\n    struct sockaddr_in serv_addr;\n    struct hostent *server, *socksserver;\n    fd_set fdset;\n    int read_size, tls12 = 0, tls13only = 0;\n    int sent = 0, arg = 0, head_only = 0, with_headers = 0, upgrayedd = 0;\n    char *path = NULL, *url = NULL, *proxyurl = NULL;\n    struct TLSContext *context;\n#if defined(__BEOS__)\n    struct timeval tv;\n    int i, j;\n    /* BeOS has a fixed stack of 256K, which makes this real tight. */\n    unsigned char client_message[1024];\n    unsigned char read_buffer[1024];\n    char hostname[64], sockshost[64], *buffer;\n#else\n    char hostname[256], sockshost[256], *buffer;\n    unsigned char read_buffer[BIG_STRING_SIZE];\n    unsigned char client_message[8192];\n#endif\n\n    proxyurl = getenv(\"ALL_PROXY\");\n    if (proxyurl != NULL && !strlen(proxyurl)) proxyurl = NULL;\n\n    for(;;) {\n        if (++arg >= argc) {\n           if (proxy) break;\n\n           help(1, argv[0]);\n           return 1;\n        }\n        if (argv[arg][0] != '-') {\n           url = argv[arg];\n           break;\n        }\n\n        if (strchr(argv[arg], 'v')) { help(0, argv[0]); return 0; }\n        if (strchr(argv[arg], 'h')) { help(1, argv[0]); return 0; }\n        if (strchr(argv[arg], 'i')) { with_headers = 1; }\n        if (strchr(argv[arg], 'H')) { head_only = 1; with_headers = 1; }\n        if (strchr(argv[arg], 'N')) { proxyurl = NULL; }\n        if (strchr(argv[arg], '3')) { tls13only = 1; }\n        if (strchr(argv[arg], 'u')) { upgrayedd = 1; }\n        if (strchr(argv[arg], 's')) { spoof10 = 1; }\n        if (strchr(argv[arg], 't')) { forever = 1; }\n        if (strchr(argv[arg], 'q')) { quiet = 1; }\n        if (strchr(argv[arg], 'p')) { proxy = 1; }\n        if (strchr(argv[arg], '2')) { tls12 = 1; }\n    }\n\n    if (proxy) {\n        /* receiving a proxy request from stdin */\n\n        char method[10], purl[2048], c;\n        int mc = 0, mu = 0, got_method = 0, got_url = 0;\n\n        if (url) proxyurl = url;\n\n        head_only = 0; quiet = 1; with_headers = 0; http09 = 1;\n        method[0] = '\\0'; purl[0] = '\\0';\n        for(;;) {\n            if (!read(STDIN_FILENO, &c, 1))\n                return 1; /* something's wrong */\n\n            if (c == ' ') {\n                if (!got_method) { got_method = 1; continue; }\n                if (!got_url) { got_url = 1; http09 = 0; break; }\n                return 1; /* something's wrong here too */\n            }\n                     \n            if (c == '\\r') {\n                if (!got_method) return 1;\n                if (got_url) return 1; /* ?! */\n                got_url = 1; continue;\n            }\n\n            if (c == '\\n') {\n                if (got_method) break;\n                return 1; /* something's wrong here too */\n            }\n\n            if (!got_method) {\n                method[mc++] = (char)c; method[mc] = '\\0';\n                if (mc == 9) return 1; /* bogus method */\n                continue;\n            }\n\n            if (!got_url) {\n                purl[mu++] = (char)c; purl[mu] = '\\0';\n                if (mu == 2047) return 1; /* too long */\n                continue;\n            }\n\n            fprintf(stderr, \"unhandled character: %c\\n\", (char)c);\n            return 255;\n        }\n        \n        /* at this point, we either have a complete 0.9 request, or a 1.0/1.1\n           request with more bytes to follow. */\n\n        if (!strlen(method) || !strlen(purl)) return 1;\n\n        if (http09 && strcmp(method, \"GET\")) {\n            /* handle specially */\n            fprintf(stdout, \"Only GET is supported for HTTP/0.9\\n\");\n            return 1;\n        }\n        if (!strcmp(method, \"CONNECT\")) {\n            error(\"CONNECT is not supported by this proxy\", 1);\n        }\n\n        if (!(path = parse_url(purl, hostname, &portno, &proto))) {\n            error(\"Did not understand URL\", 1);\n        }\n        if (proto != 80 && proto != 443) {\n            error(\"Unsupported protocol\", 1);\n        }\n\n        if (upgrayedd && proto == 80) {\n            proto = 443;\n            if (portno == 80) portno = 443;\n        }\n\n        if (http09) {\n            /* convert into an HTTP/1.0 request, headers suppressed */\n\n            buffer = malloc(strlen(hostname) + strlen(path) + 256);\n            if (proto != portno) {\n                (void)sprintf(buffer,\n                              \"GET %s HTTP/1.0\\r\\n\"\n                              \"Host: %s:%d\\r\\n\"\n                              \"User-Agent: carl\\r\\n\"\n                              \"Connection: close\\r\\n\"\n                              \"\\r\\n\",\n                (strlen(path) ? path : \"/\"), hostname, portno);\n            } else {\n                (void)sprintf(buffer,\n                              \"GET %s HTTP/1.0\\r\\n\"\n                              \"Host: %s\\r\\n\"\n                              \"User-Agent: carl\\r\\n\"\n                              \"Connection: close\\r\\n\"\n                              \"\\r\\n\",\n                (strlen(path) ? path : \"/\"), hostname);\n            }\n        } else {\n            /* HTTP/1.0 or 1.1. read the rest of the headers */\n            char *has_host;\n            char hosthost[512], hostport[512];\n            int crlf = 0;\n\n            read_size = 0;\n            numcrs = 0;\n            with_headers = 1;\n\n            for(;;) {\n                if (!read(STDIN_FILENO, &c, 1))\n                    return 1; /* underflow */\n                read_buffer[read_size++] = c;\n                if (read_size == sizeof(read_buffer)) return 1; /* overflow */\n\n                if (c == '\\n') {\n                    if (++numcrs == 2) break; else continue;\n                }\n                if (c == '\\r') continue;\n                numcrs = 0;\n            }\n            numcrs = 0;\n            if (read_size < 4) return 1; /* unpossible */\n            if (read_buffer[(read_size-1)] == read_buffer[(read_size-2)]) {\n                /* ends in \\n\\n, hmm */\n                read_buffer[(read_size-1)] = '\\0';\n            } else if (read_buffer[(read_size-4)] == '\\r' &&\n                   read_buffer[(read_size-1)] == read_buffer[(read_size-3)]) {\n                /* can only end in \\r\\n\\r\\n */\n                read_buffer[(read_size-2)] = '\\0';\n                crlf = 1;\n            } else return 1; /* huh? */\n\n            /* compute host header. we need to either add it or check it.\n               some clients will append :80 (WebTV), so generate both. */\n            (void)sprintf(hostport, \"Host: %s:%d%s\",\n                          hostname, portno, (crlf) ? \"\\r\\n\" : \"\\n\");\n            (void)sprintf(hosthost, \"Host: %s%s\",\n                          hostname, (crlf) ? \"\\r\\n\" : \"\\n\");\n\n            if (has_host = strstr((char *)read_buffer, \"Host: \")) {\n                /* to make this simpler, RFC 7230 gives us a way to cheat.\n                   if there is a Host: header here, it must match the hostname\n                   in the URL. if it doesn't, abort. */\n\n                /* multiple Host: headers? eat my shorts. */\n                if (strstr(++has_host, \"Host: \")) return 1;\n\n                /* header is bogus? eat more of my shorts. */\n                if (proto != portno) { /* only allow host:port */\n                    if (!strstr((char *)read_buffer, hostport)) return 1;\n                } else { /* allow either */\n                    if (!strstr((char *)read_buffer, hosthost) &&\n                        !strstr((char *)read_buffer, hostport)) return 1;\n                }\n\n                /* acceptable; use client header set */\n                buffer = malloc(strlen(method) + strlen(path) +\n                                strlen((char *)read_buffer) + 256);\n                (void)sprintf(buffer, \"%s %s %s%s\",\n                              method, (strlen(path) ? path : \"/\"),\n                              read_buffer, (crlf) ? \"\\r\\n\" : \"\\n\");\n            } else {\n                /* add Host: header */\n                buffer = malloc(strlen(method) + strlen(path) +\n                                strlen((char *)read_buffer) +\n                                strlen((portno != proto) ? hostport :\n                                                           hosthost) + 256);\n                (void)sprintf(buffer, \"%s %s %s%s%s\",\n                              method, (strlen(path) ? path : \"/\"),\n                              read_buffer,\n                              (portno != proto) ? hostport : hosthost,\n                              (crlf) ? \"\\r\\n\" : \"\\n\");\n            }\n        }\n    } else {\n        /* url provided on command line */\n\n        if (!(path = parse_url(url, hostname, &portno, &proto))) {\n            if (!quiet) fprintf(stderr, \"%s: couldn't parse url\\n\", argv[0]);\n            return 1;\n        }\n        if (proto == 1080) {\n            if (!quiet) fprintf(stderr, \"%s: socks only allowed for proxies\\n\",\n                                argv[0]);\n            return 1;\n        }\n        if (proto != 80 && proto != 443) {\n            if (!quiet) fprintf(stderr, \"%s: unsupported protocol\\n\", argv[0]);\n            return 1;\n        }\n\n        if (upgrayedd && proto == 80) {\n            proto = 443;\n            if (portno == 80) portno = 443;\n        }\n\n        buffer = malloc(strlen(hostname) + strlen(path) + 256);\n        if (proto != portno) {\n            (void)sprintf(buffer,\n\"%s %s HTTP/1.0\\r\\n\"\n\"Host: %s:%d\\r\\n\"\n\"User-Agent: carl\\r\\n\"\n\"Connection: close\\r\\n\"\n\"\\r\\n\",\n            (head_only ? \"HEAD\" : \"GET\"), (strlen(path) ? path : \"/\"),\n             hostname, portno);\n        } else {\n            (void)sprintf(buffer,\n\"%s %s HTTP/1.0\\r\\n\"\n\"Host: %s\\r\\n\"\n\"User-Agent: carl\\r\\n\"\n\"Connection: close\\r\\n\"\n\"\\r\\n\",\n            (head_only ? \"HEAD\" : \"GET\"), (strlen(path) ? path : \"/\"),\n             hostname);\n        }\n    }\n\n    signal(SIGPIPE, SIG_IGN);\n    signal(SIGALRM, timeout);\nretrial: /* considered harmful */\n    if (!forever) (void)alarm(10);\n    \n    sockfd = socket(AF_INET, SOCK_STREAM, 0);\n    if (sockfd < 0) \n        error(\"socket\", 255);\n    /* nb: have to re-resolve during a fallback because we might have stale\n       data from other queries */\n    server = gethostbyname(hostname);\n    if (server == NULL) {\n        if (proxy) error(\"Host not found\", 2);\n        if (!quiet) fprintf(stderr, \"host not found: %s\\n\", hostname);\n        return 2;\n    }\n    memset((char *) &serv_addr, 0, sizeof(serv_addr)); /* blocking socket */\n    serv_addr.sin_family = AF_INET;\n\n    if (proxyurl) {\n\n        /* basic socks 4 client, no NO_PROXY support yet */\n\n        if (parse_url(proxyurl, sockshost, &socksport, &socksproto)) {\n            unsigned char spacket[9];\n            size_t sbytes = 0;\n\n            if (socksproto != 1080) {\n                if (!quiet) fprintf(stderr, \"unsupported proxy protocol\\n\");\n                return 1;\n            }\n            if (server->h_length != 4) {\n                if (!quiet) fprintf(stderr, \"IPv6 not supported for SOCKS4\\n\");\n                return 3;\n            }\n\n            spacket[0] = 0x04; /* socks v4 */\n            spacket[1] = 0x01; /* connect  */\n            spacket[2] = portno >> 8;\n            spacket[3] = portno & 0xff;\n            spacket[4] = (unsigned char)server->h_addr[0]; \n            spacket[5] = (unsigned char)server->h_addr[1]; \n            spacket[6] = (unsigned char)server->h_addr[2]; \n            spacket[7] = (unsigned char)server->h_addr[3]; \n            spacket[8] = 0x00;\n\n            socksserver = gethostbyname(sockshost);\n            if (socksserver == NULL) {\n                if (!quiet) fprintf(stderr, \"SOCKS proxy not found: %s\\n\",\n                                            sockshost);\n                return 2;\n            }\n            memcpy((char *)&serv_addr.sin_addr.s_addr,\n                   (char *)socksserver->h_addr, socksserver->h_length);\n            serv_addr.sin_port = htons(socksport);\n#if defined(macintosh)\n            mac_connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr),\n                \"connect to SOCKS\", 4);\n#else\n            if (connect(sockfd,(struct sockaddr *)&serv_addr,\n                        sizeof(serv_addr)) < 0) \n                error(\"connect to SOCKS\", 4);\n#endif\n\n            /* we should be able to send this much without blocking */\n            if (send(sockfd, spacket, 9, 0) != 9)\n                error(\"send to SOCKS\", 4);\n\n            while ((read_size = recv(sockfd, (char *)&spacket[sbytes],\n                                     9-sbytes, 0)) > 0) {\n                sbytes += read_size;\n                if (sbytes == 8) break;\n            }\n\n            if (sbytes != 8 || spacket[0] != 0x00 ||\n                    spacket[1] < 0x5a || spacket[1] > 0x5d) {\n                error(\"SOCKS connect failed\", 5);\n            }\n            if (spacket[1] != 0x5a) {\n                if (proxy) error(\"SOCKS connect failed\", 5);\n                if (!quiet) fprintf(stderr, \"SOCKS connect: %i\\n\", spacket[1]);\n                return 5;\n            }\n            proxycon = 1;\n        } else {\n            error(\"illegal proxy URL\", 1);\n        }\n    }\n\n    /* connect to host */\n                \n    if (!proxycon) {\n        memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);\n        serv_addr.sin_port = htons(portno);\n#if defined(macintosh)\n        mac_connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr),\n           \"connect\", 5);\n#else\n        if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) \n           error(\"connect\", 5);\n#endif\n    }\n\n    /* set up http or tls */\n\n    if (proto == 443) {\n#if defined(__BEOS__)\n#warning BeOS port currently limited to TLS 1.2\n        /* the stack overhead is apparently too much for it */\n        context = tls_create_context(0, TLS_V12);\n#else\n        context = tls_create_context(0, (tls12) ? TLS_V12 : TLS_V13);\n#endif\n        if (!tls_sni_set(context, hostname)) error(\"TLS context failure\", 255);\n        tls_client_connect(context);\n        https_send_pending(sockfd, context);\n    } else {\n        /* on plain HTTP, try to send the initial request right now */\n        size_t buffer_index = 0;\n        size_t buffer_len = strlen(buffer);\n\n        while (buffer_len) {\n            int res = send(sockfd, (char *)&buffer[buffer_index],\n                           buffer_len, 0);\n            if (res > 0) {\n                buffer_len -= res;\n                buffer_index += res;\n            }\n        }\n    }\n\n    /* read from socket and, if needed, stdin */\n\n#if defined(__BEOS__)\n    (void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);\n#endif\n    if (proto == 80) {\n        for(;;) {\n            if (!forever) (void)alarm(10);\n            FD_ZERO(&fdset);\n            FD_SET(sockfd, &fdset);\n\n#if !defined(__BEOS__)\n            FD_SET(STDIN_FILENO, &fdset);\n            (void)select(sockfd + 1, &fdset, NULL, NULL, NULL); /* wait */\n#else\n            /* In BeOS and Win32 select() only works on sockets, not on\n               standard file handles, so we must ping-pong. */\n            tv.tv_sec = 0;\n            tv.tv_usec = TIMESLICE;\n            (void)select(sockfd + 1, &fdset, NULL, NULL, &tv); /* wait */\n#endif\n\n            /* send any post-headers data, like POST forms, etc. */\n            if (stdin_pending()) {\n                size_t buffer_index = 0;\n                read_size = read(STDIN_FILENO, read_buffer, sizeof(read_buffer));\n\n                while (read_size) {\n                    int res = send(sockfd, (char *)&read_buffer[buffer_index],\n                                   read_size, 0);\n                    if (res > 0) {\n                        read_size -= res;\n                        buffer_index += res;\n                    }\n                }\n            }\n\n            if (FD_ISSET(sockfd, &fdset)) {\n                if ((read_size = recv(sockfd, client_message, sizeof(client_message) , 0)) > 0) {\n                    bytesread += read_size;\n                    if (!with_headers) {\n                        size_t i = 0;\n\n                        for(i=0; i<read_size; i++) {\n                            if (client_message[i] == '\\r') continue;\n                            if (client_message[i] == '\\n') numcrs++;\n                                else numcrs = 0;\n                            if (numcrs == 2) { break; }\n                        }\n                        if (numcrs < 2) continue;\n                        with_headers = 1; spoof10 = 0; /* paranoia */\n                        for(i++; i<read_size; i++) \n                            fwrite(&(client_message[i]), 1, 1, stdout);\n                    } else {\n                        if (spoof10) {\n                            if (read_size > 7 &&\n                                    client_message[0] == 'H' &&\n                                    client_message[1] == 'T' &&\n                                    client_message[2] == 'T' &&\n                                    client_message[3] == 'P' &&\n                                    client_message[4] == '/' &&\n                                    client_message[5] == '1' &&\n                                    client_message[6] == '.' &&\n                                    client_message[7] == '1') {\n                                client_message[7] = '0';\n                                spoof10 = 0;\n                            }\n                        }\n                        fwrite(client_message, read_size, 1, stdout);\n                    }\n                } else break; /* ready socket, no bytes: connection closed */\n            }\n\n            /* some sort of signal, loop around */\n        }\n    } else if (proto == 443) {\n        for(;;) {\n            int i;\n\n#if defined(__MACHTEN__)\n            /* it seems to get stuck here without this */\n            fprintf(stderr, \"\");\n#endif\n\n            if (!forever) (void)alarm(10);\n            FD_ZERO(&fdset);\n            FD_SET(sockfd, &fdset);\n#if !defined(__BEOS__)\n            FD_SET(STDIN_FILENO, &fdset);\n            (void)select(sockfd + 1, &fdset, NULL, NULL, NULL); /* wait */\n#else\n            tv.tv_sec = 0;\n            tv.tv_usec = TIMESLICE;\n            (void)select(sockfd + 1, &fdset, NULL, NULL, &tv); /* wait */\n#endif\n\n            /* service socket first, since we may still be setting up TLS */\n            if (FD_ISSET(sockfd, &fdset)) {\n                if ((read_size = recv(sockfd, client_message, sizeof(client_message) , 0)) > 0) {\n                    int i = tls_consume_stream(context, client_message, read_size, validate_certificate);\n                    if (i < 0) {\n#if !defined(__BEOS__)\n                        /* only fallback if allowed and if during hello\n                           (elsewise it's an error) */\n                        if (!tls12 && !tls13only && (tls_established(context) < 1)) {\n#if DEBUG\n                            fprintf(stderr, \"warning: failed tls 1.3, error %d, falling back\\n\", i);\n#endif\n                            tls12 = 1;\n                            close(sockfd);\n                            tls_destroy_context(context);\n                            goto retrial;\n                        }\n#endif\n                        if (errno > 0) perror(\"tls_consume_stream\");\n                        if (!quiet) fprintf(stderr, \"fatal TLS error: %d\\n\", i);\n                        return 6;\n                    }\n                    https_send_pending(sockfd, context);\n\n                    /* no point in anything further until TLS established */\n                    if (!tls_established(context)) continue;\n\n                    /* TLS up, try to send initial portion of request now */\n                    if (!sent) {\n                        tls_write(context, (unsigned char *)buffer, strlen(buffer));\n                        https_send_pending(sockfd, context);\n                        sent = 1;\n                    }\n\n                    /* prioritize POST data yet to be sent */\n#if defined(__BEOS__)\n                    if (stdindone) /* can't reliably detect stdin waiting */\n#else\n                    if (!stdin_pending() || stdindone)\n#endif\n                    /* drain everything waiting on the socket */\n                    for(;;) {\n                        /* drain TLS buffer first, in case we got it all */\n                        while (read_size = tls_read(context, read_buffer, sizeof(read_buffer))) {\n                            bytesread += read_size;\n                            if (!with_headers) {\n                                for(i=0; i<read_size; i++) {\n                                    if (read_buffer[i] == '\\r') continue;\n                                    if (read_buffer[i] == '\\n') numcrs++;\n                                        else numcrs = 0;\n                                    if (numcrs == 2) { break; }\n                                }\n                                if (numcrs < 2) continue;\n                                with_headers = 1; spoof10 = 0; /* paranoia */\n#if defined(__BEOS__)\n                                /* whyyyyyy */\n                                for(i++; i<read_size; i++)\n                                    write(STDOUT_FILENO, &(read_buffer[i]), 1);\n#else\n                                for(i++; i<read_size; i++)\n                                    fwrite(&(read_buffer[i]), 1, 1, stdout);\n#endif\n                            } else {\n                                if (spoof10) {\n                                    if (read_size > 7 &&\n                                            read_buffer[0] == 'H' &&\n                                            read_buffer[1] == 'T' &&\n                                            read_buffer[2] == 'T' &&\n                                            read_buffer[3] == 'P' &&\n                                            read_buffer[4] == '/' &&\n                                            read_buffer[5] == '1' &&\n                                            read_buffer[6] == '.' &&\n                                            read_buffer[7] == '1') {\n                                        read_buffer[7] = '0';\n                                        spoof10 = 0;\n                                    }\n                                }\n#if defined(__BEOS__)\n                                /* whyyyyyyy II: the wrath of wtf */\n                                for(i=0; i<read_size; i++)\n                                    write(STDOUT_FILENO, &(read_buffer[i]), 1);\n#else\n                                fwrite(read_buffer, read_size, 1, stdout);\n#endif\n                            }\n                        }\n                        /* go back for more */\n                        if ((read_size = recv(sockfd, client_message, sizeof(client_message) , 0)) <= 0) break;\n                        i = tls_consume_stream(context, client_message, read_size, validate_certificate);\n                        if (i < 0) {\n                            if (errno > 0) perror(\"tls_consume_stream\");\n                            if (!quiet) fprintf(stderr, \"fatal TLS error: %d\\n\", i);\n                            return 6;\n                        }\n                    }\n                } else break; /* ready socket, no bytes: connection closed */\n            }\n\n            /* send any post-headers data, like POST forms, etc. */\n            if (sent) stdindone = 1; /* default done when request sent */\n            if (stdin_pending() && sent) {\n                /* no point until TLS is established */\n                if (!tls_established(context)) continue;\n\n                read_size = read(STDIN_FILENO, read_buffer, sizeof(read_buffer));\n                if (read_size > 0) {\n                    tls_write(context, (unsigned char *)read_buffer, read_size);\n                    https_send_pending(sockfd, context);\n                    stdindone = 0; /* prioritize STDIN on future selects */\n                }\n            }\n        }\n    } else { /* profit! */ }\n\n#if DEBUG\nfprintf(stderr, \"proper exit, bytes left=%d\\n\", context->application_buffer_len);\n#endif\n\n    if (!bytesread) {\n        if (proto == 443 && context->error_code) {\n            (void)sprintf((char *)read_buffer,\n                          \"TLS alert received: %d\\n\", context->error_code);\n            error((char *)read_buffer, 6);\n        }\n        error(\"No data received\", 253);\n    }\n    free(buffer);\n    return 0;\n}\n"
  },
  {
    "path": "carl.md",
    "content": "# carl(1) - Crypto Ancienne Resource Loader\n\nCrypto Ancienne\n\n```\ncarl [options] url\n```\n\n\n<a name=\"description\"></a>\n\n# Description\n\n**carl**\nis both a demonstration application for the Crypto Ancienne TLS library and a utility reminiscent of the much more comprehensive\n**curl**(1),\nof which its name is a desperate pun. It may also be more suitable as a\n**curl**(1)\nsubstitute for the older systems that Crypto Ancienne caters to, since\nit has no prerequisites other than a compatible C compiler.\n\nLike its inspiration,\n**carl**\nfetches URLs, emitting them to standard output. However,\n**carl**\nonly supports HTTP and HTTPS (and only HTTP/0.9, HTTP/1.0 and HTTP/1.1), although it will also parse SOCKS URLs and use them as proxies (see\n**ENVIRONMENT**).\n\n**carl**\ncan also accept complete\nHTTP and HTTPS requests over standard input (see\n**PROXY**\n**MODE**).\nIf connected to\n**inetd**(8)\nor a similar utility, this can act as a complete proxy solution, including for some browsers which may not speak HTTPS or\ncurrent TLS versions themselves but can be trained or tricked to send requests for\n**https://**\nURLs to it.\n\n\n<a name=\"options\"></a>\n\n# Options\n\nIn general, options do not match\n**curl**(1)'s.\n\n\n* **-q**  \n  Quiet mode; no verbose errors are displayed (see\n  **EXIT**\n  **STATUS**).\n* **-t**  \n  Disable timeouts. Otherwise, transactions that take longer than 10 seconds are aborted. Necessary for slower systems that may not negotiate TLS quickly enough. Given that Crypto Ancienne specifically caters to such systems, this option may become the default in future versions.\n* **-H**  \n  Use\n  **HEAD**\n  as the request method instead of\n  **GET**.\n  In this mode, HTTP(S) headers are displayed automatically, along with any residual message body that may be transmitted by some servers. Other methods such as\n  **POST**\n  must be specified as proxy requests (i.e., sent over standard input when\n  **-p**\n  is specified).\n* **-i**  \n  Dump both headers and body, even if\n  **-H**\n  isn't specified. Irrelevant in proxy mode (when\n  **-p**\n  is specified).\n* **-N**  \n  Ignore the\n  **ALL_PROXY**\n  environment variable, if it exists (see\n  **ENVIRONMENT**).\n* **-u**  \n  Treat all HTTP URLs as HTTPS, even if they are specified as HTTP. This includes URLs received in proxy mode (when\n  **-p**\n  is specified).\n* **-s**  \n  Downgrade HTTP/1.1 replies to HTTP/1.0 for consumers or clients which are intolerant. Irrelevant if headers are not displayed (i.e., without\n  **-H**,\n  **-p**\n  or\n  **-i**).\n* **-2**  \n  Maximally negotiate TLS 1.2 instead of TLS 1.3. This is primarily for analysing handshake failures; under typical circumstances requiring this option to access a site should be considered a bug.\n* **-3**  \n  Conversely, do not allow fallbacks to a TLS 1.2 context if negotiating a TLS 1.3 context fails. By default\n  **carl**\n  will retry such connections to account for those hosts that genuinely support TLS 1.2 but not any of the ciphers that TLS 1.2 and TLS 1.3 would have in common. These sites are getting fewer and fewer, and thus this option may become the default in future versions.\n* **-p**  \n  Enables proxy mode (see\n  **PROXY**\n  **MODE**).\n  **-i**,\n  **-q**,\n  and\n  **-H**,\n  if they are specified, are ignored. If a URL is provided, it may only be a\n  **socks://**\n  or\n  **socks5://**\n  URL, which is used as a SOCKS proxy for\n  **carl**\n  to relay through (see the\n  **ALL_PROXY**\n  environment variable in\n  **ENVIRONMENT**).\n* **-v**  \n  Display version string (the same as the main library).\n* **-h**  \n  Display a synopsis of these options.\n  \n\n<a name=\"proxy-mode\"></a>\n\n# Proxy Mode\n\nIf the\n**-p**\noption is specified,\n**carl**\nwill accept a full proxy client request for an\n**http://**\nor\n**https://**\nURL from standard input. It must be formatted as a standard HTTP proxy request with method\nand fully-specified URL minimally compliant to RFC 7230, though\n**carl**\nis tolerant, and will quietly adjust client requests as needed or requested (see also the\n**-u**\nand\n**-s**\noptions). A full HTTP reply with all remote headers will be sent in response.\n\nThe request must be delimited by the standard two-CRLF separator. If the method is intended to send data to the server, such as\n**POST**,\nthe payload may trail the request headers after it.\n**carl**\ndoes no encoding of this data; your application must do that itself.\n\nIn proxy mode, the _url_ argument may only be used to specify a SOCKS proxy through which the request will be forwarded. If the\n**ALL_PROXY**\nenvironment variable exists, specifying a SOCKS URL on the command line will override it (or use\n**-N**\nto ignore it; see\n**ENVIRONMENT**).\nOtherwise,\n**carl**\nwill connect directly.\n\nThe\n**CONNECT**\nmethod is intentionally not implemented.\n\n**carl**\ndoes not bind any server port itself. However, because this mode accepts data on standard input, any\n**inetd**(8)\nor\n**inetd**(8)-like\nsuperserver environment such as\n**xinetd**(8)\nor\n**micro_inetd**(1)\ncan be used to make it accessible on the network. _Careful: if you bind an external interface, you've just made your computer into an open HTTP proxy!_\n**carl**\nimplements no access controls or authentication, so check your superserver's documentation on how to only bind an internal interface or the loopback.\n\n<a name=\"environment\"></a>\n\n# Environment\n\n\n* **ALL_PROXY**  \n  **carl**\n  has built-in SOCKSv4 client support. If a SOCKS URL (either\n  **socks://**\n  or\n  **socks5://**,\n  which is treated as a synonym) is specified in this environment variable, all requests will be forwarded through it.\n  If a port number is not specified in the URL, it is assumed to be 1080. Any provided path or arguments are ignored.\n  **carl**\n  does not support authentication or SOCKSv5 features, and requires your DNS be able to resolve hostnames.\n* This variable is ignored if\n  **-N**\n  is specified on the command line, and it is overridden in proxy mode\n  (**-p**)\n  if a SOCKS URL is specified on the command line.\n\n**NO_PROXY**\nis not currently implemented.\n\n<a name=\"exit-status\"></a>\n\n# Exit Status\n\nA possibly helpful message may also appear unless it is suppressed by\n**-q**.\nThese exit return codes may be expanded in future versions.\n\n* **0**\n  No error.\n* **1**\n  The request is pathological (nonsense, inappropriate or incomplete). This can also occur when a non-SOCKS proxy is provided\n  (**carl**\n  does not talk to other HTTP proxies; they are vapid and uninteresting at parties).\n* **2**\n  The host or proxy host could not be resolved.\n* **3**\n  The host resolved to an IPv6 address, but\n  **carl**\n  doesn't support those yet.\n* **4**\n  The connection to the SOCKS proxy failed.\n* **5**\n  The connection to the HTTP(S) server failed.\n* **6**\n  The TLS response from the HTTPS server could not be processed.\n* **253**\n  No data was received.\n* **254**\n  Timeout. Consider using\n  **-t**\n  if the system is slower and the request should have worked.\n* **255**\n  General failure.\n  \n\n<a name=\"notes\"></a>\n\n# Notes\n\n**carl**\ndoes not currently evaluate certificates for validity, so its encryption support is best considered opportunistic and it\nshould not be used for high-security environments.\n\n\n<a name=\"see-also\"></a>\n\n# See Also\n\n**curl**(1)\n\n\n<a name=\"home-page\"></a>\n\n# Home Page\n\nhttps://github.com/classilla/cryanc\n\n\n<a name=\"author\"></a>\n\n# Author\n\n(C)2020-3 Cameron Kaiser and Contributors. All rights reserved. Additional copyrights apply; see the home page for full credits. BSD license.\n"
  },
  {
    "path": "carl_mpw.sit.hqx",
    "content": "(This file must be converted with BinHex 4.0)\r:\"fe`GbjcDA3!8dP8090*9#%!N!3(2`#3\"!GM8h4eCQC*G#!SBbNa16Nh,6)`-$)\rJ3@aKC'4TEL\"6HA0dC@ec,#\"*EQ-Z,#\"SG(4`1Lm[Gj!$,Q&XB@4ND@jcHA-ZBfp\rY,e0dG@CQ5A3[$3SD!!83!!!(2`#3!h)!!3#3!h)5J`fPT9*PFf9bGQ9NTD8!TC!\r%!3!!-`\"!i%BaaZ\"'EBi!N!d$)pi!N!2j!!!1lJ!!\"RB!!Qe`G`!3BB`!N!J$i2q\r3\"!#3%U@3\"!%!!$!!32rrRC!!rrqGN!!!!!3U!*!(FJ!!e4ArN!3!N!UPN!3\"!!!\rq!!$J4M)6i%Bb%`#3!h)!!!3U!*!$FJ!1l2%!!!DS!!!#BJ#3\"!m!3h*j3@jM4e9\r655jMF(!!!@U[9%9B9&)UBfJ\"!*!C!Ai!N!0I!*!%$`\"#`G8(%mPY1BkXpfff4h,\rhP&`fPHPdiY`@#kYN4LJr,DBE$%r#52FFKGQlRd5$CKdGjHH`bXG902a2&rFQRke\r%K)I4#ZjA`aK-&[9JBb*CPYpD*Da-E!#'EZ#,ipm[!%,\"e)jH8QEYYM+ZZp(Rb%F\rMZqNI9E@TDImM6F0fbJdlDm#Sm+B9@m&[L)d[V()cM1iL[B!-43B-pZD&MPRkb@)\rM21LXMIlZd3\"!#mP-0T0qe@Z\"L\"eQ%$`LN[IiYl&&HQC1-9BfQTeY(p5KpD6DED`\r,GV[1$LSR&ip#\"11+R9k&*dRf365C*$CGA#L4qe'M3ieE88r@iLA)'XecYR!&-B8\r`XIYcGUaNL6k%@4VpSP[R&Qj5b1ZMR\"@+CPjYYENSL`NapAT'rK3C9BS3U#181FK\r'SpR))UNRj'A'#fV)+02YY09#f454rYhFMlr8k,q(-Yl1i)cLe'IJfm8-AUB-dVF\rJ,)iVf5,*H5k(B5Z$ZF4$lkp%ld1Z$lSj$92cX-qr,ET4kNJ+r1&jC-eP'8`llqr\rFIb&-8X2Ra5pKUZET+S4q$\"d9'DT*I'H'R,Md5H2%Y+X2Hd+L4Kj%U8#1J'L4B99\rC!K-mb%J$l1l)1Ae%eVce4G%UHclkTl-SX)eC+15b5TT8,AZY+YLpCDQ$TJY*jp`\r[*r@E\")YK&3B0AIXP*FqA`V*69BTmLUJql`F`0,%@Kl$'b,RNl249N!$G6E@Jd6*\rZm`IU-INDU6[C4'e-SAd5KC`4\"(-L'ZbGll6aDLRee`d$9Fh1kQ6E$1e6`lIFZak\rhjkJ31eS%M,q2,QA2*4q[GQ1bkReK#%VGAa\"Le8ZkcMR$fXPlaiUSh[1B2#MTKr+\r$CeEa,\"(4Q-m'r'[Ml`mUaJ)`KP@fhA#bDEIT+-YfAdHTlS,&Y8SIN35#X8,p)2E\rj9RlS&p+02Li'qV$&mN`KUSaiTC!%!3!!1!!!i%BafH\"'DKB!N!2j!*!$b3#3!h)\r!#2R(!!!&'J!!!Lm!N!32!%eKDf9QD@aP!!&KQe4&@&408&-J!3#3'3'Z!*!$I!#\r3\"!m!3X(8kN$5bh)@kD[*Y#X@09\"p404TA$#a3BG)#SCfQMF\"2bZ4`'I1JL-YjC!\r!A1[pP\"rK&5!&*QH@H)m-e$44%rkIr*!!c@NpV-hB8\"YkM9YV$a9epd$@Xi*&Xq2\rJXcH'GF*aH49B#pBBG9r@ca%620rAhI8piqHjj[UjJUX`3X(8Z\"G9kEqH2AhN!FX\rD)D#fk$%K$3AImmB)Iae[bjrJl$kLUe&`%d(CH#4GKqF4jfZb(dX&c5R2mUk1)cj\r-[\"+Y5`(0EedbmY0JTKZ@`Vdm3`FTRQ4*XVmTTJ@KRarG1-2D\"&[QE%Sj2BG[ZlI\rFeZhXi09&C!3D4$iFQ+VrQEp,hTZ5bqH(54`(*f4SP06%*@*+0dii8'bG0XPReIa\r@aiQrG1P%AaPIN!\"ADp%U'&MASY$U(MRIbTSH2Q\"[k%DIASBMp3qGqX-RDHhKjIh\rF#cmFX89TeBfENmSSkqP0d%l\"d#1TLVj![0XEc4EK$lLmPK'Zhr-3%B4ijl'`+'e\r8UNI[*04C-BQFrp%d!#PiRqCS1`B3!GY'cDJe29i&*jTf,KIIBZhj8&K$c2kPJGL\rkL!feQHh[kr-NB3-'MP$2Bp13!\"F+lQ'%G$EQh%hM&LVU*2RleUSPJLh4E%EdLVK\r`0Ll&d4YDPfY#S1NcSjPY)IDIJ[3P*QAk6%V'&Y9r([[bmRbcT80IqPB5[YT&p*U\rY(j!!k,qri86&qI1$Rb'Cl13'J%XCV,fFZ%qICM(R*p&kh9d#%KJe2'dU0Tc)kaP\rSiS8AUp9T+km+Ce*Ni0XD8D1'ZBND(Zj3DFjXH$N9Bj5#dN\"'D#NHLBckq)b'r1L\r1!mPCf14Fl1\"`q'$hYl&15h)$ZE-&KXZ9Nje4NV%rH,VCm!D9hYRHqTk+YUS1NX-\rL,SfVcGcj`Jk)k#+e-FeLHr18q,fZ!!!!:\r"
  },
  {
    "path": "cryanc.c",
    "content": "/* Crypto Ancienne v2.0\n   A pre-C99 cryptography library for the Internet of Old Things\n\n   DISCLAIMER:\n   The use of this library does not make your application cryptographically\n   secure, and certain systems may entirely lack any technological means to\n   make that possible. Its functionality and security should be regarded as,\n   at best, \"good enough to shoot yourself in the foot with.\"\n\n   Copyright (c) 2020-3 Cameron Kaiser and contributors. All rights reserved.\n\n   Based on TLSe. Copyright (c) 2016-2021, Eduard Suica.\n   Based on libtomcrypt. By Tom St Denis and contributors. Unlicense.\n   Based on public domain works by D. J. Bernstein.\n   Allegedly includes an alleged ARC4 random routine from OpenBSD (allegedly).\n   Copyright (c) 1996 David Mazieres.\n   All rights reserved.\n\n   BSD license.\n*/\n\n/********************************************************************************\n Copyright (c) 2016-2023, Eduard Suica\n All rights reserved.\n \n Redistribution and use in source and binary forms, with or without modification,\n are permitted provided that the following conditions are met:\n \n 1. Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n \n 2. Redistributions in binary form must reproduce the above copyright notice, this\n list of conditions and the following disclaimer in the documentation and/or other\n materials provided with the distribution.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n POSSIBILITY OF SUCH DAMAGE.\n ********************************************************************************/\n#ifndef TLSE_C\n#define TLSE_C\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <time.h>\n#ifdef _WIN32\n#ifdef SSL_COMPATIBLE_INTERFACE\n#include <winsock2.h>\n#endif\n#include <windows.h>\n#include <wincrypt.h>\n#ifndef strcasecmp\n    #define strcasecmp stricmp\n#endif\n#else\n/* hton* and ntoh* functions */\n#if defined(__BEOS__)\n/* weird */\n#include <netdb.h>\n#else\n#include <arpa/inet.h>\n#endif\n#include <unistd.h>\n#include <errno.h>\n#endif\n\n#include <limits.h>\n#include <sys/time.h>\n\n/*****************************************************************************\n Start of architecture-dependent recipes\n ****************************************************************************/\n\n/* AIX: not compliant with SUS until 5L */\n#if defined(_AIX)\n#if defined(_AIX51)\n/* AIX 5L and up */\n#warning compiling for current AIX\n#else\n/* AIX 4 and under */\n#warning compiling for AIX before 5L\n#include <stdarg.h>\n#define NOT_POSIX 1\n#endif\n#if defined(__ibmxl__)\n#warning not tested with xlc\n#endif\n#endif\n\n/* IRIX on MIPS (MIPSPro preferred, probably works with Nekoware gcc) */\n#if defined(sgi) || defined(__sgi)\n#warning compiling for IRIX on MIPS\n#ifdef __GNUC__\n#warning not tested on gcc\n#else\n#ifdef _SGI_COMPILER_VERSION\n#if (_SGI_COMPILER_VERSION < 744)\n#warning not tested on this version of MIPSPro, consider c99\n#endif\n#else\n#ifdef _COMPILER_VERSION\n#warning not tested on this version of MIPSPro, consider c99\n#endif\n#endif\n#endif\n#define NO_FUNNY_ALIGNMENT 1 /* reacts badly to unaligned pointer access */\n#endif\n\n/* BeOS R5 (BeBox or GTFO) */\n#if defined(__BEOS__)\n#warning compiling for BeOS R5 - PARTIALLY WORKING, see notes\n/* mostly POSIX but not SUS */\n#define NOT_POSIX 1\n#include <stdarg.h>\n#include <inttypes.h>\n#include <endian.h>\n#if __POWERPC__\n#ifndef __BIG_ENDIAN__\n#define __BIG_ENDIAN__ 1\n#endif\n#endif\n/* pad libc */\n#define usleep(x) snooze(x)\n#if defined(__MWERKS__)\n#warning Metrowerks compiler detected - DISABLE OPTIMIZATION\n/* Mwerks enforces a 32K function-local data limit which some functions hit,\n   which is made worse by BeOS's pathetic 256K stack limit per thread. */\n#define BIG_STRING_SIZE 0x0800\n#else\n#ifdef __GNUC__\n#if __POWERPC__\n#warning Fred Fish egcs detected - check your include paths are correct\n#else\n#warning Intel gcc - not supported\n#endif\n#else\n/* huh? */\n#warning this compiler is not supported\n#endif\n#endif\n#endif\n\n/* SunOS 4 and Solaris 2+ */\n#if defined(sun) || defined(__sun)\n#if defined(__SVR4) || defined(__svr4__)\n/* Solaris is not officially supported yet */\n#warning compiling for Solaris\n#define NOT_POSIX 1\n#include <stdarg.h>\n#include <inttypes.h>\n#if (defined(__sparc) || defined(__sparc__))\n#define NO_FUNNY_ALIGNMENT 1\n#define __BIG_ENDIAN__ 1\n#endif\n#else\n/* SunOS 4 or OS/MP ... needs a LOT of help! */\n#warning compiling for SunOS 4 and OS/MP\n#include <stdarg.h>\n/* Seems to lack the usual macros for endianness. */\n#ifndef __BIG_ENDIAN__\n#define __BIG_ENDIAN__ 1\n#endif\n#define NOT_POSIX 1\n#define LTC_NO_PROTOTYPES 1 /* clashes with qsort() */\n#define NO_FUNNY_ALIGNMENT 1 /* reacts badly to unaligned pointer access */\n/* SunOS 4 realloc() doesn't work like other implementations */\nchar *_crealloc(void *p, unsigned s) { return (p) ? realloc(p,s) : malloc(s); }\n#define TLS_REALLOC(p,s) _crealloc(p,s)\n#define XREALLOC _crealloc\n/* pad libc a bit */\n#define memmove(d,s,l) (bcopy((char *)(s),(char *)(d),(l)))\n#define raise(s) (kill(getpid(),s))\n#endif\n#endif\n\n/* MachTen and Power MachTen */\n#if defined(__MACHTEN__)\n#warning compiling for MachTen\n#define NOT_POSIX 1\n#include <stdarg.h>\n/* /usr/macppc/include/machine/types.h is incomplete */\ntypedef long long int64_t;\ntypedef unsigned long long u_int64_t;\n#endif\n\n/* Tru64 on Alpha, may also work for old-sk00l Digital UNIX or OSF/1 */\n#if defined (__digital__) && defined (__unix__)\n#warning compiling for Tru64\n#if defined (__alpha) && defined (__DECC)\n#warning DEC/Compaq C compiler on Alpha - must compile with -misalign\n/* mostly POSIX but not SUS */\n#define NOT_POSIX 1\n#define __WCHAR_TYPE__ 1 /* seems to already have it */\n/* big surprise, Alpha hates unaligned pointers. yeah, you were shocked.\n   however, NO_FUNNY_ALIGNMENT is still not enough for it, so no point\n   in using it yet! */\n/* #define NO_FUNNY_ALIGNMENT 1 */\n#include <stdarg.h>\n#include <inttypes.h>\n#else\n#warning unsupported configuration\n#endif\n#endif\n\n/* SCO Xenix and Unix 4.2 (pre-OpenServer)*/\n#if defined (M_XENIX) && !defined(_SCO_DS)\n\n#if !defined(M_UNIX) /* Xenix 2.3.4 */\n#warning compiling for SCO Xenix\n#include <stddef.h>\n\n/* Xenix's realloc is also weird */\nchar *_crealloc(void *p, unsigned s) { return (p) ? realloc(p,s) : malloc(s); }\n#define TLS_REALLOC(p,s) _crealloc(p,s)\n#define XREALLOC _crealloc\n\n/*from https://www.samba.org/WinFS_report/winfs_dev/sun/solaris/source/2.50a/replace.c */ \nchar *strstr(char *s, char *p)\n{\n\tint len = strlen(p);\n\n\twhile ( *s != '\\0' ) {\n\t\tif ( strncmp(s, p, len) == 0 )\n\t\treturn s;\n\t\ts++;\n\t}\n\n\treturn NULL;\n}\n\n#define memmove(d,s,l) (bcopy((char *)(s),(char *)(d),(l)))\n#else\n#warning compiling for SCO Unix\n#endif /* Xenix 2.3.4 */\n\n#define LTC_NO_PROTOTYPES\n#define NOT_POSIX 1\n#include <sys/types.h>\n#include <stdarg.h>\n\nint usleep(unsigned int useconds)\n{\n   struct timeval temptval;\n\n   if (useconds <= 0) return;\n   temptval.tv_sec = useconds / 1000000;\n   temptval.tv_usec = useconds % 1000000;\n   if (select(0,NULL,NULL,NULL,&temptval) == -1 && errno != 4)\n   {\n\t  perror(\"sleep with select\");\n\t  exit(1);\n\t}\n }\n\n#endif /* SCO Xenix, Unix, ODT */\n\n/* Distinguish NeXTSTEP/OpenSTEP from Rhapsody and from Mac OS X */\n#if defined(__MACH__)\n#if !defined(__APPLE__)\n/* NeXTSTEP (at least 3.3)/OpenSTEP 4+ */\n#warning compiling for NeXTSTEP-OpenSTEP\n#define NOT_POSIX 1\n#define LTC_NO_PROTOTYPES 1 /* conflicts with built-in defs */\n#include <stdarg.h>\n#include <sys/signal.h>\n#else\n#if !defined(__APPLE_CC__)\n#error unsupported compiler on Darwin-like platform\n#error send your patch to fix this - you can help\n#else\n#if (__APPLE_CC__ == 1)\n/* MacPorts compiler, assume this is SUS */\n#warning compiling for MacPorts toolchain\n#else\n#if (__APPLE_CC__ < 913)\n/* Rhapsody to early OS X class compiler, including Mac OS X Server v1.x */\n#warning compiling for Rhapsody-Mac OS X Server-Public Beta\n#include <stdarg.h>\n#define NOT_POSIX 1\n#else\n/* Mac OS X with Xcode-provided gcc or clang */\n#warning compiling for Mac OS X with Xcode\n#endif\n#endif\n#endif\n#endif\n#endif\n\n/* A/UX (might work with 2, tested on 3.1) */\n#if defined(__AUX__)\n/* Needs BSD compat library for usleep. */\n#warning compiling for A/UX - remember to include -lbsd or /lib/libbsd.a\n#include <stdarg.h>\n/* Seems to lack the usual macros for endianness. */\n#ifndef __BIG_ENDIAN__\n#define __BIG_ENDIAN__ 1\n#endif\n#define NOT_POSIX 1\n#endif\n\n/* HP-UX (tested on 11.31 IA-64 and 10.20/11.11/11.23 PA-RISC) */\n#if defined(__hpux)\n#if !defined(__ia64) && !defined(__hppa)\n#error HP-UX support not tested on other architectures besides ia64 and hppa\n#error send your patch to fix this - you can help\n#endif\n#define __BIG_ENDIAN__ 1\n#define NO_FUNNY_ALIGNMENT 1\n/* HP-UX 10.x and under */\n#if defined(oldhpux)\n#warning compiling for HP-UX before 11\n#define NOT_POSIX 1\n#include <stdarg.h>\n#include <sys/_inttypes.h>\n#include <unistd.h>\n#else\n/* HP-UX 11 and up */\n#warning compiling for current HP-UX\n#endif\n#endif\n\n/* AmigaOS with ADE gcc 2.95.3 and ixemul */\n#if defined(__amiga__) || defined(__AMIGA__)\n#warning compiling for AmigaOS\n#if !defined(__ixemul)\n#error currently requires ixemul for proper POSIX semantics\n#error send your patch to fix this - you can help\n#endif\n#if !defined(__mc68000__) && !defined(__mc68000) && !defined(mc68000)\n#warning not a 68K target, assuming native PowerPC, unsupported\n#endif\n#if !defined(__GNUC__)\n#warning non-gcc compiler detected, unsupported\n#else\n#warning remember to use -mstackextend\n#endif\n#define NOT_POSIX 1\n#include <stdarg.h>\n#include <unistd.h>\n#ifndef __BIG_ENDIAN__\n#define __BIG_ENDIAN__ 1\n#endif\n/* Don't let the stack bloat */\n#define BIG_STRING_SIZE 0x1000\n#endif\n\n/* Mac OS with MrC (possibly also SC). This is REALLY BUGGY. */\n/* MrC doesn't understand #warning, so we turn off our helpful diagnostics. */\n#ifdef MPW_C\n#include <stdarg.h>\n#define NOT_POSIX 1\n#define __BIG_ENDIAN__ 1\n/* This works around issues with the compiler (PowerPC handles misaligned\n   accesses just fine). */\n#define NO_FUNNY_ALIGNMENT 1\n/* This makes it a bit more stable. Not sure what the optimum value is. */\n#define BIG_STRING_SIZE 0x0800\n#define inline\n/* ^ ... to nothing. These compilers don't understand this keyword, but they\n   automatically inline short functions. */\n#endif\n\n/* Architectures we will always break up aligned accesses on */\n#ifndef FUNNY_ALIGNMENT_OK\n#ifndef NO_FUNNY_ALIGNMENT\n#if (defined(mips) || defined(_mips) || defined(__mips) || defined(__mips__) || defined(_MIPS_) || defined(__MIPS__) || defined(__MIPSEL__) || defined(__MIPSEB__))\n#warning detected MIPS architecture, forcing aligned memory access\n#define NO_FUNNY_ALIGNMENT 1\n#endif\n#if (defined(__sparc) || defined(__sparc__))\n#warning detected SPARC architecture, forcing aligned memory access\n#define NO_FUNNY_ALIGNMENT 1\n#endif\n#if (defined(__hppa) || defined(__hppa__))\n#warning detected PA-RISC architecture, forcing aligned memory access\n#define NO_FUNNY_ALIGNMENT 1\n#endif\n#if (defined(__sh__))\n#warning detected SuperH architecture, forcing aligned memory access\n#define NO_FUNNY_ALIGNMENT 1\n#endif\n#endif\n#endif\n\n/*****************************************************************************\n End of architecture-dependent recipes (mostly)\n ****************************************************************************/\n#ifndef BIG_STRING_SIZE\n#define BIG_STRING_SIZE 0xFFFF\n#endif\n\n/* We use __BIG_ENDIAN__ as a canonical macro, so flatten any variant defs. */\n#ifndef __BIG_ENDIAN__\n#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN)\n#if (__BYTE_ORDER == __BIG_ENDIAN)\n#define __BIG_ENDIAN__ 1\n#endif\n#endif\n#endif\n\n#ifndef __BIG_ENDIAN__\n#if defined(BYTE_ORDER) && defined(BIG_ENDIAN)\n#if (BYTE_ORDER == BIG_ENDIAN)\n#define __BIG_ENDIAN__ 1\n#endif\n#endif\n#endif\n\n#if __BIG_ENDIAN__\n#ifndef MPW_C\n#warning big endian platform\n#endif\n#else\n#warning little or middle endian platform\n#endif\n\n#ifdef NO_FUNNY_ALIGNMENT\n/* These are inherently big endian, since they replace htons()/ntohs(). */\n#define __toshort(w,x) ((w[(x)] << 8) + (w[(x)+1]))\nvoid __short(void *where, unsigned int index, unsigned short value) {\n\tchar *p = (char *)where;\n\tp[index] = value >> 8;\n\tp[index+1] = (value & 0xff);\n}\n#if __BIG_ENDIAN__\n/* Just memcpy() the long long dudes */\n#else\n/* Convert native long long to big endian. */\nvoid __llong(void *where, uint64_t value) {\n\tchar *p = (char *)where;\n\tp[7] = value & 0xff;\n\tp[6] = value >> 8;\n\tp[5] = value >> 16;\n\tp[4] = value >> 24;\n\tp[3] = value >> 32;\n\tp[2] = value >> 40;\n\tp[1] = value >> 48;\n\tp[0] = value >> 56;\n}\n#endif\n#endif\n\n/* Default: assume POSIX-SUS (current Linux and BSDs, etc.) */\n\n#if !defined(NOT_POSIX)\n#warning compiling for POSIX-SUS\n#include <stdint.h>\n#include <unistd.h>\n#include <stdarg.h>\n#else\n#ifndef MPW_C\n#warning compiling with compatibility stubs\n#endif\n\n/* Sys-dep work arounds for old headers */\n\n/* provide definitions if we don't have stdint.h. */\n/* Mach and inttypes.h define these elsewhere. */\n#if !defined(_INTTYPES_H_) && !defined(_INTTYPES_H) && !defined(__INTTYPES_INCLUDED)\n#if !defined(_MACHTYPES_H_)\n\n   typedef signed char             int8_t;\n   typedef signed short            int16_t;\n   typedef signed int              int32_t;\n#ifdef  __64BIT__\n   typedef signed long             int64_t;\n   typedef int64_t                 intptr_t;\n#else\n   /* ILP32 */\n   typedef signed long long        int64_t;\n   typedef int32_t                 intptr_t;\n#endif\n\n   typedef unsigned char           uint8_t;\n   typedef unsigned short          uint16_t;\n   typedef unsigned int            uint32_t;\n#ifdef  __64BIT__\n   typedef unsigned long           uint64_t;\n   typedef uint64_t                uintptr_t;\n#else\n   /* ILP32 */\n   typedef unsigned long long      uint64_t;\n   typedef uint32_t                uintptr_t;\n#endif\n\n#else\n   /* Rhapsody and other Mach derivatives need these but not the above */\n   typedef u_int8_t                uint8_t;\n   typedef u_int16_t               uint16_t;\n   typedef u_int32_t               uint32_t;\n   typedef u_int64_t               uint64_t;\n#ifdef  __64BIT__\n   typedef int64_t                 intptr_t;\n   typedef uint64_t                uintptr_t;\n/* We can't typedef these on OS X Public Beta or the build will fail */\n#else\n#if !defined(__APPLE_CC__) || (__APPLE_CC__ < 784)\n   typedef int32_t                 intptr_t;\n   typedef uint32_t                uintptr_t;\n#endif\n#endif\n#endif\n\n#endif\n#endif\n\n#define CRYPT 0x0117\n#define LTC_NO_ROLC\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n * This has been modified to be dependent on the core Crypto Ancienne\n * library by Cameron Kaiser and implement arc4random with extensions.\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://math.libtomcrypt.com\n * Modified for Crypto Ancienne by Cameron Kaiser\n */\n#ifndef BN_H_\n#define BN_H_\n\n#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))\n #if defined(LTM2)\n  #define LTM3\n #endif\n #if defined(LTM1)\n  #define LTM2\n #endif\n #define LTM1\n\n #if defined(LTM_ALL)\n  #define BN_ERROR_C\n  #define BN_FAST_MP_INVMOD_C\n  #define BN_FAST_MP_MONTGOMERY_REDUCE_C\n  #define BN_FAST_S_MP_MUL_DIGS_C\n  #define BN_FAST_S_MP_MUL_HIGH_DIGS_C\n  #define BN_FAST_S_MP_SQR_C\n  #define BN_MP_2EXPT_C\n  #define BN_MP_ABS_C\n  #define BN_MP_ADD_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_ADDMOD_C\n  #define BN_MP_AND_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_CLEAR_MULTI_C\n  #define BN_MP_CMP_C\n  #define BN_MP_CMP_D_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_CNT_LSB_C\n  #define BN_MP_COPY_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_DIV_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_DIV_3_C\n  #define BN_MP_DIV_D_C\n  #define BN_MP_DR_IS_MODULUS_C\n  #define BN_MP_DR_REDUCE_C\n  #define BN_MP_DR_SETUP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_EXPORT_C\n  #define BN_MP_EXPT_D_C\n  #define BN_MP_EXPT_D_EX_C\n  #define BN_MP_EXPTMOD_C\n  #define BN_MP_EXPTMOD_FAST_C\n  #define BN_MP_EXTEUCLID_C\n  #define BN_MP_FREAD_C\n  #define BN_MP_FWRITE_C\n  #define BN_MP_GCD_C\n  #define BN_MP_GET_INT_C\n  #define BN_MP_GET_LONG_C\n  #define BN_MP_GET_LONG_LONG_C\n  #define BN_MP_GROW_C\n  #define BN_MP_IMPORT_C\n  #define BN_MP_INIT_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_INIT_SET_C\n  #define BN_MP_INIT_SET_INT_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_INVMOD_C\n  #define BN_MP_INVMOD_SLOW_C\n  #define BN_MP_IS_SQUARE_C\n  #define BN_MP_JACOBI_C\n  #define BN_MP_KARATSUBA_MUL_C\n  #define BN_MP_KARATSUBA_SQR_C\n  #define BN_MP_LCM_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_MOD_C\n  #define BN_MP_MOD_2D_C\n  #define BN_MP_MOD_D_C\n  #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C\n  #define BN_MP_MONTGOMERY_REDUCE_C\n  #define BN_MP_MONTGOMERY_SETUP_C\n  #define BN_MP_MUL_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_MULMOD_C\n  #define BN_MP_N_ROOT_C\n  #define BN_MP_N_ROOT_EX_C\n  #define BN_MP_NEG_C\n  #define BN_MP_OR_C\n  #define BN_MP_PRIME_FERMAT_C\n  #define BN_MP_PRIME_IS_DIVISIBLE_C\n  #define BN_MP_PRIME_IS_PRIME_C\n  #define BN_MP_PRIME_MILLER_RABIN_C\n  #define BN_MP_PRIME_NEXT_PRIME_C\n  #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C\n  #define BN_MP_PRIME_RANDOM_EX_C\n  #define BN_MP_RADIX_SIZE_C\n  #define BN_MP_RADIX_SMAP_C\n  #define BN_MP_RAND_C\n  #define BN_MP_READ_RADIX_C\n  #define BN_MP_READ_SIGNED_BIN_C\n  #define BN_MP_READ_UNSIGNED_BIN_C\n  #define BN_MP_REDUCE_C\n  #define BN_MP_REDUCE_2K_C\n  #define BN_MP_REDUCE_2K_L_C\n  #define BN_MP_REDUCE_2K_SETUP_C\n  #define BN_MP_REDUCE_2K_SETUP_L_C\n  #define BN_MP_REDUCE_IS_2K_C\n  #define BN_MP_REDUCE_IS_2K_L_C\n  #define BN_MP_REDUCE_SETUP_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_SET_C\n  #define BN_MP_SET_INT_C\n  #define BN_MP_SET_LONG_C\n  #define BN_MP_SET_LONG_LONG_C\n  #define BN_MP_SHRINK_C\n  #define BN_MP_SIGNED_BIN_SIZE_C\n  #define BN_MP_SQR_C\n  #define BN_MP_SQRMOD_C\n  #define BN_MP_SQRT_C\n  #define BN_MP_SQRTMOD_PRIME_C\n  #define BN_MP_SUB_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_SUBMOD_C\n  #define BN_MP_TO_SIGNED_BIN_C\n  #define BN_MP_TO_SIGNED_BIN_N_C\n  #define BN_MP_TO_UNSIGNED_BIN_C\n  #define BN_MP_TO_UNSIGNED_BIN_N_C\n  #define BN_MP_TOOM_MUL_C\n  #define BN_MP_TOOM_SQR_C\n  #define BN_MP_TORADIX_C\n  #define BN_MP_TORADIX_N_C\n  #define BN_MP_UNSIGNED_BIN_SIZE_C\n  #define BN_MP_XOR_C\n  #define BN_MP_ZERO_C\n  #define BN_PRIME_TAB_C\n  #define BN_REVERSE_C\n  #define BN_S_MP_ADD_C\n  #define BN_S_MP_EXPTMOD_C\n  #define BN_S_MP_MUL_DIGS_C\n  #define BN_S_MP_MUL_HIGH_DIGS_C\n  #define BN_S_MP_SQR_C\n  #define BN_S_MP_SUB_C\n  #define BNCORE_C\n #endif\n\n #if defined(BN_ERROR_C)\n  #define BN_MP_ERROR_TO_STRING_C\n #endif\n\n #if defined(BN_FAST_MP_INVMOD_C)\n  #define BN_MP_ISEVEN_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_COPY_C\n  #define BN_MP_MOD_C\n  #define BN_MP_SET_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_ISODD_C\n  #define BN_MP_SUB_C\n  #define BN_MP_CMP_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_CMP_D_C\n  #define BN_MP_ADD_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_FAST_S_MP_MUL_DIGS_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_FAST_S_MP_SQR_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_2EXPT_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_GROW_C\n #endif\n\n #if defined(BN_MP_ABS_C)\n  #define BN_MP_COPY_C\n #endif\n\n #if defined(BN_MP_ADD_C)\n  #define BN_S_MP_ADD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_ADD_D_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_ADDMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_ADD_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MOD_C\n #endif\n\n #if defined(BN_MP_AND_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_CLAMP_C)\n #endif\n\n #if defined(BN_MP_CLEAR_C)\n #endif\n\n #if defined(BN_MP_CLEAR_MULTI_C)\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_CMP_C)\n  #define BN_MP_CMP_MAG_C\n #endif\n\n #if defined(BN_MP_CMP_D_C)\n #endif\n\n #if defined(BN_MP_CMP_MAG_C)\n #endif\n\n #if defined(BN_MP_CNT_LSB_C)\n  #define BN_MP_ISZERO_C\n #endif\n\n #if defined(BN_MP_COPY_C)\n  #define BN_MP_GROW_C\n #endif\n\n #if defined(BN_MP_COUNT_BITS_C)\n #endif\n\n #if defined(BN_MP_DIV_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_COPY_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_SET_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_ABS_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CMP_C\n  #define BN_MP_SUB_C\n  #define BN_MP_ADD_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_MULTI_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_INIT_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_DIV_2_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_DIV_2D_C)\n  #define BN_MP_COPY_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_INIT_C\n  #define BN_MP_MOD_2D_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n #endif\n\n #if defined(BN_MP_DIV_3_C)\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_DIV_D_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_COPY_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_DIV_3_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_DR_IS_MODULUS_C)\n #endif\n\n #if defined(BN_MP_DR_REDUCE_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_DR_SETUP_C)\n #endif\n\n #if defined(BN_MP_EXCH_C)\n #endif\n\n #if defined(BN_MP_EXPORT_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_EXPT_D_C)\n  #define BN_MP_EXPT_D_EX_C\n #endif\n\n #if defined(BN_MP_EXPT_D_EX_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_SET_C\n  #define BN_MP_MUL_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_SQR_C\n #endif\n\n #if defined(BN_MP_EXPTMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_INVMOD_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_ABS_C\n  #define BN_MP_CLEAR_MULTI_C\n  #define BN_MP_REDUCE_IS_2K_L_C\n  #define BN_S_MP_EXPTMOD_C\n  #define BN_MP_DR_IS_MODULUS_C\n  #define BN_MP_REDUCE_IS_2K_C\n  #define BN_MP_ISODD_C\n  #define BN_MP_EXPTMOD_FAST_C\n #endif\n\n #if defined(BN_MP_EXPTMOD_FAST_C)\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_INIT_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MONTGOMERY_SETUP_C\n  #define BN_FAST_MP_MONTGOMERY_REDUCE_C\n  #define BN_MP_MONTGOMERY_REDUCE_C\n  #define BN_MP_DR_SETUP_C\n  #define BN_MP_DR_REDUCE_C\n  #define BN_MP_REDUCE_2K_SETUP_C\n  #define BN_MP_REDUCE_2K_C\n  #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C\n  #define BN_MP_MULMOD_C\n  #define BN_MP_SET_C\n  #define BN_MP_MOD_C\n  #define BN_MP_COPY_C\n  #define BN_MP_SQR_C\n  #define BN_MP_MUL_C\n  #define BN_MP_EXCH_C\n #endif\n\n #if defined(BN_MP_EXTEUCLID_C)\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_SET_C\n  #define BN_MP_COPY_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_DIV_C\n  #define BN_MP_MUL_C\n  #define BN_MP_SUB_C\n  #define BN_MP_NEG_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_FREAD_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_S_RMAP_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_CMP_D_C\n #endif\n\n #if defined(BN_MP_FWRITE_C)\n  #define BN_MP_RADIX_SIZE_C\n  #define BN_MP_TORADIX_C\n #endif\n\n #if defined(BN_MP_GCD_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_ABS_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CNT_LSB_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_EXCH_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_GET_INT_C)\n #endif\n\n #if defined(BN_MP_GET_LONG_C)\n #endif\n\n #if defined(BN_MP_GET_LONG_LONG_C)\n #endif\n\n #if defined(BN_MP_GROW_C)\n #endif\n\n #if defined(BN_MP_IMPORT_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_INIT_C)\n #endif\n\n #if defined(BN_MP_INIT_COPY_C)\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_COPY_C\n #endif\n\n #if defined(BN_MP_INIT_MULTI_C)\n  #define BN_MP_ERR_C\n  #define BN_MP_INIT_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_INIT_SET_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SET_C\n #endif\n\n #if defined(BN_MP_INIT_SET_INT_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SET_INT_C\n #endif\n\n #if defined(BN_MP_INIT_SIZE_C)\n  #define BN_MP_INIT_C\n #endif\n\n #if defined(BN_MP_INVMOD_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_ISODD_C\n  #define BN_FAST_MP_INVMOD_C\n  #define BN_MP_INVMOD_SLOW_C\n #endif\n\n #if defined(BN_MP_INVMOD_SLOW_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_MOD_C\n  #define BN_MP_COPY_C\n  #define BN_MP_ISEVEN_C\n  #define BN_MP_SET_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_ISODD_C\n  #define BN_MP_ADD_C\n  #define BN_MP_SUB_C\n  #define BN_MP_CMP_C\n  #define BN_MP_CMP_D_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_IS_SQUARE_C)\n  #define BN_MP_MOD_D_C\n  #define BN_MP_INIT_SET_INT_C\n  #define BN_MP_MOD_C\n  #define BN_MP_GET_INT_C\n  #define BN_MP_SQRT_C\n  #define BN_MP_SQR_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_JACOBI_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CNT_LSB_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_MOD_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_KARATSUBA_MUL_C)\n  #define BN_MP_MUL_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_S_MP_ADD_C\n  #define BN_MP_ADD_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_KARATSUBA_SQR_C)\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_SQR_C\n  #define BN_S_MP_ADD_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_ADD_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_LCM_C)\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_GCD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_DIV_C\n  #define BN_MP_MUL_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_LSHD_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_RSHD_C\n #endif\n\n #if defined(BN_MP_MOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_DIV_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_ADD_C\n #endif\n\n #if defined(BN_MP_MOD_2D_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_COPY_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_MOD_D_C)\n  #define BN_MP_DIV_D_C\n #endif\n\n #if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_2EXPT_C\n  #define BN_MP_SET_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_MONTGOMERY_REDUCE_C)\n  #define BN_FAST_MP_MONTGOMERY_REDUCE_C\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_MONTGOMERY_SETUP_C)\n #endif\n\n #if defined(BN_MP_MUL_C)\n  #define BN_MP_TOOM_MUL_C\n  #define BN_MP_KARATSUBA_MUL_C\n  #define BN_FAST_S_MP_MUL_DIGS_C\n  #define BN_S_MP_MUL_C\n  #define BN_S_MP_MUL_DIGS_C\n #endif\n\n #if defined(BN_MP_MUL_2_C)\n  #define BN_MP_GROW_C\n #endif\n\n #if defined(BN_MP_MUL_2D_C)\n  #define BN_MP_COPY_C\n  #define BN_MP_GROW_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_MUL_D_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_MULMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_MUL_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MOD_C\n #endif\n\n #if defined(BN_MP_N_ROOT_C)\n  #define BN_MP_N_ROOT_EX_C\n #endif\n\n #if defined(BN_MP_N_ROOT_EX_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SET_C\n  #define BN_MP_COPY_C\n  #define BN_MP_EXPT_D_EX_C\n  #define BN_MP_MUL_C\n  #define BN_MP_SUB_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_DIV_C\n  #define BN_MP_CMP_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_NEG_C)\n  #define BN_MP_COPY_C\n  #define BN_MP_ISZERO_C\n #endif\n\n #if defined(BN_MP_OR_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_FERMAT_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_INIT_C\n  #define BN_MP_EXPTMOD_C\n  #define BN_MP_CMP_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_IS_DIVISIBLE_C)\n  #define BN_MP_MOD_D_C\n #endif\n\n #if defined(BN_MP_PRIME_IS_PRIME_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_PRIME_IS_DIVISIBLE_C\n  #define BN_MP_INIT_C\n  #define BN_MP_SET_C\n  #define BN_MP_PRIME_MILLER_RABIN_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_MILLER_RABIN_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_CNT_LSB_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_EXPTMOD_C\n  #define BN_MP_CMP_C\n  #define BN_MP_SQRMOD_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_NEXT_PRIME_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_SET_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_ISEVEN_C\n  #define BN_MP_MOD_D_C\n  #define BN_MP_INIT_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_PRIME_MILLER_RABIN_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)\n #endif\n\n #if defined(BN_MP_PRIME_RANDOM_EX_C)\n  #define BN_MP_READ_UNSIGNED_BIN_C\n  #define BN_MP_PRIME_IS_PRIME_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_ADD_D_C\n #endif\n\n #if defined(BN_MP_RADIX_SIZE_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_DIV_D_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_RADIX_SMAP_C)\n  #define BN_MP_S_RMAP_C\n #endif\n\n #if defined(BN_MP_RAND_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_LSHD_C\n #endif\n\n #if defined(BN_MP_READ_RADIX_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_S_RMAP_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_ISZERO_C\n #endif\n\n #if defined(BN_MP_READ_SIGNED_BIN_C)\n  #define BN_MP_READ_UNSIGNED_BIN_C\n #endif\n\n #if defined(BN_MP_READ_UNSIGNED_BIN_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_REDUCE_C)\n  #define BN_MP_REDUCE_SETUP_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_MUL_C\n  #define BN_S_MP_MUL_HIGH_DIGS_C\n  #define BN_FAST_S_MP_MUL_HIGH_DIGS_C\n  #define BN_MP_MOD_2D_C\n  #define BN_S_MP_MUL_DIGS_C\n  #define BN_MP_SUB_C\n  #define BN_MP_CMP_D_C\n  #define BN_MP_SET_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_ADD_C\n  #define BN_MP_CMP_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_REDUCE_2K_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_MUL_D_C\n  #define BN_S_MP_ADD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_REDUCE_2K_L_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_MUL_C\n  #define BN_S_MP_ADD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_REDUCE_2K_SETUP_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_2EXPT_C\n  #define BN_MP_CLEAR_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_REDUCE_2K_SETUP_L_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_2EXPT_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_REDUCE_IS_2K_C)\n  #define BN_MP_REDUCE_2K_C\n  #define BN_MP_COUNT_BITS_C\n #endif\n\n #if defined(BN_MP_REDUCE_IS_2K_L_C)\n #endif\n\n #if defined(BN_MP_REDUCE_SETUP_C)\n  #define BN_MP_2EXPT_C\n  #define BN_MP_DIV_C\n #endif\n\n #if defined(BN_MP_RSHD_C)\n  #define BN_MP_ZERO_C\n #endif\n\n #if defined(BN_MP_SET_C)\n  #define BN_MP_ZERO_C\n #endif\n\n #if defined(BN_MP_SET_INT_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_SET_LONG_C)\n #endif\n\n #if defined(BN_MP_SET_LONG_LONG_C)\n #endif\n\n #if defined(BN_MP_SHRINK_C)\n #endif\n\n #if defined(BN_MP_SIGNED_BIN_SIZE_C)\n  #define BN_MP_UNSIGNED_BIN_SIZE_C\n #endif\n\n #if defined(BN_MP_SQR_C)\n  #define BN_MP_TOOM_SQR_C\n  #define BN_MP_KARATSUBA_SQR_C\n  #define BN_FAST_S_MP_SQR_C\n  #define BN_S_MP_SQR_C\n #endif\n\n #if defined(BN_MP_SQRMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SQR_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MOD_C\n #endif\n\n #if defined(BN_MP_SQRT_C)\n  #define BN_MP_N_ROOT_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_DIV_C\n  #define BN_MP_ADD_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_SQRTMOD_PRIME_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_JACOBI_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_MOD_D_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_EXPTMOD_C\n  #define BN_MP_COPY_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_ISEVEN_C\n  #define BN_MP_SET_INT_C\n  #define BN_MP_SQRMOD_C\n  #define BN_MP_MULMOD_C\n  #define BN_MP_SET_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_SUB_C)\n  #define BN_S_MP_ADD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_SUB_D_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_SUBMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SUB_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MOD_C\n #endif\n\n #if defined(BN_MP_TO_SIGNED_BIN_C)\n  #define BN_MP_TO_UNSIGNED_BIN_C\n #endif\n\n #if defined(BN_MP_TO_SIGNED_BIN_N_C)\n  #define BN_MP_SIGNED_BIN_SIZE_C\n  #define BN_MP_TO_SIGNED_BIN_C\n #endif\n\n #if defined(BN_MP_TO_UNSIGNED_BIN_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_TO_UNSIGNED_BIN_N_C)\n  #define BN_MP_UNSIGNED_BIN_SIZE_C\n  #define BN_MP_TO_UNSIGNED_BIN_C\n #endif\n\n #if defined(BN_MP_TOOM_MUL_C)\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_MOD_2D_C\n  #define BN_MP_COPY_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_MUL_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_ADD_C\n  #define BN_MP_SUB_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_DIV_3_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_TOOM_SQR_C)\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_MOD_2D_C\n  #define BN_MP_COPY_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_SQR_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_ADD_C\n  #define BN_MP_SUB_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_DIV_3_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_TORADIX_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_DIV_D_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_S_RMAP_C\n #endif\n\n #if defined(BN_MP_TORADIX_N_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_DIV_D_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_S_RMAP_C\n #endif\n\n #if defined(BN_MP_UNSIGNED_BIN_SIZE_C)\n  #define BN_MP_COUNT_BITS_C\n #endif\n\n #if defined(BN_MP_XOR_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_ZERO_C)\n #endif\n\n #if defined(BN_PRIME_TAB_C)\n #endif\n\n #if defined(BN_REVERSE_C)\n #endif\n\n #if defined(BN_S_MP_ADD_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_S_MP_EXPTMOD_C)\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_INIT_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_REDUCE_SETUP_C\n  #define BN_MP_REDUCE_C\n  #define BN_MP_REDUCE_2K_SETUP_L_C\n  #define BN_MP_REDUCE_2K_L_C\n  #define BN_MP_MOD_C\n  #define BN_MP_COPY_C\n  #define BN_MP_SQR_C\n  #define BN_MP_MUL_C\n  #define BN_MP_SET_C\n  #define BN_MP_EXCH_C\n #endif\n\n #if defined(BN_S_MP_MUL_DIGS_C)\n  #define BN_FAST_S_MP_MUL_DIGS_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_S_MP_MUL_HIGH_DIGS_C)\n  #define BN_FAST_S_MP_MUL_HIGH_DIGS_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_S_MP_SQR_C)\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_S_MP_SUB_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BNCORE_C)\n #endif\n\n #ifdef LTM3\n  #define LTM_LAST\n #endif\n/* super class file for PK algos */\n\n/* default ... include all MPI */\n#define LTM_ALL\n\n/* RSA only (does not support DH/DSA/ECC) */\n/* #define SC_RSA_1 */\n\n/* For reference.... On an Athlon64 optimizing for speed...\n\n   LTM's mpi.o with all functions [striped] is 142KiB in size.\n\n */\n\n/* Works for RSA only, mpi.o is 68KiB */\n#ifdef SC_RSA_1\n #define BN_MP_SHRINK_C\n #define BN_MP_LCM_C\n #define BN_MP_PRIME_RANDOM_EX_C\n #define BN_MP_INVMOD_C\n #define BN_MP_GCD_C\n #define BN_MP_MOD_C\n #define BN_MP_MULMOD_C\n #define BN_MP_ADDMOD_C\n #define BN_MP_EXPTMOD_C\n #define BN_MP_SET_INT_C\n #define BN_MP_INIT_MULTI_C\n #define BN_MP_CLEAR_MULTI_C\n #define BN_MP_UNSIGNED_BIN_SIZE_C\n #define BN_MP_TO_UNSIGNED_BIN_C\n #define BN_MP_MOD_D_C\n #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C\n #define BN_REVERSE_C\n #define BN_PRIME_TAB_C\n\n/* other modifiers */\n #define BN_MP_DIV_SMALL    /* Slower division, not critical */\n\n/* here we are on the last pass so we turn things off.  The functions classes are still there\n * but we remove them specifically from the build.  This also invokes tweaks in functions\n * like removing support for even moduli, etc...\n */\n #ifdef LTM_LAST\n  #undef  BN_MP_TOOM_MUL_C\n  #undef  BN_MP_TOOM_SQR_C\n  #undef  BN_MP_KARATSUBA_MUL_C\n  #undef  BN_MP_KARATSUBA_SQR_C\n  #undef  BN_MP_REDUCE_C\n  #undef  BN_MP_REDUCE_SETUP_C\n  #undef  BN_MP_DR_IS_MODULUS_C\n  #undef  BN_MP_DR_SETUP_C\n  #undef  BN_MP_DR_REDUCE_C\n  #undef  BN_MP_REDUCE_IS_2K_C\n  #undef  BN_MP_REDUCE_2K_SETUP_C\n  #undef  BN_MP_REDUCE_2K_C\n  #undef  BN_S_MP_EXPTMOD_C\n  #undef  BN_MP_DIV_3_C\n  #undef  BN_S_MP_MUL_HIGH_DIGS_C\n  #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C\n  #undef  BN_FAST_MP_INVMOD_C\n\n/* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold\n * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines]\n * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without\n * trouble.\n */\n  #undef  BN_S_MP_MUL_DIGS_C\n  #undef  BN_S_MP_SQR_C\n  #undef  BN_MP_MONTGOMERY_REDUCE_C\n #endif\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */ \n#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))\n #if defined(LTM2)\n  #define LTM3\n #endif\n #if defined(LTM1)\n  #define LTM2\n #endif\n #define LTM1\n\n #if defined(LTM_ALL)\n  #define BN_ERROR_C\n  #define BN_FAST_MP_INVMOD_C\n  #define BN_FAST_MP_MONTGOMERY_REDUCE_C\n  #define BN_FAST_S_MP_MUL_DIGS_C\n  #define BN_FAST_S_MP_MUL_HIGH_DIGS_C\n  #define BN_FAST_S_MP_SQR_C\n  #define BN_MP_2EXPT_C\n  #define BN_MP_ABS_C\n  #define BN_MP_ADD_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_ADDMOD_C\n  #define BN_MP_AND_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_CLEAR_MULTI_C\n  #define BN_MP_CMP_C\n  #define BN_MP_CMP_D_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_CNT_LSB_C\n  #define BN_MP_COPY_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_DIV_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_DIV_3_C\n  #define BN_MP_DIV_D_C\n  #define BN_MP_DR_IS_MODULUS_C\n  #define BN_MP_DR_REDUCE_C\n  #define BN_MP_DR_SETUP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_EXPORT_C\n  #define BN_MP_EXPT_D_C\n  #define BN_MP_EXPT_D_EX_C\n  #define BN_MP_EXPTMOD_C\n  #define BN_MP_EXPTMOD_FAST_C\n  #define BN_MP_EXTEUCLID_C\n  #define BN_MP_FREAD_C\n  #define BN_MP_FWRITE_C\n  #define BN_MP_GCD_C\n  #define BN_MP_GET_INT_C\n  #define BN_MP_GET_LONG_C\n  #define BN_MP_GET_LONG_LONG_C\n  #define BN_MP_GROW_C\n  #define BN_MP_IMPORT_C\n  #define BN_MP_INIT_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_INIT_SET_C\n  #define BN_MP_INIT_SET_INT_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_INVMOD_C\n  #define BN_MP_INVMOD_SLOW_C\n  #define BN_MP_IS_SQUARE_C\n  #define BN_MP_JACOBI_C\n  #define BN_MP_KARATSUBA_MUL_C\n  #define BN_MP_KARATSUBA_SQR_C\n  #define BN_MP_LCM_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_MOD_C\n  #define BN_MP_MOD_2D_C\n  #define BN_MP_MOD_D_C\n  #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C\n  #define BN_MP_MONTGOMERY_REDUCE_C\n  #define BN_MP_MONTGOMERY_SETUP_C\n  #define BN_MP_MUL_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_MULMOD_C\n  #define BN_MP_N_ROOT_C\n  #define BN_MP_N_ROOT_EX_C\n  #define BN_MP_NEG_C\n  #define BN_MP_OR_C\n  #define BN_MP_PRIME_FERMAT_C\n  #define BN_MP_PRIME_IS_DIVISIBLE_C\n  #define BN_MP_PRIME_IS_PRIME_C\n  #define BN_MP_PRIME_MILLER_RABIN_C\n  #define BN_MP_PRIME_NEXT_PRIME_C\n  #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C\n  #define BN_MP_PRIME_RANDOM_EX_C\n  #define BN_MP_RADIX_SIZE_C\n  #define BN_MP_RADIX_SMAP_C\n  #define BN_MP_RAND_C\n  #define BN_MP_READ_RADIX_C\n  #define BN_MP_READ_SIGNED_BIN_C\n  #define BN_MP_READ_UNSIGNED_BIN_C\n  #define BN_MP_REDUCE_C\n  #define BN_MP_REDUCE_2K_C\n  #define BN_MP_REDUCE_2K_L_C\n  #define BN_MP_REDUCE_2K_SETUP_C\n  #define BN_MP_REDUCE_2K_SETUP_L_C\n  #define BN_MP_REDUCE_IS_2K_C\n  #define BN_MP_REDUCE_IS_2K_L_C\n  #define BN_MP_REDUCE_SETUP_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_SET_C\n  #define BN_MP_SET_INT_C\n  #define BN_MP_SET_LONG_C\n  #define BN_MP_SET_LONG_LONG_C\n  #define BN_MP_SHRINK_C\n  #define BN_MP_SIGNED_BIN_SIZE_C\n  #define BN_MP_SQR_C\n  #define BN_MP_SQRMOD_C\n  #define BN_MP_SQRT_C\n  #define BN_MP_SQRTMOD_PRIME_C\n  #define BN_MP_SUB_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_SUBMOD_C\n  #define BN_MP_TO_SIGNED_BIN_C\n  #define BN_MP_TO_SIGNED_BIN_N_C\n  #define BN_MP_TO_UNSIGNED_BIN_C\n  #define BN_MP_TO_UNSIGNED_BIN_N_C\n  #define BN_MP_TOOM_MUL_C\n  #define BN_MP_TOOM_SQR_C\n  #define BN_MP_TORADIX_C\n  #define BN_MP_TORADIX_N_C\n  #define BN_MP_UNSIGNED_BIN_SIZE_C\n  #define BN_MP_XOR_C\n  #define BN_MP_ZERO_C\n  #define BN_PRIME_TAB_C\n  #define BN_REVERSE_C\n  #define BN_S_MP_ADD_C\n  #define BN_S_MP_EXPTMOD_C\n  #define BN_S_MP_MUL_DIGS_C\n  #define BN_S_MP_MUL_HIGH_DIGS_C\n  #define BN_S_MP_SQR_C\n  #define BN_S_MP_SUB_C\n  #define BNCORE_C\n #endif\n\n #if defined(BN_ERROR_C)\n  #define BN_MP_ERROR_TO_STRING_C\n #endif\n\n #if defined(BN_FAST_MP_INVMOD_C)\n  #define BN_MP_ISEVEN_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_COPY_C\n  #define BN_MP_MOD_C\n  #define BN_MP_SET_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_ISODD_C\n  #define BN_MP_SUB_C\n  #define BN_MP_CMP_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_CMP_D_C\n  #define BN_MP_ADD_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_FAST_S_MP_MUL_DIGS_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_FAST_S_MP_SQR_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_2EXPT_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_GROW_C\n #endif\n\n #if defined(BN_MP_ABS_C)\n  #define BN_MP_COPY_C\n #endif\n\n #if defined(BN_MP_ADD_C)\n  #define BN_S_MP_ADD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_ADD_D_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_ADDMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_ADD_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MOD_C\n #endif\n\n #if defined(BN_MP_AND_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_CLAMP_C)\n #endif\n\n #if defined(BN_MP_CLEAR_C)\n #endif\n\n #if defined(BN_MP_CLEAR_MULTI_C)\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_CMP_C)\n  #define BN_MP_CMP_MAG_C\n #endif\n\n #if defined(BN_MP_CMP_D_C)\n #endif\n\n #if defined(BN_MP_CMP_MAG_C)\n #endif\n\n #if defined(BN_MP_CNT_LSB_C)\n  #define BN_MP_ISZERO_C\n #endif\n\n #if defined(BN_MP_COPY_C)\n  #define BN_MP_GROW_C\n #endif\n\n #if defined(BN_MP_COUNT_BITS_C)\n #endif\n\n #if defined(BN_MP_DIV_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_COPY_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_SET_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_ABS_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CMP_C\n  #define BN_MP_SUB_C\n  #define BN_MP_ADD_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_MULTI_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_INIT_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_DIV_2_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_DIV_2D_C)\n  #define BN_MP_COPY_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_INIT_C\n  #define BN_MP_MOD_2D_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n #endif\n\n #if defined(BN_MP_DIV_3_C)\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_DIV_D_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_COPY_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_DIV_3_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_DR_IS_MODULUS_C)\n #endif\n\n #if defined(BN_MP_DR_REDUCE_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_DR_SETUP_C)\n #endif\n\n #if defined(BN_MP_EXCH_C)\n #endif\n\n #if defined(BN_MP_EXPORT_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_EXPT_D_C)\n  #define BN_MP_EXPT_D_EX_C\n #endif\n\n #if defined(BN_MP_EXPT_D_EX_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_SET_C\n  #define BN_MP_MUL_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_SQR_C\n #endif\n\n #if defined(BN_MP_EXPTMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_INVMOD_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_ABS_C\n  #define BN_MP_CLEAR_MULTI_C\n  #define BN_MP_REDUCE_IS_2K_L_C\n  #define BN_S_MP_EXPTMOD_C\n  #define BN_MP_DR_IS_MODULUS_C\n  #define BN_MP_REDUCE_IS_2K_C\n  #define BN_MP_ISODD_C\n  #define BN_MP_EXPTMOD_FAST_C\n #endif\n\n #if defined(BN_MP_EXPTMOD_FAST_C)\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_INIT_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MONTGOMERY_SETUP_C\n  #define BN_FAST_MP_MONTGOMERY_REDUCE_C\n  #define BN_MP_MONTGOMERY_REDUCE_C\n  #define BN_MP_DR_SETUP_C\n  #define BN_MP_DR_REDUCE_C\n  #define BN_MP_REDUCE_2K_SETUP_C\n  #define BN_MP_REDUCE_2K_C\n  #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C\n  #define BN_MP_MULMOD_C\n  #define BN_MP_SET_C\n  #define BN_MP_MOD_C\n  #define BN_MP_COPY_C\n  #define BN_MP_SQR_C\n  #define BN_MP_MUL_C\n  #define BN_MP_EXCH_C\n #endif\n\n #if defined(BN_MP_EXTEUCLID_C)\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_SET_C\n  #define BN_MP_COPY_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_DIV_C\n  #define BN_MP_MUL_C\n  #define BN_MP_SUB_C\n  #define BN_MP_NEG_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_FREAD_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_S_RMAP_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_CMP_D_C\n #endif\n\n #if defined(BN_MP_FWRITE_C)\n  #define BN_MP_RADIX_SIZE_C\n  #define BN_MP_TORADIX_C\n #endif\n\n #if defined(BN_MP_GCD_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_ABS_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CNT_LSB_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_EXCH_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_GET_INT_C)\n #endif\n\n #if defined(BN_MP_GET_LONG_C)\n #endif\n\n #if defined(BN_MP_GET_LONG_LONG_C)\n #endif\n\n #if defined(BN_MP_GROW_C)\n #endif\n\n #if defined(BN_MP_IMPORT_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_INIT_C)\n #endif\n\n #if defined(BN_MP_INIT_COPY_C)\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_COPY_C\n #endif\n\n #if defined(BN_MP_INIT_MULTI_C)\n  #define BN_MP_ERR_C\n  #define BN_MP_INIT_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_INIT_SET_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SET_C\n #endif\n\n #if defined(BN_MP_INIT_SET_INT_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SET_INT_C\n #endif\n\n #if defined(BN_MP_INIT_SIZE_C)\n  #define BN_MP_INIT_C\n #endif\n\n #if defined(BN_MP_INVMOD_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_ISODD_C\n  #define BN_FAST_MP_INVMOD_C\n  #define BN_MP_INVMOD_SLOW_C\n #endif\n\n #if defined(BN_MP_INVMOD_SLOW_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_MOD_C\n  #define BN_MP_COPY_C\n  #define BN_MP_ISEVEN_C\n  #define BN_MP_SET_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_ISODD_C\n  #define BN_MP_ADD_C\n  #define BN_MP_SUB_C\n  #define BN_MP_CMP_C\n  #define BN_MP_CMP_D_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_IS_SQUARE_C)\n  #define BN_MP_MOD_D_C\n  #define BN_MP_INIT_SET_INT_C\n  #define BN_MP_MOD_C\n  #define BN_MP_GET_INT_C\n  #define BN_MP_SQRT_C\n  #define BN_MP_SQR_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_JACOBI_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CNT_LSB_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_MOD_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_KARATSUBA_MUL_C)\n  #define BN_MP_MUL_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_S_MP_ADD_C\n  #define BN_MP_ADD_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_KARATSUBA_SQR_C)\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_SQR_C\n  #define BN_S_MP_ADD_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_ADD_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_LCM_C)\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_GCD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_DIV_C\n  #define BN_MP_MUL_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_LSHD_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_RSHD_C\n #endif\n\n #if defined(BN_MP_MOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_DIV_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_ADD_C\n #endif\n\n #if defined(BN_MP_MOD_2D_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_COPY_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_MOD_D_C)\n  #define BN_MP_DIV_D_C\n #endif\n\n #if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_2EXPT_C\n  #define BN_MP_SET_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_MONTGOMERY_REDUCE_C)\n  #define BN_FAST_MP_MONTGOMERY_REDUCE_C\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_MONTGOMERY_SETUP_C)\n #endif\n\n #if defined(BN_MP_MUL_C)\n  #define BN_MP_TOOM_MUL_C\n  #define BN_MP_KARATSUBA_MUL_C\n  #define BN_FAST_S_MP_MUL_DIGS_C\n  #define BN_S_MP_MUL_C\n  #define BN_S_MP_MUL_DIGS_C\n #endif\n\n #if defined(BN_MP_MUL_2_C)\n  #define BN_MP_GROW_C\n #endif\n\n #if defined(BN_MP_MUL_2D_C)\n  #define BN_MP_COPY_C\n  #define BN_MP_GROW_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_MUL_D_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_MULMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_MUL_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MOD_C\n #endif\n\n #if defined(BN_MP_N_ROOT_C)\n  #define BN_MP_N_ROOT_EX_C\n #endif\n\n #if defined(BN_MP_N_ROOT_EX_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SET_C\n  #define BN_MP_COPY_C\n  #define BN_MP_EXPT_D_EX_C\n  #define BN_MP_MUL_C\n  #define BN_MP_SUB_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_DIV_C\n  #define BN_MP_CMP_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_NEG_C)\n  #define BN_MP_COPY_C\n  #define BN_MP_ISZERO_C\n #endif\n\n #if defined(BN_MP_OR_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_FERMAT_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_INIT_C\n  #define BN_MP_EXPTMOD_C\n  #define BN_MP_CMP_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_IS_DIVISIBLE_C)\n  #define BN_MP_MOD_D_C\n #endif\n\n #if defined(BN_MP_PRIME_IS_PRIME_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_PRIME_IS_DIVISIBLE_C\n  #define BN_MP_INIT_C\n  #define BN_MP_SET_C\n  #define BN_MP_PRIME_MILLER_RABIN_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_MILLER_RABIN_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_CNT_LSB_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_EXPTMOD_C\n  #define BN_MP_CMP_C\n  #define BN_MP_SQRMOD_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_NEXT_PRIME_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_SET_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_ISEVEN_C\n  #define BN_MP_MOD_D_C\n  #define BN_MP_INIT_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_PRIME_MILLER_RABIN_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)\n #endif\n\n #if defined(BN_MP_PRIME_RANDOM_EX_C)\n  #define BN_MP_READ_UNSIGNED_BIN_C\n  #define BN_MP_PRIME_IS_PRIME_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_ADD_D_C\n #endif\n\n #if defined(BN_MP_RADIX_SIZE_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_DIV_D_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_RADIX_SMAP_C)\n  #define BN_MP_S_RMAP_C\n #endif\n\n #if defined(BN_MP_RAND_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_LSHD_C\n #endif\n\n #if defined(BN_MP_READ_RADIX_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_S_RMAP_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_ISZERO_C\n #endif\n\n #if defined(BN_MP_READ_SIGNED_BIN_C)\n  #define BN_MP_READ_UNSIGNED_BIN_C\n #endif\n\n #if defined(BN_MP_READ_UNSIGNED_BIN_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_REDUCE_C)\n  #define BN_MP_REDUCE_SETUP_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_MUL_C\n  #define BN_S_MP_MUL_HIGH_DIGS_C\n  #define BN_FAST_S_MP_MUL_HIGH_DIGS_C\n  #define BN_MP_MOD_2D_C\n  #define BN_S_MP_MUL_DIGS_C\n  #define BN_MP_SUB_C\n  #define BN_MP_CMP_D_C\n  #define BN_MP_SET_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_ADD_C\n  #define BN_MP_CMP_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_REDUCE_2K_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_MUL_D_C\n  #define BN_S_MP_ADD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_REDUCE_2K_L_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_MUL_C\n  #define BN_S_MP_ADD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_REDUCE_2K_SETUP_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_2EXPT_C\n  #define BN_MP_CLEAR_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_REDUCE_2K_SETUP_L_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_2EXPT_C\n  #define BN_MP_COUNT_BITS_C\n  #define BN_S_MP_SUB_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_REDUCE_IS_2K_C)\n  #define BN_MP_REDUCE_2K_C\n  #define BN_MP_COUNT_BITS_C\n #endif\n\n #if defined(BN_MP_REDUCE_IS_2K_L_C)\n #endif\n\n #if defined(BN_MP_REDUCE_SETUP_C)\n  #define BN_MP_2EXPT_C\n  #define BN_MP_DIV_C\n #endif\n\n #if defined(BN_MP_RSHD_C)\n  #define BN_MP_ZERO_C\n #endif\n\n #if defined(BN_MP_SET_C)\n  #define BN_MP_ZERO_C\n #endif\n\n #if defined(BN_MP_SET_INT_C)\n  #define BN_MP_ZERO_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_SET_LONG_C)\n #endif\n\n #if defined(BN_MP_SET_LONG_LONG_C)\n #endif\n\n #if defined(BN_MP_SHRINK_C)\n #endif\n\n #if defined(BN_MP_SIGNED_BIN_SIZE_C)\n  #define BN_MP_UNSIGNED_BIN_SIZE_C\n #endif\n\n #if defined(BN_MP_SQR_C)\n  #define BN_MP_TOOM_SQR_C\n  #define BN_MP_KARATSUBA_SQR_C\n  #define BN_FAST_S_MP_SQR_C\n  #define BN_S_MP_SQR_C\n #endif\n\n #if defined(BN_MP_SQRMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SQR_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MOD_C\n #endif\n\n #if defined(BN_MP_SQRT_C)\n  #define BN_MP_N_ROOT_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_DIV_C\n  #define BN_MP_ADD_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_SQRTMOD_PRIME_C)\n  #define BN_MP_CMP_D_C\n  #define BN_MP_ZERO_C\n  #define BN_MP_JACOBI_C\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_MOD_D_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_EXPTMOD_C\n  #define BN_MP_COPY_C\n  #define BN_MP_SUB_D_C\n  #define BN_MP_ISEVEN_C\n  #define BN_MP_SET_INT_C\n  #define BN_MP_SQRMOD_C\n  #define BN_MP_MULMOD_C\n  #define BN_MP_SET_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_SUB_C)\n  #define BN_S_MP_ADD_C\n  #define BN_MP_CMP_MAG_C\n  #define BN_S_MP_SUB_C\n #endif\n\n #if defined(BN_MP_SUB_D_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_ADD_D_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_MP_SUBMOD_C)\n  #define BN_MP_INIT_C\n  #define BN_MP_SUB_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_MOD_C\n #endif\n\n #if defined(BN_MP_TO_SIGNED_BIN_C)\n  #define BN_MP_TO_UNSIGNED_BIN_C\n #endif\n\n #if defined(BN_MP_TO_SIGNED_BIN_N_C)\n  #define BN_MP_SIGNED_BIN_SIZE_C\n  #define BN_MP_TO_SIGNED_BIN_C\n #endif\n\n #if defined(BN_MP_TO_UNSIGNED_BIN_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_ISZERO_C\n  #define BN_MP_DIV_2D_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_TO_UNSIGNED_BIN_N_C)\n  #define BN_MP_UNSIGNED_BIN_SIZE_C\n  #define BN_MP_TO_UNSIGNED_BIN_C\n #endif\n\n #if defined(BN_MP_TOOM_MUL_C)\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_MOD_2D_C\n  #define BN_MP_COPY_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_MUL_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_ADD_C\n  #define BN_MP_SUB_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_DIV_3_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_TOOM_SQR_C)\n  #define BN_MP_INIT_MULTI_C\n  #define BN_MP_MOD_2D_C\n  #define BN_MP_COPY_C\n  #define BN_MP_RSHD_C\n  #define BN_MP_SQR_C\n  #define BN_MP_MUL_2_C\n  #define BN_MP_ADD_C\n  #define BN_MP_SUB_C\n  #define BN_MP_DIV_2_C\n  #define BN_MP_MUL_2D_C\n  #define BN_MP_MUL_D_C\n  #define BN_MP_DIV_3_C\n  #define BN_MP_LSHD_C\n  #define BN_MP_CLEAR_MULTI_C\n #endif\n\n #if defined(BN_MP_TORADIX_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_DIV_D_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_S_RMAP_C\n #endif\n\n #if defined(BN_MP_TORADIX_N_C)\n  #define BN_MP_ISZERO_C\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_DIV_D_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_S_RMAP_C\n #endif\n\n #if defined(BN_MP_UNSIGNED_BIN_SIZE_C)\n  #define BN_MP_COUNT_BITS_C\n #endif\n\n #if defined(BN_MP_XOR_C)\n  #define BN_MP_INIT_COPY_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_MP_ZERO_C)\n #endif\n\n #if defined(BN_PRIME_TAB_C)\n #endif\n\n #if defined(BN_REVERSE_C)\n #endif\n\n #if defined(BN_S_MP_ADD_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BN_S_MP_EXPTMOD_C)\n  #define BN_MP_COUNT_BITS_C\n  #define BN_MP_INIT_C\n  #define BN_MP_CLEAR_C\n  #define BN_MP_REDUCE_SETUP_C\n  #define BN_MP_REDUCE_C\n  #define BN_MP_REDUCE_2K_SETUP_L_C\n  #define BN_MP_REDUCE_2K_L_C\n  #define BN_MP_MOD_C\n  #define BN_MP_COPY_C\n  #define BN_MP_SQR_C\n  #define BN_MP_MUL_C\n  #define BN_MP_SET_C\n  #define BN_MP_EXCH_C\n #endif\n\n #if defined(BN_S_MP_MUL_DIGS_C)\n  #define BN_FAST_S_MP_MUL_DIGS_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_S_MP_MUL_HIGH_DIGS_C)\n  #define BN_FAST_S_MP_MUL_HIGH_DIGS_C\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_S_MP_SQR_C)\n  #define BN_MP_INIT_SIZE_C\n  #define BN_MP_CLAMP_C\n  #define BN_MP_EXCH_C\n  #define BN_MP_CLEAR_C\n #endif\n\n #if defined(BN_S_MP_SUB_C)\n  #define BN_MP_GROW_C\n  #define BN_MP_CLAMP_C\n #endif\n\n #if defined(BNCORE_C)\n #endif\n\n #ifdef LTM3\n  #define LTM_LAST\n #endif\n#else\n #define LTM_LAST\n#endif \n#else\n #define LTM_LAST\n#endif \n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* detect 64-bit mode if possible */\n#if defined(__x86_64__)\n #if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT))\n  #define MP_64BIT\n #endif\n#endif\n\n/* some default configurations.\n *\n * A \"mp_digit\" must be able to hold DIGIT_BIT + 1 bits\n * A \"mp_word\" must be able to hold 2*DIGIT_BIT + 1 bits\n *\n * At the very least a mp_digit must be able to hold 7 bits\n * [any size beyond that is ok provided it doesn't overflow the data type]\n */\n#ifdef MP_8BIT\ntypedef uint8_t    mp_digit;\ntypedef uint16_t   mp_word;\n #define MP_SIZEOF_MP_DIGIT    1\n #ifdef DIGIT_BIT\n  #error You must not define DIGIT_BIT when using MP_8BIT\n #endif\n#elif defined(MP_16BIT)\ntypedef uint16_t   mp_digit;\ntypedef uint32_t   mp_word;\n #define MP_SIZEOF_MP_DIGIT    2\n #ifdef DIGIT_BIT\n  #error You must not define DIGIT_BIT when using MP_16BIT\n #endif\n#elif defined(MP_64BIT)\n/* for GCC only on supported platforms */\n #ifndef CRYPT\ntypedef unsigned long long   ulong64;\ntypedef signed long long     long64;\n #endif\n\ntypedef uint64_t             mp_digit;\n #if defined(_WIN32)\ntypedef unsigned __int128    mp_word;\n #elif defined(__GNUC__)\ntypedef unsigned long        mp_word __attribute__ ((mode(TI)));\n #else\n\n/* it seems you have a problem\n * but we assume you can somewhere define your own uint128_t */\ntypedef uint128_t            mp_word;\n #endif\n\n #define DIGIT_BIT    60\n#else\n/* this is the default case, 28-bit digits */\n\n/* this is to make porting into LibTomCrypt easier :-) */\n #ifndef CRYPT\ntypedef unsigned long long   ulong64;\ntypedef signed long long     long64;\n #endif\n\ntypedef uint32_t             mp_digit;\ntypedef uint64_t             mp_word;\n\n #ifdef MP_31BIT\n/* this is an extension that uses 31-bit digits */\n  #define DIGIT_BIT    31\n #else\n/* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */\n  #define DIGIT_BIT    28\n  #define MP_28BIT\n #endif\n#endif\n\n/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */\n#ifndef DIGIT_BIT\n #define DIGIT_BIT    (((CHAR_BIT * MP_SIZEOF_MP_DIGIT) - 1))     /* bits per digit */\ntypedef uint_least32_t   mp_min_u32;\n#else\ntypedef mp_digit         mp_min_u32;\n#endif\n\n/* use our internal implementation of alleged alleged rc4 */\n#define MP_GEN_RANDOM        aarc4random_maybe\n\n#define MP_DIGIT_BIT         DIGIT_BIT\n#define MP_MASK              ((((mp_digit)1) << ((mp_digit)DIGIT_BIT)) - ((mp_digit)1))\n#define MP_DIGIT_MAX         MP_MASK\n\n/* equalities */\n#define MP_LT                -1 /* less than */\n#define MP_EQ                0  /* equal to */\n#define MP_GT                1  /* greater than */\n\n#define MP_ZPOS              0  /* positive integer */\n#define MP_NEG               1  /* negative */\n\n#define MP_OKAY              0  /* ok result */\n#define MP_MEM               -2 /* out of mem */\n#define MP_VAL               -3 /* invalid input */\n#define MP_RANGE             MP_VAL\n\n#define MP_YES               1 /* yes response */\n#define MP_NO                0 /* no response */\n\n/* Primality generation flags */\n#define LTM_PRIME_BBS        0x0001 /* BBS style prime */\n#define LTM_PRIME_SAFE       0x0002 /* Safe prime (p-1)/2 == prime */\n#define LTM_PRIME_2MSB_ON    0x0008 /* force 2nd MSB to 1 */\n\ntypedef int   mp_err;\n\n/* you'll have to tune these... */\nextern int KARATSUBA_MUL_CUTOFF,\n           KARATSUBA_SQR_CUTOFF,\n           TOOM_MUL_CUTOFF,\n           TOOM_SQR_CUTOFF;\n\n/* define this to use lower memory usage routines (exptmods mostly) */\n/* #define MP_LOW_MEM */\n\n/* default precision */\n#ifndef MP_PREC\n #ifndef MP_LOW_MEM\n  #define MP_PREC    32                      /* default digits of precision */\n #else\n  #define MP_PREC    8                       /* default digits of precision */\n #endif\n#endif\n\n/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */\n#define MP_WARRAY    (1 << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT)) + 1))\n\n/* the infamous mp_int structure */\ntypedef struct  {\n    int      used, alloc, sign;\n    mp_digit *dp;\n} mp_int;\n\n/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */\ntypedef int ltm_prime_callback (unsigned char *dst, int len, void *dat);\n\n\n#define USED(m)        ((m)->used)\n#define DIGIT(m, k)    ((m)->dp[(k)])\n#define SIGN(m)        ((m)->sign)\n\n/* error code to char* string */\nconst char *mp_error_to_string(int code);\n\n/* ---> init and deinit bignum functions <--- */\n/* init a bignum */\nint mp_init(mp_int *a);\n\n/* free a bignum */\nvoid mp_clear(mp_int *a);\n\n/* init a null terminated series of arguments */\nint mp_init_multi(mp_int *mp, ...);\n\n/* clear a null terminated series of arguments */\nvoid mp_clear_multi(mp_int *mp, ...);\n\n/* exchange two ints */\nvoid mp_exch(mp_int *a, mp_int *b);\n\n/* shrink ram required for a bignum */\nint mp_shrink(mp_int *a);\n\n/* grow an int to a given size */\nint mp_grow(mp_int *a, int size);\n\n/* init to a given number of digits */\nint mp_init_size(mp_int *a, int size);\n\n/* ---> Basic Manipulations <--- */\n#define mp_iszero(a)    (((a)->used == 0) ? MP_YES : MP_NO)\n#define mp_iseven(a)    ((((a)->used > 0) && (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO)\n#define mp_isodd(a)     ((((a)->used > 0) && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO)\n#define mp_isneg(a)     (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)\n\n/* set to zero */\nvoid mp_zero(mp_int *a);\n\n/* set to a digit */\nvoid mp_set(mp_int *a, mp_digit b);\n\n/* set a 32-bit const */\nint mp_set_int(mp_int *a, unsigned long b);\n\n/* set a platform dependent unsigned long value */\nint mp_set_long(mp_int *a, unsigned long b);\n\n/* set a platform dependent unsigned long long value */\nint mp_set_long_long(mp_int *a, unsigned long long b);\n\n/* get a 32-bit value */\nunsigned long mp_get_int(mp_int *a);\n\n/* get a platform dependent unsigned long value */\nunsigned long mp_get_long(mp_int *a);\n\n/* get a platform dependent unsigned long long value */\nunsigned long long mp_get_long_long(mp_int *a);\n\n/* initialize and set a digit */\nint mp_init_set(mp_int *a, mp_digit b);\n\n/* initialize and set 32-bit value */\nint mp_init_set_int(mp_int *a, unsigned long b);\n\n/* copy, b = a */\nint mp_copy(mp_int *a, mp_int *b);\n\n/* inits and copies, a = b */\nint mp_init_copy(mp_int *a, mp_int *b);\n\n/* trim unused digits */\nvoid mp_clamp(mp_int *a);\n\n/* import binary data */\nint mp_import(mp_int *rop, size_t count, int order, size_t size, int endian, size_t nails, const void *op);\n\n/* export binary data */\nint mp_export(void *rop, size_t *countp, int order, size_t size, int endian, size_t nails, mp_int *op);\n\n/* ---> digit manipulation <--- */\n\n/* right shift by \"b\" digits */\nvoid mp_rshd(mp_int *a, int b);\n\n/* left shift by \"b\" digits */\nint mp_lshd(mp_int *a, int b);\n\n/* c = a / 2**b, implemented as c = a >> b */\nint mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);\n\n/* b = a/2 */\nint mp_div_2(mp_int *a, mp_int *b);\n\n/* c = a * 2**b, implemented as c = a << b */\nint mp_mul_2d(mp_int *a, int b, mp_int *c);\n\n/* b = a*2 */\nint mp_mul_2(mp_int *a, mp_int *b);\n\n/* c = a mod 2**b */\nint mp_mod_2d(mp_int *a, int b, mp_int *c);\n\n/* computes a = 2**b */\nint mp_2expt(mp_int *a, int b);\n\n/* Counts the number of lsbs which are zero before the first zero bit */\nint mp_cnt_lsb(mp_int *a);\n\n/* I Love Earth! */\n\n/* makes a pseudo-random int of a given size */\nint mp_rand(mp_int *a, int digits);\n\n/* ---> binary operations <--- */\n/* c = a XOR b  */\nint mp_xor(mp_int *a, mp_int *b, mp_int *c);\n\n/* c = a OR b */\nint mp_or(mp_int *a, mp_int *b, mp_int *c);\n\n/* c = a AND b */\nint mp_and(mp_int *a, mp_int *b, mp_int *c);\n\n/* ---> Basic arithmetic <--- */\n\n/* b = -a */\nint mp_neg(mp_int *a, mp_int *b);\n\n/* b = |a| */\nint mp_abs(mp_int *a, mp_int *b);\n\n/* compare a to b */\nint mp_cmp(mp_int *a, mp_int *b);\n\n/* compare |a| to |b| */\nint mp_cmp_mag(mp_int *a, mp_int *b);\n\n/* c = a + b */\nint mp_add(mp_int *a, mp_int *b, mp_int *c);\n\n/* c = a - b */\nint mp_sub(mp_int *a, mp_int *b, mp_int *c);\n\n/* c = a * b */\nint mp_mul(mp_int *a, mp_int *b, mp_int *c);\n\n/* b = a*a  */\nint mp_sqr(mp_int *a, mp_int *b);\n\n/* a/b => cb + d == a */\nint mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);\n\n/* c = a mod b, 0 <= c < b  */\nint mp_mod(mp_int *a, mp_int *b, mp_int *c);\n\n/* ---> single digit functions <--- */\n\n/* compare against a single digit */\nint mp_cmp_d(mp_int *a, mp_digit b);\n\n/* c = a + b */\nint mp_add_d(mp_int *a, mp_digit b, mp_int *c);\n\n/* c = a - b */\nint mp_sub_d(mp_int *a, mp_digit b, mp_int *c);\n\n/* c = a * b */\nint mp_mul_d(mp_int *a, mp_digit b, mp_int *c);\n\n/* a/b => cb + d == a */\nint mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);\n\n/* a/3 => 3c + d == a */\nint mp_div_3(mp_int *a, mp_int *c, mp_digit *d);\n\n/* c = a**b */\nint mp_expt_d(mp_int *a, mp_digit b, mp_int *c);\nint mp_expt_d_ex(mp_int *a, mp_digit b, mp_int *c, int fast);\n\n/* c = a mod b, 0 <= c < b  */\nint mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);\n\n/* ---> number theory <--- */\n\n/* d = a + b (mod c) */\nint mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);\n\n/* d = a - b (mod c) */\nint mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);\n\n/* d = a * b (mod c) */\nint mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);\n\n/* c = a * a (mod b) */\nint mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);\n\n/* c = 1/a (mod b) */\nint mp_invmod(mp_int *a, mp_int *b, mp_int *c);\n\n/* c = (a, b) */\nint mp_gcd(mp_int *a, mp_int *b, mp_int *c);\n\n/* produces value such that U1*a + U2*b = U3 */\nint mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);\n\n/* c = [a, b] or (a*b)/(a, b) */\nint mp_lcm(mp_int *a, mp_int *b, mp_int *c);\n\n/* finds one of the b'th root of a, such that |c|**b <= |a|\n *\n * returns error if a < 0 and b is even\n */\nint mp_n_root(mp_int *a, mp_digit b, mp_int *c);\nint mp_n_root_ex(mp_int *a, mp_digit b, mp_int *c, int fast);\n\n/* special sqrt algo */\nint mp_sqrt(mp_int *arg, mp_int *ret);\n\n/* special sqrt (mod prime) */\nint mp_sqrtmod_prime(mp_int *arg, mp_int *prime, mp_int *ret);\n\n/* is number a square? */\nint mp_is_square(mp_int *arg, int *ret);\n\n/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */\nint mp_jacobi(mp_int *a, mp_int *n, int *c);\n\n/* used to setup the Barrett reduction for a given modulus b */\nint mp_reduce_setup(mp_int *a, mp_int *b);\n\n/* Barrett Reduction, computes a (mod b) with a precomputed value c\n *\n * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely\n * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].\n */\nint mp_reduce(mp_int *a, mp_int *b, mp_int *c);\n\n/* setups the montgomery reduction */\nint mp_montgomery_setup(mp_int *a, mp_digit *mp);\n\n/* computes a = B**n mod b without division or multiplication useful for\n * normalizing numbers in a Montgomery system.\n */\nint mp_montgomery_calc_normalization(mp_int *a, mp_int *b);\n\n/* computes x/R == x (mod N) via Montgomery Reduction */\nint mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);\n\n/* returns 1 if a is a valid DR modulus */\nint mp_dr_is_modulus(mp_int *a);\n\n/* sets the value of \"d\" required for mp_dr_reduce */\nvoid mp_dr_setup(mp_int *a, mp_digit *d);\n\n/* reduces a modulo b using the Diminished Radix method */\nint mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);\n\n/* returns true if a can be reduced with mp_reduce_2k */\nint mp_reduce_is_2k(mp_int *a);\n\n/* determines k value for 2k reduction */\nint mp_reduce_2k_setup(mp_int *a, mp_digit *d);\n\n/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */\nint mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);\n\n/* returns true if a can be reduced with mp_reduce_2k_l */\nint mp_reduce_is_2k_l(mp_int *a);\n\n/* determines k value for 2k reduction */\nint mp_reduce_2k_setup_l(mp_int *a, mp_int *d);\n\n/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */\nint mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);\n\n/* d = a**b (mod c) */\nint mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);\n\n/* ---> Primes <--- */\n\n/* number of primes */\n#ifdef MP_8BIT\n #define PRIME_SIZE    31\n#else\n #define PRIME_SIZE    256\n#endif\n\n/* table of first PRIME_SIZE primes */\nextern const mp_digit ltm_prime_tab[PRIME_SIZE];\n\n/* result=1 if a is divisible by one of the first PRIME_SIZE primes */\nint mp_prime_is_divisible(mp_int *a, int *result);\n\n/* performs one Fermat test of \"a\" using base \"b\".\n * Sets result to 0 if composite or 1 if probable prime\n */\nint mp_prime_fermat(mp_int *a, mp_int *b, int *result);\n\n/* performs one Miller-Rabin test of \"a\" using base \"b\".\n * Sets result to 0 if composite or 1 if probable prime\n */\nint mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);\n\n/* This gives [for a given bit size] the number of trials required\n * such that Miller-Rabin gives a prob of failure lower than 2^-96\n */\nint mp_prime_rabin_miller_trials(int size);\n\n/* performs t rounds of Miller-Rabin on \"a\" using the first\n * t prime bases.  Also performs an initial sieve of trial\n * division.  Determines if \"a\" is prime with probability\n * of error no more than (1/4)**t.\n *\n * Sets result to 1 if probably prime, 0 otherwise\n */\nint mp_prime_is_prime(mp_int *a, int t, int *result);\n\n/* finds the next prime after the number \"a\" using \"t\" trials\n * of Miller-Rabin.\n *\n * bbs_style = 1 means the prime must be congruent to 3 mod 4\n */\nint mp_prime_next_prime(mp_int *a, int t, int bbs_style);\n\n/* makes a truly random prime of a given size (bytes),\n * call with bbs = 1 if you want it to be congruent to 3 mod 4\n *\n * You have to supply a callback which fills in a buffer with random bytes.  \"dat\" is a parameter you can\n * have passed to the callback (e.g. a state or something).  This function doesn't use \"dat\" itself\n * so it can be NULL\n *\n * The prime generated will be larger than 2^(8*size).\n */\n#define mp_prime_random(a, t, size, bbs, cb, dat)    mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs == 1) ? LTM_PRIME_BBS : 0, cb, dat)\n\n/* makes a truly random prime of a given size (bits),\n *\n * Flags are as follows:\n *\n *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4\n *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)\n *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one\n *\n * You have to supply a callback which fills in a buffer with random bytes.  \"dat\" is a parameter you can\n * have passed to the callback (e.g. a state or something).  This function doesn't use \"dat\" itself\n * so it can be NULL\n *\n */\nint mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);\n\n/* ---> radix conversion <--- */\nint mp_count_bits(mp_int *a);\n\nint mp_unsigned_bin_size(mp_int *a);\nint mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);\nint mp_to_unsigned_bin(mp_int *a, unsigned char *b);\nint mp_to_unsigned_bin_n(mp_int *a, unsigned char *b, unsigned long *outlen);\n\nint mp_signed_bin_size(mp_int *a);\nint mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);\nint mp_to_signed_bin(mp_int *a, unsigned char *b);\nint mp_to_signed_bin_n(mp_int *a, unsigned char *b, unsigned long *outlen);\n\nint mp_read_radix(mp_int *a, const char *str, int radix);\nint mp_toradix(mp_int *a, char *str, int radix);\nint mp_toradix_n(mp_int *a, char *str, int radix, int maxlen);\nint mp_radix_size(mp_int *a, int radix, int *size);\n\n#ifndef LTM_NO_FILE\nint mp_fread(mp_int *a, int radix, FILE *stream);\nint mp_fwrite(mp_int *a, int radix, FILE *stream);\n#endif\n\n#define mp_read_raw(mp, str, len)    mp_read_signed_bin((mp), (str), (len))\n#define mp_raw_size(mp)              mp_signed_bin_size(mp)\n#define mp_toraw(mp, str)            mp_to_signed_bin((mp), (str))\n#define mp_read_mag(mp, str, len)    mp_read_unsigned_bin((mp), (str), (len))\n#define mp_mag_size(mp)              mp_unsigned_bin_size(mp)\n#define mp_tomag(mp, str)            mp_to_unsigned_bin((mp), (str))\n\n#define mp_tobinary(M, S)            mp_toradix((M), (S), 2)\n#define mp_tooctal(M, S)             mp_toradix((M), (S), 8)\n#define mp_todecimal(M, S)           mp_toradix((M), (S), 10)\n#define mp_tohex(M, S)               mp_toradix((M), (S), 16)\n\n#ifdef __cplusplus\n}\n#endif\n#endif\n\n/*\n * \"Allegedly\" Arc4 random number generator for OpenBSD.\n * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.\n * Minor modifications by Cameron Kaiser for Crypto Ancienne.\n *\n * Modification and redistribution in source and binary forms is\n * permitted provided that due credit is given to the author and the\n * OpenBSD project by leaving this copyright notice intact.\n *\n * This code is derived from section 17.1 of Applied Cryptography,\n * second edition, which describes a stream cipher allegedly\n * compatible with RSA Labs \"RC4\" cipher (the actual description of\n * which is a trade secret).  The same algorithm is used as a stream\n * cipher called \"arcfour\" in Tatu Ylonen's ssh package.\n *\n * RC4 is a registered trademark of RSA Laboratories.\n */\nstruct aarc4_stream {\n\tuint8_t i;\n\tuint8_t j;\n\tuint8_t s[256];\n};\nstatic int rs_initialized = 0;\nstatic struct aarc4_stream rs;\nstatic int aarc4_count;\nstatic int aarc4_use_dev_urandom = -1;\n\nstatic void\naarc4_init(struct aarc4_stream *as)\n{\n\tint n;\n\tfor (n = 0; n < 256; n++)\n\t\tas->s[n] = n;\n\tas->i = 0;\n\tas->j = 0;\n}\nstatic void\naarc4_addrandom(struct aarc4_stream *as, unsigned char *dat, int datlen)\n{\n\tint n;\n\tuint8_t si;\n\tas->i--;\n\tfor (n = 0; n < 256; n++) {\n\t\tas->i = (as->i + 1);\n\t\tsi = as->s[as->i];\n\t\tas->j = (as->j + si + dat[n % datlen]);\n\t\tas->s[as->i] = as->s[as->j];\n\t\tas->s[as->j] = si;\n\t}\n\tas->j = as->i;\n}\nstatic uint8_t\naarc4_getbyte(struct aarc4_stream *as)\n{\n\tuint8_t si, sj;\n\tas->i = (as->i + 1);\n\tsi = as->s[as->i];\n\tas->j = (as->j + si);\n\tsj = as->s[as->j];\n\tas->s[as->i] = sj;\n\tas->s[as->j] = si;\n\treturn (as->s[(si + sj) & 0xff]);\n}\nstatic uint32_t\naarc4_getword(struct aarc4_stream *as)\n{\n\tuint32_t val;\n\tval  = aarc4_getbyte(as) << 24;\n\tval |= aarc4_getbyte(as) << 16;\n\tval |= aarc4_getbyte(as) << 8;\n\tval |= aarc4_getbyte(as);\n\treturn val;\n}\nstatic void\naarc4_stir(struct aarc4_stream *as)\n{\n\tFILE *f;\n\tstruct {\n\t\tstruct timeval tv;\n\t\tunsigned int rnd[(128 - sizeof(struct timeval)) /\n\t\t\tsizeof(unsigned int)];\n\t}       rdat;\n\tint n;\n\n        /* \n         * The systems we specialize in almost all lack OS-provided RNGs.\n         * Time of day is used as a weak source of entropy in that case;\n         * we could probably add a PRNGD client in here as well.\n         * Still, if /dev/urandom exists, smoke 'em if you got 'em.\n         */\n\tgettimeofday(&rdat.tv, NULL);\n\tif (aarc4_use_dev_urandom != 0) {\n\t\tf = fopen(\"/dev/urandom\", \"rb\");\n\t\tif (f) {\n\t\t\taarc4_use_dev_urandom = 1;\n\t\t\tn = fread(&rdat.rnd, sizeof(rdat.rnd), 1, f);\n\t\t\tfclose(f);\n\t\t} else {\n\t\t\t/* Don't waste time checking again. */\n\t\t\taarc4_use_dev_urandom = 0;\n\t\t}\n\t}\n\taarc4_addrandom(as, (void *) &rdat, sizeof(rdat));\n\n\t/*\n\t * Throw away the first N words of output, as suggested in the\n\t * paper \"Weaknesses in the Key Scheduling Algorithm of RC4\"\n\t * by Fluher, Mantin, and Shamir.  (N = 256 in our case.)\n\t */\n\tfor (n = 0; n < 256 * 4; n++)\n\t\taarc4_getbyte(as);\n\taarc4_count = 1600000;\n}\nvoid\naarc4random_stir()\n{\n\tif (!rs_initialized) {\n\t\taarc4_init(&rs);\n\t\trs_initialized = 1;\n\t}\n\taarc4_stir(&rs);\n}\nvoid\naarc4random_addrandom(unsigned char *dat, int datlen)\n{\n\tif (!rs_initialized)\n\t\taarc4random_stir();\n\taarc4_addrandom(&rs, dat, datlen);\n}\nuint32_t\naarc4random_maybe()\n{\n        /* I thought about having this read /dev/random, but there are\n           just too many questions about it depending on system version. */\n\n\taarc4_count -= 4;\n\tif (!rs_initialized || aarc4_count <= 0)\n\t\taarc4random_stir();\n\treturn aarc4_getword(&rs);\n}\n\nsize_t\naarc4random_batch_maybe(unsigned char *out, unsigned long outlen)\n{\n\t/* A batch version of the above. */\n\tsize_t i;\n\n\taarc4_count -= outlen;\n\tif (!rs_initialized || aarc4_count <= outlen)\n\t\taarc4random_stir();\n\tfor (i=0; i<outlen; i++) {\n\t\tout[i] = aarc4_getbyte(&rs);\n\t}\n\treturn outlen;\n}\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */ \n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://math.libtomcrypt.com\n */\n#ifndef TOMMATH_PRIV_H_\n#define TOMMATH_PRIV_H_\n\n#include <ctype.h>\n\n#define TOM_MIN(x, y)    (((x) < (y)) ? (x) : (y))\n\n#define TOM_MAX(x, y)    (((x) > (y)) ? (x) : (y))\n\n#ifdef __cplusplus\nextern \"C\" {\n/* C++ compilers don't like assigning void * to mp_digit * */\n #define  OPT_CAST(x)    (x *)\n\n#else\n\n/* C on the other hand doesn't care */\n #define  OPT_CAST(x)\n#endif\n\n/* define heap macros */\n#ifndef XMALLOC\n/* default to libc stuff */\n #define XMALLOC     malloc\n #define XFREE       free\n#ifndef XREALLOC\n #define XREALLOC    realloc\n#endif\n #define XCALLOC     calloc\n#else\n/* prototypes for our heap functions */\nextern void *XMALLOC(size_t n);\nextern void *XREALLOC(void *p, size_t n);\nextern void *XCALLOC(size_t n, size_t s);\nextern void XFREE(void *p);\n#endif\n\n/* lowlevel functions, do not call! */\nint s_mp_add(mp_int *a, mp_int *b, mp_int *c);\nint s_mp_sub(mp_int *a, mp_int *b, mp_int *c);\n\n#define s_mp_mul(a, b, c)    s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)\nint fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);\nint s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);\nint fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);\nint s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);\nint fast_s_mp_sqr(mp_int *a, mp_int *b);\nint s_mp_sqr(mp_int *a, mp_int *b);\nint mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);\nint mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);\nint mp_karatsuba_sqr(mp_int *a, mp_int *b);\nint mp_toom_sqr(mp_int *a, mp_int *b);\nint fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);\nint mp_invmod_slow(mp_int *a, mp_int *b, mp_int *c);\nint fast_mp_montgomery_reduce(mp_int *x, mp_int *n, mp_digit rho);\nint mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int redmode);\nint s_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int redmode);\nvoid bn_reverse(unsigned char *s, int len);\n\nextern const char *mp_s_rmap;\n\n/* Fancy macro to set an MPI from another type.\n * There are several things assumed:\n *  x is the counter and unsigned\n *  a is the pointer to the MPI\n *  b is the original value that should be set in the MPI.\n */\n#define MP_SET_XLONG(func_name, type)                            \\\n    int func_name(mp_int * a, type b)                            \\\n    {                                                            \\\n        unsigned int x;                                          \\\n        int          res;                                        \\\n                                                                 \\\n        mp_zero(a);                                              \\\n                                                                 \\\n        /* set four bits at a time */                            \\\n        for (x = 0; x < (sizeof(type) * 2u); x++) {              \\\n            /* shift the number up four bits */                  \\\n            if ((res = mp_mul_2d(a, 4, a)) != MP_OKAY) {         \\\n                return res;                                      \\\n            }                                                    \\\n                                                                 \\\n            /* OR in the top four bits of the source */          \\\n            a->dp[0] |= (b >> ((sizeof(type) * 8u) - 4u)) & 15u; \\\n                                                                 \\\n            /* shift the source up to the next four bits */      \\\n            b <<= 4;                                             \\\n                                                                 \\\n            /* ensure that digits are not clamped off */         \\\n            a->used += 1;                                        \\\n        }                                                        \\\n        mp_clamp(a);                                             \\\n        return MP_OKAY;                                          \\\n    }\n\n#ifdef __cplusplus\n}\n#endif\n#endif\n\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */ \n\n#define BN_FAST_MP_INVMOD_C\n#ifdef BN_FAST_MP_INVMOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* computes the modular inverse via binary extended euclidean algorithm,\n * that is c = 1/a mod b\n *\n * Based on slow invmod except this is optimized for the case where b is\n * odd as per HAC Note 14.64 on pp. 610\n */\nint fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c) {\n    mp_int x, y, u, v, B, D;\n    int    res, neg;\n\n    /* 2. [modified] b must be odd   */\n    if (mp_iseven(b) == MP_YES) {\n        return MP_VAL;\n    }\n\n    /* init all our temps */\n    if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {\n        return res;\n    }\n\n    /* x == modulus, y == value to invert */\n    if ((res = mp_copy(b, &x)) != MP_OKAY) {\n        goto LBL_ERR;\n    }\n\n    /* we need y = |a| */\n    if ((res = mp_mod(a, b, &y)) != MP_OKAY) {\n        goto LBL_ERR;\n    }\n\n    /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */\n    if ((res = mp_copy(&x, &u)) != MP_OKAY) {\n        goto LBL_ERR;\n    }\n    if ((res = mp_copy(&y, &v)) != MP_OKAY) {\n        goto LBL_ERR;\n    }\n    mp_set(&D, 1);\n\ntop:\n    /* 4.  while u is even do */\n    while (mp_iseven(&u) == MP_YES) {\n        /* 4.1 u = u/2 */\n        if ((res = mp_div_2(&u, &u)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n        /* 4.2 if B is odd then */\n        if (mp_isodd(&B) == MP_YES) {\n            if ((res = mp_sub(&B, &x, &B)) != MP_OKAY) {\n                goto LBL_ERR;\n            }\n        }\n        /* B = B/2 */\n        if ((res = mp_div_2(&B, &B)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* 5.  while v is even do */\n    while (mp_iseven(&v) == MP_YES) {\n        /* 5.1 v = v/2 */\n        if ((res = mp_div_2(&v, &v)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n        /* 5.2 if D is odd then */\n        if (mp_isodd(&D) == MP_YES) {\n            /* D = (D-x)/2 */\n            if ((res = mp_sub(&D, &x, &D)) != MP_OKAY) {\n                goto LBL_ERR;\n            }\n        }\n        /* D = D/2 */\n        if ((res = mp_div_2(&D, &D)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* 6.  if u >= v then */\n    if (mp_cmp(&u, &v) != MP_LT) {\n        /* u = u - v, B = B - D */\n        if ((res = mp_sub(&u, &v, &u)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n\n        if ((res = mp_sub(&B, &D, &B)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    } else {\n        /* v - v - u, D = D - B */\n        if ((res = mp_sub(&v, &u, &v)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n\n        if ((res = mp_sub(&D, &B, &D)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* if not zero goto step 4 */\n    if (mp_iszero(&u) == MP_NO) {\n        goto top;\n    }\n\n    /* now a = C, b = D, gcd == g*v */\n\n    /* if v != 1 then there is no inverse */\n    if (mp_cmp_d(&v, 1) != MP_EQ) {\n        res = MP_VAL;\n        goto LBL_ERR;\n    }\n\n    /* b is now the inverse */\n    neg = a->sign;\n    while (D.sign == MP_NEG) {\n        if ((res = mp_add(&D, b, &D)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n    mp_exch(&D, c);\n    c->sign = neg;\n    res     = MP_OKAY;\n\nLBL_ERR: mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* computes xR**-1 == x (mod N) via Montgomery Reduction\n *\n * This is an optimized implementation of montgomery_reduce\n * which uses the comba method to quickly calculate the columns of the\n * reduction.\n *\n * Based on Algorithm 14.32 on pp.601 of HAC.\n */\nint fast_mp_montgomery_reduce(mp_int *x, mp_int *n, mp_digit rho) {\n    int     ix, res, olduse;\n    mp_word W[MP_WARRAY];\n\n    /* get old used count */\n    olduse = x->used;\n\n    /* grow a as required */\n    if (x->alloc < (n->used + 1)) {\n        if ((res = mp_grow(x, n->used + 1)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* first we have to get the digits of the input into\n     * an array of double precision words W[...]\n     */\n    {\n        mp_word  *_W;\n        mp_digit *tmpx;\n\n        /* alias for the W[] array */\n        _W = W;\n\n        /* alias for the digits of  x*/\n        tmpx = x->dp;\n\n        /* copy the digits of a into W[0..a->used-1] */\n        for (ix = 0; ix < x->used; ix++) {\n            *_W++ = *tmpx++;\n        }\n\n        /* zero the high words of W[a->used..m->used*2] */\n        for ( ; ix < ((n->used * 2) + 1); ix++) {\n            *_W++ = 0;\n        }\n    }\n\n    /* now we proceed to zero successive digits\n     * from the least significant upwards\n     */\n    for (ix = 0; ix < n->used; ix++) {\n        /* mu = ai * m' mod b\n         *\n         * We avoid a double precision multiplication (which isn't required)\n         * by casting the value down to a mp_digit.  Note this requires\n         * that W[ix-1] have  the carry cleared (see after the inner loop)\n         */\n        mp_digit mu;\n        mu = (mp_digit)(((W[ix] & MP_MASK) * rho) & MP_MASK);\n\n        /* a = a + mu * m * b**i\n         *\n         * This is computed in place and on the fly.  The multiplication\n         * by b**i is handled by offseting which columns the results\n         * are added to.\n         *\n         * Note the comba method normally doesn't handle carries in the\n         * inner loop In this case we fix the carry from the previous\n         * column since the Montgomery reduction requires digits of the\n         * result (so far) [see above] to work.  This is\n         * handled by fixing up one carry after the inner loop.  The\n         * carry fixups are done in order so after these loops the\n         * first m->used words of W[] have the carries fixed\n         */\n        {\n            int      iy;\n            mp_digit *tmpn;\n            mp_word  *_W;\n\n            /* alias for the digits of the modulus */\n            tmpn = n->dp;\n\n            /* Alias for the columns set by an offset of ix */\n            _W = W + ix;\n\n            /* inner loop */\n            for (iy = 0; iy < n->used; iy++) {\n                *_W++ += ((mp_word)mu) * ((mp_word) * tmpn++);\n            }\n        }\n\n        /* now fix carry for next digit, W[ix+1] */\n        W[ix + 1] += W[ix] >> ((mp_word)DIGIT_BIT);\n    }\n\n    /* now we have to propagate the carries and\n     * shift the words downward [all those least\n     * significant digits we zeroed].\n     */\n    {\n        mp_digit *tmpx;\n        mp_word  *_W, *_W1;\n\n        /* nox fix rest of carries */\n\n        /* alias for current word */\n        _W1 = W + ix;\n\n        /* alias for next word, where the carry goes */\n        _W = W + ++ix;\n\n        for ( ; ix <= ((n->used * 2) + 1); ix++) {\n            *_W++ += *_W1++ >> ((mp_word)DIGIT_BIT);\n        }\n\n        /* copy out, A = A/b**n\n         *\n         * The result is A/b**n but instead of converting from an\n         * array of mp_word to mp_digit than calling mp_rshd\n         * we just copy them in the right order\n         */\n\n        /* alias for destination word */\n        tmpx = x->dp;\n\n        /* alias for shifted double precision result */\n        _W = W + n->used;\n\n        for (ix = 0; ix < (n->used + 1); ix++) {\n            *tmpx++ = (mp_digit)(*_W++ & ((mp_word)MP_MASK));\n        }\n\n        /* zero oldused digits, if the input a was larger than\n         * m->used+1 we'll have to clear the digits\n         */\n        for ( ; ix < olduse; ix++) {\n            *tmpx++ = 0;\n        }\n    }\n\n    /* set the max used and clamp */\n    x->used = n->used + 1;\n    mp_clamp(x);\n\n    /* if A >= m then A = A - m */\n    if (mp_cmp_mag(x, n) != MP_LT) {\n        return s_mp_sub(x, n, x);\n    }\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_FAST_S_MP_MUL_DIGS_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* Fast (comba) multiplier\n *\n * This is the fast column-array [comba] multiplier.  It is\n * designed to compute the columns of the product first\n * then handle the carries afterwards.  This has the effect\n * of making the nested loops that compute the columns very\n * simple and schedulable on super-scalar processors.\n *\n * This has been modified to produce a variable number of\n * digits of output so if say only a half-product is required\n * you don't have to compute the upper half (a feature\n * required for fast Barrett reduction).\n *\n * Based on Algorithm 14.12 on pp.595 of HAC.\n *\n */\nint fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs) {\n    int      olduse, res, pa, ix, iz;\n    mp_digit W[MP_WARRAY];\n    mp_word  _W;\n\n    /* grow the destination as required */\n    if (c->alloc < digs) {\n        if ((res = mp_grow(c, digs)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* number of output digits to produce */\n    pa = TOM_MIN(digs, a->used + b->used);\n\n    /* clear the carry */\n    _W = 0;\n    for (ix = 0; ix < pa; ix++) {\n        int      tx, ty;\n        int      iy;\n        mp_digit *tmpx, *tmpy;\n\n        /* get offsets into the two bignums */\n        ty = TOM_MIN(b->used - 1, ix);\n        tx = ix - ty;\n\n        /* setup temp aliases */\n        tmpx = a->dp + tx;\n        tmpy = b->dp + ty;\n\n        /* this is the number of times the loop will iterrate, essentially\n           while (tx++ < a->used && ty-- >= 0) { ... }\n         */\n        iy = TOM_MIN(a->used - tx, ty + 1);\n\n        /* execute loop */\n        for (iz = 0; iz < iy; ++iz) {\n            _W += ((mp_word) * tmpx++) * ((mp_word) * tmpy--);\n        }\n\n        /* store term */\n        W[ix] = ((mp_digit)_W) & MP_MASK;\n\n        /* make next carry */\n        _W = _W >> ((mp_word)DIGIT_BIT);\n    }\n\n    /* setup dest */\n    olduse  = c->used;\n    c->used = pa;\n\n    {\n        mp_digit *tmpc;\n        tmpc = c->dp;\n        for (ix = 0; ix < (pa + 1); ix++) {\n            /* now extract the previous digit [below the carry] */\n            *tmpc++ = W[ix];\n        }\n\n        /* clear unused digits [that existed in the old copy of c] */\n        for ( ; ix < olduse; ix++) {\n            *tmpc++ = 0;\n        }\n    }\n    mp_clamp(c);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* this is a modified version of fast_s_mul_digs that only produces\n * output digits *above* digs.  See the comments for fast_s_mul_digs\n * to see how it works.\n *\n * This is used in the Barrett reduction since for one of the multiplications\n * only the higher digits were needed.  This essentially halves the work.\n *\n * Based on Algorithm 14.12 on pp.595 of HAC.\n */\nint fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs) {\n    int      olduse, res, pa, ix, iz;\n    mp_digit W[MP_WARRAY];\n    mp_word  _W;\n\n    /* grow the destination as required */\n    pa = a->used + b->used;\n    if (c->alloc < pa) {\n        if ((res = mp_grow(c, pa)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* number of output digits to produce */\n    pa = a->used + b->used;\n    _W = 0;\n    for (ix = digs; ix < pa; ix++) {\n        int      tx, ty, iy;\n        mp_digit *tmpx, *tmpy;\n\n        /* get offsets into the two bignums */\n        ty = TOM_MIN(b->used - 1, ix);\n        tx = ix - ty;\n\n        /* setup temp aliases */\n        tmpx = a->dp + tx;\n        tmpy = b->dp + ty;\n\n        /* this is the number of times the loop will iterrate, essentially its\n           while (tx++ < a->used && ty-- >= 0) { ... }\n         */\n        iy = TOM_MIN(a->used - tx, ty + 1);\n\n        /* execute loop */\n        for (iz = 0; iz < iy; iz++) {\n            _W += ((mp_word) * tmpx++) * ((mp_word) * tmpy--);\n        }\n\n        /* store term */\n        W[ix] = ((mp_digit)_W) & MP_MASK;\n\n        /* make next carry */\n        _W = _W >> ((mp_word)DIGIT_BIT);\n    }\n\n    /* setup dest */\n    olduse  = c->used;\n    c->used = pa;\n\n    {\n        mp_digit *tmpc;\n\n        tmpc = c->dp + digs;\n        for (ix = digs; ix < pa; ix++) {\n            /* now extract the previous digit [below the carry] */\n            *tmpc++ = W[ix];\n        }\n\n        /* clear unused digits [that existed in the old copy of c] */\n        for ( ; ix < olduse; ix++) {\n            *tmpc++ = 0;\n        }\n    }\n    mp_clamp(c);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_FAST_S_MP_SQR_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* the jist of squaring...\n * you do like mult except the offset of the tmpx [one that\n * starts closer to zero] can't equal the offset of tmpy.\n * So basically you set up iy like before then you min it with\n * (ty-tx) so that it never happens.  You double all those\n * you add in the inner loop\n\n   After that loop you do the squares and add them in.\n */\n\nint fast_s_mp_sqr(mp_int *a, mp_int *b) {\n    int      olduse, res, pa, ix, iz;\n    mp_digit W[MP_WARRAY], *tmpx;\n    mp_word  W1;\n\n    /* grow the destination as required */\n    pa = a->used + a->used;\n    if (b->alloc < pa) {\n        if ((res = mp_grow(b, pa)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* number of output digits to produce */\n    W1 = 0;\n    for (ix = 0; ix < pa; ix++) {\n        int      tx, ty, iy;\n        mp_word  _W;\n        mp_digit *tmpy;\n\n        /* clear counter */\n        _W = 0;\n\n        /* get offsets into the two bignums */\n        ty = TOM_MIN(a->used - 1, ix);\n        tx = ix - ty;\n\n        /* setup temp aliases */\n        tmpx = a->dp + tx;\n        tmpy = a->dp + ty;\n\n        /* this is the number of times the loop will iterrate, essentially\n           while (tx++ < a->used && ty-- >= 0) { ... }\n         */\n        iy = TOM_MIN(a->used - tx, ty + 1);\n\n        /* now for squaring tx can never equal ty\n         * we halve the distance since they approach at a rate of 2x\n         * and we have to round because odd cases need to be executed\n         */\n        iy = TOM_MIN(iy, ((ty - tx) + 1) >> 1);\n\n        /* execute loop */\n        for (iz = 0; iz < iy; iz++) {\n            _W += ((mp_word) * tmpx++) * ((mp_word) * tmpy--);\n        }\n\n        /* double the inner product and add carry */\n        _W = _W + _W + W1;\n\n        /* even columns have the square term in them */\n        if ((ix & 1) == 0) {\n            _W += ((mp_word)a->dp[ix >> 1]) * ((mp_word)a->dp[ix >> 1]);\n        }\n\n        /* store it */\n        W[ix] = (mp_digit)(_W & MP_MASK);\n\n        /* make next carry */\n        W1 = _W >> ((mp_word)DIGIT_BIT);\n    }\n\n    /* setup dest */\n    olduse  = b->used;\n    b->used = a->used + a->used;\n\n    {\n        mp_digit *tmpb;\n        tmpb = b->dp;\n        for (ix = 0; ix < pa; ix++) {\n            *tmpb++ = W[ix] & MP_MASK;\n        }\n\n        /* clear unused digits [that existed in the old copy of c] */\n        for ( ; ix < olduse; ix++) {\n            *tmpb++ = 0;\n        }\n    }\n    mp_clamp(b);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_2EXPT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* computes a = 2**b\n *\n * Simple algorithm which zeroes the int, grows it then just sets one bit\n * as required.\n */\nint\nmp_2expt(mp_int *a, int b) {\n    int res;\n\n    /* zero a as per default */\n    mp_zero(a);\n\n    /* grow a to accomodate the single bit */\n    if ((res = mp_grow(a, (b / DIGIT_BIT) + 1)) != MP_OKAY) {\n        return res;\n    }\n\n    /* set the used count of where the bit will go */\n    a->used = (b / DIGIT_BIT) + 1;\n\n    /* put the single bit in its place */\n    a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_ABS_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* b = |a|\n *\n * Simple function copies the input and fixes the sign to positive\n */\nint\nmp_abs(mp_int *a, mp_int *b) {\n    int res;\n\n    /* copy a to b */\n    if (a != b) {\n        if ((res = mp_copy(a, b)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* force the sign of b to positive */\n    b->sign = MP_ZPOS;\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_ADD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* high level addition (handles signs) */\nint mp_add(mp_int *a, mp_int *b, mp_int *c) {\n    int sa, sb, res;\n\n    /* get sign of both inputs */\n    sa = a->sign;\n    sb = b->sign;\n\n    /* handle two cases, not four */\n    if (sa == sb) {\n        /* both positive or both negative */\n        /* add their magnitudes, copy the sign */\n        c->sign = sa;\n        res     = s_mp_add(a, b, c);\n    } else {\n        /* one positive, the other negative */\n        /* subtract the one with the greater magnitude from */\n        /* the one of the lesser magnitude.  The result gets */\n        /* the sign of the one with the greater magnitude. */\n        if (mp_cmp_mag(a, b) == MP_LT) {\n            c->sign = sb;\n            res     = s_mp_sub(b, a, c);\n        } else {\n            c->sign = sa;\n            res     = s_mp_sub(a, b, c);\n        }\n    }\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_ADD_D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* single digit addition */\nint\nmp_add_d(mp_int *a, mp_digit b, mp_int *c) {\n    int      res, ix, oldused;\n    mp_digit *tmpa, *tmpc, mu;\n\n    /* grow c as required */\n    if (c->alloc < (a->used + 1)) {\n        if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* if a is negative and |a| >= b, call c = |a| - b */\n    if ((a->sign == MP_NEG) && ((a->used > 1) || (a->dp[0] >= b))) {\n        /* temporarily fix sign of a */\n        a->sign = MP_ZPOS;\n\n        /* c = |a| - b */\n        res = mp_sub_d(a, b, c);\n\n        /* fix sign  */\n        a->sign = c->sign = MP_NEG;\n\n        /* clamp */\n        mp_clamp(c);\n\n        return res;\n    }\n\n    /* old number of used digits in c */\n    oldused = c->used;\n\n    /* sign always positive */\n    c->sign = MP_ZPOS;\n\n    /* source alias */\n    tmpa = a->dp;\n\n    /* destination alias */\n    tmpc = c->dp;\n\n    /* if a is positive */\n    if (a->sign == MP_ZPOS) {\n        /* add digit, after this we're propagating\n         * the carry.\n         */\n        *tmpc    = *tmpa++ + b;\n        mu       = *tmpc >> DIGIT_BIT;\n        *tmpc++ &= MP_MASK;\n\n        /* now handle rest of the digits */\n        for (ix = 1; ix < a->used; ix++) {\n            *tmpc    = *tmpa++ + mu;\n            mu       = *tmpc >> DIGIT_BIT;\n            *tmpc++ &= MP_MASK;\n        }\n        /* set final carry */\n        ix++;\n        *tmpc++ = mu;\n\n        /* setup size */\n        c->used = a->used + 1;\n    } else {\n        /* a was negative and |a| < b */\n        c->used = 1;\n\n        /* the result is a single digit */\n        if (a->used == 1) {\n            *tmpc++ = b - a->dp[0];\n        } else {\n            *tmpc++ = b;\n        }\n\n        /* setup count so the clearing of oldused\n         * can fall through correctly\n         */\n        ix = 1;\n    }\n\n    /* now zero to oldused */\n    while (ix++ < oldused) {\n        *tmpc++ = 0;\n    }\n    mp_clamp(c);\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_ADDMOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* d = a + b (mod c) */\nint\nmp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) {\n    int    res;\n    mp_int t;\n\n    if ((res = mp_init(&t)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_add(a, b, &t)) != MP_OKAY) {\n        mp_clear(&t);\n        return res;\n    }\n    res = mp_mod(&t, c, d);\n    mp_clear(&t);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_AND_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* AND two ints together */\nint\nmp_and(mp_int *a, mp_int *b, mp_int *c) {\n    int    res, ix, px;\n    mp_int t, *x;\n\n    if (a->used > b->used) {\n        if ((res = mp_init_copy(&t, a)) != MP_OKAY) {\n            return res;\n        }\n        px = b->used;\n        x  = b;\n    } else {\n        if ((res = mp_init_copy(&t, b)) != MP_OKAY) {\n            return res;\n        }\n        px = a->used;\n        x  = a;\n    }\n\n    for (ix = 0; ix < px; ix++) {\n        t.dp[ix] &= x->dp[ix];\n    }\n\n    /* zero digits above the last from the smallest mp_int */\n    for ( ; ix < t.used; ix++) {\n        t.dp[ix] = 0;\n    }\n\n    mp_clamp(&t);\n    mp_exch(c, &t);\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_CLAMP_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* trim unused digits\n *\n * This is used to ensure that leading zero digits are\n * trimed and the leading \"used\" digit will be non-zero\n * Typically very fast.  Also fixes the sign if there\n * are no more leading digits\n */\nvoid\nmp_clamp(mp_int *a) {\n    /* decrease used while the most significant digit is\n     * zero.\n     */\n    while ((a->used > 0) && (a->dp[a->used - 1] == 0)) {\n        --(a->used);\n    }\n\n    /* reset the sign flag if used == 0 */\n    if (a->used == 0) {\n        a->sign = MP_ZPOS;\n    }\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_CLEAR_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* clear one (frees)  */\nvoid\nmp_clear(mp_int *a) {\n    int i;\n\n    /* only do anything if a hasn't been freed previously */\n    if (a->dp != NULL) {\n        /* first zero the digits */\n        for (i = 0; i < a->used; i++) {\n            a->dp[i] = 0;\n        }\n\n        /* free ram */\n        XFREE(a->dp);\n\n        /* reset members to make debugging easier */\n        a->dp    = NULL;\n        a->alloc = a->used = 0;\n        a->sign  = MP_ZPOS;\n    }\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_CLEAR_MULTI_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\nvoid mp_clear_multi(mp_int *mp, ...) {\n    mp_int  *next_mp = mp;\n    va_list args;\n\n    va_start(args, mp);\n    while (next_mp != NULL) {\n        mp_clear(next_mp);\n        next_mp = va_arg(args, mp_int *);\n    }\n    va_end(args);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_CMP_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* compare two ints (signed)*/\nint\nmp_cmp(mp_int *a, mp_int *b) {\n    /* compare based on sign */\n    if (a->sign != b->sign) {\n        if (a->sign == MP_NEG) {\n            return MP_LT;\n        } else {\n            return MP_GT;\n        }\n    }\n\n    /* compare digits */\n    if (a->sign == MP_NEG) {\n        /* if negative compare opposite direction */\n        return mp_cmp_mag(b, a);\n    } else {\n        return mp_cmp_mag(a, b);\n    }\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_CMP_D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* compare a digit */\nint mp_cmp_d(mp_int *a, mp_digit b) {\n    /* compare based on sign */\n    if (a->sign == MP_NEG) {\n        return MP_LT;\n    }\n\n    /* compare based on magnitude */\n    if (a->used > 1) {\n        return MP_GT;\n    }\n\n    /* compare the only digit of a to b */\n    if (a->dp[0] > b) {\n        return MP_GT;\n    } else if (a->dp[0] < b) {\n        return MP_LT;\n    } else {\n        return MP_EQ;\n    }\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_CMP_MAG_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* compare maginitude of two ints (unsigned) */\nint mp_cmp_mag(mp_int *a, mp_int *b) {\n    int      n;\n    mp_digit *tmpa, *tmpb;\n\n    /* compare based on # of non-zero digits */\n    if (a->used > b->used) {\n        return MP_GT;\n    }\n\n    if (a->used < b->used) {\n        return MP_LT;\n    }\n\n    /* alias for a */\n    tmpa = a->dp + (a->used - 1);\n\n    /* alias for b */\n    tmpb = b->dp + (a->used - 1);\n\n    /* compare based on digits  */\n    for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {\n        if (*tmpa > *tmpb) {\n            return MP_GT;\n        }\n\n        if (*tmpa < *tmpb) {\n            return MP_LT;\n        }\n    }\n    return MP_EQ;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_CNT_LSB_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\nstatic const int lnz[16] = {\n    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0\n};\n\n/* Counts the number of lsbs which are zero before the first zero bit */\nint mp_cnt_lsb(mp_int *a) {\n    int      x;\n    mp_digit q, qq;\n\n    /* easy out */\n    if (mp_iszero(a) == MP_YES) {\n        return 0;\n    }\n\n    /* scan lower digits until non-zero */\n    for (x = 0; (x < a->used) && (a->dp[x] == 0); x++) {\n    }\n    q  = a->dp[x];\n    x *= DIGIT_BIT;\n\n    /* now scan this digit until a 1 is found */\n    if ((q & 1) == 0) {\n        do {\n            qq  = q & 15;\n            x  += lnz[qq];\n            q >>= 4;\n        } while (qq == 0);\n    }\n    return x;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_COPY_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* copy, b = a */\nint\nmp_copy(mp_int *a, mp_int *b) {\n    int res, n;\n\n    /* if dst == src do nothing */\n    if (a == b) {\n        return MP_OKAY;\n    }\n\n    /* grow dest */\n    if (b->alloc < a->used) {\n        if ((res = mp_grow(b, a->used)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* zero b and copy the parameters over */\n    {\n        mp_digit *tmpa, *tmpb;\n\n        /* pointer aliases */\n\n        /* source */\n        tmpa = a->dp;\n\n        /* destination */\n        tmpb = b->dp;\n\n        /* copy all the digits */\n        for (n = 0; n < a->used; n++) {\n            *tmpb++ = *tmpa++;\n        }\n\n        /* clear high digits */\n        for ( ; n < b->used; n++) {\n            *tmpb++ = 0;\n        }\n    }\n\n    /* copy used count and sign */\n    b->used = a->used;\n    b->sign = a->sign;\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_COUNT_BITS_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* returns the number of bits in an int */\nint\nmp_count_bits(mp_int *a) {\n    int      r;\n    mp_digit q;\n\n    /* shortcut */\n    if (a->used == 0) {\n        return 0;\n    }\n\n    /* get number of digits and add that */\n    r = (a->used - 1) * DIGIT_BIT;\n\n    /* take the last digit and count the bits in it */\n    q = a->dp[a->used - 1];\n    while (q > ((mp_digit)0)) {\n        ++r;\n        q >>= ((mp_digit)1);\n    }\n    return r;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_DIV_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n #ifdef BN_MP_DIV_SMALL\n\n/* slower bit-bang division... also smaller */\nint mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d) {\n    mp_int ta, tb, tq, q;\n    int    res, n, n2;\n\n    /* is divisor zero ? */\n    if (mp_iszero(b) == MP_YES) {\n        return MP_VAL;\n    }\n\n    /* if a < b then q=0, r = a */\n    if (mp_cmp_mag(a, b) == MP_LT) {\n        if (d != NULL) {\n            res = mp_copy(a, d);\n        } else {\n            res = MP_OKAY;\n        }\n        if (c != NULL) {\n            mp_zero(c);\n        }\n        return res;\n    }\n\n    /* init our temps */\n    if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) {\n        return res;\n    }\n\n\n    mp_set(&tq, 1);\n    n = mp_count_bits(a) - mp_count_bits(b);\n    if (((res = mp_abs(a, &ta)) != MP_OKAY) ||\n        ((res = mp_abs(b, &tb)) != MP_OKAY) ||\n        ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||\n        ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {\n        goto LBL_ERR;\n    }\n\n    while (n-- >= 0) {\n        if (mp_cmp(&tb, &ta) != MP_GT) {\n            if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||\n                ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {\n                goto LBL_ERR;\n            }\n        }\n        if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||\n            ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* now q == quotient and ta == remainder */\n    n  = a->sign;\n    n2 = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;\n    if (c != NULL) {\n        mp_exch(c, &q);\n        c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;\n    }\n    if (d != NULL) {\n        mp_exch(d, &ta);\n        d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;\n    }\nLBL_ERR:\n    mp_clear_multi(&ta, &tb, &tq, &q, NULL);\n    return res;\n}\n\n #else\n\n/* integer signed division.\n * c*b + d == a [e.g. a/b, c=quotient, d=remainder]\n * HAC pp.598 Algorithm 14.20\n *\n * Note that the description in HAC is horribly\n * incomplete.  For example, it doesn't consider\n * the case where digits are removed from 'x' in\n * the inner loop.  It also doesn't consider the\n * case that y has fewer than three digits, etc..\n *\n * The overall algorithm is as described as\n * 14.20 from HAC but fixed to treat these cases.\n */\nint mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d) {\n    mp_int q, x, y, t1, t2;\n    int    res, n, t, i, norm, neg;\n\n    /* is divisor zero ? */\n    if (mp_iszero(b) == MP_YES) {\n        return MP_VAL;\n    }\n\n    /* if a < b then q=0, r = a */\n    if (mp_cmp_mag(a, b) == MP_LT) {\n        if (d != NULL) {\n            res = mp_copy(a, d);\n        } else {\n            res = MP_OKAY;\n        }\n        if (c != NULL) {\n            mp_zero(c);\n        }\n        return res;\n    }\n\n    if ((res = mp_init_size(&q, a->used + 2)) != MP_OKAY) {\n        return res;\n    }\n    q.used = a->used + 2;\n\n    if ((res = mp_init(&t1)) != MP_OKAY) {\n        goto LBL_Q;\n    }\n\n    if ((res = mp_init(&t2)) != MP_OKAY) {\n        goto LBL_T1;\n    }\n\n    if ((res = mp_init_copy(&x, a)) != MP_OKAY) {\n        goto LBL_T2;\n    }\n\n    if ((res = mp_init_copy(&y, b)) != MP_OKAY) {\n        goto LBL_X;\n    }\n\n    /* fix the sign */\n    neg    = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;\n    x.sign = y.sign = MP_ZPOS;\n\n    /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */\n    norm = mp_count_bits(&y) % DIGIT_BIT;\n    if (norm < (int)(DIGIT_BIT - 1)) {\n        norm = (DIGIT_BIT - 1) - norm;\n        if ((res = mp_mul_2d(&x, norm, &x)) != MP_OKAY) {\n            goto LBL_Y;\n        }\n        if ((res = mp_mul_2d(&y, norm, &y)) != MP_OKAY) {\n            goto LBL_Y;\n        }\n    } else {\n        norm = 0;\n    }\n\n    /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */\n    n = x.used - 1;\n    t = y.used - 1;\n\n    /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */\n    if ((res = mp_lshd(&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */\n        goto LBL_Y;\n    }\n\n    while (mp_cmp(&x, &y) != MP_LT) {\n        ++(q.dp[n - t]);\n        if ((res = mp_sub(&x, &y, &x)) != MP_OKAY) {\n            goto LBL_Y;\n        }\n    }\n\n    /* reset y by shifting it back down */\n    mp_rshd(&y, n - t);\n\n    /* step 3. for i from n down to (t + 1) */\n    for (i = n; i >= (t + 1); i--) {\n        if (i > x.used) {\n            continue;\n        }\n\n        /* step 3.1 if xi == yt then set q{i-t-1} to b-1,\n        * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */\n        if (x.dp[i] == y.dp[t]) {\n            q.dp[(i - t) - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);\n        } else {\n            mp_word tmp;\n            tmp  = ((mp_word)x.dp[i]) << ((mp_word)DIGIT_BIT);\n            tmp |= ((mp_word)x.dp[i - 1]);\n            tmp /= ((mp_word)y.dp[t]);\n            if (tmp > (mp_word)MP_MASK) {\n                tmp = MP_MASK;\n            }\n            q.dp[(i - t) - 1] = (mp_digit)(tmp & (mp_word)(MP_MASK));\n        }\n\n        /* while (q{i-t-1} * (yt * b + y{t-1})) >\n                 xi * b**2 + xi-1 * b + xi-2\n\n           do q{i-t-1} -= 1;\n         */\n        q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] + 1) & MP_MASK;\n        do {\n            q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1) & MP_MASK;\n\n            /* find left hand */\n            mp_zero(&t1);\n            t1.dp[0] = ((t - 1) < 0) ? 0 : y.dp[t - 1];\n            t1.dp[1] = y.dp[t];\n            t1.used  = 2;\n            if ((res = mp_mul_d(&t1, q.dp[(i - t) - 1], &t1)) != MP_OKAY) {\n                goto LBL_Y;\n            }\n\n            /* find right hand */\n            t2.dp[0] = ((i - 2) < 0) ? 0 : x.dp[i - 2];\n            t2.dp[1] = ((i - 1) < 0) ? 0 : x.dp[i - 1];\n            t2.dp[2] = x.dp[i];\n            t2.used  = 3;\n        } while (mp_cmp_mag(&t1, &t2) == MP_GT);\n\n        /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */\n        if ((res = mp_mul_d(&y, q.dp[(i - t) - 1], &t1)) != MP_OKAY) {\n            goto LBL_Y;\n        }\n\n        if ((res = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) {\n            goto LBL_Y;\n        }\n\n        if ((res = mp_sub(&x, &t1, &x)) != MP_OKAY) {\n            goto LBL_Y;\n        }\n\n        /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */\n        if (x.sign == MP_NEG) {\n            if ((res = mp_copy(&y, &t1)) != MP_OKAY) {\n                goto LBL_Y;\n            }\n            if ((res = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) {\n                goto LBL_Y;\n            }\n            if ((res = mp_add(&x, &t1, &x)) != MP_OKAY) {\n                goto LBL_Y;\n            }\n\n            q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1UL) & MP_MASK;\n        }\n    }\n\n    /* now q is the quotient and x is the remainder\n     * [which we have to normalize]\n     */\n\n    /* get sign before writing to c */\n    x.sign = (x.used == 0) ? MP_ZPOS : a->sign;\n\n    if (c != NULL) {\n        mp_clamp(&q);\n        mp_exch(&q, c);\n        c->sign = neg;\n    }\n\n    if (d != NULL) {\n        if ((res = mp_div_2d(&x, norm, &x, NULL)) != MP_OKAY) {\n            goto LBL_Y;\n        }\n        mp_exch(&x, d);\n    }\n\n    res = MP_OKAY;\n\nLBL_Y: mp_clear(&y);\nLBL_X: mp_clear(&x);\nLBL_T2: mp_clear(&t2);\nLBL_T1: mp_clear(&t1);\nLBL_Q: mp_clear(&q);\n    return res;\n}\n #endif\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_DIV_2_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* b = a/2 */\nint mp_div_2(mp_int *a, mp_int *b) {\n    int x, res, oldused;\n\n    /* copy */\n    if (b->alloc < a->used) {\n        if ((res = mp_grow(b, a->used)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    oldused = b->used;\n    b->used = a->used;\n    {\n        mp_digit r, rr, *tmpa, *tmpb;\n\n        /* source alias */\n        tmpa = a->dp + b->used - 1;\n\n        /* dest alias */\n        tmpb = b->dp + b->used - 1;\n\n        /* carry */\n        r = 0;\n        for (x = b->used - 1; x >= 0; x--) {\n            /* get the carry for the next iteration */\n            rr = *tmpa & 1;\n\n            /* shift the current digit, add in carry and store */\n            *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));\n\n            /* forward carry to next iteration */\n            r = rr;\n        }\n\n        /* zero excess digits */\n        tmpb = b->dp + b->used;\n        for (x = b->used; x < oldused; x++) {\n            *tmpb++ = 0;\n        }\n    }\n    b->sign = a->sign;\n    mp_clamp(b);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_DIV_2D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* shift right by a certain bit count (store quotient in c, optional remainder in d) */\nint mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d) {\n    mp_digit D, r, rr;\n    int      x, res;\n    mp_int   t;\n\n\n    /* if the shift count is <= 0 then we do no work */\n    if (b <= 0) {\n        res = mp_copy(a, c);\n        if (d != NULL) {\n            mp_zero(d);\n        }\n        return res;\n    }\n\n    if ((res = mp_init(&t)) != MP_OKAY) {\n        return res;\n    }\n\n    /* get the remainder */\n    if (d != NULL) {\n        if ((res = mp_mod_2d(a, b, &t)) != MP_OKAY) {\n            mp_clear(&t);\n            return res;\n        }\n    }\n\n    /* copy */\n    if ((res = mp_copy(a, c)) != MP_OKAY) {\n        mp_clear(&t);\n        return res;\n    }\n\n    /* shift by as many digits in the bit count */\n    if (b >= (int)DIGIT_BIT) {\n        mp_rshd(c, b / DIGIT_BIT);\n    }\n\n    /* shift any bit count < DIGIT_BIT */\n    D = (mp_digit)(b % DIGIT_BIT);\n    if (D != 0) {\n        mp_digit *tmpc, mask, shift;\n\n        /* mask */\n        mask = (((mp_digit)1) << D) - 1;\n\n        /* shift for lsb */\n        shift = DIGIT_BIT - D;\n\n        /* alias */\n        tmpc = c->dp + (c->used - 1);\n\n        /* carry */\n        r = 0;\n        for (x = c->used - 1; x >= 0; x--) {\n            /* get the lower  bits of this word in a temp */\n            rr = *tmpc & mask;\n\n            /* shift the current word and mix in the carry bits from the previous word */\n            *tmpc = (*tmpc >> D) | (r << shift);\n            --tmpc;\n\n            /* set the carry to the carry bits of the current word found above */\n            r = rr;\n        }\n    }\n    mp_clamp(c);\n    if (d != NULL) {\n        mp_exch(&t, d);\n    }\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_DIV_3_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* divide by three (based on routine from MPI and the GMP manual) */\nint\nmp_div_3(mp_int *a, mp_int *c, mp_digit *d) {\n    mp_int   q;\n    mp_word  w, t;\n    mp_digit b;\n    int      res, ix;\n\n    /* b = 2**DIGIT_BIT / 3 */\n    b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);\n\n    if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {\n        return res;\n    }\n\n    q.used = a->used;\n    q.sign = a->sign;\n    w      = 0;\n    for (ix = a->used - 1; ix >= 0; ix--) {\n        w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);\n\n        if (w >= 3) {\n            /* multiply w by [1/3] */\n            t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);\n\n            /* now subtract 3 * [w/3] from w, to get the remainder */\n            w -= t + t + t;\n\n            /* fixup the remainder as required since\n             * the optimization is not exact.\n             */\n            while (w >= 3) {\n                t += 1;\n                w -= 3;\n            }\n        } else {\n            t = 0;\n        }\n        q.dp[ix] = (mp_digit)t;\n    }\n\n    /* [optional] store the remainder */\n    if (d != NULL) {\n        *d = (mp_digit)w;\n    }\n\n    /* [optional] store the quotient */\n    if (c != NULL) {\n        mp_clamp(&q);\n        mp_exch(&q, c);\n    }\n    mp_clear(&q);\n\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_DIV_D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\nstatic int s_is_power_of_two(mp_digit b, int *p) {\n    int x;\n\n    /* fast return if no power of two */\n    if ((b == 0) || ((b & (b - 1)) != 0)) {\n        return 0;\n    }\n\n    for (x = 0; x < DIGIT_BIT; x++) {\n        if (b == (((mp_digit)1) << x)) {\n            *p = x;\n            return 1;\n        }\n    }\n    return 0;\n}\n\n/* single digit division (based on routine from MPI) */\nint mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d) {\n    mp_int   q;\n    mp_word  w;\n    mp_digit t;\n    int      res, ix;\n\n    /* cannot divide by zero */\n    if (b == 0) {\n        return MP_VAL;\n    }\n\n    /* quick outs */\n    if ((b == 1) || (mp_iszero(a) == MP_YES)) {\n        if (d != NULL) {\n            *d = 0;\n        }\n        if (c != NULL) {\n            return mp_copy(a, c);\n        }\n        return MP_OKAY;\n    }\n\n    /* power of two ? */\n    if (s_is_power_of_two(b, &ix) == 1) {\n        if (d != NULL) {\n            *d = a->dp[0] & ((((mp_digit)1) << ix) - 1);\n        }\n        if (c != NULL) {\n            return mp_div_2d(a, ix, c, NULL);\n        }\n        return MP_OKAY;\n    }\n\n #ifdef BN_MP_DIV_3_C\n    /* three? */\n    if (b == 3) {\n        return mp_div_3(a, c, d);\n    }\n #endif\n\n    /* no easy answer [c'est la vie].  Just division */\n    if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {\n        return res;\n    }\n\n    q.used = a->used;\n    q.sign = a->sign;\n    w      = 0;\n    for (ix = a->used - 1; ix >= 0; ix--) {\n        w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);\n\n        if (w >= b) {\n            t  = (mp_digit)(w / b);\n            w -= ((mp_word)t) * ((mp_word)b);\n        } else {\n            t = 0;\n        }\n        q.dp[ix] = (mp_digit)t;\n    }\n\n    if (d != NULL) {\n        *d = (mp_digit)w;\n    }\n\n    if (c != NULL) {\n        mp_clamp(&q);\n        mp_exch(&q, c);\n    }\n    mp_clear(&q);\n\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_DR_IS_MODULUS_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* determines if a number is a valid DR modulus */\nint mp_dr_is_modulus(mp_int *a) {\n    int ix;\n\n    /* must be at least two digits */\n    if (a->used < 2) {\n        return 0;\n    }\n\n    /* must be of the form b**k - a [a <= b] so all\n     * but the first digit must be equal to -1 (mod b).\n     */\n    for (ix = 1; ix < a->used; ix++) {\n        if (a->dp[ix] != MP_MASK) {\n            return 0;\n        }\n    }\n    return 1;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_DR_REDUCE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* reduce \"x\" in place modulo \"n\" using the Diminished Radix algorithm.\n *\n * Based on algorithm from the paper\n *\n * \"Generating Efficient Primes for Discrete Log Cryptosystems\"\n *                 Chae Hoon Lim, Pil Joong Lee,\n *          POSTECH Information Research Laboratories\n *\n * The modulus must be of a special format [see manual]\n *\n * Has been modified to use algorithm 7.10 from the LTM book instead\n *\n * Input x must be in the range 0 <= x <= (n-1)**2\n */\nint\nmp_dr_reduce(mp_int *x, mp_int *n, mp_digit k) {\n    int      err, i, m;\n    mp_word  r;\n    mp_digit mu, *tmpx1, *tmpx2;\n\n    /* m = digits in modulus */\n    m = n->used;\n\n    /* ensure that \"x\" has at least 2m digits */\n    if (x->alloc < (m + m)) {\n        if ((err = mp_grow(x, m + m)) != MP_OKAY) {\n            return err;\n        }\n    }\n\n/* top of loop, this is where the code resumes if\n * another reduction pass is required.\n */\ntop:\n    /* aliases for digits */\n    /* alias for lower half of x */\n    tmpx1 = x->dp;\n\n    /* alias for upper half of x, or x/B**m */\n    tmpx2 = x->dp + m;\n\n    /* set carry to zero */\n    mu = 0;\n\n    /* compute (x mod B**m) + k * [x/B**m] inline and inplace */\n    for (i = 0; i < m; i++) {\n        r        = (((mp_word) * tmpx2++) * (mp_word)k) + *tmpx1 + mu;\n        *tmpx1++ = (mp_digit)(r & MP_MASK);\n        mu       = (mp_digit)(r >> ((mp_word)DIGIT_BIT));\n    }\n\n    /* set final carry */\n    *tmpx1++ = mu;\n\n    /* zero words above m */\n    for (i = m + 1; i < x->used; i++) {\n        *tmpx1++ = 0;\n    }\n\n    /* clamp, sub and return */\n    mp_clamp(x);\n\n    /* if x >= n then subtract and reduce again\n     * Each successive \"recursion\" makes the input smaller and smaller.\n     */\n    if (mp_cmp_mag(x, n) != MP_LT) {\n        if ((err = s_mp_sub(x, n, x)) != MP_OKAY) {\n            return err;\n        }\n        goto top;\n    }\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_DR_SETUP_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* determines the setup value */\nvoid mp_dr_setup(mp_int *a, mp_digit *d) {\n    /* the casts are required if DIGIT_BIT is one less than\n     * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]\n     */\n    *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -\n                    ((mp_word)a->dp[0]));\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_EXCH_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* swap the elements of two integers, for cases where you can't simply swap the\n * mp_int pointers around\n */\nvoid\nmp_exch(mp_int *a, mp_int *b) {\n    mp_int t;\n\n    t  = *a;\n    *a = *b;\n    *b = t;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_EXPORT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* based on gmp's mpz_export.\n * see http://gmplib.org/manual/Integer-Import-and-Export.html\n */\nint mp_export(void *rop, size_t *countp, int order, size_t size,\n              int endian, size_t nails, mp_int *op) {\n    int           result;\n    size_t        odd_nails, nail_bytes, i, j, bits, count;\n    unsigned char odd_nail_mask;\n\n    mp_int t;\n\n    if ((result = mp_init_copy(&t, op)) != MP_OKAY) {\n        return result;\n    }\n\n    if (endian == 0) {\n        union {\n            unsigned int i;\n            char         c[4];\n        } lint;\n        lint.i = 0x01020304;\n\n        endian = (lint.c[0] == 4) ? -1 : 1;\n    }\n\n    odd_nails     = (nails % 8);\n    odd_nail_mask = 0xff;\n    for (i = 0; i < odd_nails; ++i) {\n        odd_nail_mask ^= (1 << (7 - i));\n    }\n    nail_bytes = nails / 8;\n\n    bits  = mp_count_bits(&t);\n    count = (bits / ((size * 8) - nails)) + (((bits % ((size * 8) - nails)) != 0) ? 1 : 0);\n\n    for (i = 0; i < count; ++i) {\n        for (j = 0; j < size; ++j) {\n            unsigned char *byte = (\n                (unsigned char *)rop +\n                (((order == -1) ? i : ((count - 1) - i)) * size) +\n                ((endian == -1) ? j : ((size - 1) - j))\n                );\n\n            if (j >= (size - nail_bytes)) {\n                *byte = 0;\n                continue;\n            }\n\n            *byte = (unsigned char)((j == ((size - nail_bytes) - 1)) ? (t.dp[0] & odd_nail_mask) : (t.dp[0] & 0xFF));\n\n            if ((result = mp_div_2d(&t, ((j == ((size - nail_bytes) - 1)) ? (8 - odd_nails) : 8), &t, NULL)) != MP_OKAY) {\n                mp_clear(&t);\n                return result;\n            }\n        }\n    }\n\n    mp_clear(&t);\n\n    if (countp != NULL) {\n        *countp = count;\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_EXPT_D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* wrapper function for mp_expt_d_ex() */\nint mp_expt_d(mp_int *a, mp_digit b, mp_int *c) {\n    return mp_expt_d_ex(a, b, c, 0);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_EXPT_D_EX_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* calculate c = a**b  using a square-multiply algorithm */\nint mp_expt_d_ex(mp_int *a, mp_digit b, mp_int *c, int fast) {\n    int          res;\n    unsigned int x;\n\n    mp_int g;\n\n    if ((res = mp_init_copy(&g, a)) != MP_OKAY) {\n        return res;\n    }\n\n    /* set initial result */\n    mp_set(c, 1);\n\n    if (fast != 0) {\n        while (b > 0) {\n            /* if the bit is set multiply */\n            if ((b & 1) != 0) {\n                if ((res = mp_mul(c, &g, c)) != MP_OKAY) {\n                    mp_clear(&g);\n                    return res;\n                }\n            }\n\n            /* square */\n            if (b > 1) {\n                if ((res = mp_sqr(&g, &g)) != MP_OKAY) {\n                    mp_clear(&g);\n                    return res;\n                }\n            }\n\n            /* shift to next bit */\n            b >>= 1;\n        }\n    } else {\n        for (x = 0; x < DIGIT_BIT; x++) {\n            /* square */\n            if ((res = mp_sqr(c, c)) != MP_OKAY) {\n                mp_clear(&g);\n                return res;\n            }\n\n            /* if the bit is set multiply */\n            if ((b & (mp_digit)(((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {\n                if ((res = mp_mul(c, &g, c)) != MP_OKAY) {\n                    mp_clear(&g);\n                    return res;\n                }\n            }\n\n            /* shift to next bit */\n            b <<= 1;\n        }\n    } /* if ... else */\n\n    mp_clear(&g);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_EXPTMOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n\n/* this is a shell function that calls either the normal or Montgomery\n * exptmod functions.  Originally the call to the montgomery code was\n * embedded in the normal function but that wasted alot of stack space\n * for nothing (since 99% of the time the Montgomery code would be called)\n */\nint mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) {\n    int dr;\n\n    /* modulus P must be positive */\n    if (P->sign == MP_NEG) {\n        return MP_VAL;\n    }\n\n    /* if exponent X is negative we have to recurse */\n    if (X->sign == MP_NEG) {\n #ifdef BN_MP_INVMOD_C\n        mp_int tmpG, tmpX;\n        int    err;\n\n        /* first compute 1/G mod P */\n        if ((err = mp_init(&tmpG)) != MP_OKAY) {\n            return err;\n        }\n        if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {\n            mp_clear(&tmpG);\n            return err;\n        }\n\n        /* now get |X| */\n        if ((err = mp_init(&tmpX)) != MP_OKAY) {\n            mp_clear(&tmpG);\n            return err;\n        }\n        if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {\n            mp_clear_multi(&tmpG, &tmpX, NULL);\n            return err;\n        }\n\n        /* and now compute (1/G)**|X| instead of G**X [X < 0] */\n        err = mp_exptmod(&tmpG, &tmpX, P, Y);\n        mp_clear_multi(&tmpG, &tmpX, NULL);\n        return err;\n #else\n        /* no invmod */\n        return MP_VAL;\n #endif\n    }\n\n/* modified diminished radix reduction */\n #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)\n    if (mp_reduce_is_2k_l(P) == MP_YES) {\n        return s_mp_exptmod(G, X, P, Y, 1);\n    }\n #endif\n\n #ifdef BN_MP_DR_IS_MODULUS_C\n    /* is it a DR modulus? */\n    dr = mp_dr_is_modulus(P);\n #else\n    /* default to no */\n    dr = 0;\n #endif\n\n #ifdef BN_MP_REDUCE_IS_2K_C\n    /* if not, is it a unrestricted DR modulus? */\n    if (dr == 0) {\n        dr = mp_reduce_is_2k(P) << 1;\n    }\n #endif\n\n    /* if the modulus is odd or dr != 0 use the montgomery method */\n #ifdef BN_MP_EXPTMOD_FAST_C\n    if ((mp_isodd(P) == MP_YES) || (dr != 0)) {\n        return mp_exptmod_fast(G, X, P, Y, dr);\n    } else {\n #endif\n #ifdef BN_S_MP_EXPTMOD_C\n    /* otherwise use the generic Barrett reduction technique */\n    return s_mp_exptmod(G, X, P, Y, 0);\n #else\n    /* no exptmod for evens */\n    return MP_VAL;\n #endif\n #ifdef BN_MP_EXPTMOD_FAST_C\n}\n #endif\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_EXPTMOD_FAST_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85\n *\n * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.\n * The value of k changes based on the size of the exponent.\n *\n * Uses Montgomery or Diminished Radix reduction [whichever appropriate]\n */\n\n #ifdef MP_LOW_MEM\n  #define TAB_SIZE    32\n #else\n  #define TAB_SIZE    256\n #endif\n\nint mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int redmode) {\n    mp_int   M[TAB_SIZE], res;\n    mp_digit buf, mp;\n    int      err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;\n\n    /* use a pointer to the reduction algorithm.  This allows us to use\n     * one of many reduction algorithms without modding the guts of\n     * the code with if statements everywhere.\n     */\n    int (*redux)(mp_int *, mp_int *, mp_digit);\n\n    /* find window size */\n    x = mp_count_bits(X);\n    if (x <= 7) {\n        winsize = 2;\n    } else if (x <= 36) {\n        winsize = 3;\n    } else if (x <= 140) {\n        winsize = 4;\n    } else if (x <= 450) {\n        winsize = 5;\n    } else if (x <= 1303) {\n        winsize = 6;\n    } else if (x <= 3529) {\n        winsize = 7;\n    } else {\n        winsize = 8;\n    }\n\n #ifdef MP_LOW_MEM\n    if (winsize > 5) {\n        winsize = 5;\n    }\n #endif\n\n    /* init M array */\n    /* init first cell */\n    if ((err = mp_init(&M[1])) != MP_OKAY) {\n        return err;\n    }\n\n    /* now init the second half of the array */\n    for (x = 1 << (winsize - 1); x < (1 << winsize); x++) {\n        if ((err = mp_init(&M[x])) != MP_OKAY) {\n            for (y = 1 << (winsize - 1); y < x; y++) {\n                mp_clear(&M[y]);\n            }\n            mp_clear(&M[1]);\n            return err;\n        }\n    }\n\n    /* determine and setup reduction code */\n    if (redmode == 0) {\n #ifdef BN_MP_MONTGOMERY_SETUP_C\n        /* now setup montgomery  */\n        if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) {\n            goto LBL_M;\n        }\n #else\n        err = MP_VAL;\n        goto LBL_M;\n #endif\n\n        /* automatically pick the comba one if available (saves quite a few calls/ifs) */\n #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C\n        if ((((P->used * 2) + 1) < MP_WARRAY) &&\n            (P->used < (1 << ((CHAR_BIT * sizeof(mp_word)) - (2 * DIGIT_BIT))))) {\n            redux = fast_mp_montgomery_reduce;\n        } else\n #endif\n        {\n #ifdef BN_MP_MONTGOMERY_REDUCE_C\n            /* use slower baseline Montgomery method */\n            redux = mp_montgomery_reduce;\n #else\n            err = MP_VAL;\n            goto LBL_M;\n #endif\n        }\n    } else if (redmode == 1) {\n #if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)\n        /* setup DR reduction for moduli of the form B**k - b */\n        mp_dr_setup(P, &mp);\n        redux = mp_dr_reduce;\n #else\n        err = MP_VAL;\n        goto LBL_M;\n #endif\n    } else {\n #if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)\n        /* setup DR reduction for moduli of the form 2**k - b */\n        if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {\n            goto LBL_M;\n        }\n        redux = mp_reduce_2k;\n #else\n        err = MP_VAL;\n        goto LBL_M;\n #endif\n    }\n\n    /* setup result */\n    if ((err = mp_init(&res)) != MP_OKAY) {\n        goto LBL_M;\n    }\n\n    /* create M table\n     *\n\n     *\n     * The first half of the table is not computed though accept for M[0] and M[1]\n     */\n\n    if (redmode == 0) {\n #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C\n        /* now we need R mod m */\n        if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) {\n            goto LBL_RES;\n        }\n #else\n        err = MP_VAL;\n        goto LBL_RES;\n #endif\n\n        /* now set M[1] to G * R mod m */\n        if ((err = mp_mulmod(G, &res, P, &M[1])) != MP_OKAY) {\n            goto LBL_RES;\n        }\n    } else {\n        mp_set(&res, 1);\n        if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {\n            goto LBL_RES;\n        }\n    }\n\n    /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */\n    if ((err = mp_copy(&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {\n        goto LBL_RES;\n    }\n\n    for (x = 0; x < (winsize - 1); x++) {\n        if ((err = mp_sqr(&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {\n            goto LBL_RES;\n        }\n        if ((err = redux(&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {\n            goto LBL_RES;\n        }\n    }\n\n    /* create upper table */\n    for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {\n        if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) {\n            goto LBL_RES;\n        }\n        if ((err = redux(&M[x], P, mp)) != MP_OKAY) {\n            goto LBL_RES;\n        }\n    }\n\n    /* set initial mode and bit cnt */\n    mode   = 0;\n    bitcnt = 1;\n    buf    = 0;\n    digidx = X->used - 1;\n    bitcpy = 0;\n    bitbuf = 0;\n\n    for ( ; ; ) {\n        /* grab next digit as required */\n        if (--bitcnt == 0) {\n            /* if digidx == -1 we are out of digits so break */\n            if (digidx == -1) {\n                break;\n            }\n            /* read next digit and reset bitcnt */\n            buf    = X->dp[digidx--];\n            bitcnt = (int)DIGIT_BIT;\n        }\n\n        /* grab the next msb from the exponent */\n        y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;\n        buf <<= (mp_digit)1;\n\n        /* if the bit is zero and mode == 0 then we ignore it\n         * These represent the leading zero bits before the first 1 bit\n         * in the exponent.  Technically this opt is not required but it\n         * does lower the # of trivial squaring/reductions used\n         */\n        if ((mode == 0) && (y == 0)) {\n            continue;\n        }\n\n        /* if the bit is zero and mode == 1 then we square */\n        if ((mode == 1) && (y == 0)) {\n            if ((err = mp_sqr(&res, &res)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n            if ((err = redux(&res, P, mp)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n            continue;\n        }\n\n        /* else we add it to the window */\n        bitbuf |= (y << (winsize - ++bitcpy));\n        mode    = 2;\n\n        if (bitcpy == winsize) {\n            /* ok window is filled so square as required and multiply  */\n            /* square first */\n            for (x = 0; x < winsize; x++) {\n                if ((err = mp_sqr(&res, &res)) != MP_OKAY) {\n                    goto LBL_RES;\n                }\n                if ((err = redux(&res, P, mp)) != MP_OKAY) {\n                    goto LBL_RES;\n                }\n            }\n\n            /* then multiply */\n            if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n            if ((err = redux(&res, P, mp)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n\n            /* empty window and reset */\n            bitcpy = 0;\n            bitbuf = 0;\n            mode   = 1;\n        }\n    }\n\n    /* if bits remain then square/multiply */\n    if ((mode == 2) && (bitcpy > 0)) {\n        /* square then multiply if the bit is set */\n        for (x = 0; x < bitcpy; x++) {\n            if ((err = mp_sqr(&res, &res)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n            if ((err = redux(&res, P, mp)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n\n            /* get next bit of the window */\n            bitbuf <<= 1;\n            if ((bitbuf & (1 << winsize)) != 0) {\n                /* then multiply */\n                if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) {\n                    goto LBL_RES;\n                }\n                if ((err = redux(&res, P, mp)) != MP_OKAY) {\n                    goto LBL_RES;\n                }\n            }\n        }\n    }\n\n    if (redmode == 0) {\n        /* fixup result if Montgomery reduction is used\n         * recall that any value in a Montgomery system is\n         * actually multiplied by R mod n.  So we have\n         * to reduce one more time to cancel out the factor\n         * of R.\n         */\n        if ((err = redux(&res, P, mp)) != MP_OKAY) {\n            goto LBL_RES;\n        }\n    }\n\n    /* swap res with Y */\n    mp_exch(&res, Y);\n    err = MP_OKAY;\nLBL_RES: mp_clear(&res);\nLBL_M:\n    mp_clear(&M[1]);\n    for (x = 1 << (winsize - 1); x < (1 << winsize); x++) {\n        mp_clear(&M[x]);\n    }\n    return err;\n}\n#endif\n\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_EXTEUCLID_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* Extended euclidean algorithm of (a, b) produces\n   a*u1 + b*u2 = u3\n */\nint mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) {\n    mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp;\n    int    err;\n\n    if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {\n        return err;\n    }\n\n    /* initialize, (u1,u2,u3) = (1,0,a) */\n    mp_set(&u1, 1);\n    if ((err = mp_copy(a, &u3)) != MP_OKAY) {\n        goto _ERR;\n    }\n\n    /* initialize, (v1,v2,v3) = (0,1,b) */\n    mp_set(&v2, 1);\n    if ((err = mp_copy(b, &v3)) != MP_OKAY) {\n        goto _ERR;\n    }\n\n    /* loop while v3 != 0 */\n    while (mp_iszero(&v3) == MP_NO) {\n        /* q = u3/v3 */\n        if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) {\n            goto _ERR;\n        }\n\n        /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */\n        if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) {\n            goto _ERR;\n        }\n\n        /* (u1,u2,u3) = (v1,v2,v3) */\n        if ((err = mp_copy(&v1, &u1)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_copy(&v2, &u2)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_copy(&v3, &u3)) != MP_OKAY) {\n            goto _ERR;\n        }\n\n        /* (v1,v2,v3) = (t1,t2,t3) */\n        if ((err = mp_copy(&t1, &v1)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_copy(&t2, &v2)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_copy(&t3, &v3)) != MP_OKAY) {\n            goto _ERR;\n        }\n    }\n\n    /* make sure U3 >= 0 */\n    if (u3.sign == MP_NEG) {\n        if ((err = mp_neg(&u1, &u1)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_neg(&u2, &u2)) != MP_OKAY) {\n            goto _ERR;\n        }\n        if ((err = mp_neg(&u3, &u3)) != MP_OKAY) {\n            goto _ERR;\n        }\n    }\n\n    /* copy result out */\n    if (U1 != NULL) {\n        mp_exch(U1, &u1);\n    }\n    if (U2 != NULL) {\n        mp_exch(U2, &u2);\n    }\n    if (U3 != NULL) {\n        mp_exch(U3, &u3);\n    }\n\n    err = MP_OKAY;\n_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_FREAD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* read a bigint from a file stream in ASCII */\nint mp_fread(mp_int *a, int radix, FILE *stream) {\n    int err, ch, neg, y;\n\n    /* clear a */\n    mp_zero(a);\n\n    /* if first digit is - then set negative */\n    ch = fgetc(stream);\n    if (ch == '-') {\n        neg = MP_NEG;\n        ch  = fgetc(stream);\n    } else {\n        neg = MP_ZPOS;\n    }\n\n    for ( ; ; ) {\n        /* find y in the radix map */\n        for (y = 0; y < radix; y++) {\n            if (mp_s_rmap[y] == ch) {\n                break;\n            }\n        }\n        if (y == radix) {\n            break;\n        }\n\n        /* shift up and add */\n        if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {\n            return err;\n        }\n        if ((err = mp_add_d(a, y, a)) != MP_OKAY) {\n            return err;\n        }\n\n        ch = fgetc(stream);\n    }\n    if (mp_cmp_d(a, 0) != MP_EQ) {\n        a->sign = neg;\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_FWRITE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\nint mp_fwrite(mp_int *a, int radix, FILE *stream) {\n    char *buf;\n    int  err, len, x;\n\n    if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {\n        return err;\n    }\n\n    buf = OPT_CAST(char) XMALLOC(len);\n    if (buf == NULL) {\n        return MP_MEM;\n    }\n\n    if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {\n        XFREE(buf);\n        return err;\n    }\n\n    for (x = 0; x < len; x++) {\n        if (fputc(buf[x], stream) == EOF) {\n            XFREE(buf);\n            return MP_VAL;\n        }\n    }\n\n    XFREE(buf);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_GCD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* Greatest Common Divisor using the binary method */\nint mp_gcd(mp_int *a, mp_int *b, mp_int *c) {\n    mp_int u, v;\n    int    k, u_lsb, v_lsb, res;\n\n    /* either zero than gcd is the largest */\n    if (mp_iszero(a) == MP_YES) {\n        return mp_abs(b, c);\n    }\n    if (mp_iszero(b) == MP_YES) {\n        return mp_abs(a, c);\n    }\n\n    /* get copies of a and b we can modify */\n    if ((res = mp_init_copy(&u, a)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_init_copy(&v, b)) != MP_OKAY) {\n        goto LBL_U;\n    }\n\n    /* must be positive for the remainder of the algorithm */\n    u.sign = v.sign = MP_ZPOS;\n\n    /* B1.  Find the common power of two for u and v */\n    u_lsb = mp_cnt_lsb(&u);\n    v_lsb = mp_cnt_lsb(&v);\n    k     = TOM_MIN(u_lsb, v_lsb);\n\n    if (k > 0) {\n        /* divide the power of two out */\n        if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {\n            goto LBL_V;\n        }\n\n        if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {\n            goto LBL_V;\n        }\n    }\n\n    /* divide any remaining factors of two out */\n    if (u_lsb != k) {\n        if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {\n            goto LBL_V;\n        }\n    }\n\n    if (v_lsb != k) {\n        if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {\n            goto LBL_V;\n        }\n    }\n\n    while (mp_iszero(&v) == MP_NO) {\n        /* make sure v is the largest */\n        if (mp_cmp_mag(&u, &v) == MP_GT) {\n            /* swap u and v to make sure v is >= u */\n            mp_exch(&u, &v);\n        }\n\n        /* subtract smallest from largest */\n        if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {\n            goto LBL_V;\n        }\n\n        /* Divide out all factors of two */\n        if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {\n            goto LBL_V;\n        }\n    }\n\n    /* multiply by 2**k which we divided out at the beginning */\n    if ((res = mp_mul_2d(&u, k, c)) != MP_OKAY) {\n        goto LBL_V;\n    }\n    c->sign = MP_ZPOS;\n    res     = MP_OKAY;\nLBL_V: mp_clear(&u);\nLBL_U: mp_clear(&v);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_GET_INT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* get the lower 32-bits of an mp_int */\nunsigned long mp_get_int(mp_int *a) {\n    int        i;\n    mp_min_u32 res;\n\n    if (a->used == 0) {\n        return 0;\n    }\n\n    /* get number of digits of the lsb we have to read */\n    i = TOM_MIN(a->used, (int)(((sizeof(unsigned long) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1;\n\n    /* get most significant digit of result */\n    res = DIGIT(a, i);\n\n    while (--i >= 0) {\n        res = (res << DIGIT_BIT) | DIGIT(a, i);\n    }\n\n    /* force result to 32-bits always so it is consistent on non 32-bit platforms */\n    return res & 0xFFFFFFFFUL;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_GET_LONG_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* get the lower unsigned long of an mp_int, platform dependent */\nunsigned long mp_get_long(mp_int *a) {\n    int           i;\n    unsigned long res;\n\n    if (a->used == 0) {\n        return 0;\n    }\n\n    /* get number of digits of the lsb we have to read */\n    i = TOM_MIN(a->used, (int)(((sizeof(unsigned long) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1;\n\n    /* get most significant digit of result */\n    res = DIGIT(a, i);\n\n #if (ULONG_MAX != 0xffffffffuL) || (DIGIT_BIT < 32)\n    while (--i >= 0) {\n        res = (res << DIGIT_BIT) | DIGIT(a, i);\n    }\n #endif\n    return res;\n}\n#endif\n\n\n\n#ifdef BN_MP_GET_LONG_LONG_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* get the lower unsigned long long of an mp_int, platform dependent */\nunsigned long long mp_get_long_long(mp_int *a) {\n    int i;\n    unsigned long long res;\n\n    if (a->used == 0) {\n        return 0;\n    }\n\n    /* get number of digits of the lsb we have to read */\n    i = TOM_MIN(a->used, (int)(((sizeof(unsigned long long) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1;\n\n    /* get most significant digit of result */\n    res = DIGIT(a, i);\n\n #if DIGIT_BIT < 64\n    while (--i >= 0) {\n        res = (res << DIGIT_BIT) | DIGIT(a, i);\n    }\n #endif\n    return res;\n}\n#endif\n\n\n\n#ifdef BN_MP_GROW_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* grow as required */\nint mp_grow(mp_int *a, int size) {\n    int      i;\n    mp_digit *tmp;\n\n    /* if the alloc size is smaller alloc more ram */\n    if (a->alloc < size) {\n        /* ensure there are always at least MP_PREC digits extra on top */\n        size += (MP_PREC * 2) - (size % MP_PREC);\n\n        /* reallocate the array a->dp\n         *\n         * We store the return in a temporary variable\n         * in case the operation failed we don't want\n         * to overwrite the dp member of a.\n         */\n        tmp = OPT_CAST(mp_digit) XREALLOC(a->dp, sizeof(mp_digit) * size);\n        if (tmp == NULL) {\n            /* reallocation failed but \"a\" is still valid [can be freed] */\n            return MP_MEM;\n        }\n\n        /* reallocation succeeded so set a->dp */\n        a->dp = tmp;\n\n        /* zero excess digits */\n        i        = a->alloc;\n        a->alloc = size;\n        for ( ; i < a->alloc; i++) {\n            a->dp[i] = 0;\n        }\n    }\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_IMPORT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* based on gmp's mpz_import.\n * see http://gmplib.org/manual/Integer-Import-and-Export.html\n */\nint mp_import(mp_int *rop, size_t count, int order, size_t size,\n              int endian, size_t nails, const void *op) {\n    int           result;\n    size_t        odd_nails, nail_bytes, i, j;\n    unsigned char odd_nail_mask;\n\n    mp_zero(rop);\n\n    if (endian == 0) {\n        union {\n            unsigned int i;\n            char         c[4];\n        } lint;\n        lint.i = 0x01020304;\n\n        endian = (lint.c[0] == 4) ? -1 : 1;\n    }\n\n    odd_nails     = (nails % 8);\n    odd_nail_mask = 0xff;\n    for (i = 0; i < odd_nails; ++i) {\n        odd_nail_mask ^= (1 << (7 - i));\n    }\n    nail_bytes = nails / 8;\n\n    for (i = 0; i < count; ++i) {\n        for (j = 0; j < (size - nail_bytes); ++j) {\n            unsigned char byte = *(\n                (unsigned char *)op +\n                (((order == 1) ? i : ((count - 1) - i)) * size) +\n                ((endian == 1) ? (j + nail_bytes) : (((size - 1) - j) - nail_bytes))\n                );\n\n            if (\n                (result = mp_mul_2d(rop, ((j == 0) ? (8 - odd_nails) : 8), rop)) != MP_OKAY) {\n                return result;\n            }\n\n            rop->dp[0] |= (j == 0) ? (byte & odd_nail_mask) : byte;\n            rop->used  += 1;\n        }\n    }\n\n    mp_clamp(rop);\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_INIT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* init a new mp_int */\nint mp_init(mp_int *a) {\n    int i;\n\n    /* allocate memory required and clear it */\n    a->dp = OPT_CAST(mp_digit) XMALLOC(sizeof(mp_digit) * MP_PREC);\n    if (a->dp == NULL) {\n        return MP_MEM;\n    }\n\n    /* set the digits to zero */\n    for (i = 0; i < MP_PREC; i++) {\n        a->dp[i] = 0;\n    }\n\n    /* set the used to zero, allocated digits to the default precision\n     * and sign to positive */\n    a->used  = 0;\n    a->alloc = MP_PREC;\n    a->sign  = MP_ZPOS;\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_INIT_COPY_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* creates \"a\" then copies b into it */\nint mp_init_copy(mp_int *a, mp_int *b) {\n    int res;\n\n    if ((res = mp_init_size(a, b->used)) != MP_OKAY) {\n        return res;\n    }\n    return mp_copy(b, a);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_INIT_MULTI_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\nint mp_init_multi(mp_int *mp, ...) {\n    mp_err  res      = MP_OKAY; /* Assume ok until proven otherwise */\n    int     n        = 0;       /* Number of ok inits */\n    mp_int  *cur_arg = mp;\n    va_list args;\n\n    va_start(args, mp);        /* init args to next argument from caller */\n    while (cur_arg != NULL) {\n        if (mp_init(cur_arg) != MP_OKAY) {\n            /* Oops - error! Back-track and mp_clear what we already\n               succeeded in init-ing, then return error.\n             */\n            va_list clean_args;\n\n            /* end the current list */\n            va_end(args);\n\n            /* now start cleaning up */\n            cur_arg = mp;\n            va_start(clean_args, mp);\n            while (n-- != 0) {\n                mp_clear(cur_arg);\n                cur_arg = va_arg(clean_args, mp_int *);\n            }\n            va_end(clean_args);\n            res = MP_MEM;\n            break;\n        }\n        n++;\n        cur_arg = va_arg(args, mp_int *);\n    }\n    va_end(args);\n    return res;                /* Assumed ok, if error flagged above. */\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_INIT_SET_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* initialize and set a digit */\nint mp_init_set(mp_int *a, mp_digit b) {\n    int err;\n\n    if ((err = mp_init(a)) != MP_OKAY) {\n        return err;\n    }\n    mp_set(a, b);\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_INIT_SET_INT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* initialize and set a digit */\nint mp_init_set_int(mp_int *a, unsigned long b) {\n    int err;\n\n    if ((err = mp_init(a)) != MP_OKAY) {\n        return err;\n    }\n    return mp_set_int(a, b);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_INIT_SIZE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* init an mp_init for a given size */\nint mp_init_size(mp_int *a, int size) {\n    int x;\n\n    /* pad size so there are always extra digits */\n    size += (MP_PREC * 2) - (size % MP_PREC);\n\n    /* alloc mem */\n    a->dp = OPT_CAST(mp_digit) XMALLOC(sizeof(mp_digit) * size);\n    if (a->dp == NULL) {\n        return MP_MEM;\n    }\n\n    /* set the members */\n    a->used  = 0;\n    a->alloc = size;\n    a->sign  = MP_ZPOS;\n\n    /* zero the digits */\n    for (x = 0; x < size; x++) {\n        a->dp[x] = 0;\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_INVMOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* hac 14.61, pp608 */\nint mp_invmod(mp_int *a, mp_int *b, mp_int *c) {\n    /* b cannot be negative */\n    if ((b->sign == MP_NEG) || (mp_iszero(b) == MP_YES)) {\n        return MP_VAL;\n    }\n\n #ifdef BN_FAST_MP_INVMOD_C\n    /* if the modulus is odd we can use a faster routine instead */\n    if (mp_isodd(b) == MP_YES) {\n        return fast_mp_invmod(a, b, c);\n    }\n #endif\n\n #ifdef BN_MP_INVMOD_SLOW_C\n    return mp_invmod_slow(a, b, c);\n #else\n    return MP_VAL;\n #endif\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_INVMOD_SLOW_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* hac 14.61, pp608 */\nint mp_invmod_slow(mp_int *a, mp_int *b, mp_int *c) {\n    mp_int x, y, u, v, A, B, C, D;\n    int    res;\n\n    /* b cannot be negative */\n    if ((b->sign == MP_NEG) || (mp_iszero(b) == MP_YES)) {\n        return MP_VAL;\n    }\n\n    /* init temps */\n    if ((res = mp_init_multi(&x, &y, &u, &v,\n                             &A, &B, &C, &D, NULL)) != MP_OKAY) {\n        return res;\n    }\n\n    /* x = a, y = b */\n    if ((res = mp_mod(a, b, &x)) != MP_OKAY) {\n        goto LBL_ERR;\n    }\n    if ((res = mp_copy(b, &y)) != MP_OKAY) {\n        goto LBL_ERR;\n    }\n\n    /* 2. [modified] if x,y are both even then return an error! */\n    if ((mp_iseven(&x) == MP_YES) && (mp_iseven(&y) == MP_YES)) {\n        res = MP_VAL;\n        goto LBL_ERR;\n    }\n\n    /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */\n    if ((res = mp_copy(&x, &u)) != MP_OKAY) {\n        goto LBL_ERR;\n    }\n    if ((res = mp_copy(&y, &v)) != MP_OKAY) {\n        goto LBL_ERR;\n    }\n    mp_set(&A, 1);\n    mp_set(&D, 1);\n\ntop:\n    /* 4.  while u is even do */\n    while (mp_iseven(&u) == MP_YES) {\n        /* 4.1 u = u/2 */\n        if ((res = mp_div_2(&u, &u)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n        /* 4.2 if A or B is odd then */\n        if ((mp_isodd(&A) == MP_YES) || (mp_isodd(&B) == MP_YES)) {\n            /* A = (A+y)/2, B = (B-x)/2 */\n            if ((res = mp_add(&A, &y, &A)) != MP_OKAY) {\n                goto LBL_ERR;\n            }\n            if ((res = mp_sub(&B, &x, &B)) != MP_OKAY) {\n                goto LBL_ERR;\n            }\n        }\n        /* A = A/2, B = B/2 */\n        if ((res = mp_div_2(&A, &A)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n        if ((res = mp_div_2(&B, &B)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* 5.  while v is even do */\n    while (mp_iseven(&v) == MP_YES) {\n        /* 5.1 v = v/2 */\n        if ((res = mp_div_2(&v, &v)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n        /* 5.2 if C or D is odd then */\n        if ((mp_isodd(&C) == MP_YES) || (mp_isodd(&D) == MP_YES)) {\n            /* C = (C+y)/2, D = (D-x)/2 */\n            if ((res = mp_add(&C, &y, &C)) != MP_OKAY) {\n                goto LBL_ERR;\n            }\n            if ((res = mp_sub(&D, &x, &D)) != MP_OKAY) {\n                goto LBL_ERR;\n            }\n        }\n        /* C = C/2, D = D/2 */\n        if ((res = mp_div_2(&C, &C)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n        if ((res = mp_div_2(&D, &D)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* 6.  if u >= v then */\n    if (mp_cmp(&u, &v) != MP_LT) {\n        /* u = u - v, A = A - C, B = B - D */\n        if ((res = mp_sub(&u, &v, &u)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n\n        if ((res = mp_sub(&A, &C, &A)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n\n        if ((res = mp_sub(&B, &D, &B)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    } else {\n        /* v - v - u, C = C - A, D = D - B */\n        if ((res = mp_sub(&v, &u, &v)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n\n        if ((res = mp_sub(&C, &A, &C)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n\n        if ((res = mp_sub(&D, &B, &D)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* if not zero goto step 4 */\n    if (mp_iszero(&u) == MP_NO)\n        goto top;\n\n    /* now a = C, b = D, gcd == g*v */\n\n    /* if v != 1 then there is no inverse */\n    if (mp_cmp_d(&v, 1) != MP_EQ) {\n        res = MP_VAL;\n        goto LBL_ERR;\n    }\n\n    /* if its too low */\n    while (mp_cmp_d(&C, 0) == MP_LT) {\n        if ((res = mp_add(&C, b, &C)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* too big */\n    while (mp_cmp_mag(&C, b) != MP_LT) {\n        if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* C is now the inverse */\n    mp_exch(&C, c);\n    res = MP_OKAY;\nLBL_ERR: mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_IS_SQUARE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* Check if remainders are possible squares - fast exclude non-squares */\nstatic const char rem_128[128] = {\n    0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,\n    0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,\n    1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,\n    1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,\n    0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,\n    1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,\n    1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,\n    1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1\n};\n\nstatic const char rem_105[105] = {\n    0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,\n    0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,\n    0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,\n    1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,\n    0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,\n    1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,\n    1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1\n};\n\n/* Store non-zero to ret if arg is square, and zero if not */\nint mp_is_square(mp_int *arg, int *ret) {\n    int           res;\n    mp_digit      c;\n    mp_int        t;\n    unsigned long r;\n\n    /* Default to Non-square :) */\n    *ret = MP_NO;\n\n    if (arg->sign == MP_NEG) {\n        return MP_VAL;\n    }\n\n    /* digits used?  (TSD) */\n    if (arg->used == 0) {\n        return MP_OKAY;\n    }\n\n    /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */\n    if (rem_128[127 & DIGIT(arg, 0)] == 1) {\n        return MP_OKAY;\n    }\n\n    /* Next check mod 105 (3*5*7) */\n    if ((res = mp_mod_d(arg, 105, &c)) != MP_OKAY) {\n        return res;\n    }\n    if (rem_105[c] == 1) {\n        return MP_OKAY;\n    }\n\n\n    if ((res = mp_init_set_int(&t, 11L * 13L * 17L * 19L * 23L * 29L * 31L)) != MP_OKAY) {\n        return res;\n    }\n    if ((res = mp_mod(arg, &t, &t)) != MP_OKAY) {\n        goto ERR;\n    }\n    r = mp_get_int(&t);\n\n    /* Check for other prime modules, note it's not an ERROR but we must\n     * free \"t\" so the easiest way is to goto ERR.  We know that res\n     * is already equal to MP_OKAY from the mp_mod call\n     */\n    if (((1L << (r % 11)) & 0x5C4L) != 0L) goto ERR;\n    if (((1L << (r % 13)) & 0x9E4L) != 0L) goto ERR;\n    if (((1L << (r % 17)) & 0x5CE8L) != 0L) goto ERR;\n    if (((1L << (r % 19)) & 0x4F50CL) != 0L) goto ERR;\n    if (((1L << (r % 23)) & 0x7ACCA0L) != 0L) goto ERR;\n    if (((1L << (r % 29)) & 0xC2EDD0CL) != 0L) goto ERR;\n    if (((1L << (r % 31)) & 0x6DE2B848L) != 0L) goto ERR;\n\n    /* Final check - is sqr(sqrt(arg)) == arg ? */\n    if ((res = mp_sqrt(arg, &t)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sqr(&t, &t)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    *ret = (mp_cmp_mag(&t, arg) == MP_EQ) ? MP_YES : MP_NO;\nERR: mp_clear(&t);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_JACOBI_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* computes the jacobi c = (a | n) (or Legendre if n is prime)\n * HAC pp. 73 Algorithm 2.149\n * HAC is wrong here, as the special case of (0 | 1) is not\n * handled correctly.\n */\nint mp_jacobi(mp_int *a, mp_int *n, int *c) {\n    mp_int   a1, p1;\n    int      k, s, r, res;\n    mp_digit residue;\n\n    /* if n <= 0 return MP_VAL */\n    if (mp_cmp_d(n, 0) != MP_GT) {\n        return MP_VAL;\n    }\n\n    /* step 1. handle case of a == 0 */\n    if (mp_iszero(a) == MP_YES) {\n        /* special case of a == 0 and n == 1 */\n        if (mp_cmp_d(n, 1) == MP_EQ) {\n            *c = 1;\n        } else {\n            *c = 0;\n        }\n        return MP_OKAY;\n    }\n\n    /* step 2.  if a == 1, return 1 */\n    if (mp_cmp_d(a, 1) == MP_EQ) {\n        *c = 1;\n        return MP_OKAY;\n    }\n\n    /* default */\n    s = 0;\n\n    /* step 3.  write a = a1 * 2**k  */\n    if ((res = mp_init_copy(&a1, a)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_init(&p1)) != MP_OKAY) {\n        goto LBL_A1;\n    }\n\n    /* divide out larger power of two */\n    k = mp_cnt_lsb(&a1);\n    if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {\n        goto LBL_P1;\n    }\n\n    /* step 4.  if e is even set s=1 */\n    if ((k & 1) == 0) {\n        s = 1;\n    } else {\n        /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */\n        residue = n->dp[0] & 7;\n\n        if ((residue == 1) || (residue == 7)) {\n            s = 1;\n        } else if ((residue == 3) || (residue == 5)) {\n            s = -1;\n        }\n    }\n\n    /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */\n    if (((n->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {\n        s = -s;\n    }\n\n    /* if a1 == 1 we're done */\n    if (mp_cmp_d(&a1, 1) == MP_EQ) {\n        *c = s;\n    } else {\n        /* n1 = n mod a1 */\n        if ((res = mp_mod(n, &a1, &p1)) != MP_OKAY) {\n            goto LBL_P1;\n        }\n        if ((res = mp_jacobi(&p1, &a1, &r)) != MP_OKAY) {\n            goto LBL_P1;\n        }\n        *c = s * r;\n    }\n\n    /* done */\n    res = MP_OKAY;\nLBL_P1: mp_clear(&p1);\nLBL_A1: mp_clear(&a1);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_KARATSUBA_MUL_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* c = |a| * |b| using Karatsuba Multiplication using\n * three half size multiplications\n *\n * Let B represent the radix [e.g. 2**DIGIT_BIT] and\n * let n represent half of the number of digits in\n * the min(a,b)\n *\n * a = a1 * B**n + a0\n * b = b1 * B**n + b0\n *\n * Then, a * b =>\n   a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0\n *\n * Note that a1b1 and a0b0 are used twice and only need to be\n * computed once.  So in total three half size (half # of\n * digit) multiplications are performed, a0b0, a1b1 and\n * (a1+b1)(a0+b0)\n *\n * Note that a multiplication of half the digits requires\n * 1/4th the number of single precision multiplications so in\n * total after one call 25% of the single precision multiplications\n * are saved.  Note also that the call to mp_mul can end up back\n * in this function if the a0, a1, b0, or b1 are above the threshold.\n * This is known as divide-and-conquer and leads to the famous\n * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than\n * the standard O(N**2) that the baseline/comba methods use.\n * Generally though the overhead of this method doesn't pay off\n * until a certain size (N ~ 80) is reached.\n */\nint mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c) {\n    mp_int x0, x1, y0, y1, t1, x0y0, x1y1;\n    int    B, err;\n\n    /* default the return code to an error */\n    err = MP_MEM;\n\n    /* min # of digits */\n    B = TOM_MIN(a->used, b->used);\n\n    /* now divide in two */\n    B = B >> 1;\n\n    /* init copy all the temps */\n    if (mp_init_size(&x0, B) != MP_OKAY)\n        goto ERR;\n    if (mp_init_size(&x1, a->used - B) != MP_OKAY)\n        goto X0;\n    if (mp_init_size(&y0, B) != MP_OKAY)\n        goto X1;\n    if (mp_init_size(&y1, b->used - B) != MP_OKAY)\n        goto Y0;\n\n    /* init temps */\n    if (mp_init_size(&t1, B * 2) != MP_OKAY)\n        goto Y1;\n    if (mp_init_size(&x0y0, B * 2) != MP_OKAY)\n        goto T1;\n    if (mp_init_size(&x1y1, B * 2) != MP_OKAY)\n        goto X0Y0;\n\n    /* now shift the digits */\n    x0.used = y0.used = B;\n    x1.used = a->used - B;\n    y1.used = b->used - B;\n\n    {\n        int      x;\n        mp_digit *tmpa, *tmpb, *tmpx, *tmpy;\n\n        /* we copy the digits directly instead of using higher level functions\n         * since we also need to shift the digits\n         */\n        tmpa = a->dp;\n        tmpb = b->dp;\n\n        tmpx = x0.dp;\n        tmpy = y0.dp;\n        for (x = 0; x < B; x++) {\n            *tmpx++ = *tmpa++;\n            *tmpy++ = *tmpb++;\n        }\n\n        tmpx = x1.dp;\n        for (x = B; x < a->used; x++) {\n            *tmpx++ = *tmpa++;\n        }\n\n        tmpy = y1.dp;\n        for (x = B; x < b->used; x++) {\n            *tmpy++ = *tmpb++;\n        }\n    }\n\n    /* only need to clamp the lower words since by definition the\n     * upper words x1/y1 must have a known number of digits\n     */\n    mp_clamp(&x0);\n    mp_clamp(&y0);\n\n    /* now calc the products x0y0 and x1y1 */\n    /* after this x0 is no longer required, free temp [x0==t2]! */\n    if (mp_mul(&x0, &y0, &x0y0) != MP_OKAY)\n        goto X1Y1;      /* x0y0 = x0*y0 */\n    if (mp_mul(&x1, &y1, &x1y1) != MP_OKAY)\n        goto X1Y1;      /* x1y1 = x1*y1 */\n\n    /* now calc x1+x0 and y1+y0 */\n    if (s_mp_add(&x1, &x0, &t1) != MP_OKAY)\n        goto X1Y1;      /* t1 = x1 - x0 */\n    if (s_mp_add(&y1, &y0, &x0) != MP_OKAY)\n        goto X1Y1;      /* t2 = y1 - y0 */\n    if (mp_mul(&t1, &x0, &t1) != MP_OKAY)\n        goto X1Y1;      /* t1 = (x1 + x0) * (y1 + y0) */\n\n    /* add x0y0 */\n    if (mp_add(&x0y0, &x1y1, &x0) != MP_OKAY)\n        goto X1Y1;      /* t2 = x0y0 + x1y1 */\n    if (s_mp_sub(&t1, &x0, &t1) != MP_OKAY)\n        goto X1Y1;      /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */\n\n    /* shift by B */\n    if (mp_lshd(&t1, B) != MP_OKAY)\n        goto X1Y1;      /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */\n    if (mp_lshd(&x1y1, B * 2) != MP_OKAY)\n        goto X1Y1;      /* x1y1 = x1y1 << 2*B */\n\n    if (mp_add(&x0y0, &t1, &t1) != MP_OKAY)\n        goto X1Y1;      /* t1 = x0y0 + t1 */\n    if (mp_add(&t1, &x1y1, c) != MP_OKAY)\n        goto X1Y1;      /* t1 = x0y0 + t1 + x1y1 */\n\n    /* Algorithm succeeded set the return code to MP_OKAY */\n    err = MP_OKAY;\n\nX1Y1: mp_clear(&x1y1);\nX0Y0: mp_clear(&x0y0);\nT1: mp_clear(&t1);\nY1: mp_clear(&y1);\nY0: mp_clear(&y0);\nX1: mp_clear(&x1);\nX0: mp_clear(&x0);\nERR:\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_KARATSUBA_SQR_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* Karatsuba squaring, computes b = a*a using three\n * half size squarings\n *\n * See comments of karatsuba_mul for details.  It\n * is essentially the same algorithm but merely\n * tuned to perform recursive squarings.\n */\nint mp_karatsuba_sqr(mp_int *a, mp_int *b) {\n    mp_int x0, x1, t1, t2, x0x0, x1x1;\n    int    B, err;\n\n    err = MP_MEM;\n\n    /* min # of digits */\n    B = a->used;\n\n    /* now divide in two */\n    B = B >> 1;\n\n    /* init copy all the temps */\n    if (mp_init_size(&x0, B) != MP_OKAY)\n        goto ERR;\n    if (mp_init_size(&x1, a->used - B) != MP_OKAY)\n        goto X0;\n\n    /* init temps */\n    if (mp_init_size(&t1, a->used * 2) != MP_OKAY)\n        goto X1;\n    if (mp_init_size(&t2, a->used * 2) != MP_OKAY)\n        goto T1;\n    if (mp_init_size(&x0x0, B * 2) != MP_OKAY)\n        goto T2;\n    if (mp_init_size(&x1x1, (a->used - B) * 2) != MP_OKAY)\n        goto X0X0;\n\n    {\n        int      x;\n        mp_digit *dst, *src;\n\n        src = a->dp;\n\n        /* now shift the digits */\n        dst = x0.dp;\n        for (x = 0; x < B; x++) {\n            *dst++ = *src++;\n        }\n\n        dst = x1.dp;\n        for (x = B; x < a->used; x++) {\n            *dst++ = *src++;\n        }\n    }\n\n    x0.used = B;\n    x1.used = a->used - B;\n\n    mp_clamp(&x0);\n\n    /* now calc the products x0*x0 and x1*x1 */\n    if (mp_sqr(&x0, &x0x0) != MP_OKAY)\n        goto X1X1;       /* x0x0 = x0*x0 */\n    if (mp_sqr(&x1, &x1x1) != MP_OKAY)\n        goto X1X1;       /* x1x1 = x1*x1 */\n\n    /* now calc (x1+x0)**2 */\n    if (s_mp_add(&x1, &x0, &t1) != MP_OKAY)\n        goto X1X1;       /* t1 = x1 - x0 */\n    if (mp_sqr(&t1, &t1) != MP_OKAY)\n        goto X1X1;       /* t1 = (x1 - x0) * (x1 - x0) */\n\n    /* add x0y0 */\n    if (s_mp_add(&x0x0, &x1x1, &t2) != MP_OKAY)\n        goto X1X1;       /* t2 = x0x0 + x1x1 */\n    if (s_mp_sub(&t1, &t2, &t1) != MP_OKAY)\n        goto X1X1;       /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */\n\n    /* shift by B */\n    if (mp_lshd(&t1, B) != MP_OKAY)\n        goto X1X1;       /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */\n    if (mp_lshd(&x1x1, B * 2) != MP_OKAY)\n        goto X1X1;       /* x1x1 = x1x1 << 2*B */\n\n    if (mp_add(&x0x0, &t1, &t1) != MP_OKAY)\n        goto X1X1;       /* t1 = x0x0 + t1 */\n    if (mp_add(&t1, &x1x1, b) != MP_OKAY)\n        goto X1X1;       /* t1 = x0x0 + t1 + x1x1 */\n\n    err = MP_OKAY;\n\nX1X1: mp_clear(&x1x1);\nX0X0: mp_clear(&x0x0);\nT2: mp_clear(&t2);\nT1: mp_clear(&t1);\nX1: mp_clear(&x1);\nX0: mp_clear(&x0);\nERR:\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_LCM_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* computes least common multiple as |a*b|/(a, b) */\nint mp_lcm(mp_int *a, mp_int *b, mp_int *c) {\n    int    res;\n    mp_int t1, t2;\n\n\n    if ((res = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) {\n        return res;\n    }\n\n    /* t1 = get the GCD of the two inputs */\n    if ((res = mp_gcd(a, b, &t1)) != MP_OKAY) {\n        goto LBL_T;\n    }\n\n    /* divide the smallest by the GCD */\n    if (mp_cmp_mag(a, b) == MP_LT) {\n        /* store quotient in t2 such that t2 * b is the LCM */\n        if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {\n            goto LBL_T;\n        }\n        res = mp_mul(b, &t2, c);\n    } else {\n        /* store quotient in t2 such that t2 * a is the LCM */\n        if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {\n            goto LBL_T;\n        }\n        res = mp_mul(a, &t2, c);\n    }\n\n    /* fix the sign to positive */\n    c->sign = MP_ZPOS;\n\nLBL_T:\n    mp_clear_multi(&t1, &t2, NULL);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_LSHD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* shift left a certain amount of digits */\nint mp_lshd(mp_int *a, int b) {\n    int x, res;\n\n    /* if its less than zero return */\n    if (b <= 0) {\n        return MP_OKAY;\n    }\n\n    /* grow to fit the new digits */\n    if (a->alloc < (a->used + b)) {\n        if ((res = mp_grow(a, a->used + b)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    {\n        mp_digit *top, *bottom;\n\n        /* increment the used by the shift amount then copy upwards */\n        a->used += b;\n\n        /* top */\n        top = a->dp + a->used - 1;\n\n        /* base */\n        bottom = (a->dp + a->used - 1) - b;\n\n        /* much like mp_rshd this is implemented using a sliding window\n         * except the window goes the otherway around.  Copying from\n         * the bottom to the top.  see bn_mp_rshd.c for more info.\n         */\n        for (x = a->used - 1; x >= b; x--) {\n            *top-- = *bottom--;\n        }\n\n        /* zero the lower digits */\n        top = a->dp;\n        for (x = 0; x < b; x++) {\n            *top++ = 0;\n        }\n    }\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* c = a mod b, 0 <= c < b if b > 0, b < c <= 0 if b < 0 */\nint\nmp_mod(mp_int *a, mp_int *b, mp_int *c) {\n    mp_int t;\n    int    res;\n\n    if ((res = mp_init(&t)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_div(a, b, NULL, &t)) != MP_OKAY) {\n        mp_clear(&t);\n        return res;\n    }\n\n    if ((mp_iszero(&t) != MP_NO) || (t.sign == b->sign)) {\n        res = MP_OKAY;\n        mp_exch(&t, c);\n    } else {\n        res = mp_add(b, &t, c);\n    }\n\n    mp_clear(&t);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MOD_2D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* calc a value mod 2**b */\nint\nmp_mod_2d(mp_int *a, int b, mp_int *c) {\n    int x, res;\n\n    /* if b is <= 0 then zero the int */\n    if (b <= 0) {\n        mp_zero(c);\n        return MP_OKAY;\n    }\n\n    /* if the modulus is larger than the value than return */\n    if (b >= (int)(a->used * DIGIT_BIT)) {\n        res = mp_copy(a, c);\n        return res;\n    }\n\n    /* copy */\n    if ((res = mp_copy(a, c)) != MP_OKAY) {\n        return res;\n    }\n\n    /* zero digits above the last digit of the modulus */\n    for (x = (b / DIGIT_BIT) + (((b % DIGIT_BIT) == 0) ? 0 : 1); x < c->used; x++) {\n        c->dp[x] = 0;\n    }\n    /* clear the digit that is not completely outside/inside the modulus */\n    c->dp[b / DIGIT_BIT] &=\n        (mp_digit)((((mp_digit)1) << (((mp_digit)b) % DIGIT_BIT)) - ((mp_digit)1));\n    mp_clamp(c);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MOD_D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\nint\nmp_mod_d(mp_int *a, mp_digit b, mp_digit *c) {\n    return mp_div_d(a, b, NULL, c);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/*\n * shifts with subtractions when the result is greater than b.\n *\n * The method is slightly modified to shift B unconditionally upto just under\n * the leading bit of b.  This saves alot of multiple precision shifting.\n */\nint mp_montgomery_calc_normalization(mp_int *a, mp_int *b) {\n    int x, bits, res;\n\n    /* how many bits of last digit does b use */\n    bits = mp_count_bits(b) % DIGIT_BIT;\n\n    if (b->used > 1) {\n        if ((res = mp_2expt(a, ((b->used - 1) * DIGIT_BIT) + bits - 1)) != MP_OKAY) {\n            return res;\n        }\n    } else {\n        mp_set(a, 1);\n        bits = 1;\n    }\n\n\n    /* now compute C = A * B mod b */\n    for (x = bits - 1; x < (int)DIGIT_BIT; x++) {\n        if ((res = mp_mul_2(a, a)) != MP_OKAY) {\n            return res;\n        }\n        if (mp_cmp_mag(a, b) != MP_LT) {\n            if ((res = s_mp_sub(a, b, a)) != MP_OKAY) {\n                return res;\n            }\n        }\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MONTGOMERY_REDUCE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* computes xR**-1 == x (mod N) via Montgomery Reduction */\nint\nmp_montgomery_reduce(mp_int *x, mp_int *n, mp_digit rho) {\n    int      ix, res, digs;\n    mp_digit mu;\n\n    /* can the fast reduction [comba] method be used?\n     *\n     * Note that unlike in mul you're safely allowed *less*\n     * than the available columns [255 per default] since carries\n     * are fixed up in the inner loop.\n     */\n    digs = (n->used * 2) + 1;\n    if ((digs < MP_WARRAY) &&\n        (n->used <\n         (1 << ((CHAR_BIT * sizeof(mp_word)) - (2 * DIGIT_BIT))))) {\n        return fast_mp_montgomery_reduce(x, n, rho);\n    }\n\n    /* grow the input as required */\n    if (x->alloc < digs) {\n        if ((res = mp_grow(x, digs)) != MP_OKAY) {\n            return res;\n        }\n    }\n    x->used = digs;\n\n    for (ix = 0; ix < n->used; ix++) {\n        /* mu = ai * rho mod b\n         *\n         * The value of rho must be precalculated via\n         * montgomery_setup() such that\n         * it equals -1/n0 mod b this allows the\n         * following inner loop to reduce the\n         * input one digit at a time\n         */\n        mu = (mp_digit)(((mp_word)x->dp[ix] * (mp_word)rho) & MP_MASK);\n\n        /* a = a + mu * m * b**i */\n        {\n            int      iy;\n            mp_digit *tmpn, *tmpx, u;\n            mp_word  r;\n\n            /* alias for digits of the modulus */\n            tmpn = n->dp;\n\n            /* alias for the digits of x [the input] */\n            tmpx = x->dp + ix;\n\n            /* set the carry to zero */\n            u = 0;\n\n            /* Multiply and add in place */\n            for (iy = 0; iy < n->used; iy++) {\n                /* compute product and sum */\n                r = ((mp_word)mu * (mp_word) * tmpn++) +\n                    (mp_word)u + (mp_word) * tmpx;\n\n                /* get carry */\n                u = (mp_digit)(r >> ((mp_word)DIGIT_BIT));\n\n                /* fix digit */\n                *tmpx++ = (mp_digit)(r & ((mp_word)MP_MASK));\n            }\n            /* At this point the ix'th digit of x should be zero */\n\n\n            /* propagate carries upwards as required*/\n            while (u != 0) {\n                *tmpx   += u;\n                u        = *tmpx >> DIGIT_BIT;\n                *tmpx++ &= MP_MASK;\n            }\n        }\n    }\n\n    /* at this point the n.used'th least\n     * significant digits of x are all zero\n     * which means we can shift x to the\n     * right by n.used digits and the\n     * residue is unchanged.\n     */\n\n    /* x = x/b**n.used */\n    mp_clamp(x);\n    mp_rshd(x, n->used);\n\n    /* if x >= n then x = x - n */\n    if (mp_cmp_mag(x, n) != MP_LT) {\n        return s_mp_sub(x, n, x);\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MONTGOMERY_SETUP_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* setups the montgomery reduction stuff */\nint\nmp_montgomery_setup(mp_int *n, mp_digit *rho) {\n    mp_digit x, b;\n\n/* fast inversion mod 2**k\n *\n * Based on the fact that\n *\n * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)\n *                    =>  2*X*A - X*X*A*A = 1\n *                    =>  2*(1) - (1)     = 1\n */\n    b = n->dp[0];\n\n    if ((b & 1) == 0) {\n        return MP_VAL;\n    }\n\n    x  = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */\n    x *= 2 - (b * x);              /* here x*a==1 mod 2**8 */\n #if !defined(MP_8BIT)\n    x *= 2 - (b * x);              /* here x*a==1 mod 2**16 */\n #endif\n #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))\n    x *= 2 - (b * x);           /* here x*a==1 mod 2**32 */\n #endif\n #ifdef MP_64BIT\n    x *= 2 - (b * x);           /* here x*a==1 mod 2**64 */\n #endif\n\n    /* rho = -1/m mod b */\n    *rho = (mp_digit)(((mp_word)1 << ((mp_word)DIGIT_BIT)) - x) & MP_MASK;\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MUL_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* high level multiplication (handles sign) */\nint mp_mul(mp_int *a, mp_int *b, mp_int *c) {\n    int res, neg;\n\n    neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;\n\n    /* use Toom-Cook? */\n #ifdef BN_MP_TOOM_MUL_C\n    if (TOM_MIN(a->used, b->used) >= TOOM_MUL_CUTOFF) {\n        res = mp_toom_mul(a, b, c);\n    } else\n #endif\n #ifdef BN_MP_KARATSUBA_MUL_C\n    /* use Karatsuba? */\n    if (TOM_MIN(a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {\n        res = mp_karatsuba_mul(a, b, c);\n    } else\n #endif\n    {\n        /* can we use the fast multiplier?\n         *\n         * The fast multiplier can be used if the output will\n         * have less than MP_WARRAY digits and the number of\n         * digits won't affect carry propagation\n         */\n        int digs = a->used + b->used + 1;\n\n #ifdef BN_FAST_S_MP_MUL_DIGS_C\n        if ((digs < MP_WARRAY) &&\n            (TOM_MIN(a->used, b->used) <=\n             (1 << ((CHAR_BIT * sizeof(mp_word)) - (2 * DIGIT_BIT))))) {\n            res = fast_s_mp_mul_digs(a, b, c, digs);\n        } else\n #endif\n        {\n #ifdef BN_S_MP_MUL_DIGS_C\n            res = s_mp_mul(a, b, c); /* uses s_mp_mul_digs */\n #else\n            res = MP_VAL;\n #endif\n        }\n    }\n    c->sign = (c->used > 0) ? neg : MP_ZPOS;\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MUL_2_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* b = a*2 */\nint mp_mul_2(mp_int *a, mp_int *b) {\n    int x, res, oldused;\n\n    /* grow to accomodate result */\n    if (b->alloc < (a->used + 1)) {\n        if ((res = mp_grow(b, a->used + 1)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    oldused = b->used;\n    b->used = a->used;\n\n    {\n        mp_digit r, rr, *tmpa, *tmpb;\n\n        /* alias for source */\n        tmpa = a->dp;\n\n        /* alias for dest */\n        tmpb = b->dp;\n\n        /* carry */\n        r = 0;\n        for (x = 0; x < a->used; x++) {\n            /* get what will be the *next* carry bit from the\n             * MSB of the current digit\n             */\n            rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));\n\n            /* now shift up this digit, add in the carry [from the previous] */\n            *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;\n\n            /* copy the carry that would be from the source\n             * digit into the next iteration\n             */\n            r = rr;\n        }\n\n        /* new leading digit? */\n        if (r != 0) {\n            /* add a MSB which is always 1 at this point */\n            *tmpb = 1;\n            ++(b->used);\n        }\n\n        /* now zero any excess digits on the destination\n         * that we didn't write to\n         */\n        tmpb = b->dp + b->used;\n        for (x = b->used; x < oldused; x++) {\n            *tmpb++ = 0;\n        }\n    }\n    b->sign = a->sign;\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MUL_2D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* shift left by a certain bit count */\nint mp_mul_2d(mp_int *a, int b, mp_int *c) {\n    mp_digit d;\n    int      res;\n\n    /* copy */\n    if (a != c) {\n        if ((res = mp_copy(a, c)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    if (c->alloc < (int)(c->used + (b / DIGIT_BIT) + 1)) {\n        if ((res = mp_grow(c, c->used + (b / DIGIT_BIT) + 1)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* shift by as many digits in the bit count */\n    if (b >= (int)DIGIT_BIT) {\n        if ((res = mp_lshd(c, b / DIGIT_BIT)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* shift any bit count < DIGIT_BIT */\n    d = (mp_digit)(b % DIGIT_BIT);\n    if (d != 0) {\n        mp_digit *tmpc, shift, mask, r, rr;\n        int      x;\n\n        /* bitmask for carries */\n        mask = (((mp_digit)1) << d) - 1;\n\n        /* shift for msbs */\n        shift = DIGIT_BIT - d;\n\n        /* alias */\n        tmpc = c->dp;\n\n        /* carry */\n        r = 0;\n        for (x = 0; x < c->used; x++) {\n            /* get the higher bits of the current word */\n            rr = (*tmpc >> shift) & mask;\n\n            /* shift the current word and OR in the carry */\n            *tmpc = ((*tmpc << d) | r) & MP_MASK;\n            ++tmpc;\n\n            /* set the carry to the carry bits of the current word */\n            r = rr;\n        }\n\n        /* set final carry */\n        if (r != 0) {\n            c->dp[(c->used)++] = r;\n        }\n    }\n    mp_clamp(c);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MUL_D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* multiply by a digit */\nint\nmp_mul_d(mp_int *a, mp_digit b, mp_int *c) {\n    mp_digit u, *tmpa, *tmpc;\n    mp_word  r;\n    int      ix, res, olduse;\n\n    /* make sure c is big enough to hold a*b */\n    if (c->alloc < (a->used + 1)) {\n        if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* get the original destinations used count */\n    olduse = c->used;\n\n    /* set the sign */\n    c->sign = a->sign;\n\n    /* alias for a->dp [source] */\n    tmpa = a->dp;\n\n    /* alias for c->dp [dest] */\n    tmpc = c->dp;\n\n    /* zero carry */\n    u = 0;\n\n    /* compute columns */\n    for (ix = 0; ix < a->used; ix++) {\n        /* compute product and carry sum for this term */\n        r = (mp_word)u + ((mp_word) * tmpa++ *(mp_word)b);\n\n        /* mask off higher bits to get a single digit */\n        *tmpc++ = (mp_digit)(r & ((mp_word)MP_MASK));\n\n        /* send carry into next iteration */\n        u = (mp_digit)(r >> ((mp_word)DIGIT_BIT));\n    }\n\n    /* store final carry [if any] and increment ix offset  */\n    *tmpc++ = u;\n    ++ix;\n\n    /* now zero digits above the top */\n    while (ix++ < olduse) {\n        *tmpc++ = 0;\n    }\n\n    /* set used count */\n    c->used = a->used + 1;\n    mp_clamp(c);\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_MULMOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* d = a * b (mod c) */\nint mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) {\n    int    res;\n    mp_int t;\n\n    if ((res = mp_init(&t)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_mul(a, b, &t)) != MP_OKAY) {\n        mp_clear(&t);\n        return res;\n    }\n    res = mp_mod(&t, c, d);\n    mp_clear(&t);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_N_ROOT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* wrapper function for mp_n_root_ex()\n * computes c = (a)**(1/b) such that (c)**b <= a and (c+1)**b > a\n */\nint mp_n_root(mp_int *a, mp_digit b, mp_int *c) {\n    return mp_n_root_ex(a, b, c, 0);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_N_ROOT_EX_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* find the n'th root of an integer\n *\n * Result found such that (c)**b <= a and (c+1)**b > a\n *\n * This algorithm uses Newton's approximation\n * x[i+1] = x[i] - f(x[i])/f'(x[i])\n * which will find the root in log(N) time where\n * each step involves a fair bit.  This is not meant to\n * find huge roots [square and cube, etc].\n */\nint mp_n_root_ex(mp_int *a, mp_digit b, mp_int *c, int fast) {\n    mp_int t1, t2, t3;\n    int    res, neg;\n\n    /* input must be positive if b is even */\n    if (((b & 1) == 0) && (a->sign == MP_NEG)) {\n        return MP_VAL;\n    }\n\n    if ((res = mp_init(&t1)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_init(&t2)) != MP_OKAY) {\n        goto LBL_T1;\n    }\n\n    if ((res = mp_init(&t3)) != MP_OKAY) {\n        goto LBL_T2;\n    }\n\n    /* if a is negative fudge the sign but keep track */\n    neg     = a->sign;\n    a->sign = MP_ZPOS;\n\n    /* t2 = 2 */\n    mp_set(&t2, 2);\n\n    do {\n        /* t1 = t2 */\n        if ((res = mp_copy(&t2, &t1)) != MP_OKAY) {\n            goto LBL_T3;\n        }\n\n        /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */\n\n        /* t3 = t1**(b-1) */\n        if ((res = mp_expt_d_ex(&t1, b - 1, &t3, fast)) != MP_OKAY) {\n            goto LBL_T3;\n        }\n\n        /* numerator */\n        /* t2 = t1**b */\n        if ((res = mp_mul(&t3, &t1, &t2)) != MP_OKAY) {\n            goto LBL_T3;\n        }\n\n        /* t2 = t1**b - a */\n        if ((res = mp_sub(&t2, a, &t2)) != MP_OKAY) {\n            goto LBL_T3;\n        }\n\n        /* denominator */\n        /* t3 = t1**(b-1) * b  */\n        if ((res = mp_mul_d(&t3, b, &t3)) != MP_OKAY) {\n            goto LBL_T3;\n        }\n\n        /* t3 = (t1**b - a)/(b * t1**(b-1)) */\n        if ((res = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) {\n            goto LBL_T3;\n        }\n\n        if ((res = mp_sub(&t1, &t3, &t2)) != MP_OKAY) {\n            goto LBL_T3;\n        }\n    }  while (mp_cmp(&t1, &t2) != MP_EQ);\n\n    /* result can be off by a few so check */\n    for ( ; ; ) {\n        if ((res = mp_expt_d_ex(&t1, b, &t2, fast)) != MP_OKAY) {\n            goto LBL_T3;\n        }\n\n        if (mp_cmp(&t2, a) == MP_GT) {\n            if ((res = mp_sub_d(&t1, 1, &t1)) != MP_OKAY) {\n                goto LBL_T3;\n            }\n        } else {\n            break;\n        }\n    }\n\n    /* reset the sign of a first */\n    a->sign = neg;\n\n    /* set the result */\n    mp_exch(&t1, c);\n\n    /* set the sign of the result */\n    c->sign = neg;\n\n    res = MP_OKAY;\n\nLBL_T3: mp_clear(&t3);\nLBL_T2: mp_clear(&t2);\nLBL_T1: mp_clear(&t1);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_NEG_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* b = -a */\nint mp_neg(mp_int *a, mp_int *b) {\n    int res;\n\n    if (a != b) {\n        if ((res = mp_copy(a, b)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    if (mp_iszero(b) != MP_YES) {\n        b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;\n    } else {\n        b->sign = MP_ZPOS;\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_OR_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* OR two ints together */\nint mp_or(mp_int *a, mp_int *b, mp_int *c) {\n    int    res, ix, px;\n    mp_int t, *x;\n\n    if (a->used > b->used) {\n        if ((res = mp_init_copy(&t, a)) != MP_OKAY) {\n            return res;\n        }\n        px = b->used;\n        x  = b;\n    } else {\n        if ((res = mp_init_copy(&t, b)) != MP_OKAY) {\n            return res;\n        }\n        px = a->used;\n        x  = a;\n    }\n\n    for (ix = 0; ix < px; ix++) {\n        t.dp[ix] |= x->dp[ix];\n    }\n    mp_clamp(&t);\n    mp_exch(c, &t);\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_PRIME_FERMAT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* performs one Fermat test.\n *\n * If \"a\" were prime then b**a == b (mod a) since the order of\n * the multiplicative sub-group would be phi(a) = a-1.  That means\n * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).\n *\n * Sets result to 1 if the congruence holds, or zero otherwise.\n */\nint mp_prime_fermat(mp_int *a, mp_int *b, int *result) {\n    mp_int t;\n    int    err;\n\n    /* default to composite  */\n    *result = MP_NO;\n\n    /* ensure b > 1 */\n    if (mp_cmp_d(b, 1) != MP_GT) {\n        return MP_VAL;\n    }\n\n    /* init t */\n    if ((err = mp_init(&t)) != MP_OKAY) {\n        return err;\n    }\n\n    /* compute t = b**a mod a */\n    if ((err = mp_exptmod(b, a, a, &t)) != MP_OKAY) {\n        goto LBL_T;\n    }\n\n    /* is it equal to b? */\n    if (mp_cmp(&t, b) == MP_EQ) {\n        *result = MP_YES;\n    }\n\n    err = MP_OKAY;\nLBL_T: mp_clear(&t);\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_PRIME_IS_DIVISIBLE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* determines if an integers is divisible by one\n * of the first PRIME_SIZE primes or not\n *\n * sets result to 0 if not, 1 if yes\n */\nint mp_prime_is_divisible(mp_int *a, int *result) {\n    int      err, ix;\n    mp_digit res;\n\n    /* default to not */\n    *result = MP_NO;\n\n    for (ix = 0; ix < PRIME_SIZE; ix++) {\n        /* what is a mod LBL_prime_tab[ix] */\n        if ((err = mp_mod_d(a, ltm_prime_tab[ix], &res)) != MP_OKAY) {\n            return err;\n        }\n\n        /* is the residue zero? */\n        if (res == 0) {\n            *result = MP_YES;\n            return MP_OKAY;\n        }\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_PRIME_IS_PRIME_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* performs a variable number of rounds of Miller-Rabin\n *\n * Probability of error after t rounds is no more than\n\n *\n * Sets result to 1 if probably prime, 0 otherwise\n */\nint mp_prime_is_prime(mp_int *a, int t, int *result) {\n    mp_int b;\n    int    ix, err, res;\n\n    /* default to no */\n    *result = MP_NO;\n\n    /* valid value of t? */\n    if ((t <= 0) || (t > PRIME_SIZE)) {\n        return MP_VAL;\n    }\n\n    /* is the input equal to one of the primes in the table? */\n    for (ix = 0; ix < PRIME_SIZE; ix++) {\n        if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {\n            *result = 1;\n            return MP_OKAY;\n        }\n    }\n\n    /* first perform trial division */\n    if ((err = mp_prime_is_divisible(a, &res)) != MP_OKAY) {\n        return err;\n    }\n\n    /* return if it was trivially divisible */\n    if (res == MP_YES) {\n        return MP_OKAY;\n    }\n\n    /* now perform the miller-rabin rounds */\n    if ((err = mp_init(&b)) != MP_OKAY) {\n        return err;\n    }\n\n    for (ix = 0; ix < t; ix++) {\n        /* set the prime */\n        mp_set(&b, ltm_prime_tab[ix]);\n\n        if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {\n            goto LBL_B;\n        }\n\n        if (res == MP_NO) {\n            goto LBL_B;\n        }\n    }\n\n    /* passed the test */\n    *result = MP_YES;\nLBL_B: mp_clear(&b);\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_PRIME_MILLER_RABIN_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* Miller-Rabin test of \"a\" to the base of \"b\" as described in\n * HAC pp. 139 Algorithm 4.24\n *\n * Sets result to 0 if definitely composite or 1 if probably prime.\n * Randomly the chance of error is no more than 1/4 and often\n * very much lower.\n */\nint mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result) {\n    mp_int n1, y, r;\n    int    s, j, err;\n\n    /* default */\n    *result = MP_NO;\n\n    /* ensure b > 1 */\n    if (mp_cmp_d(b, 1) != MP_GT) {\n        return MP_VAL;\n    }\n\n    /* get n1 = a - 1 */\n    if ((err = mp_init_copy(&n1, a)) != MP_OKAY) {\n        return err;\n    }\n    if ((err = mp_sub_d(&n1, 1, &n1)) != MP_OKAY) {\n        goto LBL_N1;\n    }\n\n    /* set 2**s * r = n1 */\n    if ((err = mp_init_copy(&r, &n1)) != MP_OKAY) {\n        goto LBL_N1;\n    }\n\n    /* count the number of least significant bits\n     * which are zero\n     */\n    s = mp_cnt_lsb(&r);\n\n    /* now divide n - 1 by 2**s */\n    if ((err = mp_div_2d(&r, s, &r, NULL)) != MP_OKAY) {\n        goto LBL_R;\n    }\n\n    /* compute y = b**r mod a */\n    if ((err = mp_init(&y)) != MP_OKAY) {\n        goto LBL_R;\n    }\n    if ((err = mp_exptmod(b, &r, a, &y)) != MP_OKAY) {\n        goto LBL_Y;\n    }\n\n    /* if y != 1 and y != n1 do */\n    if ((mp_cmp_d(&y, 1) != MP_EQ) && (mp_cmp(&y, &n1) != MP_EQ)) {\n        j = 1;\n        /* while j <= s-1 and y != n1 */\n        while ((j <= (s - 1)) && (mp_cmp(&y, &n1) != MP_EQ)) {\n            if ((err = mp_sqrmod(&y, a, &y)) != MP_OKAY) {\n                goto LBL_Y;\n            }\n\n            /* if y == 1 then composite */\n            if (mp_cmp_d(&y, 1) == MP_EQ) {\n                goto LBL_Y;\n            }\n\n            ++j;\n        }\n\n        /* if y != n1 then composite */\n        if (mp_cmp(&y, &n1) != MP_EQ) {\n            goto LBL_Y;\n        }\n    }\n\n    /* probably prime now */\n    *result = MP_YES;\nLBL_Y: mp_clear(&y);\nLBL_R: mp_clear(&r);\nLBL_N1: mp_clear(&n1);\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_PRIME_NEXT_PRIME_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* finds the next prime after the number \"a\" using \"t\" trials\n * of Miller-Rabin.\n *\n * bbs_style = 1 means the prime must be congruent to 3 mod 4\n */\nint mp_prime_next_prime(mp_int *a, int t, int bbs_style) {\n    int      err, res = MP_NO, x, y;\n    mp_digit res_tab[PRIME_SIZE], step, kstep;\n    mp_int   b;\n\n    /* ensure t is valid */\n    if ((t <= 0) || (t > PRIME_SIZE)) {\n        return MP_VAL;\n    }\n\n    /* force positive */\n    a->sign = MP_ZPOS;\n\n    /* simple algo if a is less than the largest prime in the table */\n    if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE - 1]) == MP_LT) {\n        /* find which prime it is bigger than */\n        for (x = PRIME_SIZE - 2; x >= 0; x--) {\n            if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {\n                if (bbs_style == 1) {\n                    /* ok we found a prime smaller or\n                     * equal [so the next is larger]\n                     *\n                     * however, the prime must be\n                     * congruent to 3 mod 4\n                     */\n                    if ((ltm_prime_tab[x + 1] & 3) != 3) {\n                        /* scan upwards for a prime congruent to 3 mod 4 */\n                        for (y = x + 1; y < PRIME_SIZE; y++) {\n                            if ((ltm_prime_tab[y] & 3) == 3) {\n                                mp_set(a, ltm_prime_tab[y]);\n                                return MP_OKAY;\n                            }\n                        }\n                    }\n                } else {\n                    mp_set(a, ltm_prime_tab[x + 1]);\n                    return MP_OKAY;\n                }\n            }\n        }\n        /* at this point a maybe 1 */\n        if (mp_cmp_d(a, 1) == MP_EQ) {\n            mp_set(a, 2);\n            return MP_OKAY;\n        }\n        /* fall through to the sieve */\n    }\n\n    /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */\n    if (bbs_style == 1) {\n        kstep = 4;\n    } else {\n        kstep = 2;\n    }\n\n    /* at this point we will use a combination of a sieve and Miller-Rabin */\n\n    if (bbs_style == 1) {\n        /* if a mod 4 != 3 subtract the correct value to make it so */\n        if ((a->dp[0] & 3) != 3) {\n            if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) {\n                return err;\n            }\n        }\n    } else {\n        if (mp_iseven(a) == MP_YES) {\n            /* force odd */\n            if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {\n                return err;\n            }\n        }\n    }\n\n    /* generate the restable */\n    for (x = 1; x < PRIME_SIZE; x++) {\n        if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {\n            return err;\n        }\n    }\n\n    /* init temp used for Miller-Rabin Testing */\n    if ((err = mp_init(&b)) != MP_OKAY) {\n        return err;\n    }\n\n    for ( ; ; ) {\n        /* skip to the next non-trivially divisible candidate */\n        step = 0;\n        do {\n            /* y == 1 if any residue was zero [e.g. cannot be prime] */\n            y = 0;\n\n            /* increase step to next candidate */\n            step += kstep;\n\n            /* compute the new residue without using division */\n            for (x = 1; x < PRIME_SIZE; x++) {\n                /* add the step to each residue */\n                res_tab[x] += kstep;\n\n                /* subtract the modulus [instead of using division] */\n                if (res_tab[x] >= ltm_prime_tab[x]) {\n                    res_tab[x] -= ltm_prime_tab[x];\n                }\n\n                /* set flag if zero */\n                if (res_tab[x] == 0) {\n                    y = 1;\n                }\n            }\n        } while ((y == 1) && (step < ((((mp_digit)1) << DIGIT_BIT) - kstep)));\n\n        /* add the step */\n        if ((err = mp_add_d(a, step, a)) != MP_OKAY) {\n            goto LBL_ERR;\n        }\n\n        /* if didn't pass sieve and step == MAX then skip test */\n        if ((y == 1) && (step >= ((((mp_digit)1) << DIGIT_BIT) - kstep))) {\n            continue;\n        }\n\n        /* is this prime? */\n        for (x = 0; x < t; x++) {\n            mp_set(&b, ltm_prime_tab[x]);\n            if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {\n                goto LBL_ERR;\n            }\n            if (res == MP_NO) {\n                break;\n            }\n        }\n\n        if (res == MP_YES) {\n            break;\n        }\n    }\n\n    err = MP_OKAY;\nLBL_ERR:\n    mp_clear(&b);\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n\nstatic const struct {\n    int k, t;\n} sizes[] = {\n    {  128, 28 },\n    {  256, 16 },\n    {  384, 10 },\n    {  512,  7 },\n    {  640,  6 },\n    {  768,  5 },\n    {  896,  4 },\n    { 1024,  4 }\n};\n\n/* returns # of RM trials required for a given bit size */\nint mp_prime_rabin_miller_trials(int size) {\n    int x;\n\n    for (x = 0; x < (int)(sizeof(sizes) / (sizeof(sizes[0]))); x++) {\n        if (sizes[x].k == size) {\n            return sizes[x].t;\n        } else if (sizes[x].k > size) {\n            return (x == 0) ? sizes[0].t : sizes[x - 1].t;\n        }\n    }\n    return sizes[x - 1].t + 1;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_PRIME_RANDOM_EX_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* makes a truly random prime of a given size (bits),\n *\n * Flags are as follows:\n *\n *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4\n *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)\n *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one\n *\n * You have to supply a callback which fills in a buffer with random bytes.  \"dat\" is a parameter you can\n * have passed to the callback (e.g. a state or something).  This function doesn't use \"dat\" itself\n * so it can be NULL\n *\n */\n\n/* This is possibly the mother of all prime generation functions, muahahahahaha! */\nint mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat) {\n    unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;\n    int           res, err, bsize, maskOR_msb_offset;\n\n    /* sanity check the input */\n    if ((size <= 1) || (t <= 0)) {\n        return MP_VAL;\n    }\n\n    /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */\n    if ((flags & LTM_PRIME_SAFE) != 0) {\n        flags |= LTM_PRIME_BBS;\n    }\n\n    /* calc the byte size */\n    bsize = (size >> 3) + ((size & 7) ? 1 : 0);\n\n    /* we need a buffer of bsize bytes */\n    tmp = OPT_CAST(unsigned char) XMALLOC(bsize);\n    if (tmp == NULL) {\n        return MP_MEM;\n    }\n\n    /* calc the maskAND value for the MSbyte*/\n    maskAND = ((size & 7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));\n\n    /* calc the maskOR_msb */\n    maskOR_msb        = 0;\n    maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;\n    if ((flags & LTM_PRIME_2MSB_ON) != 0) {\n        maskOR_msb |= 0x80 >> ((9 - size) & 7);\n    }\n\n    /* get the maskOR_lsb */\n    maskOR_lsb = 1;\n    if ((flags & LTM_PRIME_BBS) != 0) {\n        maskOR_lsb |= 3;\n    }\n\n    do {\n        /* read the bytes */\n        if (cb(tmp, bsize, dat) != bsize) {\n            err = MP_VAL;\n            goto error;\n        }\n\n        /* work over the MSbyte */\n        tmp[0] &= maskAND;\n        tmp[0] |= 1 << ((size - 1) & 7);\n\n        /* mix in the maskORs */\n        tmp[maskOR_msb_offset] |= maskOR_msb;\n        tmp[bsize - 1]         |= maskOR_lsb;\n\n        /* read it in */\n        if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) {\n            goto error;\n        }\n\n        /* is it prime? */\n        if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {\n            goto error;\n        }\n        if (res == MP_NO) {\n            continue;\n        }\n\n        if ((flags & LTM_PRIME_SAFE) != 0) {\n            /* see if (a-1)/2 is prime */\n            if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {\n                goto error;\n            }\n            if ((err = mp_div_2(a, a)) != MP_OKAY) {\n                goto error;\n            }\n\n            /* is it prime? */\n            if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {\n                goto error;\n            }\n        }\n    } while (res == MP_NO);\n\n    if ((flags & LTM_PRIME_SAFE) != 0) {\n        /* restore a to the original value */\n        if ((err = mp_mul_2(a, a)) != MP_OKAY) {\n            goto error;\n        }\n        if ((err = mp_add_d(a, 1, a)) != MP_OKAY) {\n            goto error;\n        }\n    }\n\n    err = MP_OKAY;\nerror:\n    XFREE(tmp);\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_RADIX_SIZE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* returns size of ASCII reprensentation */\nint mp_radix_size(mp_int *a, int radix, int *size) {\n    int      res, digs;\n    mp_int   t;\n    mp_digit d;\n\n    *size = 0;\n\n    /* make sure the radix is in range */\n    if ((radix < 2) || (radix > 64)) {\n        return MP_VAL;\n    }\n\n    if (mp_iszero(a) == MP_YES) {\n        *size = 2;\n        return MP_OKAY;\n    }\n\n    /* special case for binary */\n    if (radix == 2) {\n        *size = mp_count_bits(a) + ((a->sign == MP_NEG) ? 1 : 0) + 1;\n        return MP_OKAY;\n    }\n\n    /* digs is the digit count */\n    digs = 0;\n\n    /* if it's negative add one for the sign */\n    if (a->sign == MP_NEG) {\n        ++digs;\n    }\n\n    /* init a copy of the input */\n    if ((res = mp_init_copy(&t, a)) != MP_OKAY) {\n        return res;\n    }\n\n    /* force temp to positive */\n    t.sign = MP_ZPOS;\n\n    /* fetch out all of the digits */\n    while (mp_iszero(&t) == MP_NO) {\n        if ((res = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) {\n            mp_clear(&t);\n            return res;\n        }\n        ++digs;\n    }\n    mp_clear(&t);\n\n    /* return digs + 1, the 1 is for the NULL byte that would be required. */\n    *size = digs + 1;\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_RADIX_SMAP_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* chars used in radix conversions */\nconst char *mp_s_rmap = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/\";\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_RAND_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* makes a pseudo-random int of a given size */\nint\nmp_rand(mp_int *a, int digits) {\n    int      res;\n    mp_digit d;\n\n    mp_zero(a);\n    if (digits <= 0) {\n        return MP_OKAY;\n    }\n\n    /* first place a random non-zero digit */\n    do {\n        d = ((mp_digit)abs(MP_GEN_RANDOM())) & MP_MASK;\n    } while (d == 0);\n\n    if ((res = mp_add_d(a, d, a)) != MP_OKAY) {\n        return res;\n    }\n\n    while (--digits > 0) {\n        if ((res = mp_lshd(a, 1)) != MP_OKAY) {\n            return res;\n        }\n\n        if ((res = mp_add_d(a, ((mp_digit)abs(MP_GEN_RANDOM())), a)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_READ_RADIX_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* read a string [ASCII] in a given radix */\nint mp_read_radix(mp_int *a, const char *str, int radix) {\n    int  y, res, neg;\n    char ch;\n\n    /* zero the digit bignum */\n    mp_zero(a);\n\n    /* make sure the radix is ok */\n    if ((radix < 2) || (radix > 64)) {\n        return MP_VAL;\n    }\n\n    /* if the leading digit is a\n     * minus set the sign to negative.\n     */\n    if (*str == '-') {\n        ++str;\n        neg = MP_NEG;\n    } else {\n        neg = MP_ZPOS;\n    }\n\n    /* set the integer to the default of zero */\n    mp_zero(a);\n\n    /* process each digit of the string */\n    while (*str != '\\0') {\n        /* if the radix <= 36 the conversion is case insensitive\n         * this allows numbers like 1AB and 1ab to represent the same  value\n         * [e.g. in hex]\n         */\n        ch = (radix <= 36) ? (char)toupper((int)*str) : *str;\n        for (y = 0; y < 64; y++) {\n            if (ch == mp_s_rmap[y]) {\n                break;\n            }\n        }\n\n        /* if the char was found in the map\n         * and is less than the given radix add it\n         * to the number, otherwise exit the loop.\n         */\n        if (y < radix) {\n            if ((res = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) {\n                return res;\n            }\n            if ((res = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) {\n                return res;\n            }\n        } else {\n            break;\n        }\n        ++str;\n    }\n\n    /* set the sign only if a != 0 */\n    if (mp_iszero(a) != MP_YES) {\n        a->sign = neg;\n    }\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_READ_SIGNED_BIN_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* read signed bin, big endian, first byte is 0==positive or 1==negative */\nint mp_read_signed_bin(mp_int *a, const unsigned char *b, int c) {\n    int res;\n\n    /* read magnitude */\n    if ((res = mp_read_unsigned_bin(a, b + 1, c - 1)) != MP_OKAY) {\n        return res;\n    }\n\n    /* first byte is 0 for positive, non-zero for negative */\n    if (b[0] == 0) {\n        a->sign = MP_ZPOS;\n    } else {\n        a->sign = MP_NEG;\n    }\n\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_READ_UNSIGNED_BIN_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* reads a unsigned char array, assumes the msb is stored first [big endian] */\nint mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c) {\n    int res;\n\n    /* make sure there are at least two digits */\n    if (a->alloc < 2) {\n        if ((res = mp_grow(a, 2)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* zero the int */\n    mp_zero(a);\n\n    /* read the bytes in */\n    while (c-- > 0) {\n        if ((res = mp_mul_2d(a, 8, a)) != MP_OKAY) {\n            return res;\n        }\n\n #ifndef MP_8BIT\n        a->dp[0] |= *b++;\n        a->used  += 1;\n #else\n        a->dp[0]  = (*b & MP_MASK);\n        a->dp[1] |= ((*b++ >> 7U) & 1);\n        a->used  += 2;\n #endif\n    }\n    mp_clamp(a);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_REDUCE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* reduces x mod m, assumes 0 < x < m**2, mu is\n * precomputed via mp_reduce_setup.\n * From HAC pp.604 Algorithm 14.42\n */\nint mp_reduce(mp_int *x, mp_int *m, mp_int *mu) {\n    mp_int q;\n    int    res, um = m->used;\n\n    /* q = x */\n    if ((res = mp_init_copy(&q, x)) != MP_OKAY) {\n        return res;\n    }\n\n    /* q1 = x / b**(k-1)  */\n    mp_rshd(&q, um - 1);\n\n    /* according to HAC this optimization is ok */\n    if (((mp_digit)um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {\n        if ((res = mp_mul(&q, mu, &q)) != MP_OKAY) {\n            goto CLEANUP;\n        }\n    } else {\n #ifdef BN_S_MP_MUL_HIGH_DIGS_C\n        if ((res = s_mp_mul_high_digs(&q, mu, &q, um)) != MP_OKAY) {\n            goto CLEANUP;\n        }\n #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)\n        if ((res = fast_s_mp_mul_high_digs(&q, mu, &q, um)) != MP_OKAY) {\n            goto CLEANUP;\n        }\n #else\n        {\n            res = MP_VAL;\n            goto CLEANUP;\n        }\n #endif\n    }\n\n    /* q3 = q2 / b**(k+1) */\n    mp_rshd(&q, um + 1);\n\n    /* x = x mod b**(k+1), quick (no division) */\n    if ((res = mp_mod_2d(x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {\n        goto CLEANUP;\n    }\n\n    /* q = q * m mod b**(k+1), quick (no division) */\n    if ((res = s_mp_mul_digs(&q, m, &q, um + 1)) != MP_OKAY) {\n        goto CLEANUP;\n    }\n\n    /* x = x - q */\n    if ((res = mp_sub(x, &q, x)) != MP_OKAY) {\n        goto CLEANUP;\n    }\n\n    /* If x < 0, add b**(k+1) to it */\n    if (mp_cmp_d(x, 0) == MP_LT) {\n        mp_set(&q, 1);\n        if ((res = mp_lshd(&q, um + 1)) != MP_OKAY)\n            goto CLEANUP;\n        if ((res = mp_add(x, &q, x)) != MP_OKAY)\n            goto CLEANUP;\n    }\n\n    /* Back off if it's too big */\n    while (mp_cmp(x, m) != MP_LT) {\n        if ((res = s_mp_sub(x, m, x)) != MP_OKAY) {\n            goto CLEANUP;\n        }\n    }\n\nCLEANUP:\n    mp_clear(&q);\n\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_REDUCE_2K_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* reduces a modulo n where n is of the form 2**p - d */\nint mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d) {\n    mp_int q;\n    int    p, res;\n\n    if ((res = mp_init(&q)) != MP_OKAY) {\n        return res;\n    }\n\n    p = mp_count_bits(n);\ntop:\n    /* q = a/2**p, a = a mod 2**p */\n    if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if (d != 1) {\n        /* q = q * d */\n        if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {\n            goto ERR;\n        }\n    }\n\n    /* a = a + q */\n    if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if (mp_cmp_mag(a, n) != MP_LT) {\n        if ((res = s_mp_sub(a, n, a)) != MP_OKAY) {\n            goto ERR;\n        }\n        goto top;\n    }\n\nERR:\n    mp_clear(&q);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_REDUCE_2K_L_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* reduces a modulo n where n is of the form 2**p - d\n   This differs from reduce_2k since \"d\" can be larger\n   than a single digit.\n */\nint mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) {\n    mp_int q;\n    int    p, res;\n\n    if ((res = mp_init(&q)) != MP_OKAY) {\n        return res;\n    }\n\n    p = mp_count_bits(n);\ntop:\n    /* q = a/2**p, a = a mod 2**p */\n    if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* q = q * d */\n    if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* a = a + q */\n    if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if (mp_cmp_mag(a, n) != MP_LT) {\n        if ((res = s_mp_sub(a, n, a)) != MP_OKAY) {\n            goto ERR;\n        }\n        goto top;\n    }\n\nERR:\n    mp_clear(&q);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_REDUCE_2K_SETUP_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* determines the setup value */\nint mp_reduce_2k_setup(mp_int *a, mp_digit *d) {\n    int    res, p;\n    mp_int tmp;\n\n    if ((res = mp_init(&tmp)) != MP_OKAY) {\n        return res;\n    }\n\n    p = mp_count_bits(a);\n    if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {\n        mp_clear(&tmp);\n        return res;\n    }\n\n    if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {\n        mp_clear(&tmp);\n        return res;\n    }\n\n    *d = tmp.dp[0];\n    mp_clear(&tmp);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_REDUCE_2K_SETUP_L_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* determines the setup value */\nint mp_reduce_2k_setup_l(mp_int *a, mp_int *d) {\n    int    res;\n    mp_int tmp;\n\n    if ((res = mp_init(&tmp)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {\n        goto ERR;\n    }\n\nERR:\n    mp_clear(&tmp);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_REDUCE_IS_2K_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* determines if mp_reduce_2k can be used */\nint mp_reduce_is_2k(mp_int *a) {\n    int      ix, iy, iw;\n    mp_digit iz;\n\n    if (a->used == 0) {\n        return MP_NO;\n    } else if (a->used == 1) {\n        return MP_YES;\n    } else if (a->used > 1) {\n        iy = mp_count_bits(a);\n        iz = 1;\n        iw = 1;\n\n        /* Test every bit from the second digit up, must be 1 */\n        for (ix = DIGIT_BIT; ix < iy; ix++) {\n            if ((a->dp[iw] & iz) == 0) {\n                return MP_NO;\n            }\n            iz <<= 1;\n            if (iz > (mp_digit)MP_MASK) {\n                ++iw;\n                iz = 1;\n            }\n        }\n    }\n    return MP_YES;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_REDUCE_IS_2K_L_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* determines if reduce_2k_l can be used */\nint mp_reduce_is_2k_l(mp_int *a) {\n    int ix, iy;\n\n    if (a->used == 0) {\n        return MP_NO;\n    } else if (a->used == 1) {\n        return MP_YES;\n    } else if (a->used > 1) {\n        /* if more than half of the digits are -1 we're sold */\n        for (iy = ix = 0; ix < a->used; ix++) {\n            if (a->dp[ix] == MP_MASK) {\n                ++iy;\n            }\n        }\n        return (iy >= (a->used / 2)) ? MP_YES : MP_NO;\n    }\n    return MP_NO;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_REDUCE_SETUP_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* pre-calculate the value required for Barrett reduction\n * For a given modulus \"b\" it calulates the value required in \"a\"\n */\nint mp_reduce_setup(mp_int *a, mp_int *b) {\n    int res;\n\n    if ((res = mp_2expt(a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {\n        return res;\n    }\n    return mp_div(a, b, a, NULL);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_RSHD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* shift right a certain amount of digits */\nvoid mp_rshd(mp_int *a, int b) {\n    int x;\n\n    /* if b <= 0 then ignore it */\n    if (b <= 0) {\n        return;\n    }\n\n    /* if b > used then simply zero it and return */\n    if (a->used <= b) {\n        mp_zero(a);\n        return;\n    }\n\n    {\n        mp_digit *bottom, *top;\n\n        /* shift the digits down */\n\n        /* bottom */\n        bottom = a->dp;\n\n        /* top [offset into digits] */\n        top = a->dp + b;\n\n        /* this is implemented as a sliding window where\n         * the window is b-digits long and digits from\n         * the top of the window are copied to the bottom\n         *\n         * e.g.\n\n           b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->\n                     /\\                   |      ---->\n         **\\-------------------/      ---->\n         */\n        for (x = 0; x < (a->used - b); x++) {\n            *bottom++ = *top++;\n        }\n\n        /* zero the top digits */\n        for ( ; x < a->used; x++) {\n            *bottom++ = 0;\n        }\n    }\n\n    /* remove excess digits */\n    a->used -= b;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SET_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* set to a digit */\nvoid mp_set(mp_int *a, mp_digit b) {\n    mp_zero(a);\n    a->dp[0] = b & MP_MASK;\n    a->used  = (a->dp[0] != 0) ? 1 : 0;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SET_INT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* set a 32-bit const */\nint mp_set_int(mp_int *a, unsigned long b) {\n    int x, res;\n\n    mp_zero(a);\n\n    /* set four bits at a time */\n    for (x = 0; x < 8; x++) {\n        /* shift the number up four bits */\n        if ((res = mp_mul_2d(a, 4, a)) != MP_OKAY) {\n            return res;\n        }\n\n        /* OR in the top four bits of the source */\n        a->dp[0] |= (b >> 28) & 15;\n\n        /* shift the source up to the next four bits */\n        b <<= 4;\n\n        /* ensure that digits are not clamped off */\n        a->used += 1;\n    }\n    mp_clamp(a);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SET_LONG_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* set a platform dependent unsigned long int */\nMP_SET_XLONG(mp_set_long, unsigned long)\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SET_LONG_LONG_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* set a platform dependent unsigned long long int */\nMP_SET_XLONG(mp_set_long_long, unsigned long long)\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SHRINK_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* shrink a bignum */\nint mp_shrink(mp_int *a) {\n    mp_digit *tmp;\n    int      used = 1;\n\n    if (a->used > 0) {\n        used = a->used;\n    }\n\n    if (a->alloc != used) {\n        if ((tmp = OPT_CAST(mp_digit) XREALLOC(a->dp, sizeof(mp_digit) * used)) == NULL) {\n            return MP_MEM;\n        }\n        a->dp    = tmp;\n        a->alloc = used;\n    }\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SIGNED_BIN_SIZE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* get the size for an signed equivalent */\nint mp_signed_bin_size(mp_int *a) {\n    return 1 + mp_unsigned_bin_size(a);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SQR_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* computes b = a*a */\nint\nmp_sqr(mp_int *a, mp_int *b) {\n    int res;\n\n #ifdef BN_MP_TOOM_SQR_C\n    /* use Toom-Cook? */\n    if (a->used >= TOOM_SQR_CUTOFF) {\n        res = mp_toom_sqr(a, b);\n        /* Karatsuba? */\n    } else\n #endif\n #ifdef BN_MP_KARATSUBA_SQR_C\n    if (a->used >= KARATSUBA_SQR_CUTOFF) {\n        res = mp_karatsuba_sqr(a, b);\n    } else\n #endif\n    {\n #ifdef BN_FAST_S_MP_SQR_C\n        /* can we use the fast comba multiplier? */\n        if ((((a->used * 2) + 1) < MP_WARRAY) &&\n            (a->used <\n             (1 << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT)) - 1)))) {\n            res = fast_s_mp_sqr(a, b);\n        } else\n #endif\n        {\n #ifdef BN_S_MP_SQR_C\n            res = s_mp_sqr(a, b);\n #else\n            res = MP_VAL;\n #endif\n        }\n    }\n    b->sign = MP_ZPOS;\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SQRMOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* c = a * a (mod b) */\nint\nmp_sqrmod(mp_int *a, mp_int *b, mp_int *c) {\n    int    res;\n    mp_int t;\n\n    if ((res = mp_init(&t)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_sqr(a, &t)) != MP_OKAY) {\n        mp_clear(&t);\n        return res;\n    }\n    res = mp_mod(&t, b, c);\n    mp_clear(&t);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SQRT_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* this function is less generic than mp_n_root, simpler and faster */\nint mp_sqrt(mp_int *arg, mp_int *ret) {\n    int    res;\n    mp_int t1, t2;\n\n    /* must be positive */\n    if (arg->sign == MP_NEG) {\n        return MP_VAL;\n    }\n\n    /* easy out */\n    if (mp_iszero(arg) == MP_YES) {\n        mp_zero(ret);\n        return MP_OKAY;\n    }\n\n    if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_init(&t2)) != MP_OKAY) {\n        goto E2;\n    }\n\n    /* First approx. (not very bad for large arg) */\n    mp_rshd(&t1, t1.used / 2);\n\n    /* t1 > 0  */\n    if ((res = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) {\n        goto E1;\n    }\n    if ((res = mp_add(&t1, &t2, &t1)) != MP_OKAY) {\n        goto E1;\n    }\n    if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) {\n        goto E1;\n    }\n    /* And now t1 > sqrt(arg) */\n    do {\n        if ((res = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) {\n            goto E1;\n        }\n        if ((res = mp_add(&t1, &t2, &t1)) != MP_OKAY) {\n            goto E1;\n        }\n        if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) {\n            goto E1;\n        }\n        /* t1 >= sqrt(arg) >= t2 at this point */\n    } while (mp_cmp_mag(&t1, &t2) == MP_GT);\n\n    mp_exch(&t1, ret);\n\nE1: mp_clear(&t2);\nE2: mp_clear(&t1);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SQRTMOD_PRIME_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n */\n\n/* Tonelli-Shanks algorithm\n * https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm\n * https://gmplib.org/list-archives/gmp-discuss/2013-April/005300.html\n *\n */\n\nint mp_sqrtmod_prime(mp_int *n, mp_int *prime, mp_int *ret) {\n    int      res, legendre;\n    mp_int   t1, C, Q, S, Z, M, T, R, two;\n    mp_digit i;\n\n    /* first handle the simple cases */\n    if (mp_cmp_d(n, 0) == MP_EQ) {\n        mp_zero(ret);\n        return MP_OKAY;\n    }\n    if (mp_cmp_d(prime, 2) == MP_EQ) return MP_VAL;                            /* prime must be odd */\n    if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) return res;\n    if (legendre == -1) return MP_VAL;                                         /* quadratic non-residue mod prime */\n\n    if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL)) != MP_OKAY) {\n        return res;\n    }\n\n    /* SPECIAL CASE: if prime mod 4 == 3\n     * compute directly: res = n^(prime+1)/4 mod prime\n     * Handbook of Applied Cryptography algorithm 3.36\n     */\n    if ((res = mp_mod_d(prime, 4, &i)) != MP_OKAY) goto cleanup;\n    if (i == 3) {\n        if ((res = mp_add_d(prime, 1, &t1)) != MP_OKAY) goto cleanup;\n        if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup;\n        if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup;\n        if ((res = mp_exptmod(n, &t1, prime, ret)) != MP_OKAY) goto cleanup;\n        res = MP_OKAY;\n        goto cleanup;\n    }\n\n    /* NOW: Tonelli-Shanks algorithm */\n\n    /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */\n    if ((res = mp_copy(prime, &Q)) != MP_OKAY) goto cleanup;\n    if ((res = mp_sub_d(&Q, 1, &Q)) != MP_OKAY) goto cleanup;\n    /* Q = prime - 1 */\n    mp_zero(&S);\n    /* S = 0 */\n    while (mp_iseven(&Q) != MP_NO) {\n        if ((res = mp_div_2(&Q, &Q)) != MP_OKAY) goto cleanup;\n        /* Q = Q / 2 */\n        if ((res = mp_add_d(&S, 1, &S)) != MP_OKAY) goto cleanup;\n        /* S = S + 1 */\n    }\n\n    /* find a Z such that the Legendre symbol (Z|prime) == -1 */\n    if ((res = mp_set_int(&Z, 2)) != MP_OKAY) goto cleanup;\n    /* Z = 2 */\n    while (1) {\n        if ((res = mp_jacobi(&Z, prime, &legendre)) != MP_OKAY) goto cleanup;\n        if (legendre == -1) break;\n        if ((res = mp_add_d(&Z, 1, &Z)) != MP_OKAY) goto cleanup;\n        /* Z = Z + 1 */\n    }\n\n    if ((res = mp_exptmod(&Z, &Q, prime, &C)) != MP_OKAY) goto cleanup;\n    /* C = Z ^ Q mod prime */\n    if ((res = mp_add_d(&Q, 1, &t1)) != MP_OKAY) goto cleanup;\n    if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup;\n    /* t1 = (Q + 1) / 2 */\n    if ((res = mp_exptmod(n, &t1, prime, &R)) != MP_OKAY) goto cleanup;\n    /* R = n ^ ((Q + 1) / 2) mod prime */\n    if ((res = mp_exptmod(n, &Q, prime, &T)) != MP_OKAY) goto cleanup;\n    /* T = n ^ Q mod prime */\n    if ((res = mp_copy(&S, &M)) != MP_OKAY) goto cleanup;\n    /* M = S */\n    if ((res = mp_set_int(&two, 2)) != MP_OKAY) goto cleanup;\n\n    res = MP_VAL;\n    while (1) {\n        if ((res = mp_copy(&T, &t1)) != MP_OKAY) goto cleanup;\n        i = 0;\n        while (1) {\n            if (mp_cmp_d(&t1, 1) == MP_EQ) break;\n            if ((res = mp_exptmod(&t1, &two, prime, &t1)) != MP_OKAY) goto cleanup;\n            i++;\n        }\n        if (i == 0) {\n            if ((res = mp_copy(&R, ret)) != MP_OKAY) goto cleanup;\n            res = MP_OKAY;\n            goto cleanup;\n        }\n        if ((res = mp_sub_d(&M, i, &t1)) != MP_OKAY) goto cleanup;\n        if ((res = mp_sub_d(&t1, 1, &t1)) != MP_OKAY) goto cleanup;\n        if ((res = mp_exptmod(&two, &t1, prime, &t1)) != MP_OKAY) goto cleanup;\n        /* t1 = 2 ^ (M - i - 1) */\n        if ((res = mp_exptmod(&C, &t1, prime, &t1)) != MP_OKAY) goto cleanup;\n        /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */\n        if ((res = mp_sqrmod(&t1, prime, &C)) != MP_OKAY) goto cleanup;\n        /* C = (t1 * t1) mod prime */\n        if ((res = mp_mulmod(&R, &t1, prime, &R)) != MP_OKAY) goto cleanup;\n        /* R = (R * t1) mod prime */\n        if ((res = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY) goto cleanup;\n        /* T = (T * C) mod prime */\n        mp_set(&M, i);\n        /* M = i */\n    }\n\ncleanup:\n    mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL);\n    return res;\n}\n#endif\n\n\n\n#ifdef BN_MP_SUB_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* high level subtraction (handles signs) */\nint\nmp_sub(mp_int *a, mp_int *b, mp_int *c) {\n    int sa, sb, res;\n\n    sa = a->sign;\n    sb = b->sign;\n\n    if (sa != sb) {\n        /* subtract a negative from a positive, OR */\n        /* subtract a positive from a negative. */\n        /* In either case, ADD their magnitudes, */\n        /* and use the sign of the first number. */\n        c->sign = sa;\n        res     = s_mp_add(a, b, c);\n    } else {\n        /* subtract a positive from a positive, OR */\n        /* subtract a negative from a negative. */\n        /* First, take the difference between their */\n        /* magnitudes, then... */\n        if (mp_cmp_mag(a, b) != MP_LT) {\n            /* Copy the sign from the first */\n            c->sign = sa;\n            /* The first has a larger or equal magnitude */\n            res = s_mp_sub(a, b, c);\n        } else {\n            /* The result has the *opposite* sign from */\n            /* the first number. */\n            c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;\n            /* The second has a larger magnitude */\n            res = s_mp_sub(b, a, c);\n        }\n    }\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SUB_D_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* single digit subtraction */\nint\nmp_sub_d(mp_int *a, mp_digit b, mp_int *c) {\n    mp_digit *tmpa, *tmpc, mu;\n    int      res, ix, oldused;\n\n    /* grow c as required */\n    if (c->alloc < (a->used + 1)) {\n        if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* if a is negative just do an unsigned\n     * addition [with fudged signs]\n     */\n    if (a->sign == MP_NEG) {\n        a->sign = MP_ZPOS;\n        res     = mp_add_d(a, b, c);\n        a->sign = c->sign = MP_NEG;\n\n        /* clamp */\n        mp_clamp(c);\n\n        return res;\n    }\n\n    /* setup regs */\n    oldused = c->used;\n    tmpa    = a->dp;\n    tmpc    = c->dp;\n\n    /* if a <= b simply fix the single digit */\n    if (((a->used == 1) && (a->dp[0] <= b)) || (a->used == 0)) {\n        if (a->used == 1) {\n            *tmpc++ = b - *tmpa;\n        } else {\n            *tmpc++ = b;\n        }\n        ix = 1;\n\n        /* negative/1digit */\n        c->sign = MP_NEG;\n        c->used = 1;\n    } else {\n        /* positive/size */\n        c->sign = MP_ZPOS;\n        c->used = a->used;\n\n        /* subtract first digit */\n        *tmpc    = *tmpa++ - b;\n        mu       = *tmpc >> ((sizeof(mp_digit) * CHAR_BIT) - 1);\n        *tmpc++ &= MP_MASK;\n\n        /* handle rest of the digits */\n        for (ix = 1; ix < a->used; ix++) {\n            *tmpc    = *tmpa++ - mu;\n            mu       = *tmpc >> ((sizeof(mp_digit) * CHAR_BIT) - 1);\n            *tmpc++ &= MP_MASK;\n        }\n    }\n\n    /* zero excess digits */\n    while (ix++ < oldused) {\n        *tmpc++ = 0;\n    }\n    mp_clamp(c);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_SUBMOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* d = a - b (mod c) */\nint\nmp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) {\n    int    res;\n    mp_int t;\n\n\n    if ((res = mp_init(&t)) != MP_OKAY) {\n        return res;\n    }\n\n    if ((res = mp_sub(a, b, &t)) != MP_OKAY) {\n        mp_clear(&t);\n        return res;\n    }\n    res = mp_mod(&t, c, d);\n    mp_clear(&t);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_TO_SIGNED_BIN_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* store in signed [big endian] format */\nint mp_to_signed_bin(mp_int *a, unsigned char *b) {\n    int res;\n\n    if ((res = mp_to_unsigned_bin(a, b + 1)) != MP_OKAY) {\n        return res;\n    }\n    b[0] = (a->sign == MP_ZPOS) ? (unsigned char)0 : (unsigned char)1;\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_TO_SIGNED_BIN_N_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* store in signed [big endian] format */\nint mp_to_signed_bin_n(mp_int *a, unsigned char *b, unsigned long *outlen) {\n    if (*outlen < (unsigned long)mp_signed_bin_size(a)) {\n        return MP_VAL;\n    }\n    *outlen = mp_signed_bin_size(a);\n    return mp_to_signed_bin(a, b);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_TO_UNSIGNED_BIN_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* store in unsigned [big endian] format */\nint mp_to_unsigned_bin(mp_int *a, unsigned char *b) {\n    int    x, res;\n    mp_int t;\n\n    if ((res = mp_init_copy(&t, a)) != MP_OKAY) {\n        return res;\n    }\n\n    x = 0;\n    while (mp_iszero(&t) == MP_NO) {\n #ifndef MP_8BIT\n        b[x++] = (unsigned char)(t.dp[0] & 255);\n #else\n        b[x++] = (unsigned char)(t.dp[0] | ((t.dp[1] & 0x01) << 7));\n #endif\n        if ((res = mp_div_2d(&t, 8, &t, NULL)) != MP_OKAY) {\n            mp_clear(&t);\n            return res;\n        }\n    }\n    bn_reverse(b, x);\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_TOOM_MUL_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* multiplication using the Toom-Cook 3-way algorithm\n *\n * Much more complicated than Karatsuba but has a lower\n * asymptotic running time of O(N**1.464).  This algorithm is\n * only particularly useful on VERY large inputs\n * (we're talking 1000s of digits here...).\n */\nint mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) {\n    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;\n    int    res, B;\n\n    /* init temps */\n    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,\n                             &a0, &a1, &a2, &b0, &b1,\n                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {\n        return res;\n    }\n\n    /* B */\n    B = TOM_MIN(a->used, b->used) / 3;\n\n    /* a = a2 * B**2 + a1 * B + a0 */\n    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_copy(a, &a1)) != MP_OKAY) {\n        goto ERR;\n    }\n    mp_rshd(&a1, B);\n    if ((res = mp_mod_2d(&a1, DIGIT_BIT * B, &a1)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_copy(a, &a2)) != MP_OKAY) {\n        goto ERR;\n    }\n    mp_rshd(&a2, B * 2);\n\n    /* b = b2 * B**2 + b1 * B + b0 */\n    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_copy(b, &b1)) != MP_OKAY) {\n        goto ERR;\n    }\n    mp_rshd(&b1, B);\n    (void)mp_mod_2d(&b1, DIGIT_BIT * B, &b1);\n\n    if ((res = mp_copy(b, &b2)) != MP_OKAY) {\n        goto ERR;\n    }\n    mp_rshd(&b2, B * 2);\n\n    /* w0 = a0*b0 */\n    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* w4 = a2 * b2 */\n    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */\n    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */\n    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n\n\n    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */\n    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* now solve the matrix\n\n       0  0  0  0  1\n       1  2  4  8  16\n       1  1  1  1  1\n       16 8  4  2  1\n       1  0  0  0  0\n\n       using 12 subtractions, 4 shifts,\n              2 small divisions and 1 small multiplication\n     */\n\n    /* r1 - r4 */\n    if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3 - r0 */\n    if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1/2 */\n    if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3/2 */\n    if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r2 - r0 - r4 */\n    if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1 - r2 */\n    if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3 - r2 */\n    if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1 - 8r0 */\n    if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3 - 8r4 */\n    if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* 3r2 - r1 - r3 */\n    if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1 - r2 */\n    if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3 - r2 */\n    if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1/3 */\n    if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3/3 */\n    if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* at this point shift W[n] by B*n */\n    if ((res = mp_lshd(&w1, 1 * B)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_lshd(&w2, 2 * B)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_lshd(&w3, 3 * B)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_lshd(&w4, 4 * B)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {\n        goto ERR;\n    }\n\nERR:\n    mp_clear_multi(&w0, &w1, &w2, &w3, &w4,\n                   &a0, &a1, &a2, &b0, &b1,\n                   &b2, &tmp1, &tmp2, NULL);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_TOOM_SQR_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* squaring using Toom-Cook 3-way algorithm */\nint\nmp_toom_sqr(mp_int *a, mp_int *b) {\n    mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;\n    int    res, B;\n\n    /* init temps */\n    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {\n        return res;\n    }\n\n    /* B */\n    B = a->used / 3;\n\n    /* a = a2 * B**2 + a1 * B + a0 */\n    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_copy(a, &a1)) != MP_OKAY) {\n        goto ERR;\n    }\n    mp_rshd(&a1, B);\n    if ((res = mp_mod_2d(&a1, DIGIT_BIT * B, &a1)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_copy(a, &a2)) != MP_OKAY) {\n        goto ERR;\n    }\n    mp_rshd(&a2, B * 2);\n\n    /* w0 = a0*a0 */\n    if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* w4 = a2 * a2 */\n    if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* w1 = (a2 + 2(a1 + 2a0))**2 */\n    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* w3 = (a0 + 2(a1 + 2a2))**2 */\n    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n\n\n    /* w2 = (a2 + a1 + a0)**2 */\n    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* now solve the matrix\n\n       0  0  0  0  1\n       1  2  4  8  16\n       1  1  1  1  1\n       16 8  4  2  1\n       1  0  0  0  0\n\n       using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.\n     */\n\n    /* r1 - r4 */\n    if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3 - r0 */\n    if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1/2 */\n    if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3/2 */\n    if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r2 - r0 - r4 */\n    if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1 - r2 */\n    if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3 - r2 */\n    if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1 - 8r0 */\n    if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3 - 8r4 */\n    if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* 3r2 - r1 - r3 */\n    if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1 - r2 */\n    if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3 - r2 */\n    if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r1/3 */\n    if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {\n        goto ERR;\n    }\n    /* r3/3 */\n    if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    /* at this point shift W[n] by B*n */\n    if ((res = mp_lshd(&w1, 1 * B)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_lshd(&w2, 2 * B)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_lshd(&w3, 3 * B)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_lshd(&w4, 4 * B)) != MP_OKAY) {\n        goto ERR;\n    }\n\n    if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {\n        goto ERR;\n    }\n    if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {\n        goto ERR;\n    }\n\nERR:\n    mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);\n    return res;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_TORADIX_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* stores a bignum as a ASCII string in a given radix (2..64) */\nint mp_toradix(mp_int *a, char *str, int radix) {\n    int      res, digs;\n    mp_int   t;\n    mp_digit d;\n    char     *_s = str;\n\n    /* check range of the radix */\n    if ((radix < 2) || (radix > 64)) {\n        return MP_VAL;\n    }\n\n    /* quick out if its zero */\n    if (mp_iszero(a) == MP_YES) {\n        *str++ = '0';\n        *str   = '\\0';\n        return MP_OKAY;\n    }\n\n    if ((res = mp_init_copy(&t, a)) != MP_OKAY) {\n        return res;\n    }\n\n    /* if it is negative output a - */\n    if (t.sign == MP_NEG) {\n        ++_s;\n        *str++ = '-';\n        t.sign = MP_ZPOS;\n    }\n\n    digs = 0;\n    while (mp_iszero(&t) == MP_NO) {\n        if ((res = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) {\n            mp_clear(&t);\n            return res;\n        }\n        *str++ = mp_s_rmap[d];\n        ++digs;\n    }\n\n    /* reverse the digits of the string.  In this case _s points\n     * to the first digit [exluding the sign] of the number]\n     */\n    bn_reverse((unsigned char *)_s, digs);\n\n    /* append a NULL so the string is properly terminated */\n    *str = '\\0';\n\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_UNSIGNED_BIN_SIZE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* get the size for an unsigned equivalent */\nint mp_unsigned_bin_size(mp_int *a) {\n    int size = mp_count_bits(a);\n\n    return (size / 8) + (((size & 7) != 0) ? 1 : 0);\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_XOR_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* XOR two ints together */\nint\nmp_xor(mp_int *a, mp_int *b, mp_int *c) {\n    int    res, ix, px;\n    mp_int t, *x;\n\n    if (a->used > b->used) {\n        if ((res = mp_init_copy(&t, a)) != MP_OKAY) {\n            return res;\n        }\n        px = b->used;\n        x  = b;\n    } else {\n        if ((res = mp_init_copy(&t, b)) != MP_OKAY) {\n            return res;\n        }\n        px = a->used;\n        x  = a;\n    }\n\n    for (ix = 0; ix < px; ix++) {\n        t.dp[ix] ^= x->dp[ix];\n    }\n    mp_clamp(&t);\n    mp_exch(c, &t);\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_MP_ZERO_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* set to zero */\nvoid mp_zero(mp_int *a) {\n    int      n;\n    mp_digit *tmp;\n\n    a->sign = MP_ZPOS;\n    a->used = 0;\n\n    tmp = a->dp;\n    for (n = 0; n < a->alloc; n++) {\n        *tmp++ = 0;\n    }\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_PRIME_TAB_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\nconst mp_digit ltm_prime_tab[] = {\n    0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,\n    0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,\n    0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,\n    0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,\n #ifndef MP_8BIT\n    0x0083,\n    0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,\n    0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,\n    0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,\n    0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,\n\n    0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,\n    0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,\n    0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,\n    0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,\n    0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,\n    0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,\n    0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,\n    0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,\n\n    0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,\n    0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,\n    0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,\n    0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,\n    0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,\n    0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,\n    0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,\n    0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,\n\n    0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,\n    0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,\n    0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,\n    0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,\n    0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,\n    0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,\n    0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,\n    0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653\n #endif\n};\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_REVERSE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* reverse an array, used for radix code */\nvoid\nbn_reverse(unsigned char *s, int len) {\n    int           ix, iy;\n    unsigned char t;\n\n    ix = 0;\n    iy = len - 1;\n    while (ix < iy) {\n        t     = s[ix];\n        s[ix] = s[iy];\n        s[iy] = t;\n        ++ix;\n        --iy;\n    }\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_S_MP_ADD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* low level addition, based on HAC pp.594, Algorithm 14.7 */\nint\ns_mp_add(mp_int *a, mp_int *b, mp_int *c) {\n    mp_int *x;\n    int    olduse, res, min, max;\n\n    /* find sizes, we let |a| <= |b| which means we have to sort\n     * them.  \"x\" will point to the input with the most digits\n     */\n    if (a->used > b->used) {\n        min = b->used;\n        max = a->used;\n        x   = a;\n    } else {\n        min = a->used;\n        max = b->used;\n        x   = b;\n    }\n\n    /* init result */\n    if (c->alloc < (max + 1)) {\n        if ((res = mp_grow(c, max + 1)) != MP_OKAY) {\n            return res;\n        }\n    }\n\n    /* get old used digit count and set new one */\n    olduse  = c->used;\n    c->used = max + 1;\n\n    {\n        mp_digit u, *tmpa, *tmpb, *tmpc;\n        int      i;\n\n        /* alias for digit pointers */\n\n        /* first input */\n        tmpa = a->dp;\n\n        /* second input */\n        tmpb = b->dp;\n\n        /* destination */\n        tmpc = c->dp;\n\n        /* zero the carry */\n        u = 0;\n        for (i = 0; i < min; i++) {\n            /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */\n            *tmpc = *tmpa++ + *tmpb++ + u;\n\n            /* U = carry bit of T[i] */\n            u = *tmpc >> ((mp_digit)DIGIT_BIT);\n\n            /* take away carry bit from T[i] */\n            *tmpc++ &= MP_MASK;\n        }\n\n        /* now copy higher words if any, that is in A+B\n         * if A or B has more digits add those in\n         */\n        if (min != max) {\n            for ( ; i < max; i++) {\n                /* T[i] = X[i] + U */\n                *tmpc = x->dp[i] + u;\n\n                /* U = carry bit of T[i] */\n                u = *tmpc >> ((mp_digit)DIGIT_BIT);\n\n                /* take away carry bit from T[i] */\n                *tmpc++ &= MP_MASK;\n            }\n        }\n\n        /* add carry */\n        *tmpc++ = u;\n\n        /* clear digits above oldused */\n        for (i = c->used; i < olduse; i++) {\n            *tmpc++ = 0;\n        }\n    }\n\n    mp_clamp(c);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_S_MP_EXPTMOD_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n \nint s_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int redmode) {\n    mp_int   M[TAB_SIZE], res, mu;\n    mp_digit buf;\n    int      err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;\n\n    int (*redux)(mp_int *, mp_int *, mp_int *);\n\n    /* find window size */\n    x = mp_count_bits(X);\n    if (x <= 7) {\n        winsize = 2;\n    } else if (x <= 36) {\n        winsize = 3;\n    } else if (x <= 140) {\n        winsize = 4;\n    } else if (x <= 450) {\n        winsize = 5;\n    } else if (x <= 1303) {\n        winsize = 6;\n    } else if (x <= 3529) {\n        winsize = 7;\n    } else {\n        winsize = 8;\n    }\n\n #ifdef MP_LOW_MEM\n    if (winsize > 5) {\n        winsize = 5;\n    }\n #endif\n\n    /* init M array */\n    /* init first cell */\n    if ((err = mp_init(&M[1])) != MP_OKAY) {\n        return err;\n    }\n\n    /* now init the second half of the array */\n    for (x = 1 << (winsize - 1); x < (1 << winsize); x++) {\n        if ((err = mp_init(&M[x])) != MP_OKAY) {\n            for (y = 1 << (winsize - 1); y < x; y++) {\n                mp_clear(&M[y]);\n            }\n            mp_clear(&M[1]);\n            return err;\n        }\n    }\n\n    /* create mu, used for Barrett reduction */\n    if ((err = mp_init(&mu)) != MP_OKAY) {\n        goto LBL_M;\n    }\n\n    if (redmode == 0) {\n        if ((err = mp_reduce_setup(&mu, P)) != MP_OKAY) {\n            goto LBL_MU;\n        }\n        redux = mp_reduce;\n    } else {\n        if ((err = mp_reduce_2k_setup_l(P, &mu)) != MP_OKAY) {\n            goto LBL_MU;\n        }\n        redux = mp_reduce_2k_l;\n    }\n\n    /* create M table\n     *\n     * The M table contains powers of the base,\n     * e.g. M[x] = G**x mod P\n     *\n     * The first half of the table is not\n     * computed though accept for M[0] and M[1]\n     */\n    if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {\n        goto LBL_MU;\n    }\n\n    /* compute the value at M[1<<(winsize-1)] by squaring\n     * M[1] (winsize-1) times\n     */\n    if ((err = mp_copy(&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {\n        goto LBL_MU;\n    }\n\n    for (x = 0; x < (winsize - 1); x++) {\n        /* square it */\n        if ((err = mp_sqr(&M[1 << (winsize - 1)],\n                          &M[1 << (winsize - 1)])) != MP_OKAY) {\n            goto LBL_MU;\n        }\n\n        /* reduce modulo P */\n        if ((err = redux(&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {\n            goto LBL_MU;\n        }\n    }\n\n    /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)\n     * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)\n     */\n    for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {\n        if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) {\n            goto LBL_MU;\n        }\n        if ((err = redux(&M[x], P, &mu)) != MP_OKAY) {\n            goto LBL_MU;\n        }\n    }\n\n    /* setup result */\n    if ((err = mp_init(&res)) != MP_OKAY) {\n        goto LBL_MU;\n    }\n    mp_set(&res, 1);\n\n    /* set initial mode and bit cnt */\n    mode   = 0;\n    bitcnt = 1;\n    buf    = 0;\n    digidx = X->used - 1;\n    bitcpy = 0;\n    bitbuf = 0;\n\n    for ( ; ; ) {\n        /* grab next digit as required */\n        if (--bitcnt == 0) {\n            /* if digidx == -1 we are out of digits */\n            if (digidx == -1) {\n                break;\n            }\n            /* read next digit and reset the bitcnt */\n            buf    = X->dp[digidx--];\n            bitcnt = (int)DIGIT_BIT;\n        }\n\n        /* grab the next msb from the exponent */\n        y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;\n        buf <<= (mp_digit)1;\n\n        /* if the bit is zero and mode == 0 then we ignore it\n         * These represent the leading zero bits before the first 1 bit\n         * in the exponent.  Technically this opt is not required but it\n         * does lower the # of trivial squaring/reductions used\n         */\n        if ((mode == 0) && (y == 0)) {\n            continue;\n        }\n\n        /* if the bit is zero and mode == 1 then we square */\n        if ((mode == 1) && (y == 0)) {\n            if ((err = mp_sqr(&res, &res)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n            if ((err = redux(&res, P, &mu)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n            continue;\n        }\n\n        /* else we add it to the window */\n        bitbuf |= (y << (winsize - ++bitcpy));\n        mode    = 2;\n\n        if (bitcpy == winsize) {\n            /* ok window is filled so square as required and multiply  */\n            /* square first */\n            for (x = 0; x < winsize; x++) {\n                if ((err = mp_sqr(&res, &res)) != MP_OKAY) {\n                    goto LBL_RES;\n                }\n                if ((err = redux(&res, P, &mu)) != MP_OKAY) {\n                    goto LBL_RES;\n                }\n            }\n\n            /* then multiply */\n            if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n            if ((err = redux(&res, P, &mu)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n\n            /* empty window and reset */\n            bitcpy = 0;\n            bitbuf = 0;\n            mode   = 1;\n        }\n    }\n\n    /* if bits remain then square/multiply */\n    if ((mode == 2) && (bitcpy > 0)) {\n        /* square then multiply if the bit is set */\n        for (x = 0; x < bitcpy; x++) {\n            if ((err = mp_sqr(&res, &res)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n            if ((err = redux(&res, P, &mu)) != MP_OKAY) {\n                goto LBL_RES;\n            }\n\n            bitbuf <<= 1;\n            if ((bitbuf & (1 << winsize)) != 0) {\n                /* then multiply */\n                if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) {\n                    goto LBL_RES;\n                }\n                if ((err = redux(&res, P, &mu)) != MP_OKAY) {\n                    goto LBL_RES;\n                }\n            }\n        }\n    }\n\n    mp_exch(&res, Y);\n    err = MP_OKAY;\nLBL_RES: mp_clear(&res);\nLBL_MU: mp_clear(&mu);\nLBL_M:\n    mp_clear(&M[1]);\n    for (x = 1 << (winsize - 1); x < (1 << winsize); x++) {\n        mp_clear(&M[x]);\n    }\n    return err;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_S_MP_MUL_DIGS_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* multiplies |a| * |b| and only computes upto digs digits of result\n * HAC pp. 595, Algorithm 14.12  Modified so you can control how\n * many digits of output are created.\n */\nint s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs) {\n    mp_int   t;\n    int      res, pa, pb, ix, iy;\n    mp_digit u;\n    mp_word  r;\n    mp_digit tmpx, *tmpt, *tmpy;\n\n    /* can we use the fast multiplier? */\n    if (((digs) < MP_WARRAY) &&\n        (TOM_MIN(a->used, b->used) <\n         (1 << ((CHAR_BIT * sizeof(mp_word)) - (2 * DIGIT_BIT))))) {\n        return fast_s_mp_mul_digs(a, b, c, digs);\n    }\n\n    if ((res = mp_init_size(&t, digs)) != MP_OKAY) {\n        return res;\n    }\n    t.used = digs;\n\n    /* compute the digits of the product directly */\n    pa = a->used;\n    for (ix = 0; ix < pa; ix++) {\n        /* set the carry to zero */\n        u = 0;\n\n        /* limit ourselves to making digs digits of output */\n        pb = TOM_MIN(b->used, digs - ix);\n\n        /* setup some aliases */\n        /* copy of the digit from a used within the nested loop */\n        tmpx = a->dp[ix];\n\n        /* an alias for the destination shifted ix places */\n        tmpt = t.dp + ix;\n\n        /* an alias for the digits of b */\n        tmpy = b->dp;\n\n        /* compute the columns of the output and propagate the carry */\n        for (iy = 0; iy < pb; iy++) {\n            /* compute the column as a mp_word */\n            r = (mp_word) * tmpt +\n                ((mp_word)tmpx * (mp_word) * tmpy++) +\n                (mp_word)u;\n\n            /* the new column is the lower part of the result */\n            *tmpt++ = (mp_digit)(r & ((mp_word)MP_MASK));\n\n            /* get the carry word from the result */\n            u = (mp_digit)(r >> ((mp_word)DIGIT_BIT));\n        }\n        /* set carry if it is placed below digs */\n        if ((ix + iy) < digs) {\n            *tmpt = u;\n        }\n    }\n\n    mp_clamp(&t);\n    mp_exch(&t, c);\n\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_S_MP_MUL_HIGH_DIGS_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* multiplies |a| * |b| and does not compute the lower digs digits\n * [meant to get the higher part of the product]\n */\nint\ns_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs) {\n    mp_int   t;\n    int      res, pa, pb, ix, iy;\n    mp_digit u;\n    mp_word  r;\n    mp_digit tmpx, *tmpt, *tmpy;\n\n    /* can we use the fast multiplier? */\n #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C\n    if (((a->used + b->used + 1) < MP_WARRAY) &&\n        (TOM_MIN(a->used, b->used) < (1 << ((CHAR_BIT * sizeof(mp_word)) - (2 * DIGIT_BIT))))) {\n        return fast_s_mp_mul_high_digs(a, b, c, digs);\n    }\n #endif\n\n    if ((res = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) {\n        return res;\n    }\n    t.used = a->used + b->used + 1;\n\n    pa = a->used;\n    pb = b->used;\n    for (ix = 0; ix < pa; ix++) {\n        /* clear the carry */\n        u = 0;\n\n        /* left hand side of A[ix] * B[iy] */\n        tmpx = a->dp[ix];\n\n        /* alias to the address of where the digits will be stored */\n        tmpt = &(t.dp[digs]);\n\n        /* alias for where to read the right hand side from */\n        tmpy = b->dp + (digs - ix);\n\n        for (iy = digs - ix; iy < pb; iy++) {\n            /* calculate the double precision result */\n            r = (mp_word) * tmpt +\n                ((mp_word)tmpx * (mp_word) * tmpy++) +\n                (mp_word)u;\n\n            /* get the lower part */\n            *tmpt++ = (mp_digit)(r & ((mp_word)MP_MASK));\n\n            /* carry the carry */\n            u = (mp_digit)(r >> ((mp_word)DIGIT_BIT));\n        }\n        *tmpt = u;\n    }\n    mp_clamp(&t);\n    mp_exch(&t, c);\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_S_MP_SQR_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */\nint s_mp_sqr(mp_int *a, mp_int *b) {\n    mp_int   t;\n    int      res, ix, iy, pa;\n    mp_word  r;\n    mp_digit u, tmpx, *tmpt;\n\n    pa = a->used;\n    if ((res = mp_init_size(&t, (2 * pa) + 1)) != MP_OKAY) {\n        return res;\n    }\n\n    /* default used is maximum possible size */\n    t.used = (2 * pa) + 1;\n\n    for (ix = 0; ix < pa; ix++) {\n        /* first calculate the digit at 2*ix */\n        /* calculate double precision result */\n        r = (mp_word)t.dp[2 * ix] +\n            ((mp_word)a->dp[ix] * (mp_word)a->dp[ix]);\n\n        /* store lower part in result */\n        t.dp[ix + ix] = (mp_digit)(r & ((mp_word)MP_MASK));\n\n        /* get the carry */\n        u = (mp_digit)(r >> ((mp_word)DIGIT_BIT));\n\n        /* left hand side of A[ix] * A[iy] */\n        tmpx = a->dp[ix];\n\n        /* alias for where to store the results */\n        tmpt = t.dp + ((2 * ix) + 1);\n\n        for (iy = ix + 1; iy < pa; iy++) {\n            /* first calculate the product */\n            r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);\n\n            /* now calculate the double precision result, note we use\n             * addition instead of *2 since it's easier to optimize\n             */\n            r = ((mp_word) * tmpt) + r + r + ((mp_word)u);\n\n            /* store lower part */\n            *tmpt++ = (mp_digit)(r & ((mp_word)MP_MASK));\n\n            /* get carry */\n            u = (mp_digit)(r >> ((mp_word)DIGIT_BIT));\n        }\n        /* propagate upwards */\n        while (u != ((mp_digit)0)) {\n            r       = ((mp_word) * tmpt) + ((mp_word)u);\n            *tmpt++ = (mp_digit)(r & ((mp_word)MP_MASK));\n            u       = (mp_digit)(r >> ((mp_word)DIGIT_BIT));\n        }\n    }\n\n    mp_clamp(&t);\n    mp_exch(&t, b);\n    mp_clear(&t);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BN_S_MP_SUB_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */\nint\ns_mp_sub(mp_int *a, mp_int *b, mp_int *c) {\n    int olduse, res, min, max;\n\n    /* find sizes */\n    min = b->used;\n    max = a->used;\n\n    /* init result */\n    if (c->alloc < max) {\n        if ((res = mp_grow(c, max)) != MP_OKAY) {\n            return res;\n        }\n    }\n    olduse  = c->used;\n    c->used = max;\n\n    {\n        mp_digit u, *tmpa, *tmpb, *tmpc;\n        int      i;\n\n        /* alias for digit pointers */\n        tmpa = a->dp;\n        tmpb = b->dp;\n        tmpc = c->dp;\n\n        /* set carry to zero */\n        u = 0;\n        for (i = 0; i < min; i++) {\n            /* T[i] = A[i] - B[i] - U */\n            *tmpc = (*tmpa++ - *tmpb++) - u;\n\n            /* U = carry bit of T[i]\n             * Note this saves performing an AND operation since\n             * if a carry does occur it will propagate all the way to the\n             * MSB.  As a result a single shift is enough to get the carry\n             */\n            u = *tmpc >> ((mp_digit)((CHAR_BIT * sizeof(mp_digit)) - 1));\n\n            /* Clear carry from T[i] */\n            *tmpc++ &= MP_MASK;\n        }\n\n        /* now copy higher words if any, e.g. if A has more digits than B  */\n        for ( ; i < max; i++) {\n            /* T[i] = A[i] - U */\n            *tmpc = *tmpa++ - u;\n\n            /* U = carry bit of T[i] */\n            u = *tmpc >> ((mp_digit)((CHAR_BIT * sizeof(mp_digit)) - 1));\n\n            /* Clear carry from T[i] */\n            *tmpc++ &= MP_MASK;\n        }\n\n        /* clear digits above used (since we may not have grown result above) */\n        for (i = c->used; i < olduse; i++) {\n            *tmpc++ = 0;\n        }\n    }\n\n    mp_clamp(c);\n    return MP_OKAY;\n}\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n\n#ifdef BNCORE_C\n\n/* LibTomMath, multiple-precision integer library -- Tom St Denis\n *\n * LibTomMath is a library that provides multiple-precision\n * integer arithmetic as well as number theoretic functionality.\n *\n * The library was designed directly after the MPI library by\n * Michael Fromberger but has been written from scratch with\n * additional optimizations in place.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tstdenis82@gmail.com, http://libtom.org\n */\n\n/* Known optimal configurations\n\n   CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF\n   -------------------------------------------------------------\n   Intel P4 Northwood     /GCC v3.4.1   /        88/       128/LTM 0.32 ;-)\n   AMD Athlon64           /GCC v3.4.4   /        80/       120/LTM 0.35\n\n */\n\nint KARATSUBA_MUL_CUTOFF = 80,          /* Min. number of digits before Karatsuba multiplication is used. */\n    KARATSUBA_SQR_CUTOFF = 120,         /* Min. number of digits before Karatsuba squaring is used. */\n\n    TOOM_MUL_CUTOFF = 350,              /* no optimal values of these are known yet so set em high */\n    TOOM_SQR_CUTOFF = 400;\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file crypt.c\n   Build strings, Tom St Denis\n */\n\nconst char *crypt_build_settings =\n    \"LibTomCrypt \"\"1.17\"\" (Tom St Denis, tomstdenis@gmail.com)\\n\"\n                          \"LibTomCrypt is public domain software.\\n\"\n                          \"Built on \" __DATE__ \" at \" __TIME__ \"\\n\\n\\n\"\n                                                               \"Endianess: \"\n#if defined(ENDIAN_NEUTRAL)\n    \"neutral\\n\"\n#elif defined(ENDIAN_LITTLE)\n    \"little\"\n #if defined(ENDIAN_32BITWORD)\n    \" (32-bit words)\\n\"\n #else\n    \" (64-bit words)\\n\"\n #endif\n#elif defined(ENDIAN_BIG)\n    \"big\"\n #if defined(ENDIAN_32BITWORD)\n    \" (32-bit words)\\n\"\n #else\n    \" (64-bit words)\\n\"\n #endif\n#endif\n    \"Clean stack: \"\n#if defined(LTC_CLEAN_STACK)\n    \"enabled\\n\"\n#else\n    \"disabled\\n\"\n#endif\n    \"Ciphers built-in:\\n\"\n#if defined(LTC_BLOWFISH)\n    \"   Blowfish\\n\"\n#endif\n#if defined(LTC_RC2)\n    \"   LTC_RC2\\n\"\n#endif\n#if defined(LTC_RC5)\n    \"   LTC_RC5\\n\"\n#endif\n#if defined(LTC_RC6)\n    \"   LTC_RC6\\n\"\n#endif\n#if defined(LTC_SAFERP)\n    \"   Safer+\\n\"\n#endif\n#if defined(LTC_SAFER)\n    \"   Safer\\n\"\n#endif\n#if defined(LTC_RIJNDAEL)\n    \"   Rijndael\\n\"\n#endif\n#if defined(LTC_XTEA)\n    \"   LTC_XTEA\\n\"\n#endif\n#if defined(LTC_TWOFISH)\n    \"   Twofish \"\n #if defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES)\n    \"(small, tables, all_tables)\\n\"\n #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES)\n    \"(small, tables)\\n\"\n #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_ALL_TABLES)\n    \"(small, all_tables)\\n\"\n #elif defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES)\n    \"(tables, all_tables)\\n\"\n #elif defined(LTC_TWOFISH_SMALL)\n    \"(small)\\n\"\n #elif defined(LTC_TWOFISH_TABLES)\n    \"(tables)\\n\"\n #elif defined(LTC_TWOFISH_ALL_TABLES)\n    \"(all_tables)\\n\"\n #else\n    \"\\n\"\n #endif\n#endif\n#if defined(LTC_DES)\n    \"   LTC_DES\\n\"\n#endif\n#if defined(LTC_CAST5)\n    \"   LTC_CAST5\\n\"\n#endif\n#if defined(LTC_NOEKEON)\n    \"   Noekeon\\n\"\n#endif\n#if defined(LTC_SKIPJACK)\n    \"   Skipjack\\n\"\n#endif\n#if defined(LTC_KHAZAD)\n    \"   Khazad\\n\"\n#endif\n#if defined(LTC_ANUBIS)\n    \"   Anubis \"\n#endif\n#if defined(LTC_ANUBIS_TWEAK)\n    \" (tweaked)\"\n#endif\n    \"\\n\"\n#if defined(LTC_KSEED)\n    \"   LTC_KSEED\\n\"\n#endif\n#if defined(LTC_KASUMI)\n    \"   KASUMI\\n\"\n#endif\n\n    \"\\nHashes built-in:\\n\"\n#if defined(LTC_SHA512)\n    \"   LTC_SHA-512\\n\"\n#endif\n#if defined(LTC_SHA384)\n    \"   LTC_SHA-384\\n\"\n#endif\n#if defined(LTC_SHA256)\n    \"   LTC_SHA-256\\n\"\n#endif\n#if defined(LTC_SHA224)\n    \"   LTC_SHA-224\\n\"\n#endif\n#if defined(LTC_TIGER)\n    \"   LTC_TIGER\\n\"\n#endif\n#if defined(LTC_SHA1)\n    \"   LTC_SHA1\\n\"\n#endif\n#if defined(LTC_MD5)\n    \"   LTC_MD5\\n\"\n#endif\n#if defined(LTC_MD4)\n    \"   LTC_MD4\\n\"\n#endif\n#if defined(LTC_MD2)\n    \"   LTC_MD2\\n\"\n#endif\n#if defined(LTC_RIPEMD128)\n    \"   LTC_RIPEMD128\\n\"\n#endif\n#if defined(LTC_RIPEMD160)\n    \"   LTC_RIPEMD160\\n\"\n#endif\n#if defined(LTC_RIPEMD256)\n    \"   LTC_RIPEMD256\\n\"\n#endif\n#if defined(LTC_RIPEMD320)\n    \"   LTC_RIPEMD320\\n\"\n#endif\n#if defined(LTC_WHIRLPOOL)\n    \"   LTC_WHIRLPOOL\\n\"\n#endif\n#if defined(LTC_CHC_HASH)\n    \"   LTC_CHC_HASH \\n\"\n#endif\n\n    \"\\nBlock Chaining Modes:\\n\"\n#if defined(LTC_CFB_MODE)\n    \"   CFB\\n\"\n#endif\n#if defined(LTC_OFB_MODE)\n    \"   OFB\\n\"\n#endif\n#if defined(LTC_ECB_MODE)\n    \"   ECB\\n\"\n#endif\n#if defined(LTC_CBC_MODE)\n    \"   CBC\\n\"\n#endif\n#if defined(LTC_CTR_MODE)\n    \"   CTR \"\n#endif\n#if defined(LTC_CTR_OLD)\n    \" (CTR_OLD) \"\n#endif\n    \"\\n\"\n#if defined(LRW_MODE)\n    \"   LRW_MODE\"\n #if defined(LRW_TABLES)\n    \" (LRW_TABLES) \"\n #endif\n    \"\\n\"\n#endif\n#if defined(LTC_F8_MODE)\n    \"   F8 MODE\\n\"\n#endif\n#if defined(LTC_XTS_MODE)\n    \"   LTC_XTS_MODE\\n\"\n#endif\n\n    \"\\nMACs:\\n\"\n#if defined(LTC_HMAC)\n    \"   LTC_HMAC\\n\"\n#endif\n#if defined(LTC_OMAC)\n    \"   LTC_OMAC\\n\"\n#endif\n#if defined(LTC_PMAC)\n    \"   PMAC\\n\"\n#endif\n#if defined(LTC_PELICAN)\n    \"   LTC_PELICAN\\n\"\n#endif\n#if defined(LTC_XCBC)\n    \"   XCBC-MAC\\n\"\n#endif\n#if defined(LTC_F9_MODE)\n    \"   F9-MAC\\n\"\n#endif\n\n    \"\\nENC + AUTH modes:\\n\"\n#if defined(LTC_EAX_MODE)\n    \"   LTC_EAX_MODE\\n\"\n#endif\n#if defined(LTC_OCB_MODE)\n    \"   LTC_OCB_MODE\\n\"\n#endif\n#if defined(LTC_CCM_MODE)\n    \"   LTC_CCM_MODE\\n\"\n#endif\n#if defined(LTC_GCM_MODE)\n    \"   LTC_GCM_MODE \"\n#endif\n#if defined(LTC_GCM_TABLES)\n    \" (LTC_GCM_TABLES) \"\n#endif\n    \"\\n\"\n\n    \"\\nPRNG:\\n\"\n#if defined(LTC_YARROW)\n    \"   Yarrow\\n\"\n#endif\n#if defined(LTC_SPRNG)\n    \"   LTC_SPRNG\\n\"\n#endif\n#if defined(LTC_RC4)\n    \"   LTC_RC4\\n\"\n#endif\n#if defined(LTC_FORTUNA)\n    \"   Fortuna\\n\"\n#endif\n#if defined(LTC_SOBER128)\n    \"   LTC_SOBER128\\n\"\n#endif\n\n    \"\\nPK Algs:\\n\"\n#if defined(LTC_MRSA)\n    \"   RSA \\n\"\n#endif\n#if defined(LTC_MECC)\n    \"   ECC\\n\"\n#endif\n#if defined(LTC_MDSA)\n    \"   DSA\\n\"\n#endif\n#if defined(MKAT)\n    \"   Katja\\n\"\n#endif\n\n    \"\\nCompiler:\\n\"\n#if defined(WIN32)\n    \"   WIN32 platform detected.\\n\"\n#endif\n#if defined(__CYGWIN__)\n    \"   CYGWIN Detected.\\n\"\n#endif\n#if defined(__DJGPP__)\n    \"   DJGPP Detected.\\n\"\n#endif\n#if defined(_MSC_VER)\n    \"   MSVC compiler detected.\\n\"\n#endif\n#if defined(__GNUC__)\n    \"   GCC compiler detected.\\n\"\n#endif\n#if defined(INTEL_CC)\n    \"   Intel C Compiler detected.\\n\"\n#endif\n#if defined(__x86_64__)\n    \"   x86-64 detected.\\n\"\n#endif\n#if defined(LTC_PPC32)\n    \"   LTC_PPC32 defined \\n\"\n#endif\n\n    \"\\nVarious others: \"\n#if defined(LTC_BASE64)\n    \" LTC_BASE64 \"\n#endif\n#if defined(MPI)\n    \" MPI \"\n#endif\n#if defined(TRY_UNRANDOM_FIRST)\n    \" TRY_UNRANDOM_FIRST \"\n#endif\n#if defined(LTC_TEST)\n    \" LTC_TEST \"\n#endif\n#if defined(LTC_PKCS_1)\n    \" LTC_PKCS#1 \"\n#endif\n#if defined(LTC_PKCS_5)\n    \" LTC_PKCS#5 \"\n#endif\n#if defined(LTC_SMALL_CODE)\n    \" LTC_SMALL_CODE \"\n#endif\n#if defined(LTC_NO_FILE)\n    \" LTC_NO_FILE \"\n#endif\n#if defined(LTC_DER)\n    \" LTC_DER \"\n#endif\n#if defined(LTC_FAST)\n    \" LTC_FAST \"\n#endif\n#if defined(LTC_NO_FAST)\n    \" LTC_NO_FAST \"\n#endif\n#if defined(LTC_NO_BSWAP)\n    \" LTC_NO_BSWAP \"\n#endif\n#if defined(LTC_NO_ASM)\n    \" LTC_NO_ASM \"\n#endif\n#if defined(LTC_NO_TEST)\n    \" LTC_NO_TEST \"\n#endif\n#if defined(LTC_NO_TABLES)\n    \" LTC_NO_TABLES \"\n#endif\n#if defined(LTC_PTHREAD)\n    \" LTC_PTHREAD \"\n#endif\n#if defined(LTM_LTC_DESC)\n    \" LTM_DESC \"\n#endif\n#if defined(TFM_LTC_DESC)\n    \" TFM_DESC \"\n#endif\n#if defined(LTC_MECC_ACCEL)\n    \" LTC_MECC_ACCEL \"\n#endif\n#if defined(GMP_LTC_DESC)\n    \" GMP_DESC \"\n#endif\n#if defined(LTC_EASY)\n    \" (easy) \"\n#endif\n#if defined(LTC_MECC_FP)\n    \" LTC_MECC_FP \"\n#endif\n#if defined(LTC_ECC_SHAMIR)\n    \" LTC_ECC_SHAMIR \"\n#endif\n    \"\\n\"\n    \"\\n\\n\\n\"\n;\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt.c,v $ */\n/* $Revision: 1.36 $ */\n/* $Date: 2007/05/12 14:46:12 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n#include <signal.h>\n\n/**\n   @file crypt_argchk.c\n   Perform argument checking, Tom St Denis\n */\n\n#if (ARGTYPE == 0)\nvoid crypt_argchk(char *v, char *s, int d) {\n    fprintf(stderr, \"LTC_ARGCHK '%s' failure on line %d of file %s\\n\",\n            v, d, s);\n    (void)raise(SIGABRT);\n}\n#endif\n\n#ifndef TOMCRYPT_H_\n#define TOMCRYPT_H_\n#define USE_LTM\n#define LTM_DESC\n#define LTC_SHA1\n#include <assert.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <time.h>\n#include <ctype.h>\n#include <limits.h>\n\n/* use configuration data */\n#ifndef TOMCRYPT_CUSTOM_H_\n#define TOMCRYPT_CUSTOM_H_\n\n/* macros for various libc functions you can change for embedded targets */\n#ifndef XMALLOC\n #ifdef malloc\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XMALLOC    malloc\n#endif\n#ifndef XREALLOC\n #ifdef realloc\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XREALLOC    realloc\n#endif\n#ifndef XCALLOC\n #ifdef calloc\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XCALLOC    calloc\n#endif\n#ifndef XFREE\n #ifdef free\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XFREE    free\n#endif\n\n#ifndef XMEMSET\n #ifdef memset\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XMEMSET    memset\n#endif\n#ifndef XMEMCPY\n #ifdef memcpy\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XMEMCPY    memcpy\n#endif\n#ifndef XMEMCMP\n #ifdef memcmp\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XMEMCMP    memcmp\n#endif\n#ifndef XSTRCMP\n #ifdef strcmp\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XSTRCMP    strcmp\n#endif\n\n#ifndef XCLOCK\n #define XCLOCK             clock\n#endif\n#ifndef XCLOCKS_PER_SEC\n #define XCLOCKS_PER_SEC    CLOCKS_PER_SEC\n#endif\n\n#ifndef XQSORT\n #ifdef qsort\n  #define LTC_NO_PROTOTYPES\n #endif\n #define XQSORT    qsort\n#endif\n\n/* Easy button? */\n#ifdef LTC_EASY\n #define LTC_NO_CIPHERS\n #define LTC_RIJNDAEL\n #define LTC_BLOWFISH\n #define LTC_DES\n #define LTC_CAST5\n\n #define LTC_NO_MODES\n #define LTC_ECB_MODE\n #define LTC_CBC_MODE\n #define LTC_CTR_MODE\n\n #define LTC_NO_HASHES\n #define LTC_SHA1\n #define LTC_SHA512\n #define LTC_SHA384\n #define LTC_SHA256\n #define LTC_SHA224\n\n #define LTC_NO_MACS\n #define LTC_HMAC\n #define LTC_OMAC\n #define LTC_CCM_MODE\n\n #define LTC_NO_PRNGS\n #define LTC_SPRNG\n #define LTC_YARROW\n #define LTC_DEVRANDOM\n #define TRY_URANDOM_FIRST\n\n #define LTC_NO_PK\n #define LTC_MRSA\n #define LTC_MECC\n#endif\n\n/* Use small code where possible */\n/* #define LTC_SMALL_CODE */\n\n/* Enable self-test test vector checking */\n#ifndef LTC_NO_TEST\n #define LTC_TEST\n#endif\n\n/* clean the stack of functions which put private information on stack */\n/* #define LTC_CLEAN_STACK */\n\n/* disable all file related functions */\n#define LTC_NO_FILE\n/* For our purposes, we cannot assume /dev/*random is present. However, our\n   inbuilt aarc4 allegedly does have file operations even if this is set.\n   -- ck */\n\n/* do not assume we have wchar.h */\n#define LTC_NO_WCHAR\n\n/* disable all forms of ASM */\n#define LTC_NO_ASM\n\n/* disable FAST mode */\n/* #define LTC_NO_FAST */\n\n/* disable BSWAP on x86 */\n/* #define LTC_NO_BSWAP */\n\n/* ---> Symmetric Block Ciphers <--- */\n#ifndef LTC_NO_CIPHERS\n\n #define LTC_BLOWFISH\n #define LTC_RC2\n #define LTC_RC5\n #define LTC_RC6\n #define LTC_SAFERP\n #define LTC_RIJNDAEL\n #define LTC_XTEA\n\n/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format\n * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */\n #define LTC_TWOFISH\n #ifndef LTC_NO_TABLES\n  #define LTC_TWOFISH_TABLES\n/* #define LTC_TWOFISH_ALL_TABLES */\n #else\n  #define LTC_TWOFISH_SMALL\n #endif\n/* #define LTC_TWOFISH_SMALL */\n/* LTC_DES includes EDE triple-LTC_DES */\n #define LTC_DES\n #define LTC_CAST5\n #define LTC_NOEKEON\n #define LTC_SKIPJACK\n #define LTC_SAFER\n #define LTC_KHAZAD\n #define LTC_ANUBIS\n #define LTC_ANUBIS_TWEAK\n #define LTC_KSEED\n #define LTC_KASUMI\n#endif /* LTC_NO_CIPHERS */\n\n\n/* ---> Block Cipher Modes of Operation <--- */\n#ifndef LTC_NO_MODES\n\n #define LTC_CFB_MODE\n #define LTC_OFB_MODE\n #define LTC_ECB_MODE\n #define LTC_CBC_MODE\n #define LTC_CTR_MODE\n\n/* F8 chaining mode */\n #define LTC_F8_MODE\n\n/* LRW mode */\n #define LTC_LRW_MODE\n #ifndef LTC_NO_TABLES\n\n/* like GCM mode this will enable 16 8x128 tables [64KB] that make\n * seeking very fast.\n */\n  #define LRW_TABLES\n #endif\n\n/* XTS mode */\n #define LTC_XTS_MODE\n#endif /* LTC_NO_MODES */\n\n/* ---> One-Way Hash Functions <--- */\n#ifndef LTC_NO_HASHES\n\n #define LTC_CHC_HASH\n #define LTC_WHIRLPOOL\n #define LTC_SHA512\n #define LTC_SHA384\n #define LTC_SHA256\n #define LTC_SHA224\n #define LTC_TIGER\n #define LTC_SHA1\n #define LTC_MD5\n #define LTC_MD4\n #define LTC_MD2\n #define LTC_RIPEMD128\n #define LTC_RIPEMD160\n #define LTC_RIPEMD256\n #define LTC_RIPEMD320\n#endif /* LTC_NO_HASHES */\n\n/* ---> MAC functions <--- */\n#ifndef LTC_NO_MACS\n\n #define LTC_HMAC\n #define LTC_OMAC\n #define LTC_PMAC\n #define LTC_XCBC\n #define LTC_F9_MODE\n #define LTC_PELICAN\n\n #if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL)\n  #error Pelican-MAC requires LTC_RIJNDAEL\n #endif\n\n/* ---> Encrypt + Authenticate Modes <--- */\n\n #define LTC_EAX_MODE\n #if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC))\n  #error LTC_EAX_MODE requires CTR and LTC_OMAC mode\n #endif\n\n #define LTC_OCB_MODE\n #define LTC_CCM_MODE\n #define LTC_GCM_MODE\n\n/* Use 64KiB tables */\n #ifndef LTC_NO_TABLES\n  #define LTC_GCM_TABLES\n #endif\n\n/* USE SSE2? requires GCC works on x86_32 and x86_64*/\n #ifdef LTC_GCM_TABLES\n/* #define LTC_GCM_TABLES_SSE2 */\n #endif\n#endif /* LTC_NO_MACS */\n\n/* Various tidbits of modern neatoness */\n#define LTC_BASE64\n\n/* --> Pseudo Random Number Generators <--- */\n#ifndef LTC_NO_PRNGS\n\n/* Yarrow */\n #define LTC_YARROW\n/* which descriptor of AES to use?  */\n/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */\n #define LTC_YARROW_AES    0\n\n #if defined(LTC_YARROW) && !defined(LTC_CTR_MODE)\n  #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined!\n #endif\n\n/* a PRNG that simply reads from an available system source */\n #define LTC_SPRNG\n\n/* The LTC_RC4 stream cipher */\n #define LTC_RC4\n\n/* Fortuna PRNG */\n #define LTC_FORTUNA\n/* reseed every N calls to the read function */\n #define LTC_FORTUNA_WD       10\n/* number of pools (4..32) can save a bit of ram by lowering the count */\n #define LTC_FORTUNA_POOLS    32\n\n/* Greg's LTC_SOBER128 PRNG ;-0 */\n #define LTC_SOBER128\n\n/* the *nix style /dev/random device */\n #define LTC_DEVRANDOM\n/* try /dev/urandom before trying /dev/random */\n #define TRY_URANDOM_FIRST\n#endif /* LTC_NO_PRNGS */\n\n/* ---> math provider? <--- */\n#ifndef LTC_NO_MATH\n\n/* LibTomMath */\n/* #define LTM_LTC_DESC */\n\n/* TomsFastMath */\n/* #define TFM_LTC_DESC */\n#endif /* LTC_NO_MATH */\n\n/* ---> Public Key Crypto <--- */\n#ifndef LTC_NO_PK\n\n/* Include RSA support */\n #define LTC_MRSA\n\n/* Include Katja (a Rabin variant like RSA) */\n/* #define MKAT */\n\n/* Digital Signature Algorithm */\n #define LTC_MDSA\n\n/* ECC */\n #define LTC_MECC\n\n/* use Shamir's trick for point mul (speeds up signature verification) */\n #define LTC_ECC_SHAMIR\n\n #if defined(TFM_LTC_DESC) && defined(LTC_MECC)\n  #define LTC_MECC_ACCEL\n #endif\n\n/* do we want fixed point ECC */\n/* #define LTC_MECC_FP */\n\n/* Timing Resistant? */\n/* #define LTC_ECC_TIMING_RESISTANT */\n#endif /* LTC_NO_PK */\n\n/* LTC_PKCS #1 (RSA) and #5 (Password Handling) stuff */\n#ifndef LTC_NO_PKCS\n\n #define LTC_PKCS_1\n #define LTC_PKCS_5\n\n/* Include ASN.1 DER (required by DSA/RSA) */\n #define LTC_DER\n#endif /* LTC_NO_PKCS */\n\n/* cleanup */\n\n#ifdef LTC_MECC\n/* Supported ECC Key Sizes */\n #ifndef LTC_NO_CURVES\n  #define ECC112\n  #define ECC128\n  #define ECC160\n  #define ECC192\n  #define ECC224\n  #define ECC256\n  #define ECC384\n  #define ECC521\n #endif\n#endif\n\n#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(MKATJA)\n/* Include the MPI functionality?  (required by the PK algorithms) */\n #define MPI\n#endif\n\n#ifdef LTC_MRSA\n #define LTC_PKCS_1\n#endif\n\n#if defined(LTC_DER) && !defined(MPI)\n #error ASN.1 DER requires MPI functionality\n#endif\n\n#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC) || defined(MKATJA)) && !defined(LTC_DER)\n #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled\n#endif\n\n/* THREAD management */\n#ifdef LTC_PTHREAD\n\n #include <pthread.h>\n\n #define LTC_MUTEX_GLOBAL(x)    pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;\n #define LTC_MUTEX_PROTO(x)     extern pthread_mutex_t x;\n #define LTC_MUTEX_TYPE(x)      pthread_mutex_t x;\n #define LTC_MUTEX_INIT(x)      pthread_mutex_init(x, NULL);\n #define LTC_MUTEX_LOCK(x)      pthread_mutex_lock(x);\n #define LTC_MUTEX_UNLOCK(x)    pthread_mutex_unlock(x);\n\n#else\n\n/* default no functions */\n #define LTC_MUTEX_GLOBAL(x)\n #define LTC_MUTEX_PROTO(x)\n #define LTC_MUTEX_TYPE(x)\n #define LTC_MUTEX_INIT(x)\n #define LTC_MUTEX_LOCK(x)\n #define LTC_MUTEX_UNLOCK(x)\n#endif\n\n/* Debuggers */\n\n/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and LTC_RC4 work (see the code) */\n/* #define LTC_VALGRIND */\n#endif\n\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_custom.h,v $ */\n/* $Revision: 1.73 $ */\n/* $Date: 2007/05/12 14:37:41 $ */ \n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* version */\n#define CRYPT           0x0117\n#define SCRYPT          \"1.17\"\n\n/* max size of either a cipher/hash block or symmetric key [largest of the two] */\n#define MAXBLOCKSIZE    128\n\n/* descriptor table size */\n\n/* error codes [will be expanded in future releases] */\nenum {\n    CRYPT_OK=0,               /* Result OK */\n    CRYPT_ERROR,              /* Generic Error */\n    CRYPT_NOP,                /* Not a failure but no operation was performed */\n\n    CRYPT_INVALID_KEYSIZE,    /* Invalid key size given */\n    CRYPT_INVALID_ROUNDS,     /* Invalid number of rounds */\n    CRYPT_FAIL_TESTVECTOR,    /* Algorithm failed test vectors */\n\n    CRYPT_BUFFER_OVERFLOW,    /* Not enough space for output */\n    CRYPT_INVALID_PACKET,     /* Invalid input packet given */\n\n    CRYPT_INVALID_PRNGSIZE,   /* Invalid number of bits for a PRNG */\n    CRYPT_ERROR_READPRNG,     /* Could not read enough from PRNG */\n\n    CRYPT_INVALID_CIPHER,     /* Invalid cipher specified */\n    CRYPT_INVALID_HASH,       /* Invalid hash specified */\n    CRYPT_INVALID_PRNG,       /* Invalid PRNG specified */\n\n    CRYPT_MEM,                /* Out of memory */\n\n    CRYPT_PK_TYPE_MISMATCH,   /* Not equivalent types of PK keys */\n    CRYPT_PK_NOT_PRIVATE,     /* Requires a private PK key */\n\n    CRYPT_INVALID_ARG,        /* Generic invalid argument */\n    CRYPT_FILE_NOTFOUND,      /* File Not Found */\n\n    CRYPT_PK_INVALID_TYPE,    /* Invalid type of PK key */\n    CRYPT_PK_INVALID_SYSTEM,  /* Invalid PK system specified */\n    CRYPT_PK_DUP,             /* Duplicate key already in key ring */\n    CRYPT_PK_NOT_FOUND,       /* Key not found in keyring */\n    CRYPT_PK_INVALID_SIZE,    /* Invalid size input for PK parameters */\n\n    CRYPT_INVALID_PRIME_SIZE, /* Invalid size of prime requested */\n    CRYPT_PK_INVALID_PADDING  /* Invalid padding on input */\n};\n\n/* This is the build config file.\n *\n * With this you can setup what to inlcude/exclude automatically during any build.  Just comment\n * out the line that #define's the word for the thing you want to remove.  phew!\n */\n\n#ifndef TOMCRYPT_CFG_H\n#define TOMCRYPT_CFG_H\n\n#if defined(_WIN32) || defined(_MSC_VER)\n #define LTC_CALL    __cdecl\n#else\n #ifndef LTC_CALL\n  #define LTC_CALL\n #endif\n#endif\n\n#ifndef LTC_EXPORT\n #define LTC_EXPORT\n#endif\n\n/* certain platforms use macros for these, making the prototypes broken */\n#ifndef LTC_NO_PROTOTYPES\n\n/* you can change how memory allocation works ... */\nLTC_EXPORT void *LTC_CALL XMALLOC(size_t n);\nLTC_EXPORT void *LTC_CALL XREALLOC(void *p, size_t n);\nLTC_EXPORT void *LTC_CALL XCALLOC(size_t n, size_t s);\nLTC_EXPORT void LTC_CALL XFREE(void *p);\n\nLTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));\n\n\n/* change the clock function too */\nLTC_EXPORT clock_t LTC_CALL XCLOCK(void);\n\n/* various other functions */\nLTC_EXPORT void *LTC_CALL XMEMCPY(void *dest, const void *src, size_t n);\nLTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n);\nLTC_EXPORT void *LTC_CALL XMEMSET(void *s, int c, size_t n);\n\nLTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);\n#endif\n\n/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */\n#ifndef ARGTYPE\n #define ARGTYPE    0\n#endif\n\n/* Controls endianess and size of registers.  Leave uncommented to get platform neutral [slower] code\n *\n * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.\n * The x86 platforms allow this but some others [ARM for instance] do not.  On those platforms you **MUST**\n * use the portable [slower] macros.\n */\n\n/* detect x86-32 machines somewhat */\n#if !defined(__STRICT_ANSI__) && (defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__))))\n #define ENDIAN_LITTLE\n #define ENDIAN_32BITWORD\n #define LTC_FAST\n #define LTC_FAST_TYPE    unsigned long\n#endif\n\n/* detects MIPS R5900 processors (PS2) */\n#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))\n #define ENDIAN_LITTLE\n #define ENDIAN_64BITWORD\n#endif\n\n/* detect amd64 */\n#if !defined(__STRICT_ANSI__) && defined(__x86_64__)\n #define ENDIAN_LITTLE\n #define ENDIAN_64BITWORD\n #define LTC_FAST\n #define LTC_FAST_TYPE    unsigned long\n#endif\n\n/* detect PPC32 */\n#if !defined(__STRICT_ANSI__) && defined(LTC_PPC32)\n #define ENDIAN_BIG\n #define ENDIAN_32BITWORD\n #define LTC_FAST\n #define LTC_FAST_TYPE    unsigned long\n#endif\n\n/* detect sparc and sparc64 */\n#if defined(__sparc__)\n #define ENDIAN_BIG\n #if defined(__arch64__)\n  #define ENDIAN_64BITWORD\n #else\n  #define ENDIAN_32BITWORD\n #endif\n#endif\n\n\n#ifdef LTC_NO_FAST\n #ifdef LTC_FAST\n  #undef LTC_FAST\n #endif\n#endif\n\n/* No asm is a quick way to disable anything \"not portable\" */\n#ifdef LTC_NO_ASM\n #undef ENDIAN_LITTLE\n #undef ENDIAN_BIG\n #undef ENDIAN_32BITWORD\n #undef ENDIAN_64BITWORD\n #undef LTC_FAST\n #undef LTC_FAST_TYPE\n #define LTC_NO_ROLC\n #define LTC_NO_BSWAP\n#endif\n\n/* #define ENDIAN_LITTLE */\n/* #define ENDIAN_BIG */\n\n/* #define ENDIAN_32BITWORD */\n/* #define ENDIAN_64BITWORD */\n\n#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))\n #error You must specify a word size as well as endianess in tomcrypt_cfg.h\n#endif\n\n#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))\n #define ENDIAN_NEUTRAL\n#endif\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cfg.h,v $ */\n/* $Revision: 1.19 $ */\n/* $Date: 2006/12/04 02:19:48 $ */ \n\n/* fix for MSVC ...evil! */\n#ifdef _MSC_VER\n #define CONST64(n)    n ## ui64\ntypedef unsigned __int64     ulong64;\n#else\n #define CONST64(n)    n ## ULL\ntypedef unsigned long long   ulong64;\n#endif\n\n/* this is the \"32-bit at least\" data type\n * Re-define it to suit your platform but it must be at least 32-bits\n */\n#if defined(__x86_64__) || (defined(__sparc__) && defined(__arch64__))\ntypedef unsigned             ulong32;\n#else\ntypedef unsigned long        ulong32;\n#endif\n\n/* ---- HELPER MACROS ---- */\n#ifdef ENDIAN_NEUTRAL\n\n #define STORE32L(x, y)                                                                         \\\n    { (y)[3] = (unsigned char)(((x) >> 24) & 255); (y)[2] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[1] = (unsigned char)(((x) >> 8) & 255); (y)[0] = (unsigned char)((x) & 255); }\n\n #define LOAD32L(x, y)                            \\\n    { x = ((unsigned long)((y)[3] & 255) << 24) | \\\n          ((unsigned long)((y)[2] & 255) << 16) | \\\n          ((unsigned long)((y)[1] & 255) << 8) |  \\\n          ((unsigned long)((y)[0] & 255)); }\n\n #define STORE64L(x, y)                                                                         \\\n    { (y)[7] = (unsigned char)(((x) >> 56) & 255); (y)[6] = (unsigned char)(((x) >> 48) & 255); \\\n      (y)[5] = (unsigned char)(((x) >> 40) & 255); (y)[4] = (unsigned char)(((x) >> 32) & 255); \\\n      (y)[3] = (unsigned char)(((x) >> 24) & 255); (y)[2] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[1] = (unsigned char)(((x) >> 8) & 255); (y)[0] = (unsigned char)((x) & 255); }\n\n #define LOAD64L(x, y)                                                            \\\n    { x = (((ulong64)((y)[7] & 255)) << 56) | (((ulong64)((y)[6] & 255)) << 48) | \\\n          (((ulong64)((y)[5] & 255)) << 40) | (((ulong64)((y)[4] & 255)) << 32) | \\\n          (((ulong64)((y)[3] & 255)) << 24) | (((ulong64)((y)[2] & 255)) << 16) | \\\n          (((ulong64)((y)[1] & 255)) << 8) | (((ulong64)((y)[0] & 255))); }\n\n #define STORE32H(x, y)                                                                         \\\n    { (y)[0] = (unsigned char)(((x) >> 24) & 255); (y)[1] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[2] = (unsigned char)(((x) >> 8) & 255); (y)[3] = (unsigned char)((x) & 255); }\n\n #define LOAD32H(x, y)                            \\\n    { x = ((unsigned long)((y)[0] & 255) << 24) | \\\n          ((unsigned long)((y)[1] & 255) << 16) | \\\n          ((unsigned long)((y)[2] & 255) << 8) |  \\\n          ((unsigned long)((y)[3] & 255)); }\n\n #define STORE64H(x, y)                                                                         \\\n    { (y)[0] = (unsigned char)(((x) >> 56) & 255); (y)[1] = (unsigned char)(((x) >> 48) & 255); \\\n      (y)[2] = (unsigned char)(((x) >> 40) & 255); (y)[3] = (unsigned char)(((x) >> 32) & 255); \\\n      (y)[4] = (unsigned char)(((x) >> 24) & 255); (y)[5] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[6] = (unsigned char)(((x) >> 8) & 255); (y)[7] = (unsigned char)((x) & 255); }\n\n #define LOAD64H(x, y)                                                            \\\n    { x = (((ulong64)((y)[0] & 255)) << 56) | (((ulong64)((y)[1] & 255)) << 48) | \\\n          (((ulong64)((y)[2] & 255)) << 40) | (((ulong64)((y)[3] & 255)) << 32) | \\\n          (((ulong64)((y)[4] & 255)) << 24) | (((ulong64)((y)[5] & 255)) << 16) | \\\n          (((ulong64)((y)[6] & 255)) << 8) | (((ulong64)((y)[7] & 255))); }\n#endif /* ENDIAN_NEUTRAL */\n\n#ifdef ENDIAN_LITTLE\n\n #if !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))\n\n  #define STORE32H(x, y)     \\\n    asm __volatile__ (       \\\n        \"bswapl %0     \\n\\t\" \\\n        \"movl   %0,(%1)\\n\\t\" \\\n        \"bswapl %0     \\n\\t\" \\\n           ::\"r\" (x), \"r\" (y));\n\n  #define LOAD32H(x, y)    \\\n    asm __volatile__ (     \\\n        \"movl (%1),%0\\n\\t\" \\\n        \"bswapl %0\\n\\t\"    \\\n        : \"=r\" (x) : \"r\" (y));\n\n #else\n\n  #define STORE32H(x, y)                                                                        \\\n    { (y)[0] = (unsigned char)(((x) >> 24) & 255); (y)[1] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[2] = (unsigned char)(((x) >> 8) & 255); (y)[3] = (unsigned char)((x) & 255); }\n\n  #define LOAD32H(x, y)                           \\\n    { x = ((unsigned long)((y)[0] & 255) << 24) | \\\n          ((unsigned long)((y)[1] & 255) << 16) | \\\n          ((unsigned long)((y)[2] & 255) << 8) |  \\\n          ((unsigned long)((y)[3] & 255)); }\n #endif\n\n\n/* x86_64 processor */\n #if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))\n\n  #define STORE64H(x, y)     \\\n    asm __volatile__ (       \\\n        \"bswapq %0     \\n\\t\" \\\n        \"movq   %0,(%1)\\n\\t\" \\\n        \"bswapq %0     \\n\\t\" \\\n           ::\"r\" (x), \"r\" (y));\n\n  #define LOAD64H(x, y)    \\\n    asm __volatile__ (     \\\n        \"movq (%1),%0\\n\\t\" \\\n        \"bswapq %0\\n\\t\"    \\\n        : \"=r\" (x) : \"r\" (y));\n\n #else\n\n  #define STORE64H(x, y)                                                                        \\\n    { (y)[0] = (unsigned char)(((x) >> 56) & 255); (y)[1] = (unsigned char)(((x) >> 48) & 255); \\\n      (y)[2] = (unsigned char)(((x) >> 40) & 255); (y)[3] = (unsigned char)(((x) >> 32) & 255); \\\n      (y)[4] = (unsigned char)(((x) >> 24) & 255); (y)[5] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[6] = (unsigned char)(((x) >> 8) & 255); (y)[7] = (unsigned char)((x) & 255); }\n\n  #define LOAD64H(x, y)                                                           \\\n    { x = (((ulong64)((y)[0] & 255)) << 56) | (((ulong64)((y)[1] & 255)) << 48) | \\\n          (((ulong64)((y)[2] & 255)) << 40) | (((ulong64)((y)[3] & 255)) << 32) | \\\n          (((ulong64)((y)[4] & 255)) << 24) | (((ulong64)((y)[5] & 255)) << 16) | \\\n          (((ulong64)((y)[6] & 255)) << 8) | (((ulong64)((y)[7] & 255))); }\n #endif\n\n #ifdef ENDIAN_32BITWORD\n\n  #define STORE32L(x, y) \\\n    { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }\n\n  #define LOAD32L(x, y) \\\n    XMEMCPY(&(x), y, 4);\n\n  #define STORE64L(x, y)                                                                        \\\n    { (y)[7] = (unsigned char)(((x) >> 56) & 255); (y)[6] = (unsigned char)(((x) >> 48) & 255); \\\n      (y)[5] = (unsigned char)(((x) >> 40) & 255); (y)[4] = (unsigned char)(((x) >> 32) & 255); \\\n      (y)[3] = (unsigned char)(((x) >> 24) & 255); (y)[2] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[1] = (unsigned char)(((x) >> 8) & 255); (y)[0] = (unsigned char)((x) & 255); }\n\n  #define LOAD64L(x, y)                                                           \\\n    { x = (((ulong64)((y)[7] & 255)) << 56) | (((ulong64)((y)[6] & 255)) << 48) | \\\n          (((ulong64)((y)[5] & 255)) << 40) | (((ulong64)((y)[4] & 255)) << 32) | \\\n          (((ulong64)((y)[3] & 255)) << 24) | (((ulong64)((y)[2] & 255)) << 16) | \\\n          (((ulong64)((y)[1] & 255)) << 8) | (((ulong64)((y)[0] & 255))); }\n\n #else /* 64-bit words then  */\n\n  #define STORE32L(x, y) \\\n    { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }\n\n  #define LOAD32L(x, y) \\\n    { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }\n\n  #define STORE64L(x, y) \\\n    { ulong64 __t = (x); XMEMCPY(y, &__t, 8); }\n\n  #define LOAD64L(x, y) \\\n    { XMEMCPY(&(x), y, 8); }\n #endif /* ENDIAN_64BITWORD */\n#endif  /* ENDIAN_LITTLE */\n\n#ifdef ENDIAN_BIG\n #define STORE32L(x, y)                                                                         \\\n    { (y)[3] = (unsigned char)(((x) >> 24) & 255); (y)[2] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[1] = (unsigned char)(((x) >> 8) & 255); (y)[0] = (unsigned char)((x) & 255); }\n\n #define LOAD32L(x, y)                            \\\n    { x = ((unsigned long)((y)[3] & 255) << 24) | \\\n          ((unsigned long)((y)[2] & 255) << 16) | \\\n          ((unsigned long)((y)[1] & 255) << 8) |  \\\n          ((unsigned long)((y)[0] & 255)); }\n\n #define STORE64L(x, y)                                                                         \\\n    { (y)[7] = (unsigned char)(((x) >> 56) & 255); (y)[6] = (unsigned char)(((x) >> 48) & 255); \\\n      (y)[5] = (unsigned char)(((x) >> 40) & 255); (y)[4] = (unsigned char)(((x) >> 32) & 255); \\\n      (y)[3] = (unsigned char)(((x) >> 24) & 255); (y)[2] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[1] = (unsigned char)(((x) >> 8) & 255); (y)[0] = (unsigned char)((x) & 255); }\n\n #define LOAD64L(x, y)                                                            \\\n    { x = (((ulong64)((y)[7] & 255)) << 56) | (((ulong64)((y)[6] & 255)) << 48) | \\\n          (((ulong64)((y)[5] & 255)) << 40) | (((ulong64)((y)[4] & 255)) << 32) | \\\n          (((ulong64)((y)[3] & 255)) << 24) | (((ulong64)((y)[2] & 255)) << 16) | \\\n          (((ulong64)((y)[1] & 255)) << 8) | (((ulong64)((y)[0] & 255))); }\n\n #ifdef ENDIAN_32BITWORD\n\n  #define STORE32H(x, y) \\\n    { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }\n\n  #define LOAD32H(x, y) \\\n    XMEMCPY(&(x), y, 4);\n\n  #define STORE64H(x, y)                                                                        \\\n    { (y)[0] = (unsigned char)(((x) >> 56) & 255); (y)[1] = (unsigned char)(((x) >> 48) & 255); \\\n      (y)[2] = (unsigned char)(((x) >> 40) & 255); (y)[3] = (unsigned char)(((x) >> 32) & 255); \\\n      (y)[4] = (unsigned char)(((x) >> 24) & 255); (y)[5] = (unsigned char)(((x) >> 16) & 255); \\\n      (y)[6] = (unsigned char)(((x) >> 8) & 255);  (y)[7] = (unsigned char)((x) & 255); }\n\n  #define LOAD64H(x, y)                                                           \\\n    { x = (((ulong64)((y)[0] & 255)) << 56) | (((ulong64)((y)[1] & 255)) << 48) | \\\n          (((ulong64)((y)[2] & 255)) << 40) | (((ulong64)((y)[3] & 255)) << 32) | \\\n          (((ulong64)((y)[4] & 255)) << 24) | (((ulong64)((y)[5] & 255)) << 16) | \\\n          (((ulong64)((y)[6] & 255)) << 8) | (((ulong64)((y)[7] & 255))); }\n\n #else /* 64-bit words then  */\n\n  #define STORE32H(x, y) \\\n    { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }\n\n  #define LOAD32H(x, y) \\\n    { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }\n\n  #define STORE64H(x, y) \\\n    { ulong64 __t = (x); XMEMCPY(y, &__t, 8); }\n\n  #define LOAD64H(x, y) \\\n    { XMEMCPY(&(x), y, 8); }\n #endif /* ENDIAN_64BITWORD */\n#endif  /* ENDIAN_BIG */\n\n#define BSWAP(x)                                               \\\n    (((x >> 24) & 0x000000FFUL) | ((x << 24) & 0xFF000000UL) | \\\n     ((x >> 8) & 0x0000FF00UL) | ((x << 8) & 0x00FF0000UL))\n\n\n/* 32-bit Rotates */\n#if defined(_MSC_VER)\n\n/* instrinsic rotate */\n #include <stdlib.h>\n #pragma intrinsic(_lrotr,_lrotl)\n #define ROR(x, n)     _lrotr(x, n)\n #define ROL(x, n)     _lrotl(x, n)\n #define RORc(x, n)    _lrotr(x, n)\n #define ROLc(x, n)    _lrotl(x, n)\n\n#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)\n\nstatic inline unsigned ROL(unsigned word, int i) {\n    asm (\"roll %%cl,%0\"\n         : \"=r\" (word)\n         : \"0\" (word), \"c\" (i));\n    return word;\n}\n\nstatic inline unsigned ROR(unsigned word, int i) {\n    asm (\"rorl %%cl,%0\"\n         : \"=r\" (word)\n         : \"0\" (word), \"c\" (i));\n    return word;\n}\n\n #ifndef LTC_NO_ROLC\n\nstatic inline unsigned ROLc(unsigned word, const int i) {\n    asm (\"roll %2,%0\"\n         : \"=r\" (word)\n         : \"0\" (word), \"I\" (i));\n    return word;\n}\n\nstatic inline unsigned RORc(unsigned word, const int i) {\n    asm (\"rorl %2,%0\"\n         : \"=r\" (word)\n         : \"0\" (word), \"I\" (i));\n    return word;\n}\n\n #else\n\n  #define ROLc    ROL\n  #define RORc    ROR\n #endif\n\n#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)\n\nstatic inline unsigned ROL(unsigned word, int i) {\n    asm (\"rotlw %0,%0,%2\"\n         : \"=r\" (word)\n         : \"0\" (word), \"r\" (i));\n    return word;\n}\n\nstatic inline unsigned ROR(unsigned word, int i) {\n    asm (\"rotlw %0,%0,%2\"\n         : \"=r\" (word)\n         : \"0\" (word), \"r\" (32 - i));\n    return word;\n}\n\n #ifndef LTC_NO_ROLC\n\nstatic inline unsigned ROLc(unsigned word, const int i) {\n    asm (\"rotlwi %0,%0,%2\"\n         : \"=r\" (word)\n         : \"0\" (word), \"I\" (i));\n    return word;\n}\n\nstatic inline unsigned RORc(unsigned word, const int i) {\n    asm (\"rotrwi %0,%0,%2\"\n         : \"=r\" (word)\n         : \"0\" (word), \"I\" (i));\n    return word;\n}\n\n #else\n\n  #define ROLc    ROL\n  #define RORc    ROR\n #endif\n\n\n#else\n\n/* rotates the hard way */\n #define ROL(x, y)     ((((unsigned long)(x) << (unsigned long)((y) & 31)) | (((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)\n #define ROR(x, y)     (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)\n #define ROLc(x, y)    ((((unsigned long)(x) << (unsigned long)((y) & 31)) | (((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)\n #define RORc(x, y)    (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)\n#endif\n\n\n/* 64-bit Rotates */\n#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(LTC_NO_ASM)\n\nstatic inline unsigned long ROL64(unsigned long word, int i) {\n    asm (\"rolq %%cl,%0\"\n         : \"=r\" (word)\n         : \"0\" (word), \"c\" (i));\n    return word;\n}\n\nstatic inline unsigned long ROR64(unsigned long word, int i) {\n    asm (\"rorq %%cl,%0\"\n         : \"=r\" (word)\n         : \"0\" (word), \"c\" (i));\n    return word;\n}\n\n #ifndef LTC_NO_ROLC\n\nstatic inline unsigned long ROL64c(unsigned long word, const int i) {\n    asm (\"rolq %2,%0\"\n         : \"=r\" (word)\n         : \"0\" (word), \"J\" (i));\n    return word;\n}\n\nstatic inline unsigned long ROR64c(unsigned long word, const int i) {\n    asm (\"rorq %2,%0\"\n         : \"=r\" (word)\n         : \"0\" (word), \"J\" (i));\n    return word;\n}\n\n #else /* LTC_NO_ROLC */\n\n  #define ROL64c    ROL64\n  #define ROR64c    ROR64\n #endif\n\n#else /* Not x86_64  */\n\n #define ROL64(x, y)                 \\\n    ((((x) << ((ulong64)(y) & 63)) | \\\n      (((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((ulong64)64 - ((y) & 63)))) & CONST64(0xFFFFFFFFFFFFFFFF))\n\n #define ROR64(x, y)                                                          \\\n    (((((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((ulong64)(y) & CONST64(63))) | \\\n      ((x) << ((ulong64)(64 - ((y) & CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))\n\n #define ROL64c(x, y)                \\\n    ((((x) << ((ulong64)(y) & 63)) | \\\n      (((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((ulong64)64 - ((y) & 63)))) & CONST64(0xFFFFFFFFFFFFFFFF))\n\n #define ROR64c(x, y)                                                         \\\n    (((((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((ulong64)(y) & CONST64(63))) | \\\n      ((x) << ((ulong64)(64 - ((y) & CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))\n#endif\n\n#ifndef MAX\n #define TOM_MAX(x, y)    (((x) > (y)) ? (x) : (y))\n#endif\n\n#ifndef MIN\n #define TOM_MIN(x, y)    (((x) < (y)) ? (x) : (y))\n#endif\n\n/* extract a byte portably */\n#ifdef _MSC_VER\n #define byte(x, n)    ((unsigned char)((x) >> (8 * (n))))\n#else\n #define byte(x, n)    (((x) >> (8 * (n))) & 255)\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_macros.h,v $ */\n/* $Revision: 1.15 $ */\n/* $Date: 2006/11/29 23:43:57 $ */ \n\n/* ---- SYMMETRIC KEY STUFF -----\n *\n * We put each of the ciphers scheduled keys in their own structs then we put all of\n * the key formats in one union.  This makes the function prototypes easier to use.\n */\n#ifdef LTC_BLOWFISH\nstruct blowfish_key {\n    ulong32 S[4][256];\n    ulong32 K[18];\n};\n#endif\n\n#ifdef LTC_RC5\nstruct rc5_key {\n    int     rounds;\n    ulong32 K[50];\n};\n#endif\n\n#ifdef LTC_RC6\nstruct rc6_key {\n    ulong32 K[44];\n};\n#endif\n\n#ifdef LTC_SAFERP\nstruct saferp_key {\n    unsigned char K[33][16];\n    long          rounds;\n};\n#endif\n\n#ifdef LTC_RIJNDAEL\nstruct rijndael_key {\n    ulong32 eK[60], dK[60];\n    int     Nr;\n};\n#endif\n\n#ifdef LTC_KSEED\nstruct kseed_key {\n    ulong32 K[32], dK[32];\n};\n#endif\n\n#ifdef LTC_KASUMI\nstruct kasumi_key {\n    ulong32 KLi1[8], KLi2[8],\n            KOi1[8], KOi2[8], KOi3[8],\n            KIi1[8], KIi2[8], KIi3[8];\n};\n#endif\n\n#ifdef LTC_XTEA\nstruct xtea_key {\n    unsigned long A[32], B[32];\n};\n#endif\n\n#ifdef LTC_TWOFISH\n #ifndef LTC_TWOFISH_SMALL\nstruct twofish_key {\n    ulong32 S[4][256], K[40];\n};\n #else\nstruct twofish_key {\n    ulong32       K[40];\n    unsigned char S[32], start;\n};\n #endif\n#endif\n\n#ifdef LTC_SAFER\n #define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS      6\n #define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS     10\n #define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS     8\n #define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS    10\n #define LTC_SAFER_MAX_NOF_ROUNDS              13\n #define LTC_SAFER_BLOCK_LEN                   8\n #define LTC_SAFER_KEY_LEN                     (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS))\ntypedef unsigned char   safer_block_t[LTC_SAFER_BLOCK_LEN];\ntypedef unsigned char   safer_key_t[LTC_SAFER_KEY_LEN];\nstruct safer_key {\n    safer_key_t key;\n};\n#endif\n\n#ifdef LTC_RC2\nstruct rc2_key {\n    unsigned xkey[64];\n};\n#endif\n\n#ifdef LTC_DES\nstruct des_key {\n    ulong32 ek[32], dk[32];\n};\n\nstruct des3_key {\n    ulong32 ek[3][32], dk[3][32];\n};\n#endif\n\n#ifdef LTC_CAST5\nstruct cast5_key {\n    ulong32 K[32], keylen;\n};\n#endif\n\n#ifdef LTC_NOEKEON\nstruct noekeon_key {\n    ulong32 K[4], dK[4];\n};\n#endif\n\n#ifdef LTC_SKIPJACK\nstruct skipjack_key {\n    unsigned char key[10];\n};\n#endif\n\n#ifdef LTC_KHAZAD\nstruct khazad_key {\n    ulong64 roundKeyEnc[8 + 1];\n    ulong64 roundKeyDec[8 + 1];\n};\n#endif\n\n#ifdef LTC_ANUBIS\nstruct anubis_key {\n    int     keyBits;\n    int     R;\n    ulong32 roundKeyEnc[18 + 1][4];\n    ulong32 roundKeyDec[18 + 1][4];\n};\n#endif\n\n#ifdef LTC_MULTI2\nstruct multi2_key {\n    int     N;\n    ulong32 uk[8];\n};\n#endif\n\ntypedef union Symmetric_key {\n#ifdef LTC_DES\n    struct des_key      des;\n    struct des3_key     des3;\n#endif\n#ifdef LTC_RC2\n    struct rc2_key      rc2;\n#endif\n#ifdef LTC_SAFER\n    struct safer_key    safer;\n#endif\n#ifdef LTC_TWOFISH\n    struct twofish_key  twofish;\n#endif\n#ifdef LTC_BLOWFISH\n    struct blowfish_key blowfish;\n#endif\n#ifdef LTC_RC5\n    struct rc5_key      rc5;\n#endif\n#ifdef LTC_RC6\n    struct rc6_key      rc6;\n#endif\n#ifdef LTC_SAFERP\n    struct saferp_key   saferp;\n#endif\n#ifdef LTC_RIJNDAEL\n    struct rijndael_key rijndael;\n#endif\n#ifdef LTC_XTEA\n    struct xtea_key     xtea;\n#endif\n#ifdef LTC_CAST5\n    struct cast5_key    cast5;\n#endif\n#ifdef LTC_NOEKEON\n    struct noekeon_key  noekeon;\n#endif\n#ifdef LTC_SKIPJACK\n    struct skipjack_key skipjack;\n#endif\n#ifdef LTC_KHAZAD\n    struct khazad_key   khazad;\n#endif\n#ifdef LTC_ANUBIS\n    struct anubis_key   anubis;\n#endif\n#ifdef LTC_KSEED\n    struct kseed_key    kseed;\n#endif\n#ifdef LTC_KASUMI\n    struct kasumi_key   kasumi;\n#endif\n#ifdef LTC_MULTI2\n    struct multi2_key   multi2;\n#endif\n    void                *data;\n} symmetric_key;\n\n#ifdef LTC_ECB_MODE\n/** A block cipher ECB structure */\ntypedef struct {\n    /** The index of the cipher chosen */\n    int           cipher,\n    /** The block size of the given cipher */\n                  blocklen;\n    /** The scheduled key */\n    symmetric_key key;\n} symmetric_ECB;\n#endif\n\n#ifdef LTC_CFB_MODE\n/** A block cipher CFB structure */\ntypedef struct {\n    /** The index of the cipher chosen */\n    int           cipher,\n    /** The block size of the given cipher */\n                  blocklen,\n    /** The padding offset */\n                  padlen;\n    /** The current IV */\n    unsigned char IV[MAXBLOCKSIZE],\n    /** The pad used to encrypt/decrypt */\n                  pad[MAXBLOCKSIZE];\n    /** The scheduled key */\n    symmetric_key key;\n} symmetric_CFB;\n#endif\n\n#ifdef LTC_OFB_MODE\n/** A block cipher OFB structure */\ntypedef struct {\n    /** The index of the cipher chosen */\n    int           cipher,\n    /** The block size of the given cipher */\n                  blocklen,\n    /** The padding offset */\n                  padlen;\n    /** The current IV */\n    unsigned char IV[MAXBLOCKSIZE];\n    /** The scheduled key */\n    symmetric_key key;\n} symmetric_OFB;\n#endif\n\n#ifdef LTC_CBC_MODE\n/** A block cipher CBC structure */\ntypedef struct {\n    /** The index of the cipher chosen */\n    int           cipher,\n    /** The block size of the given cipher */\n                  blocklen;\n    /** The current IV */\n    unsigned char IV[MAXBLOCKSIZE];\n    /** The scheduled key */\n    symmetric_key key;\n} symmetric_CBC;\n#endif\n\n\n#ifdef LTC_CTR_MODE\n/** A block cipher CTR structure */\ntypedef struct {\n    /** The index of the cipher chosen */\n    int           cipher,\n    /** The block size of the given cipher */\n                  blocklen,\n    /** The padding offset */\n                  padlen,\n    /** The mode (endianess) of the CTR, 0==little, 1==big */\n                  mode,\n    /** counter width */\n                  ctrlen;\n\n    /** The counter */\n    unsigned char ctr[MAXBLOCKSIZE],\n    /** The pad used to encrypt/decrypt */\n                  pad[MAXBLOCKSIZE];\n    /** The scheduled key */\n    symmetric_key key;\n} symmetric_CTR;\n#endif\n\n\n#ifdef LTC_LRW_MODE\n/** A LRW structure */\ntypedef struct {\n    /** The index of the cipher chosen (must be a 128-bit block cipher) */\n    int           cipher;\n\n    /** The current IV */\n    unsigned char IV[16],\n\n    /** the tweak key */\n                  tweak[16],\n\n    /** The current pad, it's the product of the first 15 bytes against the tweak key */\n                  pad[16];\n\n    /** The scheduled symmetric key */\n    symmetric_key key;\n\n #ifdef LRW_TABLES\n    /** The pre-computed multiplication table */\n    unsigned char PC[16][256][16];\n #endif\n} symmetric_LRW;\n#endif\n\n#ifdef LTC_F8_MODE\n/** A block cipher F8 structure */\ntypedef struct {\n    /** The index of the cipher chosen */\n    int           cipher,\n    /** The block size of the given cipher */\n                  blocklen,\n    /** The padding offset */\n                  padlen;\n    /** The current IV */\n    unsigned char IV[MAXBLOCKSIZE],\n                  MIV[MAXBLOCKSIZE];\n    /** Current block count */\n    ulong32       blockcnt;\n    /** The scheduled key */\n    symmetric_key key;\n} symmetric_F8;\n#endif\n\n\n/** cipher descriptor table, last entry has \"name == NULL\" to mark the end of table */\nextern struct ltc_cipher_descriptor {\n    /** name of cipher */\n    char          *name;\n    /** internal ID */\n    unsigned char ID;\n    /** min keysize (octets) */\n    int           min_key_length,\n    /** max keysize (octets) */\n                  max_key_length,\n    /** block size (octets) */\n                  block_length,\n    /** default number of rounds */\n                  default_rounds;\n\n    /** Setup the cipher\n       @param key         The input symmetric key\n       @param keylen      The length of the input key (octets)\n       @param num_rounds  The requested number of rounds (0==default)\n       @param skey        [out] The destination of the scheduled key\n       @return CRYPT_OK if successful\n     */\n    int           (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\n\n    /** Encrypt a block\n       @param pt      The plaintext\n       @param ct      [out] The ciphertext\n       @param skey    The scheduled key\n       @return CRYPT_OK if successful\n     */\n    int           (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\n\n    /** Decrypt a block\n       @param ct      The ciphertext\n       @param pt      [out] The plaintext\n       @param skey    The scheduled key\n       @return CRYPT_OK if successful\n     */\n    int           (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\n\n    /** Test the block cipher\n        @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled\n     */\n    int           (*test)(void);\n\n    /** Terminate the context\n       @param skey    The scheduled key\n     */\n    void          (*done)(symmetric_key *skey);\n\n    /** Determine a key size\n        @param keysize    [in/out] The size of the key desired and the suggested size\n        @return CRYPT_OK if successful\n     */\n    int           (*keysize)(int *keysize);\n\n/** Accelerators **/\n\n    /** Accelerated ECB encryption\n        @param pt      Plaintext\n        @param ct      Ciphertext\n        @param blocks  The number of complete blocks to process\n        @param skey    The scheduled key context\n        @return CRYPT_OK if successful\n     */\n    int           (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey);\n\n    /** Accelerated ECB decryption\n        @param pt      Plaintext\n        @param ct      Ciphertext\n        @param blocks  The number of complete blocks to process\n        @param skey    The scheduled key context\n        @return CRYPT_OK if successful\n     */\n    int           (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey);\n\n    /** Accelerated CBC encryption\n        @param pt      Plaintext\n        @param ct      Ciphertext\n        @param blocks  The number of complete blocks to process\n        @param IV      The initial value (input/output)\n        @param skey    The scheduled key context\n        @return CRYPT_OK if successful\n     */\n    int           (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey);\n\n    /** Accelerated CBC decryption\n        @param pt      Plaintext\n        @param ct      Ciphertext\n        @param blocks  The number of complete blocks to process\n        @param IV      The initial value (input/output)\n        @param skey    The scheduled key context\n        @return CRYPT_OK if successful\n     */\n    int           (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey);\n\n    /** Accelerated CTR encryption\n        @param pt      Plaintext\n        @param ct      Ciphertext\n        @param blocks  The number of complete blocks to process\n        @param IV      The initial value (input/output)\n        @param mode    little or big endian counter (mode=0 or mode=1)\n        @param skey    The scheduled key context\n        @return CRYPT_OK if successful\n     */\n    int           (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey);\n\n    /** Accelerated LRW\n        @param pt      Plaintext\n        @param ct      Ciphertext\n        @param blocks  The number of complete blocks to process\n        @param IV      The initial value (input/output)\n        @param tweak   The LRW tweak\n        @param skey    The scheduled key context\n        @return CRYPT_OK if successful\n     */\n    int           (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);\n\n    /** Accelerated LRW\n        @param ct      Ciphertext\n        @param pt      Plaintext\n        @param blocks  The number of complete blocks to process\n        @param IV      The initial value (input/output)\n        @param tweak   The LRW tweak\n        @param skey    The scheduled key context\n        @return CRYPT_OK if successful\n     */\n    int           (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);\n\n    /** Accelerated CCM packet (one-shot)\n        @param key        The secret key to use\n        @param keylen     The length of the secret key (octets)\n        @param uskey      A previously scheduled key [optional can be NULL]\n        @param nonce      The session nonce [use once]\n        @param noncelen   The length of the nonce\n        @param header     The header for the session\n        @param headerlen  The length of the header (octets)\n        @param pt         [out] The plaintext\n        @param ptlen      The length of the plaintext (octets)\n        @param ct         [out] The ciphertext\n        @param tag        [out] The destination tag\n        @param taglen     [in/out] The max size and resulting size of the authentication tag\n        @param direction  Encrypt or Decrypt direction (0 or 1)\n        @return CRYPT_OK if successful\n     */\n    int           (*accel_ccm_memory)(\n        const unsigned char *key, unsigned long keylen,\n        symmetric_key *uskey,\n        const unsigned char *nonce, unsigned long noncelen,\n        const unsigned char *header, unsigned long headerlen,\n        unsigned char *pt, unsigned long ptlen,\n        unsigned char *ct,\n        unsigned char *tag, unsigned long *taglen,\n        int direction);\n\n    /** Accelerated GCM packet (one shot)\n        @param key        The secret key\n        @param keylen     The length of the secret key\n        @param IV         The initial vector\n        @param IVlen      The length of the initial vector\n        @param adata      The additional authentication data (header)\n        @param adatalen   The length of the adata\n        @param pt         The plaintext\n        @param ptlen      The length of the plaintext (ciphertext length is the same)\n        @param ct         The ciphertext\n        @param tag        [out] The MAC tag\n        @param taglen     [in/out] The MAC tag length\n        @param direction  Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)\n        @return CRYPT_OK on success\n     */\n    int           (*accel_gcm_memory)(\n        const unsigned char *key, unsigned long keylen,\n        const unsigned char *IV, unsigned long IVlen,\n        const unsigned char *adata, unsigned long adatalen,\n        unsigned char *pt, unsigned long ptlen,\n        unsigned char *ct,\n        unsigned char *tag, unsigned long *taglen,\n        int direction);\n\n    /** Accelerated one shot LTC_OMAC\n        @param key            The secret key\n        @param keylen         The key length (octets)\n        @param in             The message\n        @param inlen          Length of message (octets)\n        @param out            [out] Destination for tag\n        @param outlen         [in/out] Initial and final size of out\n        @return CRYPT_OK on success\n     */\n    int           (*omac_memory)(\n        const unsigned char *key, unsigned long keylen,\n        const unsigned char *in, unsigned long inlen,\n        unsigned char *out, unsigned long *outlen);\n\n    /** Accelerated one shot XCBC\n        @param key            The secret key\n        @param keylen         The key length (octets)\n        @param in             The message\n        @param inlen          Length of message (octets)\n        @param out            [out] Destination for tag\n        @param outlen         [in/out] Initial and final size of out\n        @return CRYPT_OK on success\n     */\n    int           (*xcbc_memory)(\n        const unsigned char *key, unsigned long keylen,\n        const unsigned char *in, unsigned long inlen,\n        unsigned char *out, unsigned long *outlen);\n\n    /** Accelerated one shot F9\n        @param key            The secret key\n        @param keylen         The key length (octets)\n        @param in             The message\n        @param inlen          Length of message (octets)\n        @param out            [out] Destination for tag\n        @param outlen         [in/out] Initial and final size of out\n        @return CRYPT_OK on success\n        @remark Requires manual padding\n     */\n    int           (*f9_memory)(\n        const unsigned char *key, unsigned long keylen,\n        const unsigned char *in, unsigned long inlen,\n        unsigned char *out, unsigned long *outlen);\n} cipher_descriptor[];\n\n#ifdef LTC_BLOWFISH\nint blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint blowfish_test(void);\nvoid blowfish_done(symmetric_key *skey);\nint blowfish_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor blowfish_desc;\n#endif\n\n#ifdef LTC_RC5\nint rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint rc5_test(void);\nvoid rc5_done(symmetric_key *skey);\nint rc5_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor rc5_desc;\n#endif\n\n#ifdef LTC_RC6\nint rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint rc6_test(void);\nvoid rc6_done(symmetric_key *skey);\nint rc6_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor rc6_desc;\n#endif\n\n#ifdef LTC_RC2\nint rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint rc2_test(void);\nvoid rc2_done(symmetric_key *skey);\nint rc2_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor rc2_desc;\n#endif\n\n#ifdef LTC_SAFERP\nint saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint saferp_test(void);\nvoid saferp_done(symmetric_key *skey);\nint saferp_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor saferp_desc;\n#endif\n\n#ifdef LTC_SAFER\nint safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);\nint safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);\nint safer_k64_test(void);\nint safer_sk64_test(void);\nint safer_sk128_test(void);\nvoid safer_done(symmetric_key *skey);\nint safer_64_keysize(int *keysize);\nint safer_128_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;\n#endif\n\n#ifdef LTC_RIJNDAEL\n\n/* make aes an alias */\n #define aes_setup              rijndael_setup\n #define aes_ecb_encrypt        rijndael_ecb_encrypt\n #define aes_ecb_decrypt        rijndael_ecb_decrypt\n #define aes_test               rijndael_test\n #define aes_done               rijndael_done\n #define aes_keysize            rijndael_keysize\n\n #define aes_enc_setup          rijndael_enc_setup\n #define aes_enc_ecb_encrypt    rijndael_enc_ecb_encrypt\n #define aes_enc_keysize        rijndael_enc_keysize\n\nint rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint rijndael_test(void);\nvoid rijndael_done(symmetric_key *skey);\nint rijndael_keysize(int *keysize);\nint rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nvoid rijndael_enc_done(symmetric_key *skey);\nint rijndael_enc_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor rijndael_desc, aes_desc;\nextern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc;\n#endif\n\n#ifdef LTC_XTEA\nint xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint xtea_test(void);\nvoid xtea_done(symmetric_key *skey);\nint xtea_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor xtea_desc;\n#endif\n\n#ifdef LTC_TWOFISH\nint twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint twofish_test(void);\nvoid twofish_done(symmetric_key *skey);\nint twofish_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor twofish_desc;\n#endif\n\n#ifdef LTC_DES\nint des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint des_test(void);\nvoid des_done(symmetric_key *skey);\nint des_keysize(int *keysize);\nint des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint des3_test(void);\nvoid des3_done(symmetric_key *skey);\nint des3_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor des_desc, des3_desc;\n#endif\n\n#ifdef LTC_CAST5\nint cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint cast5_test(void);\nvoid cast5_done(symmetric_key *skey);\nint cast5_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor cast5_desc;\n#endif\n\n#ifdef LTC_NOEKEON\nint noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint noekeon_test(void);\nvoid noekeon_done(symmetric_key *skey);\nint noekeon_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor noekeon_desc;\n#endif\n\n#ifdef LTC_SKIPJACK\nint skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint skipjack_test(void);\nvoid skipjack_done(symmetric_key *skey);\nint skipjack_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor skipjack_desc;\n#endif\n\n#ifdef LTC_KHAZAD\nint khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint khazad_test(void);\nvoid khazad_done(symmetric_key *skey);\nint khazad_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor khazad_desc;\n#endif\n\n#ifdef LTC_ANUBIS\nint anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint anubis_test(void);\nvoid anubis_done(symmetric_key *skey);\nint anubis_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor anubis_desc;\n#endif\n\n#ifdef LTC_KSEED\nint kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint kseed_test(void);\nvoid kseed_done(symmetric_key *skey);\nint kseed_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor kseed_desc;\n#endif\n\n#ifdef LTC_KASUMI\nint kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint kasumi_test(void);\nvoid kasumi_done(symmetric_key *skey);\nint kasumi_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor kasumi_desc;\n#endif\n\n\n#ifdef LTC_MULTI2\nint multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);\nint multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);\nint multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);\nint multi2_test(void);\nvoid multi2_done(symmetric_key *skey);\nint multi2_keysize(int *keysize);\n\nextern const struct ltc_cipher_descriptor multi2_desc;\n#endif\n\n#ifdef LTC_ECB_MODE\nint ecb_start(int cipher, const unsigned char *key,\n              int keylen, int num_rounds, symmetric_ECB *ecb);\nint ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb);\nint ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb);\nint ecb_done(symmetric_ECB *ecb);\n#endif\n\n#ifdef LTC_CFB_MODE\nint cfb_start(int cipher, const unsigned char *IV, const unsigned char *key,\n              int keylen, int num_rounds, symmetric_CFB *cfb);\nint cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);\nint cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);\nint cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb);\nint cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb);\nint cfb_done(symmetric_CFB *cfb);\n#endif\n\n#ifdef LTC_OFB_MODE\nint ofb_start(int cipher, const unsigned char *IV, const unsigned char *key,\n              int keylen, int num_rounds, symmetric_OFB *ofb);\nint ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);\nint ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);\nint ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb);\nint ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb);\nint ofb_done(symmetric_OFB *ofb);\n#endif\n\n#ifdef LTC_CBC_MODE\nint cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,\n              int keylen, int num_rounds, symmetric_CBC *cbc);\nint cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc);\nint cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc);\nint cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);\nint cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);\nint cbc_done(symmetric_CBC *cbc);\n#endif\n\n#ifdef LTC_CTR_MODE\n\n #define CTR_COUNTER_LITTLE_ENDIAN    0x0000\n #define CTR_COUNTER_BIG_ENDIAN       0x1000\n #define LTC_CTR_RFC3686              0x2000\n\nint ctr_start(int cipher,\n              const unsigned char *IV,\n              const unsigned char *key, int keylen,\n              int num_rounds, int ctr_mode,\n              symmetric_CTR *ctr);\nint ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);\nint ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);\nint ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr);\nint ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr);\nint ctr_done(symmetric_CTR *ctr);\nint ctr_test(void);\n#endif\n\n#ifdef LTC_LRW_MODE\n\n #define LRW_ENCRYPT    0\n #define LRW_DECRYPT    1\n\nint lrw_start(int cipher,\n              const unsigned char *IV,\n              const unsigned char *key, int keylen,\n              const unsigned char *tweak,\n              int num_rounds,\n              symmetric_LRW *lrw);\nint lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw);\nint lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw);\nint lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw);\nint lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw);\nint lrw_done(symmetric_LRW *lrw);\nint lrw_test(void);\n\n/* don't call */\nint lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw);\n#endif\n\n#ifdef LTC_F8_MODE\nint f8_start(int cipher, const unsigned char *IV,\n             const unsigned char *key, int keylen,\n             const unsigned char *salt_key, int skeylen,\n             int num_rounds, symmetric_F8 *f8);\nint f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8);\nint f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8);\nint f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8);\nint f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8);\nint f8_done(symmetric_F8 *f8);\nint f8_test_mode(void);\n#endif\n\n#ifdef LTC_XTS_MODE\ntypedef struct {\n    symmetric_key key1, key2;\n    int           cipher;\n} symmetric_xts;\n\nint xts_start(int                 cipher,\n              const unsigned char *key1,\n              const unsigned char *key2,\n              unsigned long       keylen,\n              int                 num_rounds,\n              symmetric_xts       *xts);\n\nint xts_encrypt(\n    const unsigned char *pt, unsigned long ptlen,\n    unsigned char *ct,\n    const unsigned char *tweak,\n    symmetric_xts *xts);\nint xts_decrypt(\n    const unsigned char *ct, unsigned long ptlen,\n    unsigned char *pt,\n    const unsigned char *tweak,\n    symmetric_xts *xts);\n\nvoid xts_done(symmetric_xts *xts);\nint  xts_test(void);\nvoid xts_mult_x(unsigned char *I);\n#endif\n\nint find_cipher(const char *name);\nint find_cipher_any(const char *name, int blocklen, int keylen);\nint find_cipher_id(unsigned char ID);\nint register_cipher(const struct ltc_cipher_descriptor *cipher);\nint unregister_cipher(const struct ltc_cipher_descriptor *cipher);\nint cipher_is_valid(int idx);\n\nLTC_MUTEX_PROTO(ltc_cipher_mutex)\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cipher.h,v $ */\n/* $Revision: 1.54 $ */\n/* $Date: 2007/05/12 14:37:41 $ */ \n\n#define LTC_SHA1\n/* ---- HASH FUNCTIONS ---- */\n#ifdef LTC_SHA512\nstruct sha512_state {\n    ulong64       length, state[8];\n    unsigned long curlen;\n    unsigned char buf[128];\n};\n#endif\n\n#ifdef LTC_SHA256\nstruct sha256_state {\n    ulong64       length;\n    ulong32       state[8], curlen;\n    unsigned char buf[64];\n};\n#endif\n\n#ifdef LTC_SHA1\nstruct sha1_state {\n    ulong64       length;\n    ulong32       state[5], curlen;\n    unsigned char buf[64];\n};\n#endif\n\n#ifdef LTC_MD5\nstruct md5_state {\n    ulong64       length;\n    ulong32       state[4], curlen;\n    unsigned char buf[64];\n};\n#endif\n\n#ifdef LTC_MD4\nstruct md4_state {\n    ulong64       length;\n    ulong32       state[4], curlen;\n    unsigned char buf[64];\n};\n#endif\n\n#ifdef LTC_TIGER\nstruct tiger_state {\n    ulong64       state[3], length;\n    unsigned long curlen;\n    unsigned char buf[64];\n};\n#endif\n\n#ifdef LTC_MD2\nstruct md2_state {\n    unsigned char chksum[16], X[48], buf[16];\n    unsigned long curlen;\n};\n#endif\n\n#ifdef LTC_RIPEMD128\nstruct rmd128_state {\n    ulong64       length;\n    unsigned char buf[64];\n    ulong32       curlen, state[4];\n};\n#endif\n\n#ifdef LTC_RIPEMD160\nstruct rmd160_state {\n    ulong64       length;\n    unsigned char buf[64];\n    ulong32       curlen, state[5];\n};\n#endif\n\n#ifdef LTC_RIPEMD256\nstruct rmd256_state {\n    ulong64       length;\n    unsigned char buf[64];\n    ulong32       curlen, state[8];\n};\n#endif\n\n#ifdef LTC_RIPEMD320\nstruct rmd320_state {\n    ulong64       length;\n    unsigned char buf[64];\n    ulong32       curlen, state[10];\n};\n#endif\n\n#ifdef LTC_WHIRLPOOL\nstruct whirlpool_state {\n    ulong64       length, state[8];\n    unsigned char buf[64];\n    ulong32       curlen;\n};\n#endif\n\n#ifdef LTC_CHC_HASH\nstruct chc_state {\n    ulong64       length;\n    unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];\n    ulong32       curlen;\n};\n#endif\n\ntypedef union Hash_state {\n    char                   dummy[1];\n#ifdef LTC_CHC_HASH\n    struct chc_state       chc;\n#endif\n#ifdef LTC_WHIRLPOOL\n    struct whirlpool_state whirlpool;\n#endif\n#ifdef LTC_SHA512\n    struct sha512_state    sha512;\n#endif\n#ifdef LTC_SHA256\n    struct sha256_state    sha256;\n#endif\n#ifdef LTC_SHA1\n    struct sha1_state      sha1;\n#endif\n#ifdef LTC_MD5\n    struct md5_state       md5;\n#endif\n#ifdef LTC_MD4\n    struct md4_state       md4;\n#endif\n#ifdef LTC_MD2\n    struct md2_state       md2;\n#endif\n#ifdef LTC_TIGER\n    struct tiger_state     tiger;\n#endif\n#ifdef LTC_RIPEMD128\n    struct rmd128_state    rmd128;\n#endif\n#ifdef LTC_RIPEMD160\n    struct rmd160_state    rmd160;\n#endif\n#ifdef LTC_RIPEMD256\n    struct rmd256_state    rmd256;\n#endif\n#ifdef LTC_RIPEMD320\n    struct rmd320_state    rmd320;\n#endif\n    void                   *data;\n} hash_state;\n\n/** hash descriptor */\nextern struct ltc_hash_descriptor {\n    /** name of hash */\n    char          *name;\n    /** internal ID */\n    unsigned char ID;\n    /** Size of digest in octets */\n    unsigned long hashsize;\n    /** Input block size in octets */\n    unsigned long blocksize;\n    /** ASN.1 OID */\n    unsigned long OID[16];\n    /** Length of DER encoding */\n    unsigned long OIDlen;\n\n    /** Init a hash state\n       @param hash   The hash to initialize\n       @return CRYPT_OK if successful\n     */\n    int           (*init)(hash_state *hash);\n\n    /** Process a block of data\n       @param hash   The hash state\n       @param in     The data to hash\n       @param inlen  The length of the data (octets)\n       @return CRYPT_OK if successful\n     */\n    int           (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen);\n\n    /** Produce the digest and store it\n       @param hash   The hash state\n       @param out    [out] The destination of the digest\n       @return CRYPT_OK if successful\n     */\n    int           (*done)(hash_state *hash, unsigned char *out);\n\n    /** Self-test\n       @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled\n     */\n    int           (*test)(void);\n\n    /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */\n    int           (*hmac_block)(const unsigned char *key, unsigned long keylen,\n                                const unsigned char *in, unsigned long inlen,\n                                unsigned char *out, unsigned long *outlen);\n} hash_descriptor[];\n\n#ifdef LTC_CHC_HASH\nint chc_register(int cipher);\nint chc_init(hash_state *md);\nint chc_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint chc_done(hash_state *md, unsigned char *hash);\nint chc_test(void);\n\nextern const struct ltc_hash_descriptor chc_desc;\n#endif\n\n#ifdef LTC_WHIRLPOOL\nint whirlpool_init(hash_state *md);\nint whirlpool_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint whirlpool_done(hash_state *md, unsigned char *hash);\nint whirlpool_test(void);\n\nextern const struct ltc_hash_descriptor whirlpool_desc;\n#endif\n\n#ifdef LTC_SHA512\nint sha512_init(hash_state *md);\nint sha512_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint sha512_done(hash_state *md, unsigned char *hash);\nint sha512_test(void);\n\nextern const struct ltc_hash_descriptor sha512_desc;\n#endif\n\n#ifdef LTC_SHA384\n #ifndef LTC_SHA512\n  #error LTC_SHA512 is required for LTC_SHA384\n #endif\nint sha384_init(hash_state *md);\n\n #define sha384_process    sha512_process\nint sha384_done(hash_state *md, unsigned char *hash);\nint sha384_test(void);\n\nextern const struct ltc_hash_descriptor sha384_desc;\n#endif\n\n#ifdef LTC_SHA256\nint sha256_init(hash_state *md);\nint sha256_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint sha256_done(hash_state *md, unsigned char *hash);\nint sha256_test(void);\n\nextern const struct ltc_hash_descriptor sha256_desc;\n\n #ifdef LTC_SHA224\n  #ifndef LTC_SHA256\n   #error LTC_SHA256 is required for LTC_SHA224\n  #endif\nint sha224_init(hash_state *md);\n\n  #define sha224_process    sha256_process\nint sha224_done(hash_state *md, unsigned char *hash);\nint sha224_test(void);\n\nextern const struct ltc_hash_descriptor sha224_desc;\n #endif\n#endif\n\n#ifdef LTC_SHA1\nint sha1_init(hash_state *md);\nint sha1_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint sha1_done(hash_state *md, unsigned char *hash);\nint sha1_test(void);\n\nextern const struct ltc_hash_descriptor sha1_desc;\n#endif\n\n#ifdef LTC_MD5\nint md5_init(hash_state *md);\nint md5_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint md5_done(hash_state *md, unsigned char *hash);\nint md5_test(void);\n\nextern const struct ltc_hash_descriptor md5_desc;\n#endif\n\n#ifdef LTC_MD4\nint md4_init(hash_state *md);\nint md4_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint md4_done(hash_state *md, unsigned char *hash);\nint md4_test(void);\n\nextern const struct ltc_hash_descriptor md4_desc;\n#endif\n\n#ifdef LTC_MD2\nint md2_init(hash_state *md);\nint md2_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint md2_done(hash_state *md, unsigned char *hash);\nint md2_test(void);\n\nextern const struct ltc_hash_descriptor md2_desc;\n#endif\n\n#ifdef LTC_TIGER\nint tiger_init(hash_state *md);\nint tiger_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint tiger_done(hash_state *md, unsigned char *hash);\nint tiger_test(void);\n\nextern const struct ltc_hash_descriptor tiger_desc;\n#endif\n\n#ifdef LTC_RIPEMD128\nint rmd128_init(hash_state *md);\nint rmd128_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint rmd128_done(hash_state *md, unsigned char *hash);\nint rmd128_test(void);\n\nextern const struct ltc_hash_descriptor rmd128_desc;\n#endif\n\n#ifdef LTC_RIPEMD160\nint rmd160_init(hash_state *md);\nint rmd160_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint rmd160_done(hash_state *md, unsigned char *hash);\nint rmd160_test(void);\n\nextern const struct ltc_hash_descriptor rmd160_desc;\n#endif\n\n#ifdef LTC_RIPEMD256\nint rmd256_init(hash_state *md);\nint rmd256_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint rmd256_done(hash_state *md, unsigned char *hash);\nint rmd256_test(void);\n\nextern const struct ltc_hash_descriptor rmd256_desc;\n#endif\n\n#ifdef LTC_RIPEMD320\nint rmd320_init(hash_state *md);\nint rmd320_process(hash_state *md, const unsigned char *in, unsigned long inlen);\nint rmd320_done(hash_state *md, unsigned char *hash);\nint rmd320_test(void);\n\nextern const struct ltc_hash_descriptor rmd320_desc;\n#endif\n\n\nint find_hash(const char *name);\nint find_hash_id(unsigned char ID);\nint find_hash_oid(const unsigned long *ID, unsigned long IDlen);\nint find_hash_any(const char *name, int digestlen);\nint register_hash(const struct ltc_hash_descriptor *hash);\nint unregister_hash(const struct ltc_hash_descriptor *hash);\nint hash_is_valid(int idx);\n\nLTC_MUTEX_PROTO(ltc_hash_mutex)\n\nint hash_memory(int hash,\n                const unsigned char *in, unsigned long inlen,\n                unsigned char *out, unsigned long *outlen);\nint hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,\n                      const unsigned char *in, unsigned long inlen, ...);\nint hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen);\nint hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen);\n\n/* a simple macro for making hash \"process\" functions */\n#define HASH_PROCESS(func_name, compress_name, state_var, block_size)               \\\n    int func_name(hash_state * md, const unsigned char *in, unsigned long inlen)    \\\n    {                                                                               \\\n        unsigned long n;                                                            \\\n        int           err;                                                          \\\n        LTC_ARGCHK(md != NULL);                                                     \\\n        LTC_ARGCHK(in != NULL);                                                     \\\n        if (md->state_var.curlen > sizeof(md->state_var.buf)) {                     \\\n            return CRYPT_INVALID_ARG;                                               \\\n        }                                                                           \\\n        while (inlen > 0) {                                                         \\\n            if (md->state_var.curlen == 0 && inlen >= block_size) {                 \\\n                if ((err = compress_name(md, (unsigned char *)in)) != CRYPT_OK) {   \\\n                    return err;                                                     \\\n                }                                                                   \\\n                md->state_var.length += block_size * 8;                             \\\n                in    += block_size;                                                \\\n                inlen -= block_size;                                                \\\n            } else {                                                                \\\n                n = TOM_MIN(inlen, (block_size - md->state_var.curlen));                \\\n                memcpy(md->state_var.buf + md->state_var.curlen, in, (size_t)n);    \\\n                md->state_var.curlen += n;                                          \\\n                in    += n;                                                         \\\n                inlen -= n;                                                         \\\n                if (md->state_var.curlen == block_size) {                           \\\n                    if ((err = compress_name(md, md->state_var.buf)) != CRYPT_OK) { \\\n                        return err;                                                 \\\n                    }                                                               \\\n                    md->state_var.length += 8 * block_size;                         \\\n                    md->state_var.curlen  = 0;                                      \\\n                }                                                                   \\\n            }                                                                       \\\n        }                                                                           \\\n        return CRYPT_OK;                                                            \\\n    }\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_hash.h,v $ */\n/* $Revision: 1.22 $ */\n/* $Date: 2007/05/12 14:32:35 $ */ \n\n#ifdef LTC_HMAC\ntypedef struct Hmac_state {\n    hash_state    md;\n    int           hash;\n    hash_state    hashstate;\n    unsigned char *key;\n} hmac_state;\n\nint hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);\nint hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen);\nint hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen);\nint hmac_test(void);\nint hmac_memory(int hash,\n                const unsigned char *key, unsigned long keylen,\n                const unsigned char *in, unsigned long inlen,\n                unsigned char *out, unsigned long *outlen);\nint hmac_memory_multi(int hash,\n                      const unsigned char *key, unsigned long keylen,\n                      unsigned char *out, unsigned long *outlen,\n                      const unsigned char *in, unsigned long inlen, ...);\nint hmac_file(int hash, const char *fname, const unsigned char *key,\n              unsigned long keylen,\n              unsigned char *dst, unsigned long *dstlen);\n#endif\n\n#ifdef LTC_OMAC\n\ntypedef struct {\n    int           cipher_idx,\n                  buflen,\n                  blklen;\n    unsigned char block[MAXBLOCKSIZE],\n                  prev[MAXBLOCKSIZE],\n                  Lu[2][MAXBLOCKSIZE];\n    symmetric_key key;\n} omac_state;\n\nint omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);\nint omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen);\nint omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen);\nint omac_memory(int cipher,\n                const unsigned char *key, unsigned long keylen,\n                const unsigned char *in, unsigned long inlen,\n                unsigned char *out, unsigned long *outlen);\nint omac_memory_multi(int cipher,\n                      const unsigned char *key, unsigned long keylen,\n                      unsigned char *out, unsigned long *outlen,\n                      const unsigned char *in, unsigned long inlen, ...);\nint omac_file(int cipher,\n              const unsigned char *key, unsigned long keylen,\n              const char *filename,\n              unsigned char *out, unsigned long *outlen);\nint omac_test(void);\n#endif /* LTC_OMAC */\n\n#ifdef LTC_PMAC\n\ntypedef struct {\n    unsigned char Ls[32][MAXBLOCKSIZE],       /* L shifted by i bits to the left */\n                  Li[MAXBLOCKSIZE],           /* value of Li [current value, we calc from previous recall] */\n                  Lr[MAXBLOCKSIZE],           /* L * x^-1 */\n                  block[MAXBLOCKSIZE],        /* currently accumulated block */\n                  checksum[MAXBLOCKSIZE];     /* current checksum */\n\n    symmetric_key key;                        /* scheduled key for cipher */\n    unsigned long block_index;                /* index # for current block */\n    int           cipher_idx,                 /* cipher idx */\n                  block_len,                  /* length of block */\n                  buflen;                     /* number of bytes in the buffer */\n} pmac_state;\n\nint pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen);\nint pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen);\nint pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen);\n\nint pmac_memory(int cipher,\n                const unsigned char *key, unsigned long keylen,\n                const unsigned char *msg, unsigned long msglen,\n                unsigned char *out, unsigned long *outlen);\n\nint pmac_memory_multi(int cipher,\n                      const unsigned char *key, unsigned long keylen,\n                      unsigned char *out, unsigned long *outlen,\n                      const unsigned char *in, unsigned long inlen, ...);\n\nint pmac_file(int cipher,\n              const unsigned char *key, unsigned long keylen,\n              const char *filename,\n              unsigned char *out, unsigned long *outlen);\n\nint pmac_test(void);\n\n/* internal functions */\nint pmac_ntz(unsigned long x);\nvoid pmac_shift_xor(pmac_state *pmac);\n#endif /* PMAC */\n\n#ifdef LTC_EAX_MODE\n\n #if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE))\n  #error LTC_EAX_MODE requires LTC_OMAC and CTR\n #endif\n\ntypedef struct {\n    unsigned char N[MAXBLOCKSIZE];\n    symmetric_CTR ctr;\n    omac_state    headeromac, ctomac;\n} eax_state;\n\nint eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen,\n             const unsigned char *nonce, unsigned long noncelen,\n             const unsigned char *header, unsigned long headerlen);\n\nint eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);\nint eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);\nint eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);\nint eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);\n\nint eax_encrypt_authenticate_memory(int cipher,\n                                    const unsigned char *key, unsigned long keylen,\n                                    const unsigned char *nonce, unsigned long noncelen,\n                                    const unsigned char *header, unsigned long headerlen,\n                                    const unsigned char *pt, unsigned long ptlen,\n                                    unsigned char *ct,\n                                    unsigned char *tag, unsigned long *taglen);\n\nint eax_decrypt_verify_memory(int cipher,\n                              const unsigned char *key, unsigned long keylen,\n                              const unsigned char *nonce, unsigned long noncelen,\n                              const unsigned char *header, unsigned long headerlen,\n                              const unsigned char *ct, unsigned long ctlen,\n                              unsigned char *pt,\n                              unsigned char *tag, unsigned long taglen,\n                              int *stat);\n\nint eax_test(void);\n#endif /* EAX MODE */\n\n#ifdef LTC_OCB_MODE\ntypedef struct {\n    unsigned char L[MAXBLOCKSIZE],            /* L value */\n                  Ls[32][MAXBLOCKSIZE],       /* L shifted by i bits to the left */\n                  Li[MAXBLOCKSIZE],           /* value of Li [current value, we calc from previous recall] */\n                  Lr[MAXBLOCKSIZE],           /* L * x^-1 */\n                  R[MAXBLOCKSIZE],            /* R value */\n                  checksum[MAXBLOCKSIZE];     /* current checksum */\n\n    symmetric_key key;                        /* scheduled key for cipher */\n    unsigned long block_index;                /* index # for current block */\n    int           cipher,                     /* cipher idx */\n                  block_len;                  /* length of block */\n} ocb_state;\n\nint ocb_init(ocb_state *ocb, int cipher,\n             const unsigned char *key, unsigned long keylen, const unsigned char *nonce);\n\nint ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct);\nint ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt);\n\nint ocb_done_encrypt(ocb_state *ocb,\n                     const unsigned char *pt, unsigned long ptlen,\n                     unsigned char *ct,\n                     unsigned char *tag, unsigned long *taglen);\n\nint ocb_done_decrypt(ocb_state *ocb,\n                     const unsigned char *ct, unsigned long ctlen,\n                     unsigned char *pt,\n                     const unsigned char *tag, unsigned long taglen, int *stat);\n\nint ocb_encrypt_authenticate_memory(int cipher,\n                                    const unsigned char *key, unsigned long keylen,\n                                    const unsigned char *nonce,\n                                    const unsigned char *pt, unsigned long ptlen,\n                                    unsigned char *ct,\n                                    unsigned char *tag, unsigned long *taglen);\n\nint ocb_decrypt_verify_memory(int cipher,\n                              const unsigned char *key, unsigned long keylen,\n                              const unsigned char *nonce,\n                              const unsigned char *ct, unsigned long ctlen,\n                              unsigned char *pt,\n                              const unsigned char *tag, unsigned long taglen,\n                              int *stat);\n\nint ocb_test(void);\n\n/* internal functions */\nvoid ocb_shift_xor(ocb_state *ocb, unsigned char *Z);\nint ocb_ntz(unsigned long x);\nint s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,\n               unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode);\n#endif /* LTC_OCB_MODE */\n\n#ifdef LTC_CCM_MODE\n\n #define CCM_ENCRYPT    0\n #define CCM_DECRYPT    1\n\nint ccm_memory(int cipher,\n               const unsigned char *key, unsigned long keylen,\n               symmetric_key *uskey,\n               const unsigned char *nonce, unsigned long noncelen,\n               const unsigned char *header, unsigned long headerlen,\n               unsigned char *pt, unsigned long ptlen,\n               unsigned char *ct,\n               unsigned char *tag, unsigned long *taglen,\n               int direction);\n\nint ccm_test(void);\n#endif /* LTC_CCM_MODE */\n\n#if defined(LRW_MODE) || defined(LTC_GCM_MODE)\nvoid gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c);\n#endif\n\n\n/* table shared between GCM and LRW */\n#if defined(LTC_GCM_TABLES) || defined(LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST))\nextern const unsigned char gcm_shift_table[];\n#endif\n\n#ifdef LTC_GCM_MODE\n\n #define GCM_ENCRYPT          0\n #define GCM_DECRYPT          1\n\n #define LTC_GCM_MODE_IV      0\n #define LTC_GCM_MODE_AAD     1\n #define LTC_GCM_MODE_TEXT    2\n\ntypedef struct {\n    symmetric_key K;\n    unsigned char H[16],             /* multiplier */\n                  X[16],             /* accumulator */\n                  Y[16],             /* counter */\n                  Y_0[16],           /* initial counter */\n                  buf[16];           /* buffer for stuff */\n\n    int           cipher,            /* which cipher */\n                  ivmode,            /* Which mode is the IV in? */\n                  mode,              /* mode the GCM code is in */\n                  buflen;            /* length of data in buf */\n\n    ulong64       totlen,            /* 64-bit counter used for IV and AAD */\n                  pttotlen;          /* 64-bit counter for the PT */\n\n #ifdef LTC_GCM_TABLES\n    unsigned char PC[16][256][16]       /* 16 tables of 8x128 */\n  #ifdef LTC_GCM_TABLES_SSE2\n    __attribute__ ((aligned(16)))\n  #endif\n    ;\n #endif\n} gcm_state;\n\nvoid gcm_mult_h(gcm_state *gcm, unsigned char *I);\n\nint gcm_init(gcm_state *gcm, int cipher,\n             const unsigned char *key, int keylen);\n\nint gcm_reset(gcm_state *gcm);\n\nint gcm_add_iv(gcm_state *gcm,\n               const unsigned char *IV, unsigned long IVlen);\n\nint gcm_add_aad(gcm_state *gcm,\n                const unsigned char *adata, unsigned long adatalen);\n\nint gcm_process(gcm_state *gcm,\n                unsigned char *pt, unsigned long ptlen,\n                unsigned char *ct,\n                int direction);\n\nint gcm_done(gcm_state *gcm,\n             unsigned char *tag, unsigned long *taglen);\n\nint gcm_memory(int cipher,\n               const unsigned char *key, unsigned long keylen,\n               const unsigned char *IV, unsigned long IVlen,\n               const unsigned char *adata, unsigned long adatalen,\n               unsigned char *pt, unsigned long ptlen,\n               unsigned char *ct,\n               unsigned char *tag, unsigned long *taglen,\n               int direction);\nint gcm_test(void);\n#endif /* LTC_GCM_MODE */\n\n#ifdef LTC_PELICAN\n\ntypedef struct pelican_state {\n    symmetric_key K;\n    unsigned char state[16];\n    int           buflen;\n} pelican_state;\n\nint pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen);\nint pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen);\nint pelican_done(pelican_state *pelmac, unsigned char *out);\nint pelican_test(void);\n\nint pelican_memory(const unsigned char *key, unsigned long keylen,\n                   const unsigned char *in, unsigned long inlen,\n                   unsigned char *out);\n#endif\n\n#ifdef LTC_XCBC\n\n/* add this to \"keylen\" to xcbc_init to use a pure three-key XCBC MAC */\n #define LTC_XCBC_PURE    0x8000UL\n\ntypedef struct {\n    unsigned char K[3][MAXBLOCKSIZE],\n                  IV[MAXBLOCKSIZE];\n\n    symmetric_key key;\n\n    int           cipher,\n                  buflen,\n                  blocksize;\n} xcbc_state;\n\nint xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen);\nint xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen);\nint xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen);\nint xcbc_memory(int cipher,\n                const unsigned char *key, unsigned long keylen,\n                const unsigned char *in, unsigned long inlen,\n                unsigned char *out, unsigned long *outlen);\nint xcbc_memory_multi(int cipher,\n                      const unsigned char *key, unsigned long keylen,\n                      unsigned char *out, unsigned long *outlen,\n                      const unsigned char *in, unsigned long inlen, ...);\nint xcbc_file(int cipher,\n              const unsigned char *key, unsigned long keylen,\n              const char *filename,\n              unsigned char *out, unsigned long *outlen);\nint xcbc_test(void);\n#endif\n\n#ifdef LTC_F9_MODE\n\ntypedef struct {\n    unsigned char akey[MAXBLOCKSIZE],\n                  ACC[MAXBLOCKSIZE],\n                  IV[MAXBLOCKSIZE];\n\n    symmetric_key key;\n\n    int           cipher,\n                  buflen,\n                  keylen,\n                  blocksize;\n} f9_state;\n\nint f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen);\nint f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen);\nint f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen);\nint f9_memory(int cipher,\n              const unsigned char *key, unsigned long keylen,\n              const unsigned char *in, unsigned long inlen,\n              unsigned char *out, unsigned long *outlen);\nint f9_memory_multi(int cipher,\n                    const unsigned char *key, unsigned long keylen,\n                    unsigned char *out, unsigned long *outlen,\n                    const unsigned char *in, unsigned long inlen, ...);\nint f9_file(int cipher,\n            const unsigned char *key, unsigned long keylen,\n            const char *filename,\n            unsigned char *out, unsigned long *outlen);\nint f9_test(void);\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_mac.h,v $ */\n/* $Revision: 1.23 $ */\n/* $Date: 2007/05/12 14:37:41 $ */ \n\n/* ---- PRNG Stuff ---- */\n#ifdef LTC_YARROW\nstruct yarrow_prng {\n    int           cipher, hash;\n    unsigned char pool[MAXBLOCKSIZE];\n    symmetric_CTR ctr;\n    LTC_MUTEX_TYPE(prng_lock)\n};\n#endif\n\n#ifdef LTC_RC4\nstruct rc4_prng {\n    int           x, y;\n    unsigned char buf[256];\n};\n#endif\n\n#ifdef LTC_FORTUNA\nstruct fortuna_prng {\n    hash_state    pool[LTC_FORTUNA_POOLS];  /* the  pools */\n\n    symmetric_key skey;\n\n    unsigned char K[32],      /* the current key */\n                  IV[16];     /* IV for CTR mode */\n\n    unsigned long pool_idx,   /* current pool we will add to */\n                  pool0_len,  /* length of 0'th pool */\n                  wd;\n\n    ulong64       reset_cnt;  /* number of times we have reset */\n    LTC_MUTEX_TYPE(prng_lock)\n};\n#endif\n\n#ifdef LTC_SOBER128\nstruct sober128_prng {\n    ulong32 R[17],               /* Working storage for the shift register */\n            initR[17],           /* saved register contents */\n            konst,               /* key dependent constant */\n            sbuf;                /* partial word encryption buffer */\n\n    int     nbuf,                /* number of part-word stream bits buffered */\n            flag,                /* first add_entropy call or not? */\n            set;                 /* did we call add_entropy to set key? */\n};\n#endif\n\ntypedef union Prng_state {\n    char                 dummy[1];\n#ifdef LTC_YARROW\n    struct yarrow_prng   yarrow;\n#endif\n#ifdef LTC_RC4\n    struct rc4_prng      rc4;\n#endif\n#ifdef LTC_FORTUNA\n    struct fortuna_prng  fortuna;\n#endif\n#ifdef LTC_SOBER128\n    struct sober128_prng sober128;\n#endif\n} prng_state;\n\n/** PRNG descriptor */\nextern struct ltc_prng_descriptor {\n    /** Name of the PRNG */\n    char          *name;\n    /** size in bytes of exported state */\n    int           export_size;\n\n    /** Start a PRNG state\n        @param prng   [out] The state to initialize\n        @return CRYPT_OK if successful\n     */\n    int           (*start)(prng_state *prng);\n\n    /** Add entropy to the PRNG\n        @param in         The entropy\n        @param inlen      Length of the entropy (octets)\\\n        @param prng       The PRNG state\n        @return CRYPT_OK if successful\n     */\n    int           (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng);\n\n    /** Ready a PRNG state to read from\n        @param prng       The PRNG state to ready\n        @return CRYPT_OK if successful\n     */\n    int           (*ready)(prng_state *prng);\n\n    /** Read from the PRNG\n        @param out     [out] Where to store the data\n        @param outlen  Length of data desired (octets)\n        @param prng    The PRNG state to read from\n        @return Number of octets read\n     */\n    unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng);\n\n    /** Terminate a PRNG state\n        @param prng   The PRNG state to terminate\n        @return CRYPT_OK if successful\n     */\n    int           (*done)(prng_state *prng);\n\n    /** Export a PRNG state\n        @param out     [out] The destination for the state\n        @param outlen  [in/out] The max size and resulting size of the PRNG state\n        @param prng    The PRNG to export\n        @return CRYPT_OK if successful\n     */\n    int           (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng);\n\n    /** Import a PRNG state\n        @param in      The data to import\n        @param inlen   The length of the data to import (octets)\n        @param prng    The PRNG to initialize/import\n        @return CRYPT_OK if successful\n     */\n    int           (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng);\n\n    /** Self-test the PRNG\n        @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled\n     */\n    int           (*test)(void);\n} prng_descriptor[];\n\n#ifdef LTC_YARROW\nint yarrow_start(prng_state *prng);\nint yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint yarrow_ready(prng_state *prng);\nunsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng);\nint yarrow_done(prng_state *prng);\nint  yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng);\nint  yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint  yarrow_test(void);\n\nextern const struct ltc_prng_descriptor yarrow_desc;\n#endif\n\n#ifdef LTC_FORTUNA\nint fortuna_start(prng_state *prng);\nint fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint fortuna_ready(prng_state *prng);\nunsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng);\nint fortuna_done(prng_state *prng);\nint  fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng);\nint  fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint  fortuna_test(void);\n\nextern const struct ltc_prng_descriptor fortuna_desc;\n#endif\n\n#ifdef LTC_RC4\nint rc4_start(prng_state *prng);\nint rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint rc4_ready(prng_state *prng);\nunsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng);\nint  rc4_done(prng_state *prng);\nint  rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng);\nint  rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint  rc4_test(void);\n\nextern const struct ltc_prng_descriptor rc4_desc;\n#endif\n\n#ifdef LTC_SPRNG\nint sprng_start(prng_state *prng);\nint sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint sprng_ready(prng_state *prng);\nunsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng);\nint sprng_done(prng_state *prng);\nint  sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);\nint  sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint  sprng_test(void);\n\nextern const struct ltc_prng_descriptor sprng_desc;\n#endif\n\n#ifdef LTC_SOBER128\nint sober128_start(prng_state *prng);\nint sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint sober128_ready(prng_state *prng);\nunsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng);\nint sober128_done(prng_state *prng);\nint  sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng);\nint  sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng);\nint  sober128_test(void);\n\nextern const struct ltc_prng_descriptor sober128_desc;\n#endif\n\nint find_prng(const char *name);\nint register_prng(const struct ltc_prng_descriptor *prng);\nint unregister_prng(const struct ltc_prng_descriptor *prng);\nint prng_is_valid(int idx);\n\nLTC_MUTEX_PROTO(ltc_prng_mutex)\n\n/* Slow RNG you **might** be able to use to seed a PRNG with.  Be careful as this\n * might not work on all platforms as planned\n */\nunsigned long rng_get_bytes(unsigned char *out,\n                            unsigned long outlen,\n                            void (        *callback)(void));\n\nint rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_prng.h,v $ */\n/* $Revision: 1.9 $ */\n/* $Date: 2007/05/12 14:32:35 $ */ \n\n/* ---- NUMBER THEORY ---- */\n\nenum {\n    PK_PUBLIC =0,\n    PK_PRIVATE=1\n};\n\nint rand_prime(void *N, long len, prng_state *prng, int wprng);\n\n/* ---- RSA ---- */\n#ifdef LTC_MRSA\n\n/* Min and Max RSA key sizes (in bits) */\n #define MIN_RSA_SIZE    1024\n #define MAX_RSA_SIZE    4096\n\n/** RSA LTC_PKCS style key */\ntypedef struct Rsa_key {\n    /** Type of key, PK_PRIVATE or PK_PUBLIC */\n    int  type;\n    /** The public exponent */\n    void *e;\n    /** The private exponent */\n    void *d;\n    /** The modulus */\n    void *N;\n    /** The p factor of N */\n    void *p;\n    /** The q factor of N */\n    void *q;\n    /** The 1/q mod p CRT param */\n    void *qP;\n    /** The d mod (p - 1) CRT param */\n    void *dP;\n    /** The d mod (q - 1) CRT param */\n    void *dQ;\n} rsa_key;\n\nint rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);\n\nint rsa_exptmod(const unsigned char *in, unsigned long inlen,\n                unsigned char *out, unsigned long *outlen, int which,\n                rsa_key *key);\n\nvoid rsa_free(rsa_key *key);\n\n/* These use LTC_PKCS #1 v2.0 padding */\n #define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, _key) \\\n    rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, LTC_LTC_PKCS_1_OAEP, _key)\n\n #define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _stat, _key) \\\n    rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_LTC_PKCS_1_OAEP, _stat, _key)\n\n #define rsa_sign_hash(_in, _inlen, _out, _outlen, _prng, _prng_idx, _hash_idx, _saltlen, _key) \\\n    rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _prng, _prng_idx, _hash_idx, _saltlen, _key)\n\n #define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_idx, _saltlen, _stat, _key) \\\n    rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_idx, _saltlen, _stat, _key)\n\n/* These can be switched between LTC_PKCS #1 v2.x and LTC_PKCS #1 v1.5 paddings */\nint rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,\n                       unsigned char *out, unsigned long *outlen,\n                       const unsigned char *lparam, unsigned long lparamlen,\n                       prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key);\n\nint rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,\n                       unsigned char *out, unsigned long *outlen,\n                       const unsigned char *lparam, unsigned long lparamlen,\n                       int hash_idx, int padding,\n                       int *stat, rsa_key *key);\n\nint rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,\n                     unsigned char *out, unsigned long *outlen,\n                     int padding,\n                     prng_state *prng, int prng_idx,\n                     int hash_idx, unsigned long saltlen,\n                     rsa_key *key);\n\nint rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,\n                       const unsigned char *hash, unsigned long hashlen,\n                       int padding,\n                       int hash_idx, unsigned long saltlen,\n                       int *stat, rsa_key *key);\n\n/* LTC_PKCS #1 import/export */\nint rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);\nint rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);\n#endif\n\n/* ---- Katja ---- */\n#ifdef MKAT\n\n/* Min and Max KAT key sizes (in bits) */\n #define MIN_KAT_SIZE    1024\n #define MAX_KAT_SIZE    4096\n\n/** Katja LTC_PKCS style key */\ntypedef struct KAT_key {\n    /** Type of key, PK_PRIVATE or PK_PUBLIC */\n    int  type;\n    /** The private exponent */\n    void *d;\n    /** The modulus */\n    void *N;\n    /** The p factor of N */\n    void *p;\n    /** The q factor of N */\n    void *q;\n    /** The 1/q mod p CRT param */\n    void *qP;\n    /** The d mod (p - 1) CRT param */\n    void *dP;\n    /** The d mod (q - 1) CRT param */\n    void *dQ;\n    /** The pq param */\n    void *pq;\n} katja_key;\n\nint katja_make_key(prng_state *prng, int wprng, int size, katja_key *key);\n\nint katja_exptmod(const unsigned char *in, unsigned long inlen,\n                  unsigned char *out, unsigned long *outlen, int which,\n                  katja_key *key);\n\nvoid katja_free(katja_key *key);\n\n/* These use LTC_PKCS #1 v2.0 padding */\nint katja_encrypt_key(const unsigned char *in, unsigned long inlen,\n                      unsigned char *out, unsigned long *outlen,\n                      const unsigned char *lparam, unsigned long lparamlen,\n                      prng_state *prng, int prng_idx, int hash_idx, katja_key *key);\n\nint katja_decrypt_key(const unsigned char *in, unsigned long inlen,\n                      unsigned char *out, unsigned long *outlen,\n                      const unsigned char *lparam, unsigned long lparamlen,\n                      int hash_idx, int *stat,\n                      katja_key *key);\n\n/* LTC_PKCS #1 import/export */\nint katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key *key);\nint katja_import(const unsigned char *in, unsigned long inlen, katja_key *key);\n#endif\n\n/* ---- ECC Routines ---- */\n#ifdef LTC_MECC\n\n/* size of our temp buffers for exported keys */\n #define ECC_BUF_SIZE    256\n\n/* max private key size */\n #define ECC_MAXSIZE     66\n\n/** Structure defines a NIST GF(p) curve */\ntypedef struct {\n    /** The size of the curve in octets */\n    int  size;\n\n    /** name of curve */\n    char *name;\n\n    /** The prime that defines the field the curve is in (encoded in hex) */\n    char *prime;\n\n    /** The fields B param (hex) */\n    char *B;\n\n    /** The order of the curve (hex) */\n    char *order;\n\n    /** The x co-ordinate of the base point on the curve (hex) */\n    char *Gx;\n\n    /** The y co-ordinate of the base point on the curve (hex) */\n    char *Gy;\n} ltc_ecc_set_type;\n\n/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */\ntypedef struct {\n    /** The x co-ordinate */\n    void *x;\n\n    /** The y co-ordinate */\n    void *y;\n\n    /** The z co-ordinate */\n    void *z;\n} ecc_point;\n\n/** An ECC key */\ntypedef struct {\n    /** Type of key, PK_PRIVATE or PK_PUBLIC */\n    int                    type;\n\n    /** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */\n    int                    idx;\n\n    /** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */\n    const ltc_ecc_set_type *dp;\n\n    /** The public key */\n    ecc_point              pubkey;\n\n    /** The private key */\n    void                   *k;\n} ecc_key;\n\n/** the ECC params provided */\nextern const ltc_ecc_set_type ltc_ecc_sets[];\n\nint  ecc_test(void);\nvoid ecc_sizes(int *low, int *high);\nint  ecc_get_size(ecc_key *key);\n\nint  ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);\nint  ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp);\nvoid ecc_free(ecc_key *key);\n\nint  ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);\nint  ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);\nint  ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp);\n\nint ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen);\nint ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);\nint ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);\n\nint  ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,\n                       unsigned char *out, unsigned long *outlen);\n\nint  ecc_encrypt_key(const unsigned char *in, unsigned long inlen,\n                     unsigned char *out, unsigned long *outlen,\n                     prng_state *prng, int wprng, int hash,\n                     ecc_key *key);\n\nint  ecc_decrypt_key(const unsigned char *in, unsigned long inlen,\n                     unsigned char *out, unsigned long *outlen,\n                     ecc_key *key);\n\nint  ecc_sign_hash(const unsigned char *in, unsigned long inlen,\n                   unsigned char *out, unsigned long *outlen,\n                   prng_state *prng, int wprng, ecc_key *key);\n\nint  ecc_verify_hash(const unsigned char *sig, unsigned long siglen,\n                     const unsigned char *hash, unsigned long hashlen,\n                     int *stat, ecc_key *key);\n\n/* low level functions */\necc_point *ltc_ecc_new_point(void);\nvoid       ltc_ecc_del_point(ecc_point *p);\nint        ltc_ecc_is_valid_idx(int n);\n\n/* point ops (mp == montgomery digit) */\n #if !defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC) || defined(GMP_LTC_DESC)\n/* R = 2P */\nint ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp);\n\n/* R = P + Q */\nint ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);\n #endif\n\n #if defined(LTC_MECC_FP)\n/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */\nint ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);\n\n/* functions for saving/loading/freeing/adding to fixed point cache */\nint ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen);\nint ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen);\nvoid ltc_ecc_fp_free(void);\nint ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock);\n\n/* lock/unlock all points currently in fixed point cache */\nvoid ltc_ecc_fp_tablelock(int lock);\n #endif\n\n/* R = kG */\nint ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);\n\n #ifdef LTC_ECC_SHAMIR\n/* kA*A + kB*B = C */\nint ltc_ecc_mul2add(ecc_point *A, void *kA,\n                    ecc_point *B, void *kB,\n                    ecc_point *C,\n                    void *modulus);\n\n  #ifdef LTC_MECC_FP\n/* Shamir's trick with optimized point multiplication using fixed point cache */\nint ltc_ecc_fp_mul2add(ecc_point *A, void *kA,\n                       ecc_point *B, void *kB,\n                       ecc_point *C, void *modulus);\n  #endif\n #endif\n\n\n/* map P to affine from projective */\nint ltc_ecc_map(ecc_point *P, void *modulus, void *mp);\n#endif\n\n#ifdef LTC_MDSA\n\n/* Max diff between group and modulus size in bytes */\n #define LTC_MDSA_DELTA        512\n\n/* Max DSA group size in bytes (default allows 4k-bit groups) */\n #define LTC_MDSA_MAX_GROUP    512\n\n/** DSA key structure */\ntypedef struct {\n    /** The key type, PK_PRIVATE or PK_PUBLIC */\n    int  type;\n\n    /** The order of the sub-group used in octets */\n    int  qord;\n\n    /** The generator  */\n    void *g;\n\n    /** The prime used to generate the sub-group */\n    void *q;\n\n    /** The large prime that generats the field the contains the sub-group */\n    void *p;\n\n    /** The private key */\n    void *x;\n\n    /** The public key */\n    void *y;\n} dsa_key;\n\nint dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);\nvoid dsa_free(dsa_key *key);\n\nint dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,\n                      void *r, void *s,\n                      prng_state *prng, int wprng, dsa_key *key);\n\nint dsa_sign_hash(const unsigned char *in, unsigned long inlen,\n                  unsigned char *out, unsigned long *outlen,\n                  prng_state *prng, int wprng, dsa_key *key);\n\nint dsa_verify_hash_raw(void *r, void *s,\n                        const unsigned char *hash, unsigned long hashlen,\n                        int *stat, dsa_key *key);\n\nint dsa_verify_hash(const unsigned char *sig, unsigned long siglen,\n                    const unsigned char *hash, unsigned long hashlen,\n                    int *stat, dsa_key *key);\n\nint dsa_encrypt_key(const unsigned char *in, unsigned long inlen,\n                    unsigned char *out, unsigned long *outlen,\n                    prng_state *prng, int wprng, int hash,\n                    dsa_key *key);\n\nint dsa_decrypt_key(const unsigned char *in, unsigned long inlen,\n                    unsigned char *out, unsigned long *outlen,\n                    dsa_key *key);\n\nint dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);\nint dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);\nint dsa_verify_key(dsa_key *key, int *stat);\n\nint dsa_shared_secret(void *private_key, void *base,\n                      dsa_key *public_key,\n                      unsigned char *out, unsigned long *outlen);\n#endif\n\n#ifdef LTC_DER\n/* DER handling */\n\nenum {\n    LTC_ASN1_EOL,\n    LTC_ASN1_BOOLEAN,\n    LTC_ASN1_INTEGER,\n    LTC_ASN1_SHORT_INTEGER,\n    LTC_ASN1_BIT_STRING,\n    LTC_ASN1_OCTET_STRING,\n    LTC_ASN1_NULL,\n    LTC_ASN1_OBJECT_IDENTIFIER,\n    LTC_ASN1_IA5_STRING,\n    LTC_ASN1_PRINTABLE_STRING,\n    LTC_ASN1_UTF8_STRING,\n    LTC_ASN1_UTCTIME,\n    LTC_ASN1_CHOICE,\n    LTC_ASN1_SEQUENCE,\n    LTC_ASN1_SET,\n    LTC_ASN1_SETOF\n};\n\n/** A LTC ASN.1 list type */\ntypedef struct ltc_asn1_list_ {\n    /** The LTC ASN.1 enumerated type identifier */\n    int                   type;\n    /** The data to encode or place for decoding */\n    void                  *data;\n    /** The size of the input or resulting output */\n    unsigned long         size;\n    /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */\n    int                   used;\n    /** prev/next entry in the list */\n    struct ltc_asn1_list_ *prev, *next, *child, *parent;\n} ltc_asn1_list;\n\n #define LTC_SET_ASN1(list, index, Type, Data, Size)          \\\n    do {                                                      \\\n        int           LTC_MACRO_temp  = (index);              \\\n        ltc_asn1_list *LTC_MACRO_list = (list);               \\\n        LTC_MACRO_list[LTC_MACRO_temp].type = (Type);         \\\n        LTC_MACRO_list[LTC_MACRO_temp].data = (void *)(Data); \\\n        LTC_MACRO_list[LTC_MACRO_temp].size = (Size);         \\\n        LTC_MACRO_list[LTC_MACRO_temp].used = 0;              \\\n    } while (0);\n\n/* SEQUENCE */\nint der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,\n                           unsigned char *out, unsigned long *outlen, int type_of);\n\n #define der_encode_sequence(list, inlen, out, outlen)    der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)\n\nint der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,\n                           ltc_asn1_list *list, unsigned long outlen, int ordered);\n\n #define der_decode_sequence(in, inlen, list, outlen)    der_decode_sequence_ex(in, inlen, list, outlen, 1)\n\nint der_length_sequence(ltc_asn1_list *list, unsigned long inlen,\n                        unsigned long *outlen);\n\n/* SET */\n #define der_decode_set(in, inlen, list, outlen)    der_decode_sequence_ex(in, inlen, list, outlen, 0)\n #define der_length_set    der_length_sequence\nint der_encode_set(ltc_asn1_list *list, unsigned long inlen,\n                   unsigned char *out, unsigned long *outlen);\n\nint der_encode_setof(ltc_asn1_list *list, unsigned long inlen,\n                     unsigned char *out, unsigned long *outlen);\n\n/* VA list handy helpers with triplets of <type, size, data> */\nint der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);\nint der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);\n\n/* FLEXI DECODER handle unknown list decoder */\nint  der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);\nvoid der_free_sequence_flexi(ltc_asn1_list *list);\nvoid der_sequence_free(ltc_asn1_list *in);\n\n/* BOOLEAN */\nint der_length_boolean(unsigned long *outlen);\nint der_encode_boolean(int in,\n                       unsigned char *out, unsigned long *outlen);\nint der_decode_boolean(const unsigned char *in, unsigned long inlen,\n                       int *out);\n\n/* INTEGER */\nint der_encode_integer(void *num, unsigned char *out, unsigned long *outlen);\nint der_decode_integer(const unsigned char *in, unsigned long inlen, void *num);\nint der_length_integer(void *num, unsigned long *len);\n\n/* INTEGER -- handy for 0..2^32-1 values */\nint der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num);\nint der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen);\nint der_length_short_integer(unsigned long num, unsigned long *outlen);\n\n/* BIT STRING */\nint der_encode_bit_string(const unsigned char *in, unsigned long inlen,\n                          unsigned char *out, unsigned long *outlen);\nint der_decode_bit_string(const unsigned char *in, unsigned long inlen,\n                          unsigned char *out, unsigned long *outlen);\nint der_length_bit_string(unsigned long nbits, unsigned long *outlen);\n\n/* OCTET STRING */\nint der_encode_octet_string(const unsigned char *in, unsigned long inlen,\n                            unsigned char *out, unsigned long *outlen);\nint der_decode_octet_string(const unsigned char *in, unsigned long inlen,\n                            unsigned char *out, unsigned long *outlen);\nint der_length_octet_string(unsigned long noctets, unsigned long *outlen);\n\n/* OBJECT IDENTIFIER */\nint der_encode_object_identifier(unsigned long *words, unsigned long nwords,\n                                 unsigned char *out, unsigned long *outlen);\nint der_decode_object_identifier(const unsigned char *in, unsigned long inlen,\n                                 unsigned long *words, unsigned long *outlen);\nint der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen);\nunsigned long der_object_identifier_bits(unsigned long x);\n\n/* IA5 STRING */\nint der_encode_ia5_string(const unsigned char *in, unsigned long inlen,\n                          unsigned char *out, unsigned long *outlen);\nint der_decode_ia5_string(const unsigned char *in, unsigned long inlen,\n                          unsigned char *out, unsigned long *outlen);\nint der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);\n\nint der_ia5_char_encode(int c);\nint der_ia5_value_decode(int v);\n\n/* Printable STRING */\nint der_encode_printable_string(const unsigned char *in, unsigned long inlen,\n                                unsigned char *out, unsigned long *outlen);\nint der_decode_printable_string(const unsigned char *in, unsigned long inlen,\n                                unsigned char *out, unsigned long *outlen);\nint der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);\n\nint der_printable_char_encode(int c);\nint der_printable_value_decode(int v);\n\n/* UTF-8 */\n #if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR)\n  #include <wchar.h>\n #else\t  \n #if  !defined(_WCHAR_H) && !defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) && !defined(__WCHAR_TYPE__) && !defined(_WCHAR_T) && !defined(__WCHARTDEF__)\ntypedef ulong32   wchar_t;\n #endif\n #endif\n\nint der_encode_utf8_string(const wchar_t *in, unsigned long inlen,\n                           unsigned char *out, unsigned long *outlen);\n\nint der_decode_utf8_string(const unsigned char *in, unsigned long inlen,\n                           wchar_t *out, unsigned long *outlen);\nunsigned long der_utf8_charsize(const wchar_t c);\nint der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen);\n\n\n/* CHOICE */\nint der_decode_choice(const unsigned char *in, unsigned long *inlen,\n                      ltc_asn1_list *list, unsigned long outlen);\n\n/* UTCTime */\ntypedef struct {\n    unsigned YY,      /* year */\n             MM,      /* month */\n             DD,      /* day */\n             hh,      /* hour */\n             mm,      /* minute */\n             ss,      /* second */\n             off_dir, /* timezone offset direction 0 == +, 1 == - */\n             off_hh,  /* timezone offset hours */\n             off_mm;  /* timezone offset minutes */\n} ltc_utctime;\n\nint der_encode_utctime(ltc_utctime *utctime,\n                       unsigned char *out, unsigned long *outlen);\n\nint der_decode_utctime(const unsigned char *in, unsigned long *inlen,\n                       ltc_utctime *out);\n\nint der_length_utctime(ltc_utctime *utctime, unsigned long *outlen);\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pk.h,v $ */\n/* $Revision: 1.81 $ */\n/* $Date: 2007/05/12 14:32:35 $ */ \n\n/** math functions **/\n#define LTC_SOURCE\n#define LTC_MP_LT     -1\n#define LTC_MP_EQ     0\n#define LTC_MP_GT     1\n\n#define LTC_MP_NO     0\n#define LTC_MP_YES    1\n\n#ifndef LTC_MECC\ntypedef void   ecc_point;\n#endif\n\n#ifndef LTC_MRSA\ntypedef void   rsa_key;\n#endif\n\n/** math descriptor */\ntypedef struct {\n    /** Name of the math provider */\n    char *name;\n\n    /** Bits per digit, amount of bits must fit in an unsigned long */\n    int  bits_per_digit;\n\n/* ---- init/deinit functions ---- */\n\n    /** initialize a bignum\n       @param   a     The number to initialize\n       @return  CRYPT_OK on success\n     */\n    int (*init)(void **a);\n\n    /** init copy\n       @param  dst    The number to initialize and write to\n       @param  src    The number to copy from\n       @return CRYPT_OK on success\n     */\n    int (*init_copy)(void **dst, void *src);\n\n    /** deinit\n       @param   a    The number to free\n       @return CRYPT_OK on success\n     */\n    void (*deinit)(void *a);\n\n/* ---- data movement ---- */\n\n    /** negate\n       @param   src   The number to negate\n       @param   dst   The destination\n       @return CRYPT_OK on success\n     */\n    int (*neg)(void *src, void *dst);\n\n    /** copy\n       @param   src   The number to copy from\n       @param   dst   The number to write to\n       @return CRYPT_OK on success\n     */\n    int (*copy)(void *src, void *dst);\n\n/* ---- trivial low level functions ---- */\n\n    /** set small constant\n       @param a    Number to write to\n       @param n    Source upto bits_per_digit (actually meant for very small constants)\n       @return CRYPT_OK on succcess\n     */\n    int (*set_int)(void *a, unsigned long n);\n\n    /** get small constant\n       @param a    Number to read, only fetches upto bits_per_digit from the number\n       @return  The lower bits_per_digit of the integer (unsigned)\n     */\n    unsigned long (*get_int)(void *a);\n\n    /** get digit n\n       @param a  The number to read from\n       @param n  The number of the digit to fetch\n       @return  The bits_per_digit  sized n'th digit of a\n     */\n    unsigned long (*get_digit)(void *a, int n);\n\n    /** Get the number of digits that represent the number\n       @param a   The number to count\n       @return The number of digits used to represent the number\n     */\n    int (*get_digit_count)(void *a);\n\n    /** compare two integers\n       @param a   The left side integer\n       @param b   The right side integer\n       @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise.  (signed comparison)\n     */\n    int (*compare)(void *a, void *b);\n\n    /** compare against int\n       @param a   The left side integer\n       @param b   The right side integer (upto bits_per_digit)\n       @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise.  (signed comparison)\n     */\n    int (*compare_d)(void *a, unsigned long n);\n\n    /** Count the number of bits used to represent the integer\n       @param a   The integer to count\n       @return The number of bits required to represent the integer\n     */\n    int (*count_bits)(void *a);\n\n    /** Count the number of LSB bits which are zero\n       @param a   The integer to count\n       @return The number of contiguous zero LSB bits\n     */\n    int (*count_lsb_bits)(void *a);\n\n    /** Compute a power of two\n       @param a  The integer to store the power in\n       @param n  The power of two you want to store (a = 2^n)\n       @return CRYPT_OK on success\n     */\n    int (*twoexpt)(void *a, int n);\n\n/* ---- radix conversions ---- */\n\n    /** read ascii string\n       @param a     The integer to store into\n       @param str   The string to read\n       @param radix The radix the integer has been represented in (2-64)\n       @return CRYPT_OK on success\n     */\n    int (*read_radix)(void *a, const char *str, int radix);\n\n    /** write number to string\n       @param a     The integer to store\n       @param str   The destination for the string\n       @param radix The radix the integer is to be represented in (2-64)\n       @return CRYPT_OK on success\n     */\n    int (*write_radix)(void *a, char *str, int radix);\n\n    /** get size as unsigned char string\n       @param a     The integer to get the size (when stored in array of octets)\n       @return The length of the integer\n     */\n    unsigned long (*unsigned_size)(void *a);\n\n    /** store an integer as an array of octets\n       @param src   The integer to store\n       @param dst   The buffer to store the integer in\n       @return CRYPT_OK on success\n     */\n    int (*unsigned_write)(void *src, unsigned char *dst);\n\n    /** read an array of octets and store as integer\n       @param dst   The integer to load\n       @param src   The array of octets\n       @param len   The number of octets\n       @return CRYPT_OK on success\n     */\n    int (*unsigned_read)(void *dst, unsigned char *src, unsigned long len);\n\n/* ---- basic math ---- */\n\n    /** add two integers\n       @param a   The first source integer\n       @param b   The second source integer\n       @param c   The destination of \"a + b\"\n       @return CRYPT_OK on success\n     */\n    int (*add)(void *a, void *b, void *c);\n\n\n    /** add two integers\n       @param a   The first source integer\n       @param b   The second source integer (single digit of upto bits_per_digit in length)\n       @param c   The destination of \"a + b\"\n       @return CRYPT_OK on success\n     */\n    int (*addi)(void *a, unsigned long b, void *c);\n\n    /** subtract two integers\n       @param a   The first source integer\n       @param b   The second source integer\n       @param c   The destination of \"a - b\"\n       @return CRYPT_OK on success\n     */\n    int (*sub)(void *a, void *b, void *c);\n\n    /** subtract two integers\n       @param a   The first source integer\n       @param b   The second source integer (single digit of upto bits_per_digit in length)\n       @param c   The destination of \"a - b\"\n       @return CRYPT_OK on success\n     */\n    int (*subi)(void *a, unsigned long b, void *c);\n\n    /** multiply two integers\n       @param a   The first source integer\n       @param b   The second source integer (single digit of upto bits_per_digit in length)\n       @param c   The destination of \"a * b\"\n       @return CRYPT_OK on success\n     */\n    int (*mul)(void *a, void *b, void *c);\n\n    /** multiply two integers\n       @param a   The first source integer\n       @param b   The second source integer (single digit of upto bits_per_digit in length)\n       @param c   The destination of \"a * b\"\n       @return CRYPT_OK on success\n     */\n    int (*muli)(void *a, unsigned long b, void *c);\n\n    /** Square an integer\n       @param a    The integer to square\n       @param b    The destination\n       @return CRYPT_OK on success\n     */\n    int (*sqr)(void *a, void *b);\n\n    /** Divide an integer\n       @param a    The dividend\n       @param b    The divisor\n       @param c    The quotient (can be NULL to signify don't care)\n       @param d    The remainder (can be NULL to signify don't care)\n       @return CRYPT_OK on success\n     */\n    int (*mpdiv)(void *a, void *b, void *c, void *d);\n\n    /** divide by two\n       @param  a   The integer to divide (shift right)\n       @param  b   The destination\n       @return CRYPT_OK on success\n     */\n    int (*div_2)(void *a, void *b);\n\n    /** Get remainder (small value)\n       @param  a    The integer to reduce\n       @param  b    The modulus (upto bits_per_digit in length)\n       @param  c    The destination for the residue\n       @return CRYPT_OK on success\n     */\n    int (*modi)(void *a, unsigned long b, unsigned long *c);\n\n    /** gcd\n       @param  a     The first integer\n       @param  b     The second integer\n       @param  c     The destination for (a, b)\n       @return CRYPT_OK on success\n     */\n    int (*gcd)(void *a, void *b, void *c);\n\n    /** lcm\n       @param  a     The first integer\n       @param  b     The second integer\n       @param  c     The destination for [a, b]\n       @return CRYPT_OK on success\n     */\n    int (*lcm)(void *a, void *b, void *c);\n\n    /** Modular multiplication\n       @param  a     The first source\n       @param  b     The second source\n       @param  c     The modulus\n       @param  d     The destination (a*b mod c)\n       @return CRYPT_OK on success\n     */\n    int (*mulmod)(void *a, void *b, void *c, void *d);\n\n    /** Modular squaring\n       @param  a     The first source\n       @param  b     The modulus\n       @param  c     The destination (a*a mod b)\n       @return CRYPT_OK on success\n     */\n    int (*sqrmod)(void *a, void *b, void *c);\n\n    /** Modular inversion\n       @param  a     The value to invert\n       @param  b     The modulus\n       @param  c     The destination (1/a mod b)\n       @return CRYPT_OK on success\n     */\n    int (*invmod)(void *, void *, void *);\n\n/* ---- reduction ---- */\n\n    /** setup montgomery\n        @param a  The modulus\n        @param b  The destination for the reduction digit\n        @return CRYPT_OK on success\n     */\n    int (*montgomery_setup)(void *a, void **b);\n\n    /** get normalization value\n        @param a   The destination for the normalization value\n        @param b   The modulus\n        @return  CRYPT_OK on success\n     */\n    int (*montgomery_normalization)(void *a, void *b);\n\n    /** reduce a number\n        @param a   The number [and dest] to reduce\n        @param b   The modulus\n        @param c   The value \"b\" from montgomery_setup()\n        @return CRYPT_OK on success\n     */\n    int (*montgomery_reduce)(void *a, void *b, void *c);\n\n    /** clean up  (frees memory)\n        @param a   The value \"b\" from montgomery_setup()\n        @return CRYPT_OK on success\n     */\n    void (*montgomery_deinit)(void *a);\n\n/* ---- exponentiation ---- */\n\n    /** Modular exponentiation\n        @param a    The base integer\n        @param b    The power (can be negative) integer\n        @param c    The modulus integer\n        @param d    The destination\n        @return CRYPT_OK on success\n     */\n    int (*exptmod)(void *a, void *b, void *c, void *d);\n\n    /** Primality testing\n        @param a     The integer to test\n        @param b     The destination of the result (FP_YES if prime)\n        @return CRYPT_OK on success\n     */\n    int (*isprime)(void *a, int *b);\n\n/* ----  (optional) ecc point math ---- */\n\n    /** ECC GF(p) point multiplication (from the NIST curves)\n        @param k   The integer to multiply the point by\n        @param G   The point to multiply\n        @param R   The destination for kG\n        @param modulus  The modulus for the field\n        @param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only)\n        @return CRYPT_OK on success\n     */\n    int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);\n\n    /** ECC GF(p) point addition\n        @param P    The first point\n        @param Q    The second point\n        @param R    The destination of P + Q\n        @param modulus  The modulus\n        @param mp   The \"b\" value from montgomery_setup()\n        @return CRYPT_OK on success\n     */\n    int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);\n\n    /** ECC GF(p) point double\n        @param P    The first point\n        @param R    The destination of 2P\n        @param modulus  The modulus\n        @param mp   The \"b\" value from montgomery_setup()\n        @return CRYPT_OK on success\n     */\n    int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp);\n\n    /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1)\n        @param P     The point to map\n        @param modulus The modulus\n        @param mp    The \"b\" value from montgomery_setup()\n        @return CRYPT_OK on success\n        @remark  The mapping can be different but keep in mind a ecc_point only has three\n                 integers (x,y,z) so if you use a different mapping you have to make it fit.\n     */\n    int (*ecc_map)(ecc_point *P, void *modulus, void *mp);\n\n    /** Computes kA*A + kB*B = C using Shamir's Trick\n        @param A        First point to multiply\n        @param kA       What to multiple A by\n        @param B        Second point to multiply\n        @param kB       What to multiple B by\n        @param C        [out] Destination point (can overlap with A or B\n        @param modulus  Modulus for curve\n        @return CRYPT_OK on success\n     */\n    int (*ecc_mul2add)(ecc_point *A, void *kA,\n                       ecc_point *B, void *kB,\n                       ecc_point *C,\n                       void *modulus);\n\n/* ---- (optional) rsa optimized math (for internal CRT) ---- */\n\n    /** RSA Key Generation\n        @param prng     An active PRNG state\n        @param wprng    The index of the PRNG desired\n        @param size     The size of the modulus (key size) desired (octets)\n        @param e        The \"e\" value (public key).  e==65537 is a good choice\n        @param key      [out] Destination of a newly created private key pair\n        @return CRYPT_OK if successful, upon error all allocated ram is freed\n     */\n    int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key);\n\n\n    /** RSA exponentiation\n       @param in       The octet array representing the base\n       @param inlen    The length of the input\n       @param out      The destination (to be stored in an octet array format)\n       @param outlen   The length of the output buffer and the resulting size (zero padded to the size of the modulus)\n       @param which    PK_PUBLIC for public RSA and PK_PRIVATE for private RSA\n       @param key      The RSA key to use\n       @return CRYPT_OK on success\n     */\n    int (*rsa_me)(const unsigned char *in, unsigned long inlen,\n                  unsigned char *out, unsigned long *outlen, int which,\n                  rsa_key *key);\n} ltc_math_descriptor;\n\nextern ltc_math_descriptor ltc_mp;\n\nint ltc_init_multi(void **a, ...);\nvoid ltc_deinit_multi(void *a, ...);\n\n#ifdef LTM_DESC\nextern const ltc_math_descriptor ltm_desc;\n#endif\n\n#ifdef TFM_DESC\nextern const ltc_math_descriptor tfm_desc;\n#endif\n\n#ifdef GMP_DESC\nextern const ltc_math_descriptor gmp_desc;\n#endif\n\n#if !defined(DESC_DEF_ONLY) && defined(LTC_SOURCE)\n #undef MP_DIGIT_BIT\n #undef mp_iszero\n #undef mp_isodd\n #undef mp_tohex\n\n #define MP_DIGIT_BIT    ltc_mp.bits_per_digit\n\n/* some handy macros */\n #define mp_init(a)                           ltc_mp.init(a)\n #define mp_init_multi     ltc_init_multi\n #define mp_clear(a)                          ltc_mp.deinit(a)\n #define mp_clear_multi    ltc_deinit_multi\n #define mp_init_copy(a, b)                   ltc_mp.init_copy(a, b)\n\n #define mp_neg(a, b)                         ltc_mp.neg(a, b)\n #define mp_copy(a, b)                        ltc_mp.copy(a, b)\n\n #define mp_set(a, b)                         ltc_mp.set_int(a, b)\n #define mp_set_int(a, b)                     ltc_mp.set_int(a, b)\n #define mp_get_int(a)                        ltc_mp.get_int(a)\n #define mp_get_digit(a, n)                   ltc_mp.get_digit(a, n)\n #define mp_get_digit_count(a)                ltc_mp.get_digit_count(a)\n #define mp_cmp(a, b)                         ltc_mp.compare(a, b)\n #define mp_cmp_d(a, b)                       ltc_mp.compare_d(a, b)\n #define mp_count_bits(a)                     ltc_mp.count_bits(a)\n #define mp_cnt_lsb(a)                        ltc_mp.count_lsb_bits(a)\n #define mp_2expt(a, b)                       ltc_mp.twoexpt(a, b)\n\n #define mp_read_radix(a, b, c)               ltc_mp.read_radix(a, b, c)\n #define mp_toradix(a, b, c)                  ltc_mp.write_radix(a, b, c)\n #define mp_unsigned_bin_size(a)              ltc_mp.unsigned_size(a)\n #define mp_to_unsigned_bin(a, b)             ltc_mp.unsigned_write(a, b)\n #define mp_read_unsigned_bin(a, b, c)        ltc_mp.unsigned_read(a, b, c)\n\n #define mp_add(a, b, c)                      ltc_mp.add(a, b, c)\n #define mp_add_d(a, b, c)                    ltc_mp.addi(a, b, c)\n #define mp_sub(a, b, c)                      ltc_mp.sub(a, b, c)\n #define mp_sub_d(a, b, c)                    ltc_mp.subi(a, b, c)\n #define mp_mul(a, b, c)                      ltc_mp.mul(a, b, c)\n #define mp_mul_d(a, b, c)                    ltc_mp.muli(a, b, c)\n #define mp_sqr(a, b)                         ltc_mp.sqr(a, b)\n #define mp_div(a, b, c, d)                   ltc_mp.mpdiv(a, b, c, d)\n #define mp_div_2(a, b)                       ltc_mp.div_2(a, b)\n #define mp_mod(a, b, c)                      ltc_mp.mpdiv(a, b, NULL, c)\n #define mp_mod_d(a, b, c)                    ltc_mp.modi(a, b, c)\n #define mp_gcd(a, b, c)                      ltc_mp.gcd(a, b, c)\n #define mp_lcm(a, b, c)                      ltc_mp.lcm(a, b, c)\n\n #define mp_mulmod(a, b, c, d)                ltc_mp.mulmod(a, b, c, d)\n #define mp_sqrmod(a, b, c)                   ltc_mp.sqrmod(a, b, c)\n #define mp_invmod(a, b, c)                   ltc_mp.invmod(a, b, c)\n\n #define mp_montgomery_setup(a, b)            ltc_mp.montgomery_setup(a, b)\n #define mp_montgomery_normalization(a, b)    ltc_mp.montgomery_normalization(a, b)\n #define mp_montgomery_reduce(a, b, c)        ltc_mp.montgomery_reduce(a, b, c)\n #define mp_montgomery_free(a)                ltc_mp.montgomery_deinit(a)\n\n #define mp_exptmod(a, b, c, d)               ltc_mp.exptmod(a, b, c, d)\n #define mp_prime_is_prime(a, b, c)           ltc_mp.isprime(a, c)\n\n #define mp_iszero(a)                         (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO)\n #define mp_isodd(a)                          (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO)\n #define mp_exch(a, b)                        do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while (0);\n\n #define mp_tohex(a, b)                       mp_toradix(a, b, 16)\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_math.h,v $ */\n/* $Revision: 1.44 $ */\n/* $Date: 2007/05/12 14:32:35 $ */ \n\n/* ---- LTC_BASE64 Routines ---- */\n#ifdef LTC_BASE64\nint base64_encode(const unsigned char *in, unsigned long len,\n                  unsigned char *out, unsigned long *outlen);\n\nint base64_decode(const unsigned char *in, unsigned long len,\n                  unsigned char *out, unsigned long *outlen);\n#endif\n\n/* ---- MEM routines ---- */\nvoid zeromem(void *dst, size_t len);\nvoid burn_stack(unsigned long len);\n\nconst char *error_to_string(int err);\n\nextern const char *crypt_build_settings;\n\n/* ---- HMM ---- */\nint crypt_fsa(void *mp, ...);\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_misc.h,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2007/05/12 14:32:35 $ */ \n\n/* Defines the LTC_ARGCHK macro used within the library */\n/* ARGTYPE is defined in mycrypt_cfg.h */\n#if ARGTYPE == 0\n\n #include <signal.h>\n\n/* this is the default LibTomCrypt macro  */\nvoid crypt_argchk(char *v, char *s, int d);\n\n #define LTC_ARGCHK(x)      if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }\n #define LTC_ARGCHKVD(x)    LTC_ARGCHK(x)\n\n#elif ARGTYPE == 1\n\n/* fatal type of error */\n #define LTC_ARGCHK(x)      assert((x))\n #define LTC_ARGCHKVD(x)    LTC_ARGCHK(x)\n\n#elif ARGTYPE == 2\n\n #define LTC_ARGCHK(x)      if (!(x)) { fprintf(stderr, \"\\nwarning: ARGCHK failed at %s:%d\\n\", __FILE__, __LINE__); }\n #define LTC_ARGCHKVD(x)    LTC_ARGCHK(x)\n\n#elif ARGTYPE == 3\n\n #define LTC_ARGCHK(x)\n #define LTC_ARGCHKVD(x)    LTC_ARGCHK(x)\n\n#elif ARGTYPE == 4\n\n #define LTC_ARGCHK(x)      if (!(x)) return CRYPT_INVALID_ARG;\n #define LTC_ARGCHKVD(x)    if (!(x)) return;\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_argchk.h,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/08/27 20:50:21 $ */ \n\n/* LTC_PKCS Header Info */\n\n/* ===> LTC_PKCS #1 -- RSA Cryptography <=== */\n#ifdef LTC_PKCS_1\n\nenum ltc_pkcs_1_v1_5_blocks {\n    LTC_LTC_PKCS_1_EMSA = 1,        /* Block type 1 (LTC_PKCS #1 v1.5 signature padding) */\n    LTC_LTC_PKCS_1_EME  = 2         /* Block type 2 (LTC_PKCS #1 v1.5 encryption padding) */\n};\n\nenum ltc_pkcs_1_paddings {\n    LTC_LTC_PKCS_1_V1_5 = 1,        /* LTC_PKCS #1 v1.5 padding (\\sa ltc_pkcs_1_v1_5_blocks) */\n    LTC_LTC_PKCS_1_OAEP = 2,        /* LTC_PKCS #1 v2.0 encryption padding */\n    LTC_LTC_PKCS_1_PSS  = 3         /* LTC_PKCS #1 v2.1 signature padding */\n};\n\nint pkcs_1_mgf1(int hash_idx,\n                const unsigned char *seed, unsigned long seedlen,\n                unsigned char *mask, unsigned long masklen);\n\nint pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out);\nint pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen);\n\n/* *** v1.5 padding */\nint pkcs_1_v1_5_encode(const unsigned char *msg,\n                       unsigned long       msglen,\n                       int                 block_type,\n                       unsigned long       modulus_bitlen,\n                       prng_state          *prng,\n                       int                 prng_idx,\n                       unsigned char       *out,\n                       unsigned long       *outlen);\n\nint pkcs_1_v1_5_decode(const unsigned char *msg,\n                       unsigned long       msglen,\n                       int                 block_type,\n                       unsigned long       modulus_bitlen,\n                       unsigned char       *out,\n                       unsigned long       *outlen,\n                       int                 *is_valid);\n\n/* *** v2.1 padding */\nint pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,\n                       const unsigned char *lparam, unsigned long lparamlen,\n                       unsigned long modulus_bitlen, prng_state *prng,\n                       int prng_idx, int hash_idx,\n                       unsigned char *out, unsigned long *outlen);\n\nint pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,\n                       const unsigned char *lparam, unsigned long lparamlen,\n                       unsigned long modulus_bitlen, int hash_idx,\n                       unsigned char *out, unsigned long *outlen,\n                       int *res);\n\nint pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,\n                      unsigned long saltlen, prng_state *prng,\n                      int prng_idx, int hash_idx,\n                      unsigned long modulus_bitlen,\n                      unsigned char *out, unsigned long *outlen);\n\nint pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,\n                      const unsigned char *sig, unsigned long siglen,\n                      unsigned long saltlen, int hash_idx,\n                      unsigned long modulus_bitlen, int *res);\n#endif /* LTC_PKCS_1 */\n\n/* ===> LTC_PKCS #5 -- Password Based Cryptography <=== */\n#ifdef LTC_PKCS_5\n\n/* Algorithm #1 (old) */\nint pkcs_5_alg1(const unsigned char *password, unsigned long password_len,\n                const unsigned char *salt,\n                int iteration_count, int hash_idx,\n                unsigned char *out, unsigned long *outlen);\n\n/* Algorithm #2 (new) */\nint pkcs_5_alg2(const unsigned char *password, unsigned long password_len,\n                const unsigned char *salt, unsigned long salt_len,\n                int iteration_count, int hash_idx,\n                unsigned char *out, unsigned long *outlen);\n#endif  /* LTC_PKCS_5 */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pkcs.h,v $ */\n/* $Revision: 1.8 $ */\n/* $Date: 2007/05/12 14:32:35 $ */ \n\n#ifdef __cplusplus\n}\n#endif\n#endif /* TOMCRYPT_H_ */\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt.h,v $ */\n/* $Revision: 1.21 $ */\n/* $Date: 2006/12/16 19:34:05 $ */ \n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_argchk.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_cipher_descriptor.c\n   Stores the cipher descriptor table, Tom St Denis\n */\n\nstruct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = {\n    { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }\n};\n\nLTC_MUTEX_GLOBAL(ltc_cipher_mutex)\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c,v $ */\n/* $Revision: 1.13 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_cipher_is_valid.c\n   Determine if cipher is valid, Tom St Denis\n */\n\n/*\n   Test if a cipher index is valid\n   @param idx   The index of the cipher to search for\n   @return CRYPT_OK if valid\n */\nint cipher_is_valid(int idx) {\n    LTC_MUTEX_LOCK(&ltc_cipher_mutex);\n    if ((idx < 0) || (idx >= TAB_SIZE) || (cipher_descriptor[idx].name == NULL)) {\n        LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n        return CRYPT_INVALID_CIPHER;\n    }\n    LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n    return CRYPT_OK;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_find_cipher.c\n   Find a cipher in the descriptor tables, Tom St Denis\n */\n\n/**\n   Find a registered cipher by name\n   @param name   The name of the cipher to look for\n   @return >= 0 if found, -1 if not present\n */\nint find_cipher(const char *name) {\n    int x;\n\n    LTC_ARGCHK(name != NULL);\n    LTC_MUTEX_LOCK(&ltc_cipher_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if ((cipher_descriptor[x].name != NULL) && !XSTRCMP(cipher_descriptor[x].name, name)) {\n            LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n            return x;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_cipher.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_find_cipher_any.c\n   Find a cipher in the descriptor tables, Tom St Denis\n */\n\n/**\n   Find a cipher flexibly.  First by name then if not present by block and key size\n   @param name        The name of the cipher desired\n   @param blocklen    The minimum length of the block cipher desired (octets)\n   @param keylen      The minimum length of the key size desired (octets)\n   @return >= 0 if found, -1 if not present\n */\nint find_cipher_any(const char *name, int blocklen, int keylen) {\n    int x;\n\n    LTC_ARGCHK(name != NULL);\n\n    x = find_cipher(name);\n    if (x != -1) return x;\n\n    LTC_MUTEX_LOCK(&ltc_cipher_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (cipher_descriptor[x].name == NULL) {\n            continue;\n        }\n        if ((blocklen <= (int)cipher_descriptor[x].block_length) && (keylen <= (int)cipher_descriptor[x].max_key_length)) {\n            LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n            return x;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_find_cipher_id.c\n   Find cipher by ID, Tom St Denis\n */\n\n/**\n   Find a cipher by ID number\n   @param ID    The ID (not same as index) of the cipher to find\n   @return >= 0 if found, -1 if not present\n */\nint find_cipher_id(unsigned char ID) {\n    int x;\n\n    LTC_MUTEX_LOCK(&ltc_cipher_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (cipher_descriptor[x].ID == ID) {\n            x = (cipher_descriptor[x].name == NULL) ? -1 : x;\n            LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n            return x;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_find_hash.c\n   Find a hash, Tom St Denis\n */\n\n/**\n   Find a registered hash by name\n   @param name   The name of the hash to look for\n   @return >= 0 if found, -1 if not present\n */\nint find_hash(const char *name) {\n    int x;\n\n    LTC_ARGCHK(name != NULL);\n    LTC_MUTEX_LOCK(&ltc_hash_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if ((hash_descriptor[x].name != NULL) && (XSTRCMP(hash_descriptor[x].name, name) == 0)) {\n            LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n            return x;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_find_hash_any.c\n   Find a hash, Tom St Denis\n */\n\n/**\n   Find a hash flexibly.  First by name then if not present by digest size\n   @param name        The name of the hash desired\n   @param digestlen   The minimum length of the digest size (octets)\n   @return >= 0 if found, -1 if not present\n */int find_hash_any(const char *name, int digestlen) {\n    int x, y, z;\n\n    LTC_ARGCHK(name != NULL);\n\n    x = find_hash(name);\n    if (x != -1) return x;\n\n    LTC_MUTEX_LOCK(&ltc_hash_mutex);\n    y = MAXBLOCKSIZE + 1;\n    z = -1;\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (hash_descriptor[x].name == NULL) {\n            continue;\n        }\n        if (((int)hash_descriptor[x].hashsize >= digestlen) && ((int)hash_descriptor[x].hashsize < y)) {\n            z = x;\n            y = hash_descriptor[x].hashsize;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n    return z;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_find_hash_id.c\n   Find hash by ID, Tom St Denis\n */\n\n/**\n   Find a hash by ID number\n   @param ID    The ID (not same as index) of the hash to find\n   @return >= 0 if found, -1 if not present\n */\nint find_hash_id(unsigned char ID) {\n    int x;\n\n    LTC_MUTEX_LOCK(&ltc_hash_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (hash_descriptor[x].ID == ID) {\n            x = (hash_descriptor[x].name == NULL) ? -1 : x;\n            LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n            return x;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_find_hash_oid.c\n   Find a hash, Tom St Denis\n */\n\nint find_hash_oid(const unsigned long *ID, unsigned long IDlen) {\n    int x;\n\n    LTC_ARGCHK(ID != NULL);\n    LTC_MUTEX_LOCK(&ltc_hash_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if ((hash_descriptor[x].name != NULL) && (hash_descriptor[x].OIDlen == IDlen) && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(unsigned long) * IDlen)) {\n            LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n            return x;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_find_prng.c\n   Find a PRNG, Tom St Denis\n */\n\n/**\n   Find a registered PRNG by name\n   @param name   The name of the PRNG to look for\n   @return >= 0 if found, -1 if not present\n */\nint find_prng(const char *name) {\n    int x;\n\n    LTC_ARGCHK(name != NULL);\n    LTC_MUTEX_LOCK(&ltc_prng_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if ((prng_descriptor[x].name != NULL) && (XSTRCMP(prng_descriptor[x].name, name) == 0)) {\n            LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n            return x;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_prng.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_fsa.c\n   LibTomCrypt FULL SPEED AHEAD!, Tom St Denis\n */\n\n/* format is ltc_mp, cipher_desc, [cipher_desc], NULL, hash_desc, [hash_desc], NULL, prng_desc, [prng_desc], NULL */\nint crypt_fsa(void *mp, ...) {\n    int     err;\n    va_list args;\n    void    *p;\n\n    va_start(args, mp);\n    if (mp != NULL) {\n        XMEMCPY(&ltc_mp, mp, sizeof(ltc_mp));\n    }\n\n    while ((p = va_arg(args, void *)) != NULL) {\n        if ((err = register_cipher(p)) != CRYPT_OK) {\n            va_end(args);\n            return err;\n        }\n    }\n\n    while ((p = va_arg(args, void *)) != NULL) {\n        if ((err = register_hash(p)) != CRYPT_OK) {\n            va_end(args);\n            return err;\n        }\n    }\n\n    while ((p = va_arg(args, void *)) != NULL) {\n        if ((err = register_prng(p)) != CRYPT_OK) {\n            va_end(args);\n            return err;\n        }\n    }\n\n    va_end(args);\n    return CRYPT_OK;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_fsa.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_hash_descriptor.c\n   Stores the hash descriptor table, Tom St Denis\n */\n\nstruct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = {\n    { NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL }\n};\n\nLTC_MUTEX_GLOBAL(ltc_hash_mutex)\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c,v $ */\n/* $Revision: 1.10 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_hash_is_valid.c\n   Determine if hash is valid, Tom St Denis\n */\n\n/*\n   Test if a hash index is valid\n   @param idx   The index of the hash to search for\n   @return CRYPT_OK if valid\n */\nint hash_is_valid(int idx) {\n    LTC_MUTEX_LOCK(&ltc_hash_mutex);\n    if ((idx < 0) || (idx >= TAB_SIZE) || (hash_descriptor[idx].name == NULL)) {\n        LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n        return CRYPT_INVALID_HASH;\n    }\n    LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n    return CRYPT_OK;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\nltc_math_descriptor ltc_mp;\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_prng_descriptor.c\n   Stores the PRNG descriptors, Tom St Denis\n */\nstruct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = {\n    { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }\n};\n\nLTC_MUTEX_GLOBAL(ltc_prng_mutex)\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c,v $ */\n/* $Revision: 1.8 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_prng_is_valid.c\n   Determine if PRNG is valid, Tom St Denis\n */\n\n/*\n   Test if a PRNG index is valid\n   @param idx   The index of the PRNG to search for\n   @return CRYPT_OK if valid\n */\nint prng_is_valid(int idx) {\n    LTC_MUTEX_LOCK(&ltc_prng_mutex);\n    if ((idx < 0) || (idx >= TAB_SIZE) || (prng_descriptor[idx].name == NULL)) {\n        LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n        return CRYPT_INVALID_PRNG;\n    }\n    LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n    return CRYPT_OK;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_register_cipher.c\n   Register a cipher, Tom St Denis\n */\n\n/**\n   Register a cipher with the descriptor table\n   @param cipher   The cipher you wish to register\n   @return value >= 0 if successfully added (or already present), -1 if unsuccessful\n */\nint register_cipher(const struct ltc_cipher_descriptor *cipher) {\n    int x;\n\n    LTC_ARGCHK(cipher != NULL);\n\n    /* is it already registered? */\n    LTC_MUTEX_LOCK(&ltc_cipher_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if ((cipher_descriptor[x].name != NULL) && (cipher_descriptor[x].ID == cipher->ID)) {\n            LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n            return x;\n        }\n    }\n\n    /* find a blank spot */\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (cipher_descriptor[x].name == NULL) {\n            XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor));\n            LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n            return x;\n        }\n    }\n\n    /* no spot */\n    LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_cipher.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_register_hash.c\n   Register a HASH, Tom St Denis\n */\n\n/**\n   Register a hash with the descriptor table\n   @param hash   The hash you wish to register\n   @return value >= 0 if successfully added (or already present), -1 if unsuccessful\n */\nint register_hash(const struct ltc_hash_descriptor *hash) {\n    int x;\n\n    LTC_ARGCHK(hash != NULL);\n\n    /* is it already registered? */\n    LTC_MUTEX_LOCK(&ltc_hash_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {\n            LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n            return x;\n        }\n    }\n\n    /* find a blank spot */\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (hash_descriptor[x].name == NULL) {\n            XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor));\n            LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n            return x;\n        }\n    }\n\n    /* no spot */\n    LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_hash.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_register_prng.c\n   Register a PRNG, Tom St Denis\n */\n\n/**\n   Register a PRNG with the descriptor table\n   @param prng   The PRNG you wish to register\n   @return value >= 0 if successfully added (or already present), -1 if unsuccessful\n */\nint register_prng(const struct ltc_prng_descriptor *prng) {\n    int x;\n\n    LTC_ARGCHK(prng != NULL);\n\n    /* is it already registered? */\n    LTC_MUTEX_LOCK(&ltc_prng_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {\n            LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n            return x;\n        }\n    }\n\n    /* find a blank spot */\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (prng_descriptor[x].name == NULL) {\n            XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor));\n            LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n            return x;\n        }\n    }\n\n    /* no spot */\n    LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n    return -1;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_prng.c,v $ */\n/* $Revision: 1.8 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_unregister_cipher.c\n   Unregister a cipher, Tom St Denis\n */\n\n/**\n   Unregister a cipher from the descriptor table\n   @param cipher   The cipher descriptor to remove\n   @return CRYPT_OK on success\n */\nint unregister_cipher(const struct ltc_cipher_descriptor *cipher) {\n    int x;\n\n    LTC_ARGCHK(cipher != NULL);\n\n    /* is it already registered? */\n    LTC_MUTEX_LOCK(&ltc_cipher_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (XMEMCMP(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) {\n            cipher_descriptor[x].name = NULL;\n            cipher_descriptor[x].ID   = 255;\n            LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n            return CRYPT_OK;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_cipher_mutex);\n    return CRYPT_ERROR;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_unregister_hash.c\n   Unregister a hash, Tom St Denis\n */\n\n/**\n   Unregister a hash from the descriptor table\n   @param hash   The hash descriptor to remove\n   @return CRYPT_OK on success\n */\nint unregister_hash(const struct ltc_hash_descriptor *hash) {\n    int x;\n\n    LTC_ARGCHK(hash != NULL);\n\n    /* is it already registered? */\n    LTC_MUTEX_LOCK(&ltc_hash_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {\n            hash_descriptor[x].name = NULL;\n            LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n            return CRYPT_OK;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_hash_mutex);\n    return CRYPT_ERROR;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file crypt_unregister_prng.c\n   Unregister a PRNG, Tom St Denis\n */\n\n/**\n   Unregister a PRNG from the descriptor table\n   @param prng   The PRNG descriptor to remove\n   @return CRYPT_OK on success\n */\nint unregister_prng(const struct ltc_prng_descriptor *prng) {\n    int x;\n\n    LTC_ARGCHK(prng != NULL);\n\n    /* is it already registered? */\n    LTC_MUTEX_LOCK(&ltc_prng_mutex);\n    for (x = 0; x < TAB_SIZE; x++) {\n        if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) != 0) {\n            prng_descriptor[x].name = NULL;\n            LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n            return CRYPT_OK;\n        }\n    }\n    LTC_MUTEX_UNLOCK(&ltc_prng_mutex);\n    return CRYPT_ERROR;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_bit_string.c\n   ASN.1 DER, encode a BIT STRING, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store a BIT STRING\n   @param in      The DER encoded BIT STRING\n   @param inlen   The size of the DER BIT STRING\n   @param out     [out] The array of bits stored (one per char)\n   @param outlen  [in/out] The number of bits stored\n   @return CRYPT_OK if successful\n */\nint der_decode_bit_string(const unsigned char *in, unsigned long inlen,\n                          unsigned char *out, unsigned long *outlen) {\n    unsigned long dlen, blen, x, y;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* packet must be at least 4 bytes */\n    if (inlen < 4) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* check for 0x03 */\n    if ((in[0] & 0x1F) != 0x03) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* offset in the data */\n    x = 1;\n\n    /* get the length of the data */\n    if (in[x] & 0x80) {\n        /* long format get number of length bytes */\n        y = in[x++] & 0x7F;\n\n        /* invalid if 0 or > 2 */\n        if ((y == 0) || (y > 2)) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* read the data len */\n        dlen = 0;\n        while (y--) {\n            dlen = (dlen << 8) | (unsigned long)in[x++];\n        }\n    } else {\n        /* short format */\n        dlen = in[x++] & 0x7F;\n    }\n\n    /* is the data len too long or too short? */\n    if ((dlen == 0) || (dlen + x > inlen)) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* get padding count */\n    blen = ((dlen - 1) << 3) - (in[x++] & 7);\n\n    /* too many bits? */\n    if (blen > *outlen) {\n        *outlen = blen;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* decode/store the bits */\n    for (y = 0; y < blen; y++) {\n        out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0;\n        if ((y & 7) == 7) {\n            ++x;\n        }\n    }\n\n    /* we done */\n    *outlen = blen;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_boolean.c\n   ASN.1 DER, decode a BOOLEAN, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Read a BOOLEAN\n   @param in      The destination for the DER encoded BOOLEAN\n   @param inlen   The size of the DER BOOLEAN\n   @param out     [out]  The boolean to decode\n   @return CRYPT_OK if successful\n */\nint der_decode_boolean(const unsigned char *in, unsigned long inlen,\n                       int *out) {\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n\n    if ((inlen != 3) || (in[0] != 0x01) || (in[1] != 0x01) || ((in[2] != 0x00) && (in[2] != 0xFF))) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    *out = (in[2] == 0xFF) ? 1 : 0;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c,v $ */\n/* $Revision: 1.2 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_choice.c\n   ASN.1 DER, decode a CHOICE, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Decode a CHOICE\n   @param in       The DER encoded input\n   @param inlen    [in/out] The size of the input and resulting size of read type\n   @param list     The list of items to decode\n   @param outlen   The number of items in the list\n   @return CRYPT_OK on success\n */\nint der_decode_choice(const unsigned char *in, unsigned long *inlen,\n                      ltc_asn1_list *list, unsigned long outlen) {\n    unsigned long size, x, z;\n    void          *data;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(inlen != NULL);\n    LTC_ARGCHK(list != NULL);\n\n    /* get blk size */\n    if (*inlen < 2) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* set all of the \"used\" flags to zero */\n    for (x = 0; x < outlen; x++) {\n        list[x].used = 0;\n    }\n\n    /* now scan until we have a winner */\n    for (x = 0; x < outlen; x++) {\n        size = list[x].size;\n        data = list[x].data;\n\n        switch (list[x].type) {\n            case LTC_ASN1_INTEGER:\n                if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {\n                    if (der_length_integer(data, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n            case LTC_ASN1_SHORT_INTEGER:\n                if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {\n                    if (der_length_short_integer(size, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n            case LTC_ASN1_BIT_STRING:\n                if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {\n                    if (der_length_bit_string(size, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        list[x].size = size;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n            case LTC_ASN1_OCTET_STRING:\n                if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {\n                    if (der_length_octet_string(size, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        list[x].size = size;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n            case LTC_ASN1_NULL:\n                if ((*inlen == 2) && (in[x] == 0x05) && (in[x + 1] == 0x00)) {\n                    *inlen       = 2;\n                    list[x].used = 1;\n                    return CRYPT_OK;\n                }\n                break;\n\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n                if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {\n                    if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        list[x].size = size;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n            case LTC_ASN1_IA5_STRING:\n                if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {\n                    if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        list[x].size = size;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n\n            case LTC_ASN1_PRINTABLE_STRING:\n                if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {\n                    if (der_length_printable_string(data, size, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        list[x].size = size;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n            case LTC_ASN1_UTF8_STRING:\n                if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) {\n                    if (der_length_utf8_string(data, size, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        list[x].size = size;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n            case LTC_ASN1_UTCTIME:\n                z = *inlen;\n                if (der_decode_utctime(in, &z, data) == CRYPT_OK) {\n                    list[x].used = 1;\n                    *inlen       = z;\n                    return CRYPT_OK;\n                }\n                break;\n\n            case LTC_ASN1_SET:\n            case LTC_ASN1_SETOF:\n            case LTC_ASN1_SEQUENCE:\n                if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {\n                    if (der_length_sequence(data, size, &z) == CRYPT_OK) {\n                        list[x].used = 1;\n                        *inlen       = z;\n                        return CRYPT_OK;\n                    }\n                }\n                break;\n\n            default:\n                return CRYPT_INVALID_ARG;\n        }\n    }\n\n    return CRYPT_INVALID_PACKET;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */\n/* $Revision: 1.9 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_ia5_string.c\n   ASN.1 DER, encode a IA5 STRING, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store a IA5 STRING\n   @param in      The DER encoded IA5 STRING\n   @param inlen   The size of the DER IA5 STRING\n   @param out     [out] The array of octets stored (one per char)\n   @param outlen  [in/out] The number of octets stored\n   @return CRYPT_OK if successful\n */\nint der_decode_ia5_string(const unsigned char *in, unsigned long inlen,\n                          unsigned char *out, unsigned long *outlen) {\n    unsigned long x, y, len;\n    int           t;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* must have header at least */\n    if (inlen < 2) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* check for 0x16 */\n    if ((in[0] & 0x1F) != 0x16) {\n        return CRYPT_INVALID_PACKET;\n    }\n    x = 1;\n\n    /* decode the length */\n    if (in[x] & 0x80) {\n        /* valid # of bytes in length are 1,2,3 */\n        y = in[x] & 0x7F;\n        if ((y == 0) || (y > 3) || ((x + y) > inlen)) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* read the length in */\n        len = 0;\n        ++x;\n        while (y--) {\n            len = (len << 8) | in[x++];\n        }\n    } else {\n        len = in[x++] & 0x7F;\n    }\n\n    /* is it too long? */\n    if (len > *outlen) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    if (len + x > inlen) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* read the data */\n    for (y = 0; y < len; y++) {\n        t = der_ia5_value_decode(in[x++]);\n        if (t == -1) {\n            return CRYPT_INVALID_ARG;\n        }\n        out[y] = t;\n    }\n\n    *outlen = y;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c,v $ */\n/* $Revision: 1.4 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_integer.c\n   ASN.1 DER, decode an integer, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Read a mp_int integer\n   @param in       The DER encoded data\n   @param inlen    Size of DER encoded data\n   @param num      The first mp_int to decode\n   @return CRYPT_OK if successful\n */\nint der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) {\n    unsigned long x, y, z;\n    int           err;\n\n    LTC_ARGCHK(num != NULL);\n    LTC_ARGCHK(in != NULL);\n\n    /* min DER INTEGER is 0x02 01 00 == 0 */\n    if (inlen < (1 + 1 + 1)) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* ok expect 0x02 when we AND with 0001 1111 [1F] */\n    x = 0;\n    if ((in[x++] & 0x1F) != 0x02) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* now decode the len stuff */\n    z = in[x++];\n\n    if ((z & 0x80) == 0x00) {\n        /* short form */\n\n        /* will it overflow? */\n        if (x + z > inlen) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* no so read it */\n        if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {\n            return err;\n        }\n    } else {\n        /* long form */\n        z &= 0x7F;\n\n        /* will number of length bytes overflow? (or > 4) */\n        if (((x + z) > inlen) || (z > 4) || (z == 0)) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* now read it in */\n        y = 0;\n        while (z--) {\n            y = ((unsigned long)(in[x++])) | (y << 8);\n        }\n\n        /* now will reading y bytes overrun? */\n        if ((x + y) > inlen) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* no so read it */\n        if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {\n            return err;\n        }\n    }\n\n    /* see if it's negative */\n    if (in[x] & 0x80) {\n        void *tmp;\n        if (mp_init(&tmp) != CRYPT_OK) {\n            return CRYPT_MEM;\n        }\n\n        if ((mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK) || (mp_sub(num, tmp, num) != CRYPT_OK)) {\n            mp_clear(tmp);\n            return CRYPT_MEM;\n        }\n        mp_clear(tmp);\n    }\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_object_identifier.c\n   ASN.1 DER, Decode Object Identifier, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Decode OID data and store the array of integers in words\n   @param in      The OID DER encoded data\n   @param inlen   The length of the OID data\n   @param words   [out] The destination of the OID words\n   @param outlen  [in/out] The number of OID words\n   @return CRYPT_OK if successful\n */\nint der_decode_object_identifier(const unsigned char *in, unsigned long inlen,\n                                 unsigned long *words, unsigned long *outlen) {\n    unsigned long x, y, t, len;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(words != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* header is at least 3 bytes */\n    if (inlen < 3) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* must be room for at least two words */\n    if (*outlen < 2) {\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* decode the packet header */\n    x = 0;\n    if ((in[x++] & 0x1F) != 0x06) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* get the length */\n    if (in[x] < 128) {\n        len = in[x++];\n    } else {\n        if ((in[x] < 0x81) || (in[x] > 0x82)) {\n            return CRYPT_INVALID_PACKET;\n        }\n        y   = in[x++] & 0x7F;\n        len = 0;\n        while (y--) {\n            len = (len << 8) | (unsigned long)in[x++];\n        }\n    }\n\n    if ((len < 1) || ((len + x) > inlen)) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* decode words */\n    y = 0;\n    t = 0;\n    while (len--) {\n        t = (t << 7) | (in[x] & 0x7F);\n        if (!(in[x++] & 0x80)) {\n            /* store t */\n            if (y >= *outlen) {\n                return CRYPT_BUFFER_OVERFLOW;\n            }\n            if (y == 0) {\n                words[0] = t / 40;\n                words[1] = t % 40;\n                y        = 2;\n            } else {\n                words[y++] = t;\n            }\n            t = 0;\n        }\n    }\n\n    *outlen = y;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_octet_string.c\n   ASN.1 DER, encode a OCTET STRING, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store a OCTET STRING\n   @param in      The DER encoded OCTET STRING\n   @param inlen   The size of the DER OCTET STRING\n   @param out     [out] The array of octets stored (one per char)\n   @param outlen  [in/out] The number of octets stored\n   @return CRYPT_OK if successful\n */\nint der_decode_octet_string(const unsigned char *in, unsigned long inlen,\n                            unsigned char *out, unsigned long *outlen) {\n    unsigned long x, y, len;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* must have header at least */\n    if (inlen < 2) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* check for 0x04 */\n    if ((in[0] & 0x1F) != 0x04) {\n        return CRYPT_INVALID_PACKET;\n    }\n    x = 1;\n\n    /* decode the length */\n    if (in[x] & 0x80) {\n        /* valid # of bytes in length are 1,2,3 */\n        y = in[x] & 0x7F;\n        if ((y == 0) || (y > 3) || ((x + y) > inlen)) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* read the length in */\n        len = 0;\n        ++x;\n        while (y--) {\n            len = (len << 8) | in[x++];\n        }\n    } else {\n        len = in[x++] & 0x7F;\n    }\n\n    /* is it too long? */\n    if (len > *outlen) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    if (len + x > inlen) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* read the data */\n    for (y = 0; y < len; y++) {\n        out[y] = in[x++];\n    }\n\n    *outlen = y;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c,v $ */\n/* $Revision: 1.4 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_printable_string.c\n   ASN.1 DER, encode a printable STRING, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store a printable STRING\n   @param in      The DER encoded printable STRING\n   @param inlen   The size of the DER printable STRING\n   @param out     [out] The array of octets stored (one per char)\n   @param outlen  [in/out] The number of octets stored\n   @return CRYPT_OK if successful\n */\nint der_decode_printable_string(const unsigned char *in, unsigned long inlen,\n                                unsigned char *out, unsigned long *outlen) {\n    unsigned long x, y, len;\n    int           t;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* must have header at least */\n    if (inlen < 2) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* check for 0x13 */\n    if ((in[0] & 0x1F) != 0x13) {\n        return CRYPT_INVALID_PACKET;\n    }\n    x = 1;\n\n    /* decode the length */\n    if (in[x] & 0x80) {\n        /* valid # of bytes in length are 1,2,3 */\n        y = in[x] & 0x7F;\n        if ((y == 0) || (y > 3) || ((x + y) > inlen)) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* read the length in */\n        len = 0;\n        ++x;\n        while (y--) {\n            len = (len << 8) | in[x++];\n        }\n    } else {\n        len = in[x++] & 0x7F;\n    }\n\n    /* is it too long? */\n    if (len > *outlen) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    if (len + x > inlen) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* read the data */\n    for (y = 0; y < len; y++) {\n        t = der_printable_value_decode(in[x++]);\n        if (t == -1) {\n            return CRYPT_INVALID_ARG;\n        }\n        out[y] = t;\n    }\n\n    *outlen = y;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c,v $ */\n/* $Revision: 1.4 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n\n/**\n   @file der_decode_sequence_ex.c\n   ASN.1 DER, decode a SEQUENCE, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Decode a SEQUENCE\n   @param in       The DER encoded input\n   @param inlen    The size of the input\n   @param list     The list of items to decode\n   @param outlen   The number of items in the list\n   @param ordered  Search an unordeded or ordered list\n   @return CRYPT_OK on success\n */\nint der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,\n                           ltc_asn1_list *list, unsigned long outlen, int ordered) {\n    int           err, type;\n    unsigned long size, x, y, z, i, blksize;\n    void          *data;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(list != NULL);\n\n    /* get blk size */\n    if (inlen < 2) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */\n    x = 0;\n    if ((in[x] != 0x30) && (in[x] != 0x31)) {\n        return CRYPT_INVALID_PACKET;\n    }\n    ++x;\n\n    if (in[x] < 128) {\n        blksize = in[x++];\n    } else if (in[x] & 0x80) {\n        if ((in[x] < 0x81) || (in[x] > 0x83)) {\n            return CRYPT_INVALID_PACKET;\n        }\n        y = in[x++] & 0x7F;\n\n        /* would reading the len bytes overrun? */\n        if (x + y > inlen) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* read len */\n        blksize = 0;\n        while (y--) {\n            blksize = (blksize << 8) | (unsigned long)in[x++];\n        }\n    }\n\n    /* would this blksize overflow? */\n    if (x + blksize > inlen) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* mark all as unused */\n    for (i = 0; i < outlen; i++) {\n        list[i].used = 0;\n    }\n\n    /* ok read data */\n    inlen = blksize;\n    for (i = 0; i < outlen; i++) {\n        z    = 0;\n        type = list[i].type;\n        size = list[i].size;\n        data = list[i].data;\n        if (!ordered && (list[i].used == 1)) {\n            continue;\n        }\n\n        if (type == LTC_ASN1_EOL) {\n            break;\n        }\n\n        switch (type) {\n            case LTC_ASN1_BOOLEAN:\n                z = inlen;\n                if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                if ((err = der_length_boolean(&z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_INTEGER:\n                z = inlen;\n                if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                if ((err = der_length_integer(data, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_SHORT_INTEGER:\n                z = inlen;\n                if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                if ((err = der_length_short_integer(((unsigned long *)data)[0], &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n\n                break;\n\n            case LTC_ASN1_BIT_STRING:\n                z = inlen;\n                if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                list[i].size = size;\n                if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_OCTET_STRING:\n                z = inlen;\n                if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                list[i].size = size;\n                if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_NULL:\n                if ((inlen < 2) || (in[x] != 0x05) || (in[x + 1] != 0x00)) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    err = CRYPT_INVALID_PACKET;\n                    goto LBL_ERR;\n                }\n                z = 2;\n                break;\n\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n                z = inlen;\n                if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                list[i].size = size;\n                if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_IA5_STRING:\n                z = inlen;\n                if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                list[i].size = size;\n                if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n\n            case LTC_ASN1_PRINTABLE_STRING:\n                z = inlen;\n                if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                list[i].size = size;\n                if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_UTF8_STRING:\n                z = inlen;\n                if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                list[i].size = size;\n                if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_UTCTIME:\n                z = inlen;\n                if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_SET:\n                z = inlen;\n                if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n            case LTC_ASN1_SETOF:\n            case LTC_ASN1_SEQUENCE:\n                /* detect if we have the right type */\n                if (((type == LTC_ASN1_SETOF) && ((in[x] & 0x3F) != 0x31)) || ((type == LTC_ASN1_SEQUENCE) && ((in[x] & 0x3F) != 0x30))) {\n                    err = CRYPT_INVALID_PACKET;\n                    goto LBL_ERR;\n                }\n\n                z = inlen;\n                if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                break;\n\n\n            case LTC_ASN1_CHOICE:\n                z = inlen;\n                if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {\n                    if (!ordered) {\n                        continue;\n                    }\n                    goto LBL_ERR;\n                }\n                break;\n\n            default:\n                err = CRYPT_INVALID_ARG;\n                goto LBL_ERR;\n        }\n        x           += z;\n        inlen       -= z;\n        list[i].used = 1;\n        if (!ordered) {\n            /* restart the decoder */\n            i = -1;\n        }\n    }\n\n    for (i = 0; i < outlen; i++) {\n        if (list[i].used == 0) {\n            err = CRYPT_INVALID_PACKET;\n            goto LBL_ERR;\n        }\n    }\n    err = CRYPT_OK;\n\nLBL_ERR:\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c,v $ */\n/* $Revision: 1.16 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_sequence_flexi.c\n   ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis\n */\n\n#ifdef LTC_DER\n\nstatic unsigned long fetch_length(const unsigned char *in, unsigned long inlen) {\n    unsigned long x, y, z;\n\n    y = 0;\n\n    /* skip type and read len */\n    if (inlen < 2) {\n        return 0xFFFFFFFF;\n    }\n    ++in;\n    ++y;\n\n    /* read len */\n    x = *in++;\n    ++y;\n\n    /* <128 means literal */\n    if (x < 128) {\n        return x + y;\n    }\n    x     &= 0x7F; /* the lower 7 bits are the length of the length */\n    inlen -= 2;\n\n    /* len means len of len! */\n    if ((x == 0) || (x > 4) || (x > inlen)) {\n        return 0xFFFFFFFF;\n    }\n\n    y += x;\n    z  = 0;\n    while (x--) {\n        z = (z << 8) | ((unsigned long)*in);\n        ++in;\n    }\n    return z + y;\n}\n\n/**\n   ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.\n   @param in      The input buffer\n   @param inlen   [in/out] The length of the input buffer and on output the amount of decoded data\n   @param out     [out] A pointer to the linked list\n   @return CRYPT_OK on success.\n */\nint der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out) {\n    ltc_asn1_list *l;\n    unsigned long err, type, len, totlen, x, y;\n    void          *realloc_tmp;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(inlen != NULL);\n    LTC_ARGCHK(out != NULL);\n\n    l      = NULL;\n    totlen = 0;\n\n    /* scan the input and and get lengths and what not */\n    while (*inlen) {\n        /* read the type byte */\n        type = *in;\n\n        /* fetch length */\n        len = fetch_length(in, *inlen);\n        if (len > *inlen) {\n            err = CRYPT_INVALID_PACKET;\n            goto error;\n        }\n\n        /* alloc new link */\n        if (l == NULL) {\n            l = XCALLOC(1, sizeof(*l));\n            if (l == NULL) {\n                err = CRYPT_MEM;\n                goto error;\n            }\n        } else {\n            l->next = XCALLOC(1, sizeof(*l));\n            if (l->next == NULL) {\n                err = CRYPT_MEM;\n                goto error;\n            }\n            l->next->prev = l;\n            l             = l->next;\n        }\n\n        /* now switch on type */\n        switch (type) {\n            case 0x01: /* BOOLEAN */\n                l->type = LTC_ASN1_BOOLEAN;\n                l->size = 1;\n                l->data = XCALLOC(1, sizeof(int));\n\n                if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                if ((err = der_length_boolean(&len)) != CRYPT_OK) {\n                    goto error;\n                }\n                break;\n\n            case 0x02: /* INTEGER */\n                /* init field */\n                l->type = LTC_ASN1_INTEGER;\n                l->size = 1;\n                if ((err = mp_init(&l->data)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                /* decode field */\n                if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                /* calc length of object */\n                if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) {\n                    goto error;\n                }\n                break;\n\n            case 0x03: /* BIT */\n                /* init field */\n                l->type = LTC_ASN1_BIT_STRING;\n                l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char.  */\n\n                if ((l->data = XCALLOC(1, l->size)) == NULL) {\n                    err = CRYPT_MEM;\n                    goto error;\n                }\n\n                if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {\n                    goto error;\n                }\n                break;\n\n            case 0x04: /* OCTET */\n\n                /* init field */\n                l->type = LTC_ASN1_OCTET_STRING;\n                l->size = len;\n\n                if ((l->data = XCALLOC(1, l->size)) == NULL) {\n                    err = CRYPT_MEM;\n                    goto error;\n                }\n\n                if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {\n                    goto error;\n                }\n                break;\n\n            case 0x05: /* NULL */\n\n                /* valid NULL is 0x05 0x00 */\n                if ((in[0] != 0x05) || (in[1] != 0x00)) {\n                    err = CRYPT_INVALID_PACKET;\n                    goto error;\n                }\n\n                /* simple to store ;-) */\n                l->type = LTC_ASN1_NULL;\n                l->data = NULL;\n                l->size = 0;\n                len     = 2;\n\n                break;\n\n            case 0x06: /* OID */\n\n                /* init field */\n                l->type = LTC_ASN1_OBJECT_IDENTIFIER;\n                l->size = len;\n\n                if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {\n                    err = CRYPT_MEM;\n                    goto error;\n                }\n\n                if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                /* resize it to save a bunch of mem */\n                if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) {\n                    /* out of heap but this is not an error */\n                    break;\n                }\n                l->data = realloc_tmp;\n                break;\n\n            case 0x0C: /* UTF8 */\n\n                /* init field */\n                l->type = LTC_ASN1_UTF8_STRING;\n                l->size = len;\n\n                if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {\n                    err = CRYPT_MEM;\n                    goto error;\n                }\n\n                if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) {\n                    goto error;\n                }\n                break;\n\n            case 0x13: /* PRINTABLE */\n\n                /* init field */\n                l->type = LTC_ASN1_PRINTABLE_STRING;\n                l->size = len;\n\n                if ((l->data = XCALLOC(1, l->size)) == NULL) {\n                    err = CRYPT_MEM;\n                    goto error;\n                }\n\n                if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) {\n                    goto error;\n                }\n                break;\n\n            case 0x16: /* IA5 */\n\n                /* init field */\n                l->type = LTC_ASN1_IA5_STRING;\n                l->size = len;\n\n                if ((l->data = XCALLOC(1, l->size)) == NULL) {\n                    err = CRYPT_MEM;\n                    goto error;\n                }\n\n                if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) {\n                    goto error;\n                }\n                break;\n\n            case 0x17: /* UTC TIME */\n\n                /* init field */\n                l->type = LTC_ASN1_UTCTIME;\n                l->size = 1;\n\n                if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {\n                    err = CRYPT_MEM;\n                    goto error;\n                }\n\n                len = *inlen;\n                if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) {\n                    goto error;\n                }\n\n                if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) {\n                    goto error;\n                }\n                break;\n\n            case 0x30: /* SEQUENCE */\n            case 0x31: /* SET */\n\n                /* init field */\n                l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET;\n\n                /* we have to decode the SEQUENCE header and get it's length */\n\n                /* move past type */\n                ++in;\n                --(*inlen);\n\n                /* read length byte */\n                x = *in++;\n                --(*inlen);\n\n                /* smallest SEQUENCE/SET header */\n                y = 2;\n\n                /* now if it's > 127 the next bytes are the length of the length */\n                if (x > 128) {\n                    x      &= 0x7F;\n                    in     += x;\n                    *inlen -= x;\n\n                    /* update sequence header len */\n                    y += x;\n                }\n\n                /* Sequence elements go as child */\n                len = len - y;\n                if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {\n                    goto error;\n                }\n\n                /* len update */\n                totlen += y;\n\n                /* link them up y0 */\n                l->child->parent = l;\n\n                break;\n\n            default:\n                /* invalid byte ... this is a soft error */\n                /* remove link */\n                l = l->prev;\n                XFREE(l->next);\n                l->next = NULL;\n                goto outside;\n        }\n\n        /* advance pointers */\n        totlen += len;\n        in     += len;\n        *inlen -= len;\n    }\n\noutside:\n\n    /* rewind l please */\n    while (l->prev != NULL || l->parent != NULL) {\n        if (l->parent != NULL) {\n            l = l->parent;\n        } else {\n            l = l->prev;\n        }\n    }\n\n    /* return */\n    *out   = l;\n    *inlen = totlen;\n    return CRYPT_OK;\n\nerror:\n    /* free list */\n    der_sequence_free(l);\n\n    return err;\n}\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c,v $ */\n/* $Revision: 1.26 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n\n/**\n   @file der_decode_sequence_multi.c\n   ASN.1 DER, decode a SEQUENCE, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Decode a SEQUENCE type using a VA list\n   @param in    Input buffer\n   @param inlen Length of input in octets\n   @remark <...> is of the form <type, size, data> (int, unsigned long, void*)\n   @return CRYPT_OK on success\n */\nint der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) {\n    int           err, type;\n    unsigned long size, x;\n    void          *data;\n    va_list       args;\n    ltc_asn1_list *list;\n\n    LTC_ARGCHK(in != NULL);\n\n    /* get size of output that will be required */\n    va_start(args, inlen);\n    x = 0;\n    for ( ; ; ) {\n        type = va_arg(args, int);\n        size = va_arg(args, unsigned long);\n        data = va_arg(args, void *);\n\n        if (type == LTC_ASN1_EOL) {\n            break;\n        }\n\n        switch (type) {\n            case LTC_ASN1_BOOLEAN:\n            case LTC_ASN1_INTEGER:\n            case LTC_ASN1_SHORT_INTEGER:\n            case LTC_ASN1_BIT_STRING:\n            case LTC_ASN1_OCTET_STRING:\n            case LTC_ASN1_NULL:\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n            case LTC_ASN1_IA5_STRING:\n            case LTC_ASN1_PRINTABLE_STRING:\n            case LTC_ASN1_UTF8_STRING:\n            case LTC_ASN1_UTCTIME:\n            case LTC_ASN1_SET:\n            case LTC_ASN1_SETOF:\n            case LTC_ASN1_SEQUENCE:\n            case LTC_ASN1_CHOICE:\n                ++x;\n                break;\n\n            default:\n                va_end(args);\n                return CRYPT_INVALID_ARG;\n        }\n    }\n    va_end(args);\n\n    /* allocate structure for x elements */\n    if (x == 0) {\n        return CRYPT_NOP;\n    }\n\n    list = XCALLOC(sizeof(*list), x);\n    if (list == NULL) {\n        return CRYPT_MEM;\n    }\n\n    /* fill in the structure */\n    va_start(args, inlen);\n    x = 0;\n    for ( ; ; ) {\n        type = va_arg(args, int);\n        size = va_arg(args, unsigned long);\n        data = va_arg(args, void *);\n\n        if (type == LTC_ASN1_EOL) {\n            break;\n        }\n\n        switch (type) {\n            case LTC_ASN1_BOOLEAN:\n            case LTC_ASN1_INTEGER:\n            case LTC_ASN1_SHORT_INTEGER:\n            case LTC_ASN1_BIT_STRING:\n            case LTC_ASN1_OCTET_STRING:\n            case LTC_ASN1_NULL:\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n            case LTC_ASN1_IA5_STRING:\n            case LTC_ASN1_PRINTABLE_STRING:\n            case LTC_ASN1_UTF8_STRING:\n            case LTC_ASN1_UTCTIME:\n            case LTC_ASN1_SEQUENCE:\n            case LTC_ASN1_SET:\n            case LTC_ASN1_SETOF:\n            case LTC_ASN1_CHOICE:\n                list[x].type   = type;\n                list[x].size   = size;\n                list[x++].data = data;\n                break;\n\n            default:\n                va_end(args);\n                err = CRYPT_INVALID_ARG;\n                goto LBL_ERR;\n        }\n    }\n    va_end(args);\n\n    err = der_decode_sequence(in, inlen, list, x);\nLBL_ERR:\n    XFREE(list);\n    return err;\n}\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c,v $ */\n/* $Revision: 1.13 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_short_integer.c\n   ASN.1 DER, decode an integer, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Read a short integer\n   @param in       The DER encoded data\n   @param inlen    Size of data\n   @param num      [out] The integer to decode\n   @return CRYPT_OK if successful\n */\nint der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num) {\n    unsigned long len, x, y;\n\n    LTC_ARGCHK(num != NULL);\n    LTC_ARGCHK(in != NULL);\n\n    /* check length */\n    if (inlen < 2) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* check header */\n    x = 0;\n    if ((in[x++] & 0x1F) != 0x02) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* get the packet len */\n    len = in[x++];\n\n    if (x + len > inlen) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* read number */\n    y = 0;\n    while (len--) {\n        y = (y << 8) | (unsigned long)in[x++];\n    }\n    *num = y;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_utctime.c\n   ASN.1 DER, decode a  UTCTIME, Tom St Denis\n */\n\n#ifdef LTC_DER\n\nstatic int char_to_int(unsigned char x) {\n    switch (x) {\n        case '0':\n            return 0;\n\n        case '1':\n            return 1;\n\n        case '2':\n            return 2;\n\n        case '3':\n            return 3;\n\n        case '4':\n            return 4;\n\n        case '5':\n            return 5;\n\n        case '6':\n            return 6;\n\n        case '7':\n            return 7;\n\n        case '8':\n            return 8;\n\n        case '9':\n            return 9;\n    }\n    return 100;\n}\n\n #define DECODE_V(y, max)                                   \\\n    y = char_to_int(buf[x]) * 10 + char_to_int(buf[x + 1]); \\\n    if (y >= max) return CRYPT_INVALID_PACKET;              \\\n    x += 2;\n\n/**\n   Decodes a UTC time structure in DER format (reads all 6 valid encoding formats)\n   @param in     Input buffer\n   @param inlen  Length of input buffer in octets\n   @param out    [out] Destination of UTC time structure\n   @return CRYPT_OK   if successful\n */\nint der_decode_utctime(const unsigned char *in, unsigned long *inlen,\n                       ltc_utctime *out) {\n    unsigned char buf[32];\n    unsigned long x;\n    int           y;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(inlen != NULL);\n    LTC_ARGCHK(out != NULL);\n\n    /* check header */\n    if ((*inlen < 2UL) || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* decode the string */\n    for (x = 0; x < in[1]; x++) {\n        y = der_ia5_value_decode(in[x + 2]);\n        if (y == -1) {\n            return CRYPT_INVALID_PACKET;\n        }\n        buf[x] = y;\n    }\n    *inlen = 2 + x;\n\n\n    /* possible encodings are\n       YYMMDDhhmmZ\n       YYMMDDhhmm+hh'mm'\n       YYMMDDhhmm-hh'mm'\n       YYMMDDhhmmssZ\n       YYMMDDhhmmss+hh'mm'\n       YYMMDDhhmmss-hh'mm'\n\n       So let's do a trivial decode upto [including] mm\n     */\n\n    x = 0;\n    DECODE_V(out->YY, 100);\n    DECODE_V(out->MM, 13);\n    DECODE_V(out->DD, 32);\n    DECODE_V(out->hh, 24);\n    DECODE_V(out->mm, 60);\n\n    /* clear timezone and seconds info */\n    out->off_dir = out->off_hh = out->off_mm = out->ss = 0;\n\n    /* now is it Z, +, - or 0-9 */\n    if (buf[x] == 'Z') {\n        return CRYPT_OK;\n    } else if ((buf[x] == '+') || (buf[x] == '-')) {\n        out->off_dir = (buf[x++] == '+') ? 0 : 1;\n        DECODE_V(out->off_hh, 24);\n        DECODE_V(out->off_mm, 60);\n        return CRYPT_OK;\n    }\n\n    /* decode seconds */\n    DECODE_V(out->ss, 60);\n\n    /* now is it Z, +, - */\n    if (buf[x] == 'Z') {\n        return CRYPT_OK;\n    } else if ((buf[x] == '+') || (buf[x] == '-')) {\n        out->off_dir = (buf[x++] == '+') ? 0 : 1;\n        DECODE_V(out->off_hh, 24);\n        DECODE_V(out->off_mm, 60);\n        return CRYPT_OK;\n    } else {\n        return CRYPT_INVALID_PACKET;\n    }\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c,v $ */\n/* $Revision: 1.9 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_decode_utf8_string.c\n   ASN.1 DER, encode a UTF8 STRING, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store a UTF8 STRING\n   @param in      The DER encoded UTF8 STRING\n   @param inlen   The size of the DER UTF8 STRING\n   @param out     [out] The array of utf8s stored (one per char)\n   @param outlen  [in/out] The number of utf8s stored\n   @return CRYPT_OK if successful\n */\nint der_decode_utf8_string(const unsigned char *in, unsigned long inlen,\n                           wchar_t *out, unsigned long *outlen) {\n    wchar_t       tmp;\n    unsigned long x, y, z, len;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* must have header at least */\n    if (inlen < 2) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* check for 0x0C */\n    if ((in[0] & 0x1F) != 0x0C) {\n        return CRYPT_INVALID_PACKET;\n    }\n    x = 1;\n\n    /* decode the length */\n    if (in[x] & 0x80) {\n        /* valid # of bytes in length are 1,2,3 */\n        y = in[x] & 0x7F;\n        if ((y == 0) || (y > 3) || ((x + y) > inlen)) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* read the length in */\n        len = 0;\n        ++x;\n        while (y--) {\n            len = (len << 8) | in[x++];\n        }\n    } else {\n        len = in[x++] & 0x7F;\n    }\n\n    if (len + x > inlen) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* proceed to decode */\n    for (y = 0; x < inlen; ) {\n        /* get first byte */\n        tmp = in[x++];\n\n        /* count number of bytes */\n        for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF);\n\n        if ((z > 4) || (x + (z - 1) > inlen)) {\n            return CRYPT_INVALID_PACKET;\n        }\n\n        /* decode, grab upper bits */\n        tmp >>= z;\n\n        /* grab remaining bytes */\n        if (z > 1) {\n            --z;\n        }\n        while (z-- != 0) {\n            if ((in[x] & 0xC0) != 0x80) {\n                return CRYPT_INVALID_PACKET;\n            }\n            tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);\n        }\n\n        if (y > *outlen) {\n            *outlen = y;\n            return CRYPT_BUFFER_OVERFLOW;\n        }\n        out[y++] = tmp;\n    }\n    *outlen = y;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c,v $ */\n/* $Revision: 1.8 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_bit_string.c\n   ASN.1 DER, encode a BIT STRING, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store a BIT STRING\n   @param in       The array of bits to store (one per char)\n   @param inlen    The number of bits tostore\n   @param out      [out] The destination for the DER encoded BIT STRING\n   @param outlen   [in/out] The max size and resulting size of the DER BIT STRING\n   @return CRYPT_OK if successful\n */\nint der_encode_bit_string(const unsigned char *in, unsigned long inlen,\n                          unsigned char *out, unsigned long *outlen) {\n    unsigned long len, x, y;\n    unsigned char buf;\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* avoid overflows */\n    if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (len > *outlen) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* store header (include bit padding count in length) */\n    x = 0;\n    y = (inlen >> 3) + ((inlen & 7) ? 1 : 0) + 1;\n\n    out[x++] = 0x03;\n    if (y < 128) {\n        out[x++] = (unsigned char)y;\n    } else if (y < 256) {\n        out[x++] = 0x81;\n        out[x++] = (unsigned char)y;\n    } else if (y < 65536) {\n        out[x++] = 0x82;\n        out[x++] = (unsigned char)((y >> 8) & 255);\n        out[x++] = (unsigned char)(y & 255);\n    }\n\n    /* store number of zero padding bits */\n    out[x++] = (unsigned char)((8 - inlen) & 7);\n\n    /* store the bits in big endian format */\n    for (y = buf = 0; y < inlen; y++) {\n        buf |= (in[y] ? 1 : 0) << (7 - (y & 7));\n        if ((y & 7) == 7) {\n            out[x++] = buf;\n            buf      = 0;\n        }\n    }\n    /* store last byte */\n    if (inlen & 7) {\n        out[x++] = buf;\n    }\n    *outlen = x;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_boolean.c\n   ASN.1 DER, encode a BOOLEAN, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store a BOOLEAN\n   @param in       The boolean to encode\n   @param out      [out] The destination for the DER encoded BOOLEAN\n   @param outlen   [in/out] The max size and resulting size of the DER BOOLEAN\n   @return CRYPT_OK if successful\n */\nint der_encode_boolean(int in,\n                       unsigned char *out, unsigned long *outlen) {\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(out != NULL);\n\n    if (*outlen < 3) {\n        *outlen = 3;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    *outlen = 3;\n    out[0]  = 0x01;\n    out[1]  = 0x01;\n    out[2]  = in ? 0xFF : 0x00;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c,v $ */\n/* $Revision: 1.4 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_ia5_string.c\n   ASN.1 DER, encode a IA5 STRING, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Store an IA5 STRING\n   @param in       The array of IA5 to store (one per char)\n   @param inlen    The number of IA5 to store\n   @param out      [out] The destination for the DER encoded IA5 STRING\n   @param outlen   [in/out] The max size and resulting size of the DER IA5 STRING\n   @return CRYPT_OK if successful\n */\nint der_encode_ia5_string(const unsigned char *in, unsigned long inlen,\n                          unsigned char *out, unsigned long *outlen) {\n    unsigned long x, y, len;\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* get the size */\n    if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* too big? */\n    if (len > *outlen) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* encode the header+len */\n    x        = 0;\n    out[x++] = 0x16;\n    if (inlen < 128) {\n        out[x++] = (unsigned char)inlen;\n    } else if (inlen < 256) {\n        out[x++] = 0x81;\n        out[x++] = (unsigned char)inlen;\n    } else if (inlen < 65536UL) {\n        out[x++] = 0x82;\n        out[x++] = (unsigned char)((inlen >> 8) & 255);\n        out[x++] = (unsigned char)(inlen & 255);\n    } else if (inlen < 16777216UL) {\n        out[x++] = 0x83;\n        out[x++] = (unsigned char)((inlen >> 16) & 255);\n        out[x++] = (unsigned char)((inlen >> 8) & 255);\n        out[x++] = (unsigned char)(inlen & 255);\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* store octets */\n    for (y = 0; y < inlen; y++) {\n        out[x++] = der_ia5_char_encode(in[y]);\n    }\n\n    /* retun length */\n    *outlen = x;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_integer.c\n   ASN.1 DER, encode an integer, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */\n\n/**\n   Store a mp_int integer\n   @param num      The first mp_int to encode\n   @param out      [out] The destination for the DER encoded integers\n   @param outlen   [in/out] The max size and resulting size of the DER encoded integers\n   @return CRYPT_OK if successful\n */\nint der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) {\n    unsigned long tmplen, y;\n    int           err, leading_zero;\n\n    LTC_ARGCHK(num != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* find out how big this will be */\n    if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (*outlen < tmplen) {\n        *outlen = tmplen;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    if (mp_cmp_d(num, 0) != LTC_MP_LT) {\n        /* we only need a leading zero if the msb of the first byte is one */\n        if (((mp_count_bits(num) & 7) == 0) || (mp_iszero(num) == LTC_MP_YES)) {\n            leading_zero = 1;\n        } else {\n            leading_zero = 0;\n        }\n\n        /* get length of num in bytes (plus 1 since we force the msbyte to zero) */\n        y = mp_unsigned_bin_size(num) + leading_zero;\n    } else {\n        leading_zero = 0;\n        y            = mp_count_bits(num);\n        y            = y + (8 - (y & 7));\n        y            = y >> 3;\n        if (((mp_cnt_lsb(num) + 1) == mp_count_bits(num)) && ((mp_count_bits(num) & 7) == 0)) --y;\n    }\n\n    /* now store initial data */\n    *out++ = 0x02;\n    if (y < 128) {\n        /* short form */\n        *out++ = (unsigned char)y;\n    } else if (y < 256) {\n        *out++ = 0x81;\n        *out++ = (unsigned char)y;\n    } else if (y < 65536UL) {\n        *out++ = 0x82;\n        *out++ = (unsigned char)((y >> 8) & 255);\n        *out++ = (unsigned char)y;\n    } else if (y < 16777216UL) {\n        *out++ = 0x83;\n        *out++ = (unsigned char)((y >> 16) & 255);\n        *out++ = (unsigned char)((y >> 8) & 255);\n        *out++ = (unsigned char)y;\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* now store msbyte of zero if num is non-zero */\n    if (leading_zero) {\n        *out++ = 0x00;\n    }\n\n    /* if it's not zero store it as big endian */\n    if (mp_cmp_d(num, 0) == LTC_MP_GT) {\n        /* now store the mpint */\n        if ((err = mp_to_unsigned_bin(num, out)) != CRYPT_OK) {\n            return err;\n        }\n    } else if (mp_iszero(num) != LTC_MP_YES) {\n        void *tmp;\n\n        /* negative */\n        if (mp_init(&tmp) != CRYPT_OK) {\n            return CRYPT_MEM;\n        }\n\n        /* 2^roundup and subtract */\n        y = mp_count_bits(num);\n        y = y + (8 - (y & 7));\n        if (((mp_cnt_lsb(num) + 1) == mp_count_bits(num)) && ((mp_count_bits(num) & 7) == 0)) y -= 8;\n        if ((mp_2expt(tmp, y) != CRYPT_OK) || (mp_add(tmp, num, tmp) != CRYPT_OK)) {\n            mp_clear(tmp);\n            return CRYPT_MEM;\n        }\n        if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) {\n            mp_clear(tmp);\n            return err;\n        }\n        mp_clear(tmp);\n    }\n\n    /* we good */\n    *outlen = tmplen;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c,v $ */\n/* $Revision: 1.9 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_object_identifier.c\n   ASN.1 DER, Encode Object Identifier, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Encode an OID\n   @param words   The words to encode  (upto 32-bits each)\n   @param nwords  The number of words in the OID\n   @param out     [out] Destination of OID data\n   @param outlen  [in/out] The max and resulting size of the OID\n   @return CRYPT_OK if successful\n */\nint der_encode_object_identifier(unsigned long *words, unsigned long nwords,\n                                 unsigned char *out, unsigned long *outlen) {\n    unsigned long i, x, y, z, t, mask, wordbuf;\n    int           err;\n\n    LTC_ARGCHK(words != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* check length */\n    if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) {\n        return err;\n    }\n    if (x > *outlen) {\n        *outlen = x;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* compute length to store OID data */\n    z       = 0;\n    wordbuf = words[0] * 40 + words[1];\n    for (y = 1; y < nwords; y++) {\n        t  = der_object_identifier_bits(wordbuf);\n        z += t / 7 + ((t % 7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);\n        if (y < nwords - 1) {\n            wordbuf = words[y + 1];\n        }\n    }\n\n    /* store header + length */\n    x        = 0;\n    out[x++] = 0x06;\n    if (z < 128) {\n        out[x++] = (unsigned char)z;\n    } else if (z < 256) {\n        out[x++] = 0x81;\n        out[x++] = (unsigned char)z;\n    } else if (z < 65536UL) {\n        out[x++] = 0x82;\n        out[x++] = (unsigned char)((z >> 8) & 255);\n        out[x++] = (unsigned char)(z & 255);\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* store first byte */\n    wordbuf = words[0] * 40 + words[1];\n    for (i = 1; i < nwords; i++) {\n        /* store 7 bit words in little endian */\n        t = wordbuf & 0xFFFFFFFF;\n        if (t) {\n            y    = x;\n            mask = 0;\n            while (t) {\n                out[x++] = (unsigned char)((t & 0x7F) | mask);\n                t      >>= 7;\n                mask    |= 0x80; /* upper bit is set on all but the last byte */\n            }\n            /* now swap bytes y...x-1 */\n            z = x - 1;\n            while (y < z) {\n                t      = out[y];\n                out[y] = out[z];\n                out[z] = (unsigned char)t;\n                ++y;\n                --z;\n            }\n        } else {\n            /* zero word */\n            out[x++] = 0x00;\n        }\n\n        if (i < nwords - 1) {\n            wordbuf = words[i + 1];\n        }\n    }\n\n    *outlen = x;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_octet_string.c\n   ASN.1 DER, encode a OCTET STRING, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store an OCTET STRING\n   @param in       The array of OCTETS to store (one per char)\n   @param inlen    The number of OCTETS to store\n   @param out      [out] The destination for the DER encoded OCTET STRING\n   @param outlen   [in/out] The max size and resulting size of the DER OCTET STRING\n   @return CRYPT_OK if successful\n */\nint der_encode_octet_string(const unsigned char *in, unsigned long inlen,\n                            unsigned char *out, unsigned long *outlen) {\n    unsigned long x, y, len;\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* get the size */\n    if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* too big? */\n    if (len > *outlen) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* encode the header+len */\n    x        = 0;\n    out[x++] = 0x04;\n    if (inlen < 128) {\n        out[x++] = (unsigned char)inlen;\n    } else if (inlen < 256) {\n        out[x++] = 0x81;\n        out[x++] = (unsigned char)inlen;\n    } else if (inlen < 65536UL) {\n        out[x++] = 0x82;\n        out[x++] = (unsigned char)((inlen >> 8) & 255);\n        out[x++] = (unsigned char)(inlen & 255);\n    } else if (inlen < 16777216UL) {\n        out[x++] = 0x83;\n        out[x++] = (unsigned char)((inlen >> 16) & 255);\n        out[x++] = (unsigned char)((inlen >> 8) & 255);\n        out[x++] = (unsigned char)(inlen & 255);\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* store octets */\n    for (y = 0; y < inlen; y++) {\n        out[x++] = in[y];\n    }\n\n    /* retun length */\n    *outlen = x;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_printable_string.c\n   ASN.1 DER, encode a printable STRING, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Store an printable STRING\n   @param in       The array of printable to store (one per char)\n   @param inlen    The number of printable to store\n   @param out      [out] The destination for the DER encoded printable STRING\n   @param outlen   [in/out] The max size and resulting size of the DER printable STRING\n   @return CRYPT_OK if successful\n */\nint der_encode_printable_string(const unsigned char *in, unsigned long inlen,\n                                unsigned char *out, unsigned long *outlen) {\n    unsigned long x, y, len;\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* get the size */\n    if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* too big? */\n    if (len > *outlen) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* encode the header+len */\n    x        = 0;\n    out[x++] = 0x13;\n    if (inlen < 128) {\n        out[x++] = (unsigned char)inlen;\n    } else if (inlen < 256) {\n        out[x++] = 0x81;\n        out[x++] = (unsigned char)inlen;\n    } else if (inlen < 65536UL) {\n        out[x++] = 0x82;\n        out[x++] = (unsigned char)((inlen >> 8) & 255);\n        out[x++] = (unsigned char)(inlen & 255);\n    } else if (inlen < 16777216UL) {\n        out[x++] = 0x83;\n        out[x++] = (unsigned char)((inlen >> 16) & 255);\n        out[x++] = (unsigned char)((inlen >> 8) & 255);\n        out[x++] = (unsigned char)(inlen & 255);\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* store octets */\n    for (y = 0; y < inlen; y++) {\n        out[x++] = der_printable_char_encode(in[y]);\n    }\n\n    /* retun length */\n    *outlen = x;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n\n/**\n   @file der_encode_sequence_ex.c\n   ASN.1 DER, encode a SEQUENCE, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Encode a SEQUENCE\n   @param list      The list of items to encode\n   @param inlen     The number of items in the list\n   @param out       [out] The destination\n   @param outlen    [in/out] The size of the output\n   @param type_of   LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF\n   @return CRYPT_OK on success\n */\nint der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,\n                           unsigned char *out, unsigned long *outlen, int type_of) {\n    int           err, type;\n    unsigned long size, x, y, z, i;\n    void          *data;\n\n    LTC_ARGCHK(list != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* get size of output that will be required */\n    y = 0;\n    for (i = 0; i < inlen; i++) {\n        type = list[i].type;\n        size = list[i].size;\n        data = list[i].data;\n\n        if (type == LTC_ASN1_EOL) {\n            break;\n        }\n\n        switch (type) {\n            case LTC_ASN1_BOOLEAN:\n                if ((err = der_length_boolean(&x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_INTEGER:\n                if ((err = der_length_integer(data, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_SHORT_INTEGER:\n                if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_BIT_STRING:\n                if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_OCTET_STRING:\n                if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_NULL:\n                y += 2;\n                break;\n\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n                if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_IA5_STRING:\n                if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_PRINTABLE_STRING:\n                if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_UTF8_STRING:\n                if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_UTCTIME:\n                if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_SET:\n            case LTC_ASN1_SETOF:\n            case LTC_ASN1_SEQUENCE:\n                if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            default:\n                err = CRYPT_INVALID_ARG;\n                goto LBL_ERR;\n        }\n    }\n\n    /* calc header size */\n    z = y;\n    if (y < 128) {\n        y += 2;\n    } else if (y < 256) {\n        /* 0x30 0x81 LL */\n        y += 3;\n    } else if (y < 65536UL) {\n        /* 0x30 0x82 LL LL */\n        y += 4;\n    } else if (y < 16777216UL) {\n        /* 0x30 0x83 LL LL LL */\n        y += 5;\n    } else {\n        err = CRYPT_INVALID_ARG;\n        goto LBL_ERR;\n    }\n\n    /* too big ? */\n    if (*outlen < y) {\n        *outlen = y;\n        err     = CRYPT_BUFFER_OVERFLOW;\n        goto LBL_ERR;\n    }\n\n    /* store header */\n    x        = 0;\n    out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;\n\n    if (z < 128) {\n        out[x++] = (unsigned char)z;\n    } else if (z < 256) {\n        out[x++] = 0x81;\n        out[x++] = (unsigned char)z;\n    } else if (z < 65536UL) {\n        out[x++] = 0x82;\n        out[x++] = (unsigned char)((z >> 8UL) & 255);\n        out[x++] = (unsigned char)(z & 255);\n    } else if (z < 16777216UL) {\n        out[x++] = 0x83;\n        out[x++] = (unsigned char)((z >> 16UL) & 255);\n        out[x++] = (unsigned char)((z >> 8UL) & 255);\n        out[x++] = (unsigned char)(z & 255);\n    }\n\n    /* store data */\n    *outlen -= x;\n    for (i = 0; i < inlen; i++) {\n        type = list[i].type;\n        size = list[i].size;\n        data = list[i].data;\n\n        if (type == LTC_ASN1_EOL) {\n            break;\n        }\n\n        switch (type) {\n            case LTC_ASN1_BOOLEAN:\n                z = *outlen;\n                if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_INTEGER:\n                z = *outlen;\n                if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_SHORT_INTEGER:\n                z = *outlen;\n                if ((err = der_encode_short_integer(*((unsigned long *)data), out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_BIT_STRING:\n                z = *outlen;\n                if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_OCTET_STRING:\n                z = *outlen;\n                if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_NULL:\n                out[x++] = 0x05;\n                out[x++] = 0x00;\n                *outlen -= 2;\n                break;\n\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n                z = *outlen;\n                if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_IA5_STRING:\n                z = *outlen;\n                if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_PRINTABLE_STRING:\n                z = *outlen;\n                if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_UTF8_STRING:\n                z = *outlen;\n                if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_UTCTIME:\n                z = *outlen;\n                if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_SET:\n                z = *outlen;\n                if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_SETOF:\n                z = *outlen;\n                if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            case LTC_ASN1_SEQUENCE:\n                z = *outlen;\n                if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                x       += z;\n                *outlen -= z;\n                break;\n\n            default:\n                err = CRYPT_INVALID_ARG;\n                goto LBL_ERR;\n        }\n    }\n    *outlen = x;\n    err     = CRYPT_OK;\n\nLBL_ERR:\n    return err;\n}\n#endif\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n\n/**\n   @file der_encode_sequence_multi.c\n   ASN.1 DER, encode a SEQUENCE, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Encode a SEQUENCE type using a VA list\n   @param out    [out] Destination for data\n   @param outlen [in/out] Length of buffer and resulting length of output\n   @remark <...> is of the form <type, size, data> (int, unsigned long, void*)\n   @return CRYPT_OK on success\n */\nint der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) {\n    int           err, type;\n    unsigned long size, x;\n    void          *data;\n    va_list       args;\n    ltc_asn1_list *list;\n\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* get size of output that will be required */\n    va_start(args, outlen);\n    x = 0;\n    for ( ; ; ) {\n        type = va_arg(args, int);\n        size = va_arg(args, unsigned long);\n        data = va_arg(args, void *);\n\n        if (type == LTC_ASN1_EOL) {\n            break;\n        }\n\n        switch (type) {\n            case LTC_ASN1_BOOLEAN:\n            case LTC_ASN1_INTEGER:\n            case LTC_ASN1_SHORT_INTEGER:\n            case LTC_ASN1_BIT_STRING:\n            case LTC_ASN1_OCTET_STRING:\n            case LTC_ASN1_NULL:\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n            case LTC_ASN1_IA5_STRING:\n            case LTC_ASN1_PRINTABLE_STRING:\n            case LTC_ASN1_UTF8_STRING:\n            case LTC_ASN1_UTCTIME:\n            case LTC_ASN1_SEQUENCE:\n            case LTC_ASN1_SET:\n            case LTC_ASN1_SETOF:\n                ++x;\n                break;\n\n            default:\n                va_end(args);\n                return CRYPT_INVALID_ARG;\n        }\n    }\n    va_end(args);\n\n    /* allocate structure for x elements */\n    if (x == 0) {\n        return CRYPT_NOP;\n    }\n\n    list = XCALLOC(sizeof(*list), x);\n    if (list == NULL) {\n        return CRYPT_MEM;\n    }\n\n    /* fill in the structure */\n    va_start(args, outlen);\n    x = 0;\n    for ( ; ; ) {\n        type = va_arg(args, int);\n        size = va_arg(args, unsigned long);\n        data = va_arg(args, void *);\n\n        if (type == LTC_ASN1_EOL) {\n            break;\n        }\n\n        switch (type) {\n            case LTC_ASN1_BOOLEAN:\n            case LTC_ASN1_INTEGER:\n            case LTC_ASN1_SHORT_INTEGER:\n            case LTC_ASN1_BIT_STRING:\n            case LTC_ASN1_OCTET_STRING:\n            case LTC_ASN1_NULL:\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n            case LTC_ASN1_IA5_STRING:\n            case LTC_ASN1_PRINTABLE_STRING:\n            case LTC_ASN1_UTF8_STRING:\n            case LTC_ASN1_UTCTIME:\n            case LTC_ASN1_SEQUENCE:\n            case LTC_ASN1_SET:\n            case LTC_ASN1_SETOF:\n                list[x].type   = type;\n                list[x].size   = size;\n                list[x++].data = data;\n                break;\n\n            default:\n                va_end(args);\n                err = CRYPT_INVALID_ARG;\n                goto LBL_ERR;\n        }\n    }\n    va_end(args);\n\n    err = der_encode_sequence(list, x, out, outlen);\nLBL_ERR:\n    XFREE(list);\n    return err;\n}\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c,v $ */\n/* $Revision: 1.12 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_set.c\n   ASN.1 DER, Encode a SET, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/* LTC define to ASN.1 TAG */\nstatic int ltc_to_asn1(int v) {\n    switch (v) {\n        case LTC_ASN1_BOOLEAN:\n            return 0x01;\n\n        case LTC_ASN1_INTEGER:\n        case LTC_ASN1_SHORT_INTEGER:\n            return 0x02;\n\n        case LTC_ASN1_BIT_STRING:\n            return 0x03;\n\n        case LTC_ASN1_OCTET_STRING:\n            return 0x04;\n\n        case LTC_ASN1_NULL:\n            return 0x05;\n\n        case LTC_ASN1_OBJECT_IDENTIFIER:\n            return 0x06;\n\n        case LTC_ASN1_UTF8_STRING:\n            return 0x0C;\n\n        case LTC_ASN1_PRINTABLE_STRING:\n            return 0x13;\n\n        case LTC_ASN1_IA5_STRING:\n            return 0x16;\n\n        case LTC_ASN1_UTCTIME:\n            return 0x17;\n\n        case LTC_ASN1_SEQUENCE:\n            return 0x30;\n\n        case LTC_ASN1_SET:\n        case LTC_ASN1_SETOF:\n            return 0x31;\n\n        default:\n            return -1;\n    }\n}\n\nstatic int qsort_helper_set(const void *a, const void *b) {\n    ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b;\n    int           r;\n\n    r = ltc_to_asn1(A->type) - ltc_to_asn1(B->type);\n\n    /* for QSORT the order is UNDEFINED if they are \"equal\" which means it is NOT DETERMINISTIC.  So we force it to be :-) */\n    if (r == 0) {\n        /* their order in the original list now determines the position */\n        return A->used - B->used;\n    } else {\n        return r;\n    }\n}\n\n/*\n   Encode a SET type\n   @param list      The list of items to encode\n   @param inlen     The number of items in the list\n   @param out       [out] The destination\n   @param outlen    [in/out] The size of the output\n   @return CRYPT_OK on success\n */\nint der_encode_set(ltc_asn1_list *list, unsigned long inlen,\n                   unsigned char *out, unsigned long *outlen) {\n    ltc_asn1_list *copy;\n    unsigned long x;\n    int           err;\n\n    /* make copy of list */\n    copy = XCALLOC(inlen, sizeof(*copy));\n    if (copy == NULL) {\n        return CRYPT_MEM;\n    }\n\n    /* fill in used member with index so we can fully sort it */\n    for (x = 0; x < inlen; x++) {\n        copy[x]      = list[x];\n        copy[x].used = x;\n    }\n\n    /* sort it by the \"type\" field */\n    XQSORT(copy, inlen, sizeof(*copy), &qsort_helper_set);\n\n    /* call der_encode_sequence_ex() */\n    err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);\n\n    /* free list */\n    XFREE(copy);\n\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c,v $ */\n/* $Revision: 1.12 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_setof.c\n   ASN.1 DER, Encode SET OF, Tom St Denis\n */\n\n#ifdef LTC_DER\n\nstruct edge {\n    unsigned char *start;\n    unsigned long size;\n};\n\nstatic int qsort_helper(const void *a, const void *b) {\n    struct edge   *A = (struct edge *)a, *B = (struct edge *)b;\n    int           r;\n    unsigned long x;\n\n    /* compare min length */\n    r = XMEMCMP(A->start, B->start, TOM_MIN(A->size, B->size));\n\n    if ((r == 0) && (A->size != B->size)) {\n        if (A->size > B->size) {\n            for (x = B->size; x < A->size; x++) {\n                if (A->start[x]) {\n                    return 1;\n                }\n            }\n        } else {\n            for (x = A->size; x < B->size; x++) {\n                if (B->start[x]) {\n                    return -1;\n                }\n            }\n        }\n    }\n\n    return r;\n}\n\n/**\n   Encode a SETOF stucture\n   @param list      The list of items to encode\n   @param inlen     The number of items in the list\n   @param out       [out] The destination\n   @param outlen    [in/out] The size of the output\n   @return CRYPT_OK on success\n */\nint der_encode_setof(ltc_asn1_list *list, unsigned long inlen,\n                     unsigned char *out, unsigned long *outlen) {\n    unsigned long x, y, z, hdrlen;\n    int           err;\n    struct edge   *edges;\n    unsigned char *ptr, *buf;\n\n    /* check that they're all the same type */\n    for (x = 1; x < inlen; x++) {\n        if (list[x].type != list[x - 1].type) {\n            return CRYPT_INVALID_ARG;\n        }\n    }\n\n    /* alloc buffer to store copy of output */\n    buf = XCALLOC(1, *outlen);\n    if (buf == NULL) {\n        return CRYPT_MEM;\n    }\n\n    /* encode list */\n    if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) {\n        XFREE(buf);\n        return err;\n    }\n\n    /* allocate edges */\n    edges = XCALLOC(inlen, sizeof(*edges));\n    if (edges == NULL) {\n        XFREE(buf);\n        return CRYPT_MEM;\n    }\n\n    /* skip header */\n    ptr = buf + 1;\n\n    /* now skip length data */\n    x = *ptr++;\n    if (x >= 0x80) {\n        ptr += (x & 0x7F);\n    }\n\n    /* get the size of the static header */\n    hdrlen = ((unsigned long)ptr) - ((unsigned long)buf);\n\n\n    /* scan for edges */\n    x = 0;\n    while (ptr < (buf + *outlen)) {\n        /* store start */\n        edges[x].start = ptr;\n\n        /* skip type */\n        z = 1;\n\n        /* parse length */\n        y = ptr[z++];\n        if (y < 128) {\n            edges[x].size = y;\n        } else {\n            y            &= 0x7F;\n            edges[x].size = 0;\n            while (y--) {\n                edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]);\n            }\n        }\n\n        /* skip content */\n        edges[x].size += z;\n        ptr           += edges[x].size;\n        ++x;\n    }\n\n    /* sort based on contents (using edges) */\n    XQSORT(edges, inlen, sizeof(*edges), &qsort_helper);\n\n    /* copy static header */\n    XMEMCPY(out, buf, hdrlen);\n\n    /* copy+sort using edges+indecies to output from buffer */\n    for (y = hdrlen, x = 0; x < inlen; x++) {\n        XMEMCPY(out + y, edges[x].start, edges[x].size);\n        y += edges[x].size;\n    }\n\n #ifdef LTC_CLEAN_STACK\n    zeromem(buf, *outlen);\n #endif\n\n    /* free buffers */\n    XFREE(edges);\n    XFREE(buf);\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c,v $ */\n/* $Revision: 1.12 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_short_integer.c\n   ASN.1 DER, encode an integer, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store a short integer in the range (0,2^32-1)\n   @param num      The integer to encode\n   @param out      [out] The destination for the DER encoded integers\n   @param outlen   [in/out] The max size and resulting size of the DER encoded integers\n   @return CRYPT_OK if successful\n */\nint der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen) {\n    unsigned long len, x, y, z;\n    int           err;\n\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* force to 32 bits */\n    num &= 0xFFFFFFFFUL;\n\n    /* find out how big this will be */\n    if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (*outlen < len) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* get len of output */\n    z = 0;\n    y = num;\n    while (y) {\n        ++z;\n        y >>= 8;\n    }\n\n    /* handle zero */\n    if (z == 0) {\n        z = 1;\n    }\n\n    /* see if msb is set */\n    z += (num & (1UL << ((z << 3) - 1))) ? 1 : 0;\n\n    /* adjust the number so the msB is non-zero */\n    for (x = 0; (z <= 4) && (x < (4 - z)); x++) {\n        num <<= 8;\n    }\n\n    /* store header */\n    x        = 0;\n    out[x++] = 0x02;\n    out[x++] = (unsigned char)z;\n\n    /* if 31st bit is set output a leading zero and decrement count */\n    if (z == 5) {\n        out[x++] = 0;\n        --z;\n    }\n\n    /* store values */\n    for (y = 0; y < z; y++) {\n        out[x++] = (unsigned char)((num >> 24) & 0xFF);\n        num    <<= 8;\n    }\n\n    /* we good */\n    *outlen = x;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c,v $ */\n/* $Revision: 1.8 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_utctime.c\n   ASN.1 DER, encode a  UTCTIME, Tom St Denis\n */\n\n#ifdef LTC_DER\n\nstatic const char baseten[] = \"0123456789\";\n\n #define STORE_V(y)                                         \\\n    out[x++] = der_ia5_char_encode(baseten[(y / 10) % 10]); \\\n    out[x++] = der_ia5_char_encode(baseten[y % 10]);\n\n/**\n   Encodes a UTC time structure in DER format\n   @param utctime      The UTC time structure to encode\n   @param out          The destination of the DER encoding of the UTC time structure\n   @param outlen       [in/out] The length of the DER encoding\n   @return CRYPT_OK if successful\n */\nint der_encode_utctime(ltc_utctime *utctime,\n                       unsigned char *out, unsigned long *outlen) {\n    unsigned long x, tmplen;\n    int           err;\n\n    LTC_ARGCHK(utctime != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) {\n        return err;\n    }\n    if (tmplen > *outlen) {\n        *outlen = tmplen;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* store header */\n    out[0] = 0x17;\n\n    /* store values */\n    x = 2;\n    STORE_V(utctime->YY);\n    STORE_V(utctime->MM);\n    STORE_V(utctime->DD);\n    STORE_V(utctime->hh);\n    STORE_V(utctime->mm);\n    STORE_V(utctime->ss);\n\n    if (utctime->off_mm || utctime->off_hh) {\n        out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+');\n        STORE_V(utctime->off_hh);\n        STORE_V(utctime->off_mm);\n    } else {\n        out[x++] = der_ia5_char_encode('Z');\n    }\n\n    /* store length */\n    out[1] = (unsigned char)(x - 2);\n\n    /* all good let's return */\n    *outlen = x;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c,v $ */\n/* $Revision: 1.10 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_encode_utf8_string.c\n   ASN.1 DER, encode a UTF8 STRING, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Store an UTF8 STRING\n   @param in       The array of UTF8 to store (one per wchar_t)\n   @param inlen    The number of UTF8 to store\n   @param out      [out] The destination for the DER encoded UTF8 STRING\n   @param outlen   [in/out] The max size and resulting size of the DER UTF8 STRING\n   @return CRYPT_OK if successful\n */\nint der_encode_utf8_string(const wchar_t *in, unsigned long inlen,\n                           unsigned char *out, unsigned long *outlen) {\n    unsigned long x, y, len;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* get the size */\n    for (x = len = 0; x < inlen; x++) {\n        if ((in[x] < 0) || (in[x] > 0x1FFFF)) {\n            return CRYPT_INVALID_ARG;\n        }\n        len += der_utf8_charsize(in[x]);\n    }\n\n    if (len < 128) {\n        y = 2 + len;\n    } else if (len < 256) {\n        y = 3 + len;\n    } else if (len < 65536UL) {\n        y = 4 + len;\n    } else if (len < 16777216UL) {\n        y = 5 + len;\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* too big? */\n    if (y > *outlen) {\n        *outlen = len;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* encode the header+len */\n    x        = 0;\n    out[x++] = 0x0C;\n    if (len < 128) {\n        out[x++] = (unsigned char)len;\n    } else if (len < 256) {\n        out[x++] = 0x81;\n        out[x++] = (unsigned char)len;\n    } else if (len < 65536UL) {\n        out[x++] = 0x82;\n        out[x++] = (unsigned char)((len >> 8) & 255);\n        out[x++] = (unsigned char)(len & 255);\n    } else if (len < 16777216UL) {\n        out[x++] = 0x83;\n        out[x++] = (unsigned char)((len >> 16) & 255);\n        out[x++] = (unsigned char)((len >> 8) & 255);\n        out[x++] = (unsigned char)(len & 255);\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* store UTF8 */\n    for (y = 0; y < inlen; y++) {\n        switch (der_utf8_charsize(in[y])) {\n            case 1:\n                out[x++] = (unsigned char)in[y];\n                break;\n\n            case 2:\n                out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F);\n                out[x++] = 0x80 | (in[y] & 0x3F);\n                break;\n\n            case 3:\n                out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F);\n                out[x++] = 0x80 | ((in[y] >> 6) & 0x3F);\n                out[x++] = 0x80 | (in[y] & 0x3F);\n                break;\n\n            case 4:\n                out[x++] = 0xF0 | ((in[y] >> 18) & 0x07);\n                out[x++] = 0x80 | ((in[y] >> 12) & 0x3F);\n                out[x++] = 0x80 | ((in[y] >> 6) & 0x3F);\n                out[x++] = 0x80 | (in[y] & 0x3F);\n                break;\n        }\n    }\n\n    /* retun length */\n    *outlen = x;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c,v $ */\n/* $Revision: 1.9 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_bit_string.c\n   ASN.1 DER, get length of BIT STRING, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Gets length of DER encoding of BIT STRING\n   @param nbits  The number of bits in the string to encode\n   @param outlen [out] The length of the DER encoding for the given string\n   @return CRYPT_OK if successful\n */\nint der_length_bit_string(unsigned long nbits, unsigned long *outlen) {\n    unsigned long nbytes;\n\n    LTC_ARGCHK(outlen != NULL);\n\n    /* get the number of the bytes */\n    nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;\n\n    if (nbytes < 128) {\n        /* 03 LL PP DD DD DD ... */\n        *outlen = 2 + nbytes;\n    } else if (nbytes < 256) {\n        /* 03 81 LL PP DD DD DD ... */\n        *outlen = 3 + nbytes;\n    } else if (nbytes < 65536) {\n        /* 03 82 LL LL PP DD DD DD ... */\n        *outlen = 4 + nbytes;\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    return CRYPT_OK;\n}\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c,v $ */\n/* $Revision: 1.3 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_boolean.c\n   ASN.1 DER, get length of a BOOLEAN, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Gets length of DER encoding of a BOOLEAN\n   @param outlen [out] The length of the DER encoding\n   @return CRYPT_OK if successful\n */\nint der_length_boolean(unsigned long *outlen) {\n    LTC_ARGCHK(outlen != NULL);\n    *outlen = 3;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c,v $ */\n/* $Revision: 1.3 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_ia5_string.c\n   ASN.1 DER, get length of IA5 STRING, Tom St Denis\n */\n\n#ifdef LTC_DER\n\nstatic const struct {\n    int code, value;\n} ia5_table[] = {\n    { '\\0',   0 },\n    { '\\a',   7 },\n    { '\\b',   8 },\n    { '\\t',   9 },\n    { '\\n',  10 },\n    { '\\f',  12 },\n    { '\\r',  13 },\n    { ' ',   32 },\n    { '!',   33 },\n    { '\"',   34 },\n    { '#',   35 },\n    { '$',   36 },\n    { '%',   37 },\n    { '&',   38 },\n    { '\\'',  39 },\n    { '(',   40 },\n    { ')',   41 },\n    { '*',   42 },\n    { '+',   43 },\n    { ',',   44 },\n    { '-',   45 },\n    { '.',   46 },\n    { '/',   47 },\n    { '0',   48 },\n    { '1',   49 },\n    { '2',   50 },\n    { '3',   51 },\n    { '4',   52 },\n    { '5',   53 },\n    { '6',   54 },\n    { '7',   55 },\n    { '8',   56 },\n    { '9',   57 },\n    { ':',   58 },\n    { ';',   59 },\n    { '<',   60 },\n    { '=',   61 },\n    { '>',   62 },\n    { '?',   63 },\n    { '@',   64 },\n    { 'A',   65 },\n    { 'B',   66 },\n    { 'C',   67 },\n    { 'D',   68 },\n    { 'E',   69 },\n    { 'F',   70 },\n    { 'G',   71 },\n    { 'H',   72 },\n    { 'I',   73 },\n    { 'J',   74 },\n    { 'K',   75 },\n    { 'L',   76 },\n    { 'M',   77 },\n    { 'N',   78 },\n    { 'O',   79 },\n    { 'P',   80 },\n    { 'Q',   81 },\n    { 'R',   82 },\n    { 'S',   83 },\n    { 'T',   84 },\n    { 'U',   85 },\n    { 'V',   86 },\n    { 'W',   87 },\n    { 'X',   88 },\n    { 'Y',   89 },\n    { 'Z',   90 },\n    { '[',   91 },\n    { '\\\\',  92 },\n    { ']',   93 },\n    { '^',   94 },\n    { '_',   95 },\n    { '`',   96 },\n    { 'a',   97 },\n    { 'b',   98 },\n    { 'c',   99 },\n    { 'd',  100 },\n    { 'e',  101 },\n    { 'f',  102 },\n    { 'g',  103 },\n    { 'h',  104 },\n    { 'i',  105 },\n    { 'j',  106 },\n    { 'k',  107 },\n    { 'l',  108 },\n    { 'm',  109 },\n    { 'n',  110 },\n    { 'o',  111 },\n    { 'p',  112 },\n    { 'q',  113 },\n    { 'r',  114 },\n    { 's',  115 },\n    { 't',  116 },\n    { 'u',  117 },\n    { 'v',  118 },\n    { 'w',  119 },\n    { 'x',  120 },\n    { 'y',  121 },\n    { 'z',  122 },\n    { '{',  123 },\n    { '|',  124 },\n    { '}',  125 },\n    { '~',  126 }\n};\n\nint der_ia5_char_encode(int c) {\n    int x;\n\n    for (x = 0; x < (int)(sizeof(ia5_table) / sizeof(ia5_table[0])); x++) {\n        if (ia5_table[x].code == c) {\n            return ia5_table[x].value;\n        }\n    }\n    return -1;\n}\n\nint der_ia5_value_decode(int v) {\n    int x;\n\n    for (x = 0; x < (int)(sizeof(ia5_table) / sizeof(ia5_table[0])); x++) {\n        if (ia5_table[x].value == v) {\n            return ia5_table[x].code;\n        }\n    }\n    return -1;\n}\n\n/**\n   Gets length of DER encoding of IA5 STRING\n   @param octets   The values you want to encode\n   @param noctets  The number of octets in the string to encode\n   @param outlen   [out] The length of the DER encoding for the given string\n   @return CRYPT_OK if successful\n */\nint der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) {\n    unsigned long x;\n\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(octets != NULL);\n\n    /* scan string for validity */\n    for (x = 0; x < noctets; x++) {\n        if (der_ia5_char_encode(octets[x]) == -1) {\n            return CRYPT_INVALID_ARG;\n        }\n    }\n\n    if (noctets < 128) {\n        /* 16 LL DD DD DD ... */\n        *outlen = 2 + noctets;\n    } else if (noctets < 256) {\n        /* 16 81 LL DD DD DD ... */\n        *outlen = 3 + noctets;\n    } else if (noctets < 65536UL) {\n        /* 16 82 LL LL DD DD DD ... */\n        *outlen = 4 + noctets;\n    } else if (noctets < 16777216UL) {\n        /* 16 83 LL LL LL DD DD DD ... */\n        *outlen = 5 + noctets;\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    return CRYPT_OK;\n}\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c,v $ */\n/* $Revision: 1.3 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_integer.c\n   ASN.1 DER, get length of encoding, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Gets length of DER encoding of num\n   @param num    The int to get the size of\n   @param outlen [out] The length of the DER encoding for the given integer\n   @return CRYPT_OK if successful\n */\nint der_length_integer(void *num, unsigned long *outlen) {\n    unsigned long z, len;\n    int           leading_zero;\n\n    LTC_ARGCHK(num != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    if (mp_cmp_d(num, 0) != LTC_MP_LT) {\n        /* positive */\n\n        /* we only need a leading zero if the msb of the first byte is one */\n        if (((mp_count_bits(num) & 7) == 0) || (mp_iszero(num) == LTC_MP_YES)) {\n            leading_zero = 1;\n        } else {\n            leading_zero = 0;\n        }\n\n        /* size for bignum */\n        z = len = leading_zero + mp_unsigned_bin_size(num);\n    } else {\n        /* it's negative */\n        /* find power of 2 that is a multiple of eight and greater than count bits */\n        leading_zero = 0;\n        z            = mp_count_bits(num);\n        z            = z + (8 - (z & 7));\n        if (((mp_cnt_lsb(num) + 1) == mp_count_bits(num)) && ((mp_count_bits(num) & 7) == 0)) --z;\n        len = z = z >> 3;\n    }\n\n    /* now we need a length */\n    if (z < 128) {\n        /* short form */\n        ++len;\n    } else {\n        /* long form (relies on z != 0), assumes length bytes < 128 */\n        ++len;\n\n        while (z) {\n            ++len;\n            z >>= 8;\n        }\n    }\n\n    /* we need a 0x02 to indicate it's INTEGER */\n    ++len;\n\n    /* return length */\n    *outlen = len;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_object_identifier.c\n   ASN.1 DER, get length of Object Identifier, Tom St Denis\n */\n\n#ifdef LTC_DER\n\nunsigned long der_object_identifier_bits(unsigned long x) {\n    unsigned long c;\n\n    x &= 0xFFFFFFFF;\n    c  = 0;\n    while (x) {\n        ++c;\n        x >>= 1;\n    }\n    return c;\n}\n\n/**\n   Gets length of DER encoding of Object Identifier\n   @param nwords   The number of OID words\n   @param words    The actual OID words to get the size of\n   @param outlen   [out] The length of the DER encoding for the given string\n   @return CRYPT_OK if successful\n */\nint der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen) {\n    unsigned long y, z, t, wordbuf;\n\n    LTC_ARGCHK(words != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n\n    /* must be >= 2 words */\n    if (nwords < 2) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* word1 = 0,1,2,3 and word2 0..39 */\n    if ((words[0] > 3) || ((words[0] < 2) && (words[1] > 39))) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* leading word is the first two */\n    z       = 0;\n    wordbuf = words[0] * 40 + words[1];\n    for (y = 1; y < nwords; y++) {\n        t  = der_object_identifier_bits(wordbuf);\n        z += t / 7 + ((t % 7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);\n        if (y < nwords - 1) {\n            /* grab next word */\n            wordbuf = words[y + 1];\n        }\n    }\n\n    /* now depending on the length our length encoding changes */\n    if (z < 128) {\n        z += 2;\n    } else if (z < 256) {\n        z += 3;\n    } else if (z < 65536UL) {\n        z += 4;\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    *outlen = z;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_octet_string.c\n   ASN.1 DER, get length of OCTET STRING, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Gets length of DER encoding of OCTET STRING\n   @param noctets  The number of octets in the string to encode\n   @param outlen   [out] The length of the DER encoding for the given string\n   @return CRYPT_OK if successful\n */\nint der_length_octet_string(unsigned long noctets, unsigned long *outlen) {\n    LTC_ARGCHK(outlen != NULL);\n\n    if (noctets < 128) {\n        /* 04 LL DD DD DD ... */\n        *outlen = 2 + noctets;\n    } else if (noctets < 256) {\n        /* 04 81 LL DD DD DD ... */\n        *outlen = 3 + noctets;\n    } else if (noctets < 65536UL) {\n        /* 04 82 LL LL DD DD DD ... */\n        *outlen = 4 + noctets;\n    } else if (noctets < 16777216UL) {\n        /* 04 83 LL LL LL DD DD DD ... */\n        *outlen = 5 + noctets;\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    return CRYPT_OK;\n}\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c,v $ */\n/* $Revision: 1.3 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_printable_string.c\n   ASN.1 DER, get length of Printable STRING, Tom St Denis\n */\n\n#ifdef LTC_DER\n\nstatic const struct {\n    int code, value;\n} printable_table[] = {\n    { ' ',   32 },\n    { '\\'',  39 },\n    { '(',   40 },\n    { ')',   41 },\n    { '+',   43 },\n    { ',',   44 },\n    { '-',   45 },\n    { '.',   46 },\n    { '/',   47 },\n    { '0',   48 },\n    { '1',   49 },\n    { '2',   50 },\n    { '3',   51 },\n    { '4',   52 },\n    { '5',   53 },\n    { '6',   54 },\n    { '7',   55 },\n    { '8',   56 },\n    { '9',   57 },\n    { ':',   58 },\n    { '=',   61 },\n    { '?',   63 },\n    { 'A',   65 },\n    { 'B',   66 },\n    { 'C',   67 },\n    { 'D',   68 },\n    { 'E',   69 },\n    { 'F',   70 },\n    { 'G',   71 },\n    { 'H',   72 },\n    { 'I',   73 },\n    { 'J',   74 },\n    { 'K',   75 },\n    { 'L',   76 },\n    { 'M',   77 },\n    { 'N',   78 },\n    { 'O',   79 },\n    { 'P',   80 },\n    { 'Q',   81 },\n    { 'R',   82 },\n    { 'S',   83 },\n    { 'T',   84 },\n    { 'U',   85 },\n    { 'V',   86 },\n    { 'W',   87 },\n    { 'X',   88 },\n    { 'Y',   89 },\n    { 'Z',   90 },\n    { 'a',   97 },\n    { 'b',   98 },\n    { 'c',   99 },\n    { 'd',  100 },\n    { 'e',  101 },\n    { 'f',  102 },\n    { 'g',  103 },\n    { 'h',  104 },\n    { 'i',  105 },\n    { 'j',  106 },\n    { 'k',  107 },\n    { 'l',  108 },\n    { 'm',  109 },\n    { 'n',  110 },\n    { 'o',  111 },\n    { 'p',  112 },\n    { 'q',  113 },\n    { 'r',  114 },\n    { 's',  115 },\n    { 't',  116 },\n    { 'u',  117 },\n    { 'v',  118 },\n    { 'w',  119 },\n    { 'x',  120 },\n    { 'y',  121 },\n    { 'z',  122 },\n};\n\nint der_printable_char_encode(int c) {\n    int x;\n\n    for (x = 0; x < (int)(sizeof(printable_table) / sizeof(printable_table[0])); x++) {\n        if (printable_table[x].code == c) {\n            return printable_table[x].value;\n        }\n    }\n    return -1;\n}\n\nint der_printable_value_decode(int v) {\n    int x;\n\n    for (x = 0; x < (int)(sizeof(printable_table) / sizeof(printable_table[0])); x++) {\n        if (printable_table[x].value == v) {\n            return printable_table[x].code;\n        }\n    }\n    return -1;\n}\n\n/**\n   Gets length of DER encoding of Printable STRING\n   @param octets   The values you want to encode\n   @param noctets  The number of octets in the string to encode\n   @param outlen   [out] The length of the DER encoding for the given string\n   @return CRYPT_OK if successful\n */\nint der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) {\n    unsigned long x;\n\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(octets != NULL);\n\n    /* scan string for validity */\n    for (x = 0; x < noctets; x++) {\n        if (der_printable_char_encode(octets[x]) == -1) {\n            return CRYPT_INVALID_ARG;\n        }\n    }\n\n    if (noctets < 128) {\n        /* 16 LL DD DD DD ... */\n        *outlen = 2 + noctets;\n    } else if (noctets < 256) {\n        /* 16 81 LL DD DD DD ... */\n        *outlen = 3 + noctets;\n    } else if (noctets < 65536UL) {\n        /* 16 82 LL LL DD DD DD ... */\n        *outlen = 4 + noctets;\n    } else if (noctets < 16777216UL) {\n        /* 16 83 LL LL LL DD DD DD ... */\n        *outlen = 5 + noctets;\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    return CRYPT_OK;\n}\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c,v $ */\n/* $Revision: 1.3 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_sequence.c\n   ASN.1 DER, length a SEQUENCE, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Get the length of a DER sequence\n   @param list   The sequences of items in the SEQUENCE\n   @param inlen  The number of items\n   @param outlen [out] The length required in octets to store it\n   @return CRYPT_OK on success\n */\nint der_length_sequence(ltc_asn1_list *list, unsigned long inlen,\n                        unsigned long *outlen) {\n    int           err, type;\n    unsigned long size, x, y, z, i;\n    void          *data;\n\n    LTC_ARGCHK(list != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* get size of output that will be required */\n    y = 0;\n    for (i = 0; i < inlen; i++) {\n        type = list[i].type;\n        size = list[i].size;\n        data = list[i].data;\n\n        if (type == LTC_ASN1_EOL) {\n            break;\n        }\n\n        switch (type) {\n            case LTC_ASN1_BOOLEAN:\n                if ((err = der_length_boolean(&x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_INTEGER:\n                if ((err = der_length_integer(data, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_SHORT_INTEGER:\n                if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_BIT_STRING:\n                if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_OCTET_STRING:\n                if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_NULL:\n                y += 2;\n                break;\n\n            case LTC_ASN1_OBJECT_IDENTIFIER:\n                if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_IA5_STRING:\n                if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_PRINTABLE_STRING:\n                if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_UTCTIME:\n                if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_UTF8_STRING:\n                if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n            case LTC_ASN1_SET:\n            case LTC_ASN1_SETOF:\n            case LTC_ASN1_SEQUENCE:\n                if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {\n                    goto LBL_ERR;\n                }\n                y += x;\n                break;\n\n\n            default:\n                err = CRYPT_INVALID_ARG;\n                goto LBL_ERR;\n        }\n    }\n\n    /* calc header size */\n    z = y;\n    if (y < 128) {\n        y += 2;\n    } else if (y < 256) {\n        /* 0x30 0x81 LL */\n        y += 3;\n    } else if (y < 65536UL) {\n        /* 0x30 0x82 LL LL */\n        y += 4;\n    } else if (y < 16777216UL) {\n        /* 0x30 0x83 LL LL LL */\n        y += 5;\n    } else {\n        err = CRYPT_INVALID_ARG;\n        goto LBL_ERR;\n    }\n\n    /* store size */\n    *outlen = y;\n    err     = CRYPT_OK;\n\nLBL_ERR:\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c,v $ */\n/* $Revision: 1.14 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_short_integer.c\n   ASN.1 DER, get length of encoding, Tom St Denis\n */\n\n\n#ifdef LTC_DER\n\n/**\n   Gets length of DER encoding of num\n   @param num    The integer to get the size of\n   @param outlen [out] The length of the DER encoding for the given integer\n   @return CRYPT_OK if successful\n */\nint der_length_short_integer(unsigned long num, unsigned long *outlen) {\n    unsigned long z, y, len;\n\n    LTC_ARGCHK(outlen != NULL);\n\n    /* force to 32 bits */\n    num &= 0xFFFFFFFFUL;\n\n    /* get the number of bytes */\n    z = 0;\n    y = num;\n    while (y) {\n        ++z;\n        y >>= 8;\n    }\n\n    /* handle zero */\n    if (z == 0) {\n        z = 1;\n    }\n\n    /* we need a 0x02 to indicate it's INTEGER */\n    len = 1;\n\n    /* length byte */\n    ++len;\n\n    /* bytes in value */\n    len += z;\n\n    /* see if msb is set */\n    len += (num & (1UL << ((z << 3) - 1))) ? 1 : 0;\n\n    /* return length */\n    *outlen = len;\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_utctime.c\n   ASN.1 DER, get length of UTCTIME, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Gets length of DER encoding of UTCTIME\n   @param utctime      The UTC time structure to get the size of\n   @param outlen [out] The length of the DER encoding\n   @return CRYPT_OK if successful\n */\nint der_length_utctime(ltc_utctime *utctime, unsigned long *outlen) {\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(utctime != NULL);\n\n    if ((utctime->off_hh == 0) && (utctime->off_mm == 0)) {\n        /* we encode as YYMMDDhhmmssZ */\n        *outlen = 2 + 13;\n    } else {\n        /* we encode as YYMMDDhhmmss{+|-}hh'mm' */\n        *outlen = 2 + 17;\n    }\n\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_length_utf8_string.c\n   ASN.1 DER, get length of UTF8 STRING, Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/** Return the size in bytes of a UTF-8 character\n   @param c   The UTF-8 character to measure\n   @return    The size in bytes\n */\nunsigned long der_utf8_charsize(const wchar_t c) {\n    if (c <= 0x7F) {\n        return 1;\n    } else if (c <= 0x7FF) {\n        return 2;\n    } else if (c <= 0xFFFF) {\n        return 3;\n    } else {\n        return 4;\n    }\n}\n\n/**\n   Gets length of DER encoding of UTF8 STRING\n   @param in       The characters to measure the length of\n   @param noctets  The number of octets in the string to encode\n   @param outlen   [out] The length of the DER encoding for the given string\n   @return CRYPT_OK if successful\n */\nint der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen) {\n    unsigned long x, len;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    len = 0;\n    for (x = 0; x < noctets; x++) {\n        if ((in[x] < 0) || (in[x] > 0x10FFFF)) {\n            return CRYPT_INVALID_ARG;\n        }\n        len += der_utf8_charsize(in[x]);\n    }\n\n    if (len < 128) {\n        /* 0C LL DD DD DD ... */\n        *outlen = 2 + len;\n    } else if (len < 256) {\n        /* 0C 81 LL DD DD DD ... */\n        *outlen = 3 + len;\n    } else if (len < 65536UL) {\n        /* 0C 82 LL LL DD DD DD ... */\n        *outlen = 4 + len;\n    } else if (len < 16777216UL) {\n        /* 0C 83 LL LL LL DD DD DD ... */\n        *outlen = 5 + len;\n    } else {\n        return CRYPT_INVALID_ARG;\n    }\n\n    return CRYPT_OK;\n}\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file der_sequence_free.c\n   ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis\n */\n\n#ifdef LTC_DER\n\n/**\n   Free memory allocated by der_decode_sequence_flexi()\n   @param in     The list to free\n */\nvoid der_sequence_free(ltc_asn1_list *in) {\n    ltc_asn1_list *l;\n\n    /* walk to the start of the chain */\n    while (in->prev != NULL || in->parent != NULL) {\n        if (in->parent != NULL) {\n            in = in->parent;\n        } else {\n            in = in->prev;\n        }\n    }\n\n    /* now walk the list and free stuff */\n    while (in != NULL) {\n        /* is there a child? */\n        if (in->child) {\n            /* disconnect */\n            in->child->parent = NULL;\n            der_sequence_free(in->child);\n        }\n\n        switch (in->type) {\n            case LTC_ASN1_SET:\n            case LTC_ASN1_SETOF:\n            case LTC_ASN1_SEQUENCE:\n                break;\n\n            case LTC_ASN1_INTEGER:\n                if (in->data != NULL) {\n                    mp_clear(in->data);\n                }\n                break;\n\n            default:\n                if (in->data != NULL) {\n                    XFREE(in->data);\n                }\n        }\n\n        /* move to next and free current */\n        l = in->next;\n        XFREE(in);\n        in = l;\n    }\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c,v $ */\n/* $Revision: 1.4 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/* This holds the key settings.  ***MUST*** be organized by size from smallest to largest. */\nconst ltc_ecc_set_type ltc_ecc_sets[] = {\n #ifdef ECC112\n    {\n        14,\n        \"SECP112R1\",\n        \"DB7C2ABF62E35E668076BEAD208B\",\n        \"659EF8BA043916EEDE8911702B22\",\n        \"DB7C2ABF62E35E7628DFAC6561C5\",\n        \"09487239995A5EE76B55F9C2F098\",\n        \"A89CE5AF8724C0A23E0E0FF77500\"\n    },\n #endif\n #ifdef ECC128\n    {\n        16,\n        \"SECP128R1\",\n        \"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF\",\n        \"E87579C11079F43DD824993C2CEE5ED3\",\n        \"FFFFFFFE0000000075A30D1B9038A115\",\n        \"161FF7528B899B2D0C28607CA52C5B86\",\n        \"CF5AC8395BAFEB13C02DA292DDED7A83\",\n    },\n #endif\n #ifdef ECC160\n    {\n        20,\n        \"SECP160R1\",\n        \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF\",\n        \"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45\",\n        \"0100000000000000000001F4C8F927AED3CA752257\",\n        \"4A96B5688EF573284664698968C38BB913CBFC82\",\n        \"23A628553168947D59DCC912042351377AC5FB32\",\n    },\n #endif\n #ifdef ECC192\n    {\n        24,\n        \"ECC-192\",\n        \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF\",\n        \"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1\",\n        \"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831\",\n        \"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012\",\n        \"7192B95FFC8DA78631011ED6B24CDD573F977A11E794811\",\n    },\n #endif\n #ifdef ECC224\n    {\n        28,\n        \"ECC-224\",\n        \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001\",\n        \"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4\",\n        \"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D\",\n        \"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21\",\n        \"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34\",\n    },\n #endif\n #ifdef ECC256\n    {\n        32,\n        \"ECC-256\",\n        \"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF\",\n        \"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B\",\n        \"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551\",\n        \"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296\",\n        \"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5\",\n    },\n #endif\n #ifdef TLS_CURVE25519\n    {\n        32,\n        \"X25519\",\n        \"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED\",\n        \"0000000000000000000000000000000000000000000000000000000000000000\",\n        \"1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED\",\n        \"0000000000000000000000000000000000000000000000000000000000000009\",\n        \"20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9\",\n    },\n #endif\n #ifdef ECC384\n    {\n        48,\n        \"ECC-384\",\n        \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF\",\n        \"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF\",\n        \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973\",\n        \"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7\",\n        \"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F\",\n    },\n #endif\n #ifdef ECC521\n    {\n        66,\n        \"ECC-521\",\n        \"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\",\n        \"51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00\",\n        \"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409\",\n        \"C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66\",\n        \"11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650\",\n    },\n #endif\n    {\n        0,\n        NULL, NULL, NULL, NULL, NULL, NULL\n    }\n};\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc.c,v $ */\n/* $Revision: 1.40 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_ansi_x963_export.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/** ECC X9.63 (Sec. 4.3.6) uncompressed export\n   @param key     Key to export\n   @param out     [out] destination of export\n   @param outlen  [in/out]  Length of destination and final output size\n   Return CRYPT_OK on success\n */\nint ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen) {\n    unsigned char buf[ECC_BUF_SIZE];\n    unsigned long numlen;\n\n    LTC_ARGCHK(key != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    if (ltc_ecc_is_valid_idx(key->idx) == 0) {\n        return CRYPT_INVALID_ARG;\n    }\n    numlen = key->dp->size;\n\n    if (*outlen < (1 + 2 * numlen)) {\n        *outlen = 1 + 2 * numlen;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* store byte 0x04 */\n    out[0] = 0x04;\n\n    /* pad and store x */\n    zeromem(buf, sizeof(buf));\n    mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - mp_unsigned_bin_size(key->pubkey.x)));\n    XMEMCPY(out + 1, buf, numlen);\n\n    /* pad and store y */\n    zeromem(buf, sizeof(buf));\n    mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - mp_unsigned_bin_size(key->pubkey.y)));\n    XMEMCPY(out + 1 + numlen, buf, numlen);\n\n    *outlen = 1 + 2 * numlen;\n    return CRYPT_OK;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_ansi_x963_import.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/** Import an ANSI X9.63 format public key\n   @param in      The input data to read\n   @param inlen   The length of the input data\n   @param key     [out] destination to store imported key \\\n */\nint ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key) {\n    return ecc_ansi_x963_import_ex(in, inlen, key, NULL);\n}\n\nint ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp) {\n    int x, err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* must be odd */\n    if ((inlen & 1) == 0) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* init key */\n    if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {\n        return CRYPT_MEM;\n    }\n\n    /* check for 4, 6 or 7 */\n    if ((in[0] != 4) && (in[0] != 6) && (in[0] != 7)) {\n        err = CRYPT_INVALID_PACKET;\n        goto error;\n    }\n\n    /* read data */\n    if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)in + 1, (inlen - 1) >> 1)) != CRYPT_OK) {\n        goto error;\n    }\n\n    if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)in + 1 + ((inlen - 1) >> 1), (inlen - 1) >> 1)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) {\n        goto error;\n    }\n\n    if (dp == NULL) {\n        /* determine the idx */\n        for (x = 0; ltc_ecc_sets[x].size != 0; x++) {\n            if ((unsigned)ltc_ecc_sets[x].size >= ((inlen - 1) >> 1)) {\n                break;\n            }\n        }\n        if (ltc_ecc_sets[x].size == 0) {\n            err = CRYPT_INVALID_PACKET;\n            goto error;\n        }\n        /* set the idx */\n        key->idx = x;\n        key->dp  = &ltc_ecc_sets[x];\n    } else {\n        if (((inlen - 1) >> 1) != (unsigned long)dp->size) {\n            err = CRYPT_INVALID_PACKET;\n            goto error;\n        }\n        key->idx = -1;\n        key->dp  = dp;\n    }\n    key->type = PK_PUBLIC;\n\n    /* we're done */\n    return CRYPT_OK;\nerror:\n    mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c,v $ */\n/* $Revision: 1.11 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_decrypt_key.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Decrypt an ECC encrypted key\n   @param in       The ciphertext\n   @param inlen    The length of the ciphertext (octets)\n   @param out      [out] The plaintext\n   @param outlen   [in/out] The max size and resulting size of the plaintext\n   @param key      The corresponding private ECC key\n   @return CRYPT_OK if successful\n */\nint ecc_decrypt_key(const unsigned char *in, unsigned long inlen,\n                    unsigned char *out, unsigned long *outlen,\n                    ecc_key *key) {\n    unsigned char *ecc_shared, *skey, *pub_expt;\n    unsigned long x, y, hashOID[32];\n    int           hash, err;\n    ecc_key       pubkey;\n    ltc_asn1_list decode[3];\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* right key type? */\n    if (key->type != PK_PRIVATE) {\n        return CRYPT_PK_NOT_PRIVATE;\n    }\n\n    /* decode to find out hash */\n    LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID) / sizeof(hashOID[0]));\n\n    if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) {\n        return err;\n    }\n\n    hash = find_hash_oid(hashOID, decode[0].size);\n    if (hash_is_valid(hash) != CRYPT_OK) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* we now have the hash! */\n\n    /* allocate memory */\n    pub_expt   = XMALLOC(ECC_BUF_SIZE);\n    ecc_shared = XMALLOC(ECC_BUF_SIZE);\n    skey       = XMALLOC(MAXBLOCKSIZE);\n    if ((pub_expt == NULL) || (ecc_shared == NULL) || (skey == NULL)) {\n        if (pub_expt != NULL) {\n            XFREE(pub_expt);\n        }\n        if (ecc_shared != NULL) {\n            XFREE(ecc_shared);\n        }\n        if (skey != NULL) {\n            XFREE(skey);\n        }\n        return CRYPT_MEM;\n    }\n    LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE);\n    LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);\n\n    /* read the structure in now */\n    if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* import ECC key from packet */\n    if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* make shared key */\n    x = ECC_BUF_SIZE;\n    if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) {\n        ecc_free(&pubkey);\n        goto LBL_ERR;\n    }\n    ecc_free(&pubkey);\n\n    y = TOM_MIN(ECC_BUF_SIZE, MAXBLOCKSIZE);\n    if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* ensure the hash of the shared secret is at least as big as the encrypt itself */\n    if (decode[2].size > y) {\n        err = CRYPT_INVALID_PACKET;\n        goto LBL_ERR;\n    }\n\n    /* avoid buffer overflow */\n    if (*outlen < decode[2].size) {\n        *outlen = decode[2].size;\n        err     = CRYPT_BUFFER_OVERFLOW;\n        goto LBL_ERR;\n    }\n\n    /* Decrypt the key */\n    for (x = 0; x < decode[2].size; x++) {\n        out[x] = skey[x] ^ ecc_shared[x];\n    }\n    *outlen = x;\n\n    err = CRYPT_OK;\nLBL_ERR:\n #ifdef LTC_CLEAN_STACK\n    zeromem(pub_expt, ECC_BUF_SIZE);\n    zeromem(ecc_shared, ECC_BUF_SIZE);\n    zeromem(skey, MAXBLOCKSIZE);\n #endif\n\n    XFREE(pub_expt);\n    XFREE(ecc_shared);\n    XFREE(skey);\n\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_encrypt_key.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Encrypt a symmetric key with ECC\n   @param in         The symmetric key you want to encrypt\n   @param inlen      The length of the key to encrypt (octets)\n   @param out        [out] The destination for the ciphertext\n   @param outlen     [in/out] The max size and resulting size of the ciphertext\n   @param prng       An active PRNG state\n   @param wprng      The index of the PRNG you wish to use\n   @param hash       The index of the hash you want to use\n   @param key        The ECC key you want to encrypt to\n   @return CRYPT_OK if successful\n */\nint ecc_encrypt_key(const unsigned char *in, unsigned long inlen,\n                    unsigned char *out, unsigned long *outlen,\n                    prng_state *prng, int wprng, int hash,\n                    ecc_key *key) {\n    unsigned char *pub_expt, *ecc_shared, *skey;\n    ecc_key       pubkey;\n    unsigned long x, y, pubkeysize;\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* check that wprng/cipher/hash are not invalid */\n    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {\n        return err;\n    }\n\n    if ((err = hash_is_valid(hash)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (inlen > hash_descriptor[hash].hashsize) {\n        return CRYPT_INVALID_HASH;\n    }\n\n    /* make a random key and export the public copy */\n    if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {\n        return err;\n    }\n\n    pub_expt   = XMALLOC(ECC_BUF_SIZE);\n    ecc_shared = XMALLOC(ECC_BUF_SIZE);\n    skey       = XMALLOC(MAXBLOCKSIZE);\n    if ((pub_expt == NULL) || (ecc_shared == NULL) || (skey == NULL)) {\n        if (pub_expt != NULL) {\n            XFREE(pub_expt);\n        }\n        if (ecc_shared != NULL) {\n            XFREE(ecc_shared);\n        }\n        if (skey != NULL) {\n            XFREE(skey);\n        }\n        ecc_free(&pubkey);\n        return CRYPT_MEM;\n    }\n\n    pubkeysize = ECC_BUF_SIZE;\n    if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {\n        ecc_free(&pubkey);\n        goto LBL_ERR;\n    }\n\n    /* make random key */\n    x = ECC_BUF_SIZE;\n    if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {\n        ecc_free(&pubkey);\n        goto LBL_ERR;\n    }\n    ecc_free(&pubkey);\n    y = MAXBLOCKSIZE;\n    if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* Encrypt key */\n    for (x = 0; x < inlen; x++) {\n        skey[x] ^= in[x];\n    }\n\n    err = der_encode_sequence_multi(out, outlen,\n                                    LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID,\n                                    LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt,\n                                    LTC_ASN1_OCTET_STRING, inlen, skey,\n                                    LTC_ASN1_EOL, 0UL, NULL);\n\nLBL_ERR:\n #ifdef LTC_CLEAN_STACK\n    /* clean up */\n    zeromem(pub_expt, ECC_BUF_SIZE);\n    zeromem(ecc_shared, ECC_BUF_SIZE);\n    zeromem(skey, MAXBLOCKSIZE);\n #endif\n\n    XFREE(skey);\n    XFREE(ecc_shared);\n    XFREE(pub_expt);\n\n    return err;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_export.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Export an ECC key as a binary packet\n   @param out     [out] Destination for the key\n   @param outlen  [in/out] Max size and resulting size of the exported key\n   @param type    The type of key you want to export (PK_PRIVATE or PK_PUBLIC)\n   @param key     The key to export\n   @return CRYPT_OK if successful\n */\nint ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key) {\n    int           err;\n    unsigned char flags[1];\n    unsigned long key_size;\n\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* type valid? */\n    if ((key->type != PK_PRIVATE) && (type == PK_PRIVATE)) {\n        return CRYPT_PK_TYPE_MISMATCH;\n    }\n\n    if (ltc_ecc_is_valid_idx(key->idx) == 0) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* we store the NIST byte size */\n    key_size = key->dp->size;\n\n    if (type == PK_PRIVATE) {\n        flags[0] = 1;\n        err      = der_encode_sequence_multi(out, outlen,\n                                             LTC_ASN1_BIT_STRING, 1UL, flags,\n                                             LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,\n                                             LTC_ASN1_INTEGER, 1UL, key->pubkey.x,\n                                             LTC_ASN1_INTEGER, 1UL, key->pubkey.y,\n                                             LTC_ASN1_INTEGER, 1UL, key->k,\n                                             LTC_ASN1_EOL, 0UL, NULL);\n    } else {\n        flags[0] = 0;\n        err      = der_encode_sequence_multi(out, outlen,\n                                             LTC_ASN1_BIT_STRING, 1UL, flags,\n                                             LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,\n                                             LTC_ASN1_INTEGER, 1UL, key->pubkey.x,\n                                             LTC_ASN1_INTEGER, 1UL, key->pubkey.y,\n                                             LTC_ASN1_EOL, 0UL, NULL);\n    }\n\n    return err;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_export.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_free.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Free an ECC key from memory\n   @param key   The key you wish to free\n */\nvoid ecc_free(ecc_key *key) {\n    LTC_ARGCHKVD(key != NULL);\n    mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_free.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_get_size.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Get the size of an ECC key\n   @param key    The key to get the size of\n   @return The size (octets) of the key or INT_MAX on error\n */\nint ecc_get_size(ecc_key *key) {\n    LTC_ARGCHK(key != NULL);\n    if (ltc_ecc_is_valid_idx(key->idx))\n        return key->dp->size;\n    else\n        return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_get_size.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_import.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\nstatic int is_point(ecc_key *key) {\n    void *prime, *b, *t1, *t2;\n    int  err;\n\n    if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* load prime and b */\n    if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* compute y^2 */\n    if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* compute x^3 */\n    if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* compute y^2 - x^3 */\n    if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* compute y^2 - x^3 + 3x */\n    if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    while (mp_cmp_d(t1, 0) == LTC_MP_LT) {\n        if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) {\n            goto error;\n        }\n    }\n    while (mp_cmp(t1, prime) != LTC_MP_LT) {\n        if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) {\n            goto error;\n        }\n    }\n\n    /* compare to b */\n    if (mp_cmp(t1, b) != LTC_MP_EQ) {\n        err = CRYPT_INVALID_PACKET;\n    } else {\n        err = CRYPT_OK;\n    }\n\nerror:\n    mp_clear_multi(prime, b, t1, t2, NULL);\n    return err;\n}\n\n/**\n   Import an ECC key from a binary packet\n   @param in      The packet to import\n   @param inlen   The length of the packet\n   @param key     [out] The destination of the import\n   @return CRYPT_OK if successful, upon error all allocated memory will be freed\n */\nint ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) {\n    return ecc_import_ex(in, inlen, key, NULL);\n}\n\n/**\n   Import an ECC key from a binary packet, using user supplied domain params rather than one of the NIST ones\n   @param in      The packet to import\n   @param inlen   The length of the packet\n   @param key     [out] The destination of the import\n   @param dp      pointer to user supplied params; must be the same as the params used when exporting\n   @return CRYPT_OK if successful, upon error all allocated memory will be freed\n */\nint ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp) {\n    unsigned long key_size;\n    unsigned char flags[1];\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(key != NULL);\n    LTC_ARGCHK(ltc_mp.name != NULL);\n\n    /* init key */\n    if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {\n        return CRYPT_MEM;\n    }\n\n    /* find out what type of key it is */\n    if ((err = der_decode_sequence_multi(in, inlen,\n                                         LTC_ASN1_BIT_STRING, 1UL, &flags,\n                                         LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {\n        goto done;\n    }\n\n\n    if (flags[0] == 1) {\n        /* private key */\n        key->type = PK_PRIVATE;\n        if ((err = der_decode_sequence_multi(in, inlen,\n                                             LTC_ASN1_BIT_STRING, 1UL, flags,\n                                             LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,\n                                             LTC_ASN1_INTEGER, 1UL, key->pubkey.x,\n                                             LTC_ASN1_INTEGER, 1UL, key->pubkey.y,\n                                             LTC_ASN1_INTEGER, 1UL, key->k,\n                                             LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {\n            goto done;\n        }\n    } else {\n        /* public key */\n        key->type = PK_PUBLIC;\n        if ((err = der_decode_sequence_multi(in, inlen,\n                                             LTC_ASN1_BIT_STRING, 1UL, flags,\n                                             LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,\n                                             LTC_ASN1_INTEGER, 1UL, key->pubkey.x,\n                                             LTC_ASN1_INTEGER, 1UL, key->pubkey.y,\n                                             LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    if (dp == NULL) {\n        /* find the idx */\n        for (key->idx = 0; ltc_ecc_sets[key->idx].size && (unsigned long)ltc_ecc_sets[key->idx].size != key_size; ++key->idx);\n        if (ltc_ecc_sets[key->idx].size == 0) {\n            err = CRYPT_INVALID_PACKET;\n            goto done;\n        }\n        key->dp = &ltc_ecc_sets[key->idx];\n    } else {\n        key->idx = -1;\n        key->dp  = dp;\n    }\n    /* set z */\n    if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* is it a point on the curve?  */\n    if ((err = is_point(key)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* we're good */\n    return CRYPT_OK;\ndone:\n    mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n    return err;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_import.c,v $ */\n/* $Revision: 1.13 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_make_key.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Make a new ECC key\n   @param prng         An active PRNG state\n   @param wprng        The index of the PRNG you wish to use\n   @param keysize      The keysize for the new key (in octets from 20 to 65 bytes)\n   @param key          [out] Destination of the newly created key\n   @return CRYPT_OK if successful, upon error all allocated memory will be freed\n */\nint ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) {\n    int x, err;\n\n    /* find key size */\n    for (x = 0; (keysize > ltc_ecc_sets[x].size) && (ltc_ecc_sets[x].size != 0); x++);\n    keysize = ltc_ecc_sets[x].size;\n\n    if ((keysize > ECC_MAXSIZE) || (ltc_ecc_sets[x].size == 0)) {\n        return CRYPT_INVALID_KEYSIZE;\n    }\n    err      = ecc_make_key_ex(prng, wprng, key, &ltc_ecc_sets[x]);\n    key->idx = x;\n    return err;\n}\n\nint ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp) {\n    int           err;\n    ecc_point     *base;\n    void          *prime, *order;\n    unsigned char *buf;\n    int           keysize;\n\n    LTC_ARGCHK(key != NULL);\n    LTC_ARGCHK(ltc_mp.name != NULL);\n    LTC_ARGCHK(dp != NULL);\n\n    /* good prng? */\n    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {\n        return err;\n    }\n\n    key->idx = -1;\n    key->dp  = dp;\n    keysize  = dp->size;\n\n    /* allocate ram */\n    base = NULL;\n    buf  = XMALLOC(ECC_MAXSIZE);\n    if (buf == NULL) {\n        return CRYPT_MEM;\n    }\n\n    /* make up random string */\n    if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {\n        err = CRYPT_ERROR_READPRNG;\n        goto ERR_BUF;\n    }\n\n    /* setup the key variables */\n    if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, NULL)) != CRYPT_OK) {\n        goto ERR_BUF;\n    }\n    base = ltc_ecc_new_point();\n    if (base == NULL) {\n        err = CRYPT_MEM;\n        goto errkey;\n    }\n\n    /* read in the specs for this key */\n    if ((err = mp_read_radix(prime, (char *)key->dp->prime, 16)) != CRYPT_OK) {\n        goto errkey;\n    }\n    if ((err = mp_read_radix(order, (char *)key->dp->order, 16)) != CRYPT_OK) {\n        goto errkey;\n    }\n    if ((err = mp_read_radix(base->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) {\n        goto errkey;\n    }\n    if ((err = mp_read_radix(base->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) {\n        goto errkey;\n    }\n    if ((err = mp_set(base->z, 1)) != CRYPT_OK) {\n        goto errkey;\n    }\n    if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != CRYPT_OK) {\n        goto errkey;\n    }\n\n    /* the key should be smaller than the order of base point */\n    if (mp_cmp(key->k, order) != LTC_MP_LT) {\n        if ((err = mp_mod(key->k, order, key->k)) != CRYPT_OK) {\n            goto errkey;\n        }\n    }\n    /* make the public key */\n    if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, 1)) != CRYPT_OK) {\n        goto errkey;\n    }\n    key->type = PK_PRIVATE;\n\n    /* free up ram */\n    err = CRYPT_OK;\n    goto cleanup;\nerrkey:\n    mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\ncleanup:\n    ltc_ecc_del_point(base);\n    mp_clear_multi(prime, order, NULL);\nERR_BUF:\n #ifdef LTC_CLEAN_STACK\n    zeromem(buf, ECC_MAXSIZE);\n #endif\n    XFREE(buf);\n    return err;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_make_key.c,v $ */\n/* $Revision: 1.13 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_shared_secret.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Create an ECC shared secret between two keys\n   @param private_key      The private ECC key\n   @param public_key       The public key\n   @param out              [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)\n   @param outlen           [in/out] The max size and resulting size of the shared secret\n   @return CRYPT_OK if successful\n */\nint ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,\n                      unsigned char *out, unsigned long *outlen) {\n    unsigned long x;\n    ecc_point     *result;\n    void          *prime;\n    int           err;\n\n    LTC_ARGCHK(private_key != NULL);\n    LTC_ARGCHK(public_key != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* type valid? */\n    if (private_key->type != PK_PRIVATE) {\n        return CRYPT_PK_NOT_PRIVATE;\n    }\n\n    if ((ltc_ecc_is_valid_idx(private_key->idx) == 0) || (ltc_ecc_is_valid_idx(public_key->idx) == 0)) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    if (XSTRCMP(private_key->dp->name, public_key->dp->name) != 0) {\n        return CRYPT_PK_TYPE_MISMATCH;\n    }\n\n    /* make new point */\n    result = ltc_ecc_new_point();\n    if (result == NULL) {\n        return CRYPT_MEM;\n    }\n\n    if ((err = mp_init(&prime)) != CRYPT_OK) {\n        ltc_ecc_del_point(result);\n        return err;\n    }\n\n    if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1)) != CRYPT_OK) {\n        goto done;\n    }\n\n    x = (unsigned long)mp_unsigned_bin_size(prime);\n    if (*outlen < x) {\n        *outlen = x;\n        err     = CRYPT_BUFFER_OVERFLOW;\n        goto done;\n    }\n    zeromem(out, x);\n    if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) {\n        goto done;\n    }\n\n    err     = CRYPT_OK;\n    *outlen = x;\ndone:\n    mp_clear(prime);\n    ltc_ecc_del_point(result);\n    return err;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_shared_secret.c,v $ */\n/* $Revision: 1.10 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_sign_hash.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Sign a message digest\n   @param in        The message digest to sign\n   @param inlen     The length of the digest\n   @param out       [out] The destination for the signature\n   @param outlen    [in/out] The max size and resulting size of the signature\n   @param prng      An active PRNG state\n   @param wprng     The index of the PRNG you wish to use\n   @param key       A private ECC key\n   @return CRYPT_OK if successful\n */\nint ecc_sign_hash(const unsigned char *in, unsigned long inlen,\n                  unsigned char *out, unsigned long *outlen,\n                  prng_state *prng, int wprng, ecc_key *key) {\n    ecc_key pubkey;\n    void    *r, *s, *e, *p;\n    int     err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* is this a private key? */\n    if (key->type != PK_PRIVATE) {\n        return CRYPT_PK_NOT_PRIVATE;\n    }\n\n    /* is the IDX valid ?  */\n    if (ltc_ecc_is_valid_idx(key->idx) != 1) {\n        return CRYPT_PK_INVALID_TYPE;\n    }\n\n    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* get the hash and load it as a bignum into 'e' */\n    /* init the bignums */\n    if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) {\n        return err;\n    }\n    if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) {\n        goto errnokey;\n    }\n    if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != CRYPT_OK) {\n        goto errnokey;\n    }\n\n    /* make up a key and export the public copy */\n    for ( ; ; ) {\n        if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {\n            goto errnokey;\n        }\n\n        /* find r = x1 mod n */\n        if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) {\n            goto error;\n        }\n\n        if (mp_iszero(r) == LTC_MP_YES) {\n            ecc_free(&pubkey);\n        } else {\n            /* find s = (e + xr)/k */\n            if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) {\n                goto error;\n            }                                                                                /* k = 1/k */\n            if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) {\n                goto error;\n            }                                                                                /* s = xr */\n            if ((err = mp_add(e, s, s)) != CRYPT_OK) {\n                goto error;\n            }                                                                                /* s = e +  xr */\n            if ((err = mp_mod(s, p, s)) != CRYPT_OK) {\n                goto error;\n            }                                                                                /* s = e +  xr */\n            if ((err = mp_mulmod(s, pubkey.k, p, s)) != CRYPT_OK) {\n                goto error;\n            }                                                                                /* s = (e + xr)/k */\n            ecc_free(&pubkey);\n            if (mp_iszero(s) == LTC_MP_NO) {\n                break;\n            }\n        }\n    }\n\n    /* store as SEQUENCE { r, s -- integer } */\n    err = der_encode_sequence_multi(out, outlen,\n                                    LTC_ASN1_INTEGER, 1UL, r,\n                                    LTC_ASN1_INTEGER, 1UL, s,\n                                    LTC_ASN1_EOL, 0UL, NULL);\n    goto errnokey;\nerror:\n    ecc_free(&pubkey);\nerrnokey:\n    mp_clear_multi(r, s, p, e, NULL);\n    return err;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sign_hash.c,v $ */\n/* $Revision: 1.11 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_sizes.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\nvoid ecc_sizes(int *low, int *high) {\n    int i;\n\n    LTC_ARGCHKVD(low != NULL);\n    LTC_ARGCHKVD(high != NULL);\n\n    *low  = INT_MAX;\n    *high = 0;\n    for (i = 0; ltc_ecc_sets[i].size != 0; i++) {\n        if (ltc_ecc_sets[i].size < *low) {\n            *low = ltc_ecc_sets[i].size;\n        }\n        if (ltc_ecc_sets[i].size > *high) {\n            *high = ltc_ecc_sets[i].size;\n        }\n    }\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sizes.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_test.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Perform on the ECC system\n   @return CRYPT_OK if successful\n */\nint ecc_test(void) {\n    void      *modulus, *order;\n    ecc_point *G, *GG;\n    int       i, err, primality;\n\n    if ((err = mp_init_multi(&modulus, &order, NULL)) != CRYPT_OK) {\n        return err;\n    }\n\n    G  = ltc_ecc_new_point();\n    GG = ltc_ecc_new_point();\n    if ((G == NULL) || (GG == NULL)) {\n        mp_clear_multi(modulus, order, NULL);\n        ltc_ecc_del_point(G);\n        ltc_ecc_del_point(GG);\n        return CRYPT_MEM;\n    }\n\n    for (i = 0; ltc_ecc_sets[i].size; i++) {\n #if 0\n        printf(\"Testing %d\\n\", ltc_ecc_sets[i].size);\n #endif\n        if ((err = mp_read_radix(modulus, (char *)ltc_ecc_sets[i].prime, 16)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_read_radix(order, (char *)ltc_ecc_sets[i].order, 16)) != CRYPT_OK) {\n            goto done;\n        }\n\n        /* is prime actually prime? */\n        if ((err = mp_prime_is_prime(modulus, 8, &primality)) != CRYPT_OK) {\n            goto done;\n        }\n        if (primality == 0) {\n            err = CRYPT_FAIL_TESTVECTOR;\n            goto done;\n        }\n\n        /* is order prime ? */\n        if ((err = mp_prime_is_prime(order, 8, &primality)) != CRYPT_OK) {\n            goto done;\n        }\n        if (primality == 0) {\n            err = CRYPT_FAIL_TESTVECTOR;\n            goto done;\n        }\n\n        if ((err = mp_read_radix(G->x, (char *)ltc_ecc_sets[i].Gx, 16)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_read_radix(G->y, (char *)ltc_ecc_sets[i].Gy, 16)) != CRYPT_OK) {\n            goto done;\n        }\n        mp_set(G->z, 1);\n\n        /* then we should have G == (order + 1)G */\n        if ((err = mp_add_d(order, 1, order)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = ltc_mp.ecc_ptmul(order, G, GG, modulus, 1)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((mp_cmp(G->x, GG->x) != LTC_MP_EQ) || (mp_cmp(G->y, GG->y) != LTC_MP_EQ)) {\n            err = CRYPT_FAIL_TESTVECTOR;\n            goto done;\n        }\n    }\n    err = CRYPT_OK;\ndone:\n    ltc_ecc_del_point(GG);\n    ltc_ecc_del_point(G);\n    mp_clear_multi(order, modulus, NULL);\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_test.c,v $ */\n/* $Revision: 1.12 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ecc_verify_hash.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/* verify\n *\n * w  = s^-1 mod n\n * u1 = xw\n * u2 = rw\n * X = u1*G + u2*Q\n * v = X_x1 mod n\n * accept if v == r\n */\n\n/**\n   Verify an ECC signature\n   @param sig         The signature to verify\n   @param siglen      The length of the signature (octets)\n   @param hash        The hash (message digest) that was signed\n   @param hashlen     The length of the hash (octets)\n   @param stat        Result of signature, 1==valid, 0==invalid\n   @param key         The corresponding public ECC key\n   @return CRYPT_OK if successful (even if the signature is not valid)\n */\nint ecc_verify_hash(const unsigned char *sig, unsigned long siglen,\n                    const unsigned char *hash, unsigned long hashlen,\n                    int *stat, ecc_key *key) {\n    ecc_point *mG, *mQ;\n    void      *r, *s, *v, *w, *u1, *u2, *e, *p, *m;\n    void      *mp;\n    int       err;\n\n    LTC_ARGCHK(sig != NULL);\n    LTC_ARGCHK(hash != NULL);\n    LTC_ARGCHK(stat != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* default to invalid signature */\n    *stat = 0;\n    mp    = NULL;\n\n    /* is the IDX valid ?  */\n    if (ltc_ecc_is_valid_idx(key->idx) != 1) {\n        return CRYPT_PK_INVALID_TYPE;\n    }\n\n    /* allocate ints */\n    if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) {\n        return CRYPT_MEM;\n    }\n\n    /* allocate points */\n    mG = ltc_ecc_new_point();\n    mQ = ltc_ecc_new_point();\n    if ((mQ == NULL) || (mG == NULL)) {\n        err = CRYPT_MEM;\n        goto error;\n    }\n\n    /* parse header */\n    if ((err = der_decode_sequence_multi(sig, siglen,\n                                         LTC_ASN1_INTEGER, 1UL, r,\n                                         LTC_ASN1_INTEGER, 1UL, s,\n                                         LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* get the order */\n    if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* get the modulus */\n    if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* check for zero */\n    if (mp_iszero(r) || mp_iszero(s) || (mp_cmp(r, p) != LTC_MP_LT) || (mp_cmp(s, p) != LTC_MP_LT)) {\n        err = CRYPT_INVALID_PACKET;\n        goto error;\n    }\n\n    /* read hash */\n    if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /*  w  = s^-1 mod n */\n    if ((err = mp_invmod(s, p, w)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* u1 = ew */\n    if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* u2 = rw */\n    if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* find mG and mQ */\n    if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_set(mG->z, 1)) != CRYPT_OK) {\n        goto error;\n    }\n\n    if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* compute u1*mG + u2*mQ = mG */\n    if (ltc_mp.ecc_mul2add == NULL) {\n        if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, 0)) != CRYPT_OK) {\n            goto error;\n        }\n        if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0)) != CRYPT_OK) {\n            goto error;\n        }\n\n        /* find the montgomery mp */\n        if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) {\n            goto error;\n        }\n\n        /* add them */\n        if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp)) != CRYPT_OK) {\n            goto error;\n        }\n\n        /* reduce */\n        if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) {\n            goto error;\n        }\n    } else {\n        /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */\n        if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m)) != CRYPT_OK) {\n            goto error;\n        }\n    }\n\n    /* v = X_x1 mod n */\n    if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* does v == r */\n    if (mp_cmp(v, r) == LTC_MP_EQ) {\n        *stat = 1;\n    }\n\n    /* clear up and return */\n    err = CRYPT_OK;\nerror:\n    ltc_ecc_del_point(mG);\n    ltc_ecc_del_point(mQ);\n    mp_clear_multi(r, s, v, w, u1, u2, p, e, m, NULL);\n    if (mp != NULL) {\n        mp_montgomery_free(mp);\n    }\n    return err;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_verify_hash.c,v $ */\n/* $Revision: 1.14 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n\n/**\n   @file error_to_string.c\n   Convert error codes to ASCII strings, Tom St Denis\n */\n\nstatic const char * const err_2_str[] =\n{\n    \"CRYPT_OK\",\n    \"CRYPT_ERROR\",\n    \"Non-fatal 'no-operation' requested.\",\n\n    \"Invalid keysize for block cipher.\",\n    \"Invalid number of rounds for block cipher.\",\n    \"Algorithm failed test vectors.\",\n\n    \"Buffer overflow.\",\n    \"Invalid input packet.\",\n\n    \"Invalid number of bits for a PRNG.\",\n    \"Error reading the PRNG.\",\n\n    \"Invalid cipher specified.\",\n    \"Invalid hash specified.\",\n    \"Invalid PRNG specified.\",\n\n    \"Out of memory.\",\n\n    \"Invalid PK key or key type specified for function.\",\n    \"A private PK key is required.\",\n\n    \"Invalid argument provided.\",\n    \"File Not Found\",\n\n    \"Invalid PK type.\",\n    \"Invalid PK system.\",\n    \"Duplicate PK key found on keyring.\",\n    \"Key not found in keyring.\",\n    \"Invalid sized parameter.\",\n\n    \"Invalid size for prime.\",\n};\n\n/**\n   Convert an LTC error code to ASCII\n   @param err    The error code\n   @return A pointer to the ASCII NUL terminated string for the error or \"Invalid error code.\" if the err code was not valid.\n */\nconst char *error_to_string(int err) {\n    if ((err < 0) || (err >= (int)(sizeof(err_2_str) / sizeof(err_2_str[0])))) {\n        return \"Invalid error code.\";\n    } else {\n        return err_2_str[err];\n    }\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/error_to_string.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n#define DESC_DEF_ONLY\n\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/math/gmp_desc.c,v $ */\n/* $Revision: 1.16 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file hash_file.c\n   Hash a file, Tom St Denis\n */\n\n/**\n   @param hash   The index of the hash desired\n   @param fname  The name of the file you wish to hash\n   @param out    [out] The destination of the digest\n   @param outlen [in/out] The max size and resulting size of the message digest\n   @result CRYPT_OK if successful\n */\nint hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen) {\n#ifdef LTC_NO_FILE\n    return CRYPT_NOP;\n#else\n    FILE *in;\n    int  err;\n    LTC_ARGCHK(fname != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    if ((err = hash_is_valid(hash)) != CRYPT_OK) {\n        return err;\n    }\n\n    in = fopen(fname, \"rb\");\n    if (in == NULL) {\n        return CRYPT_FILE_NOTFOUND;\n    }\n\n    err = hash_filehandle(hash, in, out, outlen);\n    if (fclose(in) != 0) {\n        return CRYPT_ERROR;\n    }\n\n    return err;\n#endif\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_file.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:23 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file hash_filehandle.c\n   Hash open files, Tom St Denis\n */\n\n/**\n   Hash data from an open file handle.\n   @param hash   The index of the hash you want to use\n   @param in     The FILE* handle of the file you want to hash\n   @param out    [out] The destination of the digest\n   @param outlen [in/out] The max size and resulting size of the digest\n   @result CRYPT_OK if successful\n */\nint hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen) {\n#ifdef LTC_NO_FILE\n    return CRYPT_NOP;\n#else\n    hash_state    md;\n    unsigned char buf[512];\n    size_t        x;\n    int           err;\n\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(in != NULL);\n\n    if ((err = hash_is_valid(hash)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (*outlen < hash_descriptor[hash].hashsize) {\n        *outlen = hash_descriptor[hash].hashsize;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n    if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) {\n        return err;\n    }\n\n    *outlen = hash_descriptor[hash].hashsize;\n    do {\n        x = fread(buf, 1, sizeof(buf), in);\n        if ((err = hash_descriptor[hash].process(&md, buf, x)) != CRYPT_OK) {\n            return err;\n        }\n    } while (x == sizeof(buf));\n    err = hash_descriptor[hash].done(&md, out);\n\n #ifdef LTC_CLEAN_STACK\n    zeromem(buf, sizeof(buf));\n #endif\n    return err;\n#endif\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_filehandle.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:23 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file hash_memory.c\n   Hash memory helper, Tom St Denis\n */\n\n/**\n   Hash a block of memory and store the digest.\n   @param hash   The index of the hash you wish to use\n   @param in     The data you wish to hash\n   @param inlen  The length of the data to hash (octets)\n   @param out    [out] Where to store the digest\n   @param outlen [in/out] Max size and resulting size of the digest\n   @return CRYPT_OK if successful\n */\nint hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) {\n    hash_state *md;\n    int        err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    if ((err = hash_is_valid(hash)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (*outlen < hash_descriptor[hash].hashsize) {\n        *outlen = hash_descriptor[hash].hashsize;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    md = XMALLOC(sizeof(hash_state));\n    if (md == NULL) {\n        return CRYPT_MEM;\n    }\n\n    if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    err     = hash_descriptor[hash].done(md, out);\n    *outlen = hash_descriptor[hash].hashsize;\nLBL_ERR:\n#ifdef LTC_CLEAN_STACK\n    zeromem(md, sizeof(hash_state));\n#endif\n    XFREE(md);\n\n    return err;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_memory.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:23 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file hash_memory_multi.c\n   Hash (multiple buffers) memory helper, Tom St Denis\n */\n\n/**\n   Hash multiple (non-adjacent) blocks of memory at once.\n   @param hash   The index of the hash you wish to use\n   @param out    [out] Where to store the digest\n   @param outlen [in/out] Max size and resulting size of the digest\n   @param in     The data you wish to hash\n   @param inlen  The length of the data to hash (octets)\n   @param ...    tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care)\n   @return CRYPT_OK if successful\n */\nint hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,\n                      const unsigned char *in, unsigned long inlen, ...) {\n    hash_state          *md;\n    int                 err;\n    va_list             args;\n    const unsigned char *curptr;\n    unsigned long       curlen;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    if ((err = hash_is_valid(hash)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (*outlen < hash_descriptor[hash].hashsize) {\n        *outlen = hash_descriptor[hash].hashsize;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    md = XMALLOC(sizeof(hash_state));\n    if (md == NULL) {\n        return CRYPT_MEM;\n    }\n\n    if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    va_start(args, inlen);\n    curptr = in;\n    curlen = inlen;\n    for ( ; ; ) {\n        /* process buf */\n        if ((err = hash_descriptor[hash].process(md, curptr, curlen)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n        /* step to next */\n        curptr = va_arg(args, const unsigned char *);\n        if (curptr == NULL) {\n            break;\n        }\n        curlen = va_arg(args, unsigned long);\n    }\n    err     = hash_descriptor[hash].done(md, out);\n    *outlen = hash_descriptor[hash].hashsize;\nLBL_ERR:\n#ifdef LTC_CLEAN_STACK\n    zeromem(md, sizeof(hash_state));\n#endif\n    XFREE(md);\n    va_end(args);\n    return err;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_memory_multi.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:23 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ltc_ecc_is_valid_idx.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/** Returns whether an ECC idx is valid or not\n   @param n   The idx number to check\n   @return 1 if valid, 0 if not\n */\nint ltc_ecc_is_valid_idx(int n) {\n    int x;\n\n    for (x = 0; ltc_ecc_sets[x].size != 0; x++);\n    /* -1 is a valid index --- indicating that the domain params were supplied by the user */\n    if ((n >= -1) && (n < x)) {\n        return 1;\n    }\n    return 0;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ltc_ecc_map.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Map a projective jacbobian point back to affine space\n   @param P        [in/out] The point to map\n   @param modulus  The modulus of the field the ECC curve is in\n   @param mp       The \"b\" value from montgomery_setup()\n   @return CRYPT_OK on success\n */\nint ltc_ecc_map(ecc_point *P, void *modulus, void *mp) {\n    void *t1, *t2;\n    int  err;\n\n    LTC_ARGCHK(P != NULL);\n    LTC_ARGCHK(modulus != NULL);\n    LTC_ARGCHK(mp != NULL);\n\n    if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {\n        return CRYPT_MEM;\n    }\n\n    /* first map z back to normal */\n    if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* get 1/z */\n    if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* get 1/z^2 and 1/z^3 */\n    if ((err = mp_sqr(t1, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* multiply against x/y */\n    if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_set(P->z, 1)) != CRYPT_OK) {\n        goto done;\n    }\n\n    err = CRYPT_OK;\ndone:\n    mp_clear_multi(t1, t2, NULL);\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_map.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ltc_ecc_mul2add.c\n   ECC Crypto, Shamir's Trick, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n #ifdef LTC_ECC_SHAMIR\n\n/** Computes kA*A + kB*B = C using Shamir's Trick\n   @param A        First point to multiply\n   @param kA       What to multiple A by\n   @param B        Second point to multiply\n   @param kB       What to multiple B by\n   @param C        [out] Destination point (can overlap with A or B\n   @param modulus  Modulus for curve\n   @return CRYPT_OK on success\n */\nint ltc_ecc_mul2add(ecc_point *A, void *kA,\n                    ecc_point *B, void *kB,\n                    ecc_point *C,\n                    void *modulus) {\n    ecc_point     *precomp[16];\n    unsigned      bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble;\n    unsigned char *tA, *tB;\n    int           err, first;\n    void          *mp, *mu;\n\n    /* argchks */\n    LTC_ARGCHK(A != NULL);\n    LTC_ARGCHK(B != NULL);\n    LTC_ARGCHK(C != NULL);\n    LTC_ARGCHK(kA != NULL);\n    LTC_ARGCHK(kB != NULL);\n    LTC_ARGCHK(modulus != NULL);\n\n    /* allocate memory */\n    tA = XCALLOC(1, ECC_BUF_SIZE);\n    if (tA == NULL) {\n        return CRYPT_MEM;\n    }\n    tB = XCALLOC(1, ECC_BUF_SIZE);\n    if (tB == NULL) {\n        XFREE(tA);\n        return CRYPT_MEM;\n    }\n\n    /* get sizes */\n    lenA = mp_unsigned_bin_size(kA);\n    lenB = mp_unsigned_bin_size(kB);\n    len  = TOM_MAX(lenA, lenB);\n\n    /* sanity check */\n    if ((lenA > ECC_BUF_SIZE) || (lenB > ECC_BUF_SIZE)) {\n        err = CRYPT_INVALID_ARG;\n        goto ERR_T;\n    }\n\n    /* extract and justify kA */\n    mp_to_unsigned_bin(kA, (len - lenA) + tA);\n\n    /* extract and justify kB */\n    mp_to_unsigned_bin(kB, (len - lenB) + tB);\n\n    /* allocate the table */\n    for (x = 0; x < 16; x++) {\n        precomp[x] = ltc_ecc_new_point();\n        if (precomp[x] == NULL) {\n            for (y = 0; y < x; ++y) {\n                ltc_ecc_del_point(precomp[y]);\n            }\n            err = CRYPT_MEM;\n            goto ERR_T;\n        }\n    }\n\n    /* init montgomery reduction */\n    if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {\n        goto ERR_P;\n    }\n    if ((err = mp_init(&mu)) != CRYPT_OK) {\n        goto ERR_MP;\n    }\n    if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n\n    /* copy ones ... */\n    if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n    if ((err = mp_mulmod(A->y, mu, modulus, precomp[1]->y)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n    if ((err = mp_mulmod(A->z, mu, modulus, precomp[1]->z)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n\n    if ((err = mp_mulmod(B->x, mu, modulus, precomp[1 << 2]->x)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n    if ((err = mp_mulmod(B->y, mu, modulus, precomp[1 << 2]->y)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n    if ((err = mp_mulmod(B->z, mu, modulus, precomp[1 << 2]->z)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n\n    /* precomp [i,0](A + B) table */\n    if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], modulus, mp)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n    if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], modulus, mp)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n\n    /* precomp [0,i](A + B) table */\n    if ((err = ltc_mp.ecc_ptdbl(precomp[1 << 2], precomp[2 << 2], modulus, mp)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n    if ((err = ltc_mp.ecc_ptadd(precomp[1 << 2], precomp[2 << 2], precomp[3 << 2], modulus, mp)) != CRYPT_OK) {\n        goto ERR_MU;\n    }\n\n    /* precomp [i,j](A + B) table (i != 0, j != 0) */\n    for (x = 1; x < 4; x++) {\n        for (y = 1; y < 4; y++) {\n            if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y << 2)], precomp[x + (y << 2)], modulus, mp)) != CRYPT_OK) {\n                goto ERR_MU;\n            }\n        }\n    }\n\n    nibble  = 3;\n    first   = 1;\n    bitbufA = tA[0];\n    bitbufB = tB[0];\n\n    /* for every byte of the multiplicands */\n    for (x = -1; ; ) {\n        /* grab a nibble */\n        if (++nibble == 4) {\n            ++x;\n            if (x == len) break;\n            bitbufA = tA[x];\n            bitbufB = tB[x];\n            nibble  = 0;\n        }\n\n        /* extract two bits from both, shift/update */\n        nA      = (bitbufA >> 6) & 0x03;\n        nB      = (bitbufB >> 6) & 0x03;\n        bitbufA = (bitbufA << 2) & 0xFF;\n        bitbufB = (bitbufB << 2) & 0xFF;\n\n        /* if both zero, if first, continue */\n        if ((nA == 0) && (nB == 0) && (first == 1)) {\n            continue;\n        }\n\n        /* double twice, only if this isn't the first */\n        if (first == 0) {\n            /* double twice */\n            if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) {\n                goto ERR_MU;\n            }\n            if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) {\n                goto ERR_MU;\n            }\n        }\n\n        /* if not both zero */\n        if ((nA != 0) || (nB != 0)) {\n            if (first == 1) {\n                /* if first, copy from table */\n                first = 0;\n                if ((err = mp_copy(precomp[nA + (nB << 2)]->x, C->x)) != CRYPT_OK) {\n                    goto ERR_MU;\n                }\n                if ((err = mp_copy(precomp[nA + (nB << 2)]->y, C->y)) != CRYPT_OK) {\n                    goto ERR_MU;\n                }\n                if ((err = mp_copy(precomp[nA + (nB << 2)]->z, C->z)) != CRYPT_OK) {\n                    goto ERR_MU;\n                }\n            } else {\n                /* if not first, add from table */\n                if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB << 2)], C, modulus, mp)) != CRYPT_OK) {\n                    goto ERR_MU;\n                }\n            }\n        }\n    }\n\n    /* reduce to affine */\n    err = ltc_ecc_map(C, modulus, mp);\n\n    /* clean up */\nERR_MU:\n    mp_clear(mu);\nERR_MP:\n    mp_montgomery_free(mp);\nERR_P:\n    for (x = 0; x < 16; x++) {\n        ltc_ecc_del_point(precomp[x]);\n    }\nERR_T:\n  #ifdef LTC_CLEAN_STACK\n    zeromem(tA, ECC_BUF_SIZE);\n    zeromem(tB, ECC_BUF_SIZE);\n  #endif\n    XFREE(tA);\n    XFREE(tB);\n\n    return err;\n}\n #endif\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c,v $ */\n/* $Revision: 1.8 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ltc_ecc_mulmod.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n #ifndef LTC_ECC_TIMING_RESISTANT\n\n/* size of sliding window, don't change this! */\n  #define WINSIZE    4\n\n/**\n   Perform a point multiplication\n   @param k    The scalar to multiply by\n   @param G    The base point\n   @param R    [out] Destination for kG\n   @param modulus  The modulus of the field the ECC curve is in\n   @param map      Boolean whether to map back to affine or not (1==map, 0 == leave in projective)\n   @return CRYPT_OK on success\n */\nint ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) {\n    ecc_point     *tG, *M[8];\n    int           i, j, err;\n    void          *mu, *mp;\n    unsigned long buf;\n    int           first, bitbuf, bitcpy, bitcnt, mode, digidx;\n\n    LTC_ARGCHK(k != NULL);\n    LTC_ARGCHK(G != NULL);\n    LTC_ARGCHK(R != NULL);\n    LTC_ARGCHK(modulus != NULL);\n\n    /* init montgomery reduction */\n    if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {\n        return err;\n    }\n    if ((err = mp_init(&mu)) != CRYPT_OK) {\n        mp_montgomery_free(mp);\n        return err;\n    }\n    if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {\n        mp_montgomery_free(mp);\n        mp_clear(mu);\n        return err;\n    }\n\n    /* alloc ram for window temps */\n    for (i = 0; i < 8; i++) {\n        M[i] = ltc_ecc_new_point();\n        if (M[i] == NULL) {\n            for (j = 0; j < i; j++) {\n                ltc_ecc_del_point(M[j]);\n            }\n            mp_montgomery_free(mp);\n            mp_clear(mu);\n            return CRYPT_MEM;\n        }\n    }\n\n    /* make a copy of G incase R==G */\n    tG = ltc_ecc_new_point();\n    if (tG == NULL) {\n        err = CRYPT_MEM;\n        goto done;\n    }\n\n    /* tG = G  and convert to montgomery */\n    if (mp_cmp_d(mu, 1) == LTC_MP_EQ) {\n        if ((err = mp_copy(G->x, tG->x)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_copy(G->y, tG->y)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_copy(G->z, tG->z)) != CRYPT_OK) {\n            goto done;\n        }\n    } else {\n        if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    mp_clear(mu);\n    mu = NULL;\n\n    /* calc the M tab, which holds kG for k==8..15 */\n    /* M[0] == 8G */\n    if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* now find (8+k)G for k=1..7 */\n    for (j = 9; j < 16; j++) {\n        if ((err = ltc_mp.ecc_ptadd(M[j - 9], tG, M[j - 8], modulus, mp)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* setup sliding window */\n    mode   = 0;\n    bitcnt = 1;\n    buf    = 0;\n    digidx = mp_get_digit_count(k) - 1;\n    bitcpy = bitbuf = 0;\n    first  = 1;\n\n    /* perform ops */\n    for ( ; ; ) {\n        /* grab next digit as required */\n        if (--bitcnt == 0) {\n            if (digidx == -1) {\n                break;\n            }\n            buf    = mp_get_digit(k, digidx);\n            bitcnt = (int)ltc_mp.bits_per_digit;\n            --digidx;\n        }\n\n        /* grab the next msb from the ltiplicand */\n        i     = (buf >> (ltc_mp.bits_per_digit - 1)) & 1;\n        buf <<= 1;\n\n        /* skip leading zero bits */\n        if ((mode == 0) && (i == 0)) {\n            continue;\n        }\n\n        /* if the bit is zero and mode == 1 then we double */\n        if ((mode == 1) && (i == 0)) {\n            if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) {\n                goto done;\n            }\n            continue;\n        }\n\n        /* else we add it to the window */\n        bitbuf |= (i << (WINSIZE - ++bitcpy));\n        mode    = 2;\n\n        if (bitcpy == WINSIZE) {\n            /* if this is the first window we do a simple copy */\n            if (first == 1) {\n                /* R = kG [k = first window] */\n                if ((err = mp_copy(M[bitbuf - 8]->x, R->x)) != CRYPT_OK) {\n                    goto done;\n                }\n                if ((err = mp_copy(M[bitbuf - 8]->y, R->y)) != CRYPT_OK) {\n                    goto done;\n                }\n                if ((err = mp_copy(M[bitbuf - 8]->z, R->z)) != CRYPT_OK) {\n                    goto done;\n                }\n                first = 0;\n            } else {\n                /* normal window */\n                /* ok window is filled so double as required and add  */\n                /* double first */\n                for (j = 0; j < WINSIZE; j++) {\n                    if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) {\n                        goto done;\n                    }\n                }\n\n                /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */\n                if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf - 8], R, modulus, mp)) != CRYPT_OK) {\n                    goto done;\n                }\n            }\n            /* empty window and reset */\n            bitcpy = bitbuf = 0;\n            mode   = 1;\n        }\n    }\n\n    /* if bits remain then double/add */\n    if ((mode == 2) && (bitcpy > 0)) {\n        /* double then add */\n        for (j = 0; j < bitcpy; j++) {\n            /* only double if we have had at least one add first */\n            if (first == 0) {\n                if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) {\n                    goto done;\n                }\n            }\n\n            bitbuf <<= 1;\n            if ((bitbuf & (1 << WINSIZE)) != 0) {\n                if (first == 1) {\n                    /* first add, so copy */\n                    if ((err = mp_copy(tG->x, R->x)) != CRYPT_OK) {\n                        goto done;\n                    }\n                    if ((err = mp_copy(tG->y, R->y)) != CRYPT_OK) {\n                        goto done;\n                    }\n                    if ((err = mp_copy(tG->z, R->z)) != CRYPT_OK) {\n                        goto done;\n                    }\n                    first = 0;\n                } else {\n                    /* then add */\n                    if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK) {\n                        goto done;\n                    }\n                }\n            }\n        }\n    }\n\n    /* map R back from projective space */\n    if (map) {\n        err = ltc_ecc_map(R, modulus, mp);\n    } else {\n        err = CRYPT_OK;\n    }\ndone:\n    if (mu != NULL) {\n        mp_clear(mu);\n    }\n    mp_montgomery_free(mp);\n    ltc_ecc_del_point(tG);\n    for (i = 0; i < 8; i++) {\n        ltc_ecc_del_point(M[i]);\n    }\n    return err;\n}\n #endif\n\n #undef WINSIZE\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c,v $ */\n/* $Revision: 1.26 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ltc_ecc_mulmod_timing.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n #ifdef LTC_ECC_TIMING_RESISTANT\n\n/**\n   Perform a point multiplication  (timing resistant)\n   @param k    The scalar to multiply by\n   @param G    The base point\n   @param R    [out] Destination for kG\n   @param modulus  The modulus of the field the ECC curve is in\n   @param map      Boolean whether to map back to affine or not (1==map, 0 == leave in projective)\n   @return CRYPT_OK on success\n */\nint ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) {\n    ecc_point     *tG, *M[3];\n    int           i, j, err;\n    void          *mu, *mp;\n    unsigned long buf;\n    int           first, bitbuf, bitcpy, bitcnt, mode, digidx;\n\n    LTC_ARGCHK(k != NULL);\n    LTC_ARGCHK(G != NULL);\n    LTC_ARGCHK(R != NULL);\n    LTC_ARGCHK(modulus != NULL);\n\n    /* init montgomery reduction */\n    if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {\n        return err;\n    }\n    if ((err = mp_init(&mu)) != CRYPT_OK) {\n        mp_montgomery_free(mp);\n        return err;\n    }\n    if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {\n        mp_clear(mu);\n        mp_montgomery_free(mp);\n        return err;\n    }\n\n    /* alloc ram for window temps */\n    for (i = 0; i < 3; i++) {\n        M[i] = ltc_ecc_new_point();\n        if (M[i] == NULL) {\n            for (j = 0; j < i; j++) {\n                ltc_ecc_del_point(M[j]);\n            }\n            mp_clear(mu);\n            mp_montgomery_free(mp);\n            return CRYPT_MEM;\n        }\n    }\n\n    /* make a copy of G incase R==G */\n    tG = ltc_ecc_new_point();\n    if (tG == NULL) {\n        err = CRYPT_MEM;\n        goto done;\n    }\n\n    /* tG = G  and convert to montgomery */\n    if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) {\n        goto done;\n    }\n    mp_clear(mu);\n    mu = NULL;\n\n    /* calc the M tab */\n    /* M[0] == G */\n    if ((err = mp_copy(tG->x, M[0]->x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_copy(tG->y, M[0]->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_copy(tG->z, M[0]->z)) != CRYPT_OK) {\n        goto done;\n    }\n    /* M[1] == 2G */\n    if ((err = ltc_mp.ecc_ptdbl(tG, M[1], modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* setup sliding window */\n    mode   = 0;\n    bitcnt = 1;\n    buf    = 0;\n    digidx = mp_get_digit_count(k) - 1;\n    bitcpy = bitbuf = 0;\n    first  = 1;\n\n    /* perform ops */\n    for ( ; ; ) {\n        /* grab next digit as required */\n        if (--bitcnt == 0) {\n            if (digidx == -1) {\n                break;\n            }\n            buf    = mp_get_digit(k, digidx);\n            bitcnt = (int)MP_DIGIT_BIT;\n            --digidx;\n        }\n\n        /* grab the next msb from the ltiplicand */\n        i     = (buf >> (MP_DIGIT_BIT - 1)) & 1;\n        buf <<= 1;\n\n        if ((mode == 0) && (i == 0)) {\n            /* dummy operations */\n            if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) {\n                goto done;\n            }\n            if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) {\n                goto done;\n            }\n            continue;\n        }\n\n        if ((mode == 0) && (i == 1)) {\n            mode = 1;\n            /* dummy operations */\n            if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) {\n                goto done;\n            }\n            if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) {\n                goto done;\n            }\n            continue;\n        }\n\n        if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i ^ 1], modulus, mp)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], modulus, mp)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* copy result out */\n    if ((err = mp_copy(M[0]->x, R->x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_copy(M[0]->y, R->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_copy(M[0]->z, R->z)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* map R back from projective space */\n    if (map) {\n        err = ltc_ecc_map(R, modulus, mp);\n    } else {\n        err = CRYPT_OK;\n    }\ndone:\n    if (mu != NULL) {\n        mp_clear(mu);\n    }\n    mp_montgomery_free(mp);\n    ltc_ecc_del_point(tG);\n    for (i = 0; i < 3; i++) {\n        ltc_ecc_del_point(M[i]);\n    }\n    return err;\n}\n #endif\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c,v $ */\n/* $Revision: 1.13 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ltc_ecc_points.c\n   ECC Crypto, Tom St Denis\n */\n\n#ifdef LTC_MECC\n\n/**\n   Allocate a new ECC point\n   @return A newly allocated point or NULL on error\n */\necc_point *ltc_ecc_new_point(void) {\n    ecc_point *p;\n\n    p = XCALLOC(1, sizeof(*p));\n    if (p == NULL) {\n        return NULL;\n    }\n    if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != CRYPT_OK) {\n        XFREE(p);\n        return NULL;\n    }\n    return p;\n}\n\n/** Free an ECC point from memory\n   @param p   The point to free\n */\nvoid ltc_ecc_del_point(ecc_point *p) {\n    /* prevents free'ing null arguments */\n    if (p != NULL) {\n        mp_clear_multi(p->x, p->y, p->z, NULL); /* note: p->z may be NULL but that's ok with this function anyways */\n        XFREE(p);\n    }\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_points.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ltc_ecc_projective_add_point.c\n   ECC Crypto, Tom St Denis\n */\n\n#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC))\n\n/**\n   Add two ECC points\n   @param P        The point to add\n   @param Q        The point to add\n   @param R        [out] The destination of the double\n   @param modulus  The modulus of the field the ECC curve is in\n   @param mp       The \"b\" value from montgomery_setup()\n   @return CRYPT_OK on success\n */\nint ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp) {\n    void *t1, *t2, *x, *y, *z;\n    int  err;\n\n    LTC_ARGCHK(P != NULL);\n    LTC_ARGCHK(Q != NULL);\n    LTC_ARGCHK(R != NULL);\n    LTC_ARGCHK(modulus != NULL);\n    LTC_ARGCHK(mp != NULL);\n\n    if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* should we dbl instead? */\n    if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) {\n        goto done;\n    }\n\n    if ((mp_cmp(P->x, Q->x) == LTC_MP_EQ) &&\n        ((Q->z != NULL) && (mp_cmp(P->z, Q->z) == LTC_MP_EQ)) &&\n        ((mp_cmp(P->y, Q->y) == LTC_MP_EQ) || (mp_cmp(P->y, t1) == LTC_MP_EQ))) {\n        mp_clear_multi(t1, t2, x, y, z, NULL);\n        return ltc_ecc_projective_dbl_point(P, R, modulus, mp);\n    }\n\n    if ((err = mp_copy(P->x, x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_copy(P->y, y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_copy(P->z, z)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* if Z is one then these are no-operations */\n    if (Q->z != NULL) {\n        /* T1 = Z' * Z' */\n        if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) {\n            goto done;\n        }\n        /* X = X * T1 */\n        if ((err = mp_mul(t1, x, x)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) {\n            goto done;\n        }\n        /* T1 = Z' * T1 */\n        if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) {\n            goto done;\n        }\n        /* Y = Y * T1 */\n        if ((err = mp_mul(t1, y, y)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* T1 = Z*Z */\n    if ((err = mp_sqr(z, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* T2 = X' * T1 */\n    if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* T1 = Z * T1 */\n    if ((err = mp_mul(z, t1, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* T1 = Y' * T1 */\n    if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* Y = Y - T1 */\n    if ((err = mp_sub(y, t1, y)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(y, 0) == LTC_MP_LT) {\n        if ((err = mp_add(y, modulus, y)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T1 = 2T1 */\n    if ((err = mp_add(t1, t1, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(t1, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T1 = Y + T1 */\n    if ((err = mp_add(t1, y, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(t1, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* X = X - T2 */\n    if ((err = mp_sub(x, t2, x)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(x, 0) == LTC_MP_LT) {\n        if ((err = mp_add(x, modulus, x)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T2 = 2T2 */\n    if ((err = mp_add(t2, t2, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(t2, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T2 = X + T2 */\n    if ((err = mp_add(t2, x, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(t2, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* if Z' != 1 */\n    if (Q->z != NULL) {\n        /* Z = Z * Z' */\n        if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* Z = Z * X */\n    if ((err = mp_mul(z, x, z)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* T1 = T1 * X  */\n    if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* X = X * X */\n    if ((err = mp_sqr(x, x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* T2 = T2 * x */\n    if ((err = mp_mul(t2, x, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* T1 = T1 * X  */\n    if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* X = Y*Y */\n    if ((err = mp_sqr(y, x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* X = X - T2 */\n    if ((err = mp_sub(x, t2, x)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(x, 0) == LTC_MP_LT) {\n        if ((err = mp_add(x, modulus, x)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* T2 = T2 - X */\n    if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(t2, 0) == LTC_MP_LT) {\n        if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T2 = T2 - X */\n    if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(t2, 0) == LTC_MP_LT) {\n        if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T2 = T2 * Y */\n    if ((err = mp_mul(t2, y, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* Y = T2 - T1 */\n    if ((err = mp_sub(t2, t1, y)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(y, 0) == LTC_MP_LT) {\n        if ((err = mp_add(y, modulus, y)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* Y = Y/2 */\n    if (mp_isodd(y)) {\n        if ((err = mp_add(y, modulus, y)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    if ((err = mp_div_2(y, y)) != CRYPT_OK) {\n        goto done;\n    }\n\n    if ((err = mp_copy(x, R->x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_copy(y, R->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_copy(z, R->z)) != CRYPT_OK) {\n        goto done;\n    }\n\n    err = CRYPT_OK;\ndone:\n    mp_clear_multi(t1, t2, x, y, z, NULL);\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c,v $ */\n/* $Revision: 1.16 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b\n *\n * All curves taken from NIST recommendation paper of July 1999\n * Available at http://csrc.nist.gov/cryptval/dss.htm\n */\n\n\n/**\n   @file ltc_ecc_projective_dbl_point.c\n   ECC Crypto, Tom St Denis\n */\n\n#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC))\n\n/**\n   Double an ECC point\n   @param P   The point to double\n   @param R   [out] The destination of the double\n   @param modulus  The modulus of the field the ECC curve is in\n   @param mp       The \"b\" value from montgomery_setup()\n   @return CRYPT_OK on success\n */\nint ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp) {\n    void *t1, *t2;\n    int  err;\n\n    LTC_ARGCHK(P != NULL);\n    LTC_ARGCHK(R != NULL);\n    LTC_ARGCHK(modulus != NULL);\n    LTC_ARGCHK(mp != NULL);\n\n    if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (P != R) {\n        if ((err = mp_copy(P->x, R->x)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_copy(P->y, R->y)) != CRYPT_OK) {\n            goto done;\n        }\n        if ((err = mp_copy(P->z, R->z)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* t1 = Z * Z */\n    if ((err = mp_sqr(R->z, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* Z = Y * Z */\n    if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* Z = 2Z */\n    if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(R->z, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* T2 = X - T1 */\n    if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(t2, 0) == LTC_MP_LT) {\n        if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T1 = X + T1 */\n    if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(t1, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T2 = T1 * T2 */\n    if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* T1 = 2T2 */\n    if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(t1, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* T1 = T1 + T2 */\n    if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(t1, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* Y = 2Y */\n    if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp(R->y, modulus) != LTC_MP_LT) {\n        if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* Y = Y * Y */\n    if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* T2 = Y * Y */\n    if ((err = mp_sqr(R->y, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* T2 = T2/2 */\n    if (mp_isodd(t2)) {\n        if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    if ((err = mp_div_2(t2, t2)) != CRYPT_OK) {\n        goto done;\n    }\n    /* Y = Y * X */\n    if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n\n    /* X  = T1 * T1 */\n    if ((err = mp_sqr(t1, R->x)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* X = X - Y */\n    if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {\n        if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* X = X - Y */\n    if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {\n        if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    /* Y = Y - X */\n    if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {\n        if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n    /* Y = Y * T1 */\n    if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) {\n        goto done;\n    }\n    /* Y = Y - T2 */\n    if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK) {\n        goto done;\n    }\n    if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {\n        if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) {\n            goto done;\n        }\n    }\n\n    err = CRYPT_OK;\ndone:\n    mp_clear_multi(t1, t2, NULL);\n    return err;\n}\n#endif\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c,v $ */\n/* $Revision: 1.11 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n#define DESC_DEF_ONLY\n\n#ifdef LTM_DESC\n\n#undef mp_init\n#undef mp_init_multi\n#undef mp_clear\n#undef mp_clear_multi\n#undef mp_init_copy\n#undef mp_neg\n#undef mp_copy\n#undef mp_set\n#undef mp_set_int\n#undef mp_get_int\n#undef mp_get_digit\n#undef mp_get_digit_count\n#undef mp_cmp\n#undef mp_cmp_d\n#undef mp_count_bits\n#undef mp_cnt_lsb\n#undef mp_2expt\n#undef mp_read_radix\n#undef mp_toradix\n#undef mp_unsigned_bin_size\n#undef mp_to_unsigned_bin\n#undef mp_read_unsigned_bin\n#undef mp_add\n#undef mp_add_d\n#undef mp_sub\n#undef mp_sub_d\n#undef mp_mul\n#undef mp_mul_d\n#undef mp_sqr\n#undef mp_div\n#undef mp_div_2\n#undef mp_mod\n#undef mp_mod_d\n#undef mp_gcd\n#undef mp_lcm\n#undef mp_mulmod\n#undef mp_sqrmod\n#undef mp_invmod\n#undef mp_montgomery_setup\n#undef mp_montgomery_normalization\n#undef mp_montgomery_reduce\n#undef mp_montgomery_free\n#undef mp_exptmod\n#undef mp_prime_is_prime\n#undef mp_iszero\n#undef mp_isodd\n#undef mp_exch\n#undef mp_tohex\n\nstatic const struct {\n    int mpi_code, ltc_code;\n} mpi_to_ltc_codes[] = {\n    { MP_OKAY, CRYPT_OK          },\n    { MP_MEM,  CRYPT_MEM         },\n    { MP_VAL,  CRYPT_INVALID_ARG },\n};\n\n/**\n   Convert a MPI error to a LTC error (Possibly the most powerful function ever!  Oh wait... no)\n   @param err    The error to convert\n   @return The equivalent LTC error code or CRYPT_ERROR if none found\n */\nstatic int mpi_to_ltc_error(int err) {\n    int x;\n\n    for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes) / sizeof(mpi_to_ltc_codes[0])); x++) {\n        if (err == mpi_to_ltc_codes[x].mpi_code) {\n            return mpi_to_ltc_codes[x].ltc_code;\n        }\n    }\n    return CRYPT_ERROR;\n}\n\nstatic int init(void **a) {\n    int err;\n\n    LTC_ARGCHK(a != NULL);\n\n    *a = XCALLOC(1, sizeof(mp_int));\n    if (*a == NULL) {\n        return CRYPT_MEM;\n    }\n    if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) {\n        XFREE(*a);\n    }\n    return err;\n}\n\nstatic void deinit(void *a) {\n    LTC_ARGCHKVD(a != NULL);\n    mp_clear(a);\n    XFREE(a);\n}\n\nstatic int neg(void *a, void *b) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_neg(a, b));\n}\n\nstatic int copy(void *a, void *b) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_copy(a, b));\n}\n\nstatic int init_copy(void **a, void *b) {\n    if (init(a) != CRYPT_OK) {\n        return CRYPT_MEM;\n    }\n    return copy(b, *a);\n}\n\n/* ---- trivial ---- */\nstatic int set_int(void *a, unsigned long b) {\n    LTC_ARGCHK(a != NULL);\n    return mpi_to_ltc_error(mp_set_int(a, b));\n}\n\nstatic unsigned long get_int(void *a) {\n    LTC_ARGCHK(a != NULL);\n    return mp_get_int(a);\n}\n\nstatic unsigned long get_digit(void *a, int n) {\n    mp_int *A;\n\n    LTC_ARGCHK(a != NULL);\n    A = a;\n    return (n >= A->used || n < 0) ? 0 : A->dp[n];\n}\n\nstatic int get_digit_count(void *a) {\n    mp_int *A;\n\n    LTC_ARGCHK(a != NULL);\n    A = a;\n    return A->used;\n}\n\nstatic int compare(void *a, void *b) {\n    int ret;\n\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    ret = mp_cmp(a, b);\n    switch (ret) {\n        case MP_LT:\n            return LTC_MP_LT;\n\n        case MP_EQ:\n            return LTC_MP_EQ;\n\n        case MP_GT:\n            return LTC_MP_GT;\n    }\n    return 0;\n}\n\nstatic int compare_d(void *a, unsigned long b) {\n    int ret;\n\n    LTC_ARGCHK(a != NULL);\n    ret = mp_cmp_d(a, b);\n    switch (ret) {\n        case MP_LT:\n            return LTC_MP_LT;\n\n        case MP_EQ:\n            return LTC_MP_EQ;\n\n        case MP_GT:\n            return LTC_MP_GT;\n    }\n    return 0;\n}\n\nstatic int count_bits(void *a) {\n    LTC_ARGCHK(a != NULL);\n    return mp_count_bits(a);\n}\n\nstatic int count_lsb_bits(void *a) {\n    LTC_ARGCHK(a != NULL);\n    return mp_cnt_lsb(a);\n}\n\nstatic int twoexpt(void *a, int n) {\n    LTC_ARGCHK(a != NULL);\n    return mpi_to_ltc_error(mp_2expt(a, n));\n}\n\n/* ---- conversions ---- */\n\n/* read ascii string */\nstatic int read_radix(void *a, const char *b, int radix) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_read_radix(a, b, radix));\n}\n\n/* write one */\nstatic int write_radix(void *a, char *b, int radix) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_toradix(a, b, radix));\n}\n\n/* get size as unsigned char string */\nstatic unsigned long unsigned_size(void *a) {\n    LTC_ARGCHK(a != NULL);\n    return mp_unsigned_bin_size(a);\n}\n\n/* store */\nstatic int unsigned_write(void *a, unsigned char *b) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_to_unsigned_bin(a, b));\n}\n\n/* read */\nstatic int unsigned_read(void *a, unsigned char *b, unsigned long len) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len));\n}\n\n/* add */\nstatic int add(void *a, void *b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_add(a, b, c));\n}\n\nstatic int addi(void *a, unsigned long b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_add_d(a, b, c));\n}\n\n/* sub */\nstatic int sub(void *a, void *b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_sub(a, b, c));\n}\n\nstatic int subi(void *a, unsigned long b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_sub_d(a, b, c));\n}\n\n/* mul */\nstatic int mul(void *a, void *b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_mul(a, b, c));\n}\n\nstatic int muli(void *a, unsigned long b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_mul_d(a, b, c));\n}\n\n/* sqr */\nstatic int sqr(void *a, void *b) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_sqr(a, b));\n}\n\n/* div */\nstatic int divide(void *a, void *b, void *c, void *d) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_div(a, b, c, d));\n}\n\nstatic int div_2(void *a, void *b) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_div_2(a, b));\n}\n\n/* modi */\nstatic int modi(void *a, unsigned long b, unsigned long *c) {\n    mp_digit tmp;\n    int      err;\n\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(c != NULL);\n\n    if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) {\n        return err;\n    }\n    *c = tmp;\n    return CRYPT_OK;\n}\n\n/* gcd */\nstatic int gcd(void *a, void *b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_gcd(a, b, c));\n}\n\n/* lcm */\nstatic int lcm(void *a, void *b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_lcm(a, b, c));\n}\n\nstatic int mulmod(void *a, void *b, void *c, void *d) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    LTC_ARGCHK(d != NULL);\n    return mpi_to_ltc_error(mp_mulmod(a, b, c, d));\n}\n\nstatic int sqrmod(void *a, void *b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_sqrmod(a, b, c));\n}\n\n/* invmod */\nstatic int invmod(void *a, void *b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_invmod(a, b, c));\n}\n\n/* setup */\nstatic int montgomery_setup(void *a, void **b) {\n    int err;\n\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    *b = XCALLOC(1, sizeof(mp_digit));\n    if (*b == NULL) {\n        return CRYPT_MEM;\n    }\n    if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) {\n        XFREE(*b);\n    }\n    return err;\n}\n\n/* get normalization value */\nstatic int montgomery_normalization(void *a, void *b) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b));\n}\n\n/* reduce */\nstatic int montgomery_reduce(void *a, void *b, void *c) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c)));\n}\n\n/* clean up */\nstatic void montgomery_deinit(void *a) {\n    XFREE(a);\n}\n\nstatic int exptmod(void *a, void *b, void *c, void *d) {\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    LTC_ARGCHK(c != NULL);\n    LTC_ARGCHK(d != NULL);\n    return mpi_to_ltc_error(mp_exptmod(a, b, c, d));\n}\n\nstatic int isprime(void *a, int *b) {\n    int err;\n\n    LTC_ARGCHK(a != NULL);\n    LTC_ARGCHK(b != NULL);\n    err = mpi_to_ltc_error(mp_prime_is_prime(a, 8, b));\n    *b  = (*b == MP_YES) ? LTC_MP_YES : LTC_MP_NO;\n    return err;\n}\n\nconst ltc_math_descriptor ltm_desc = {\n    \"LibTomMath\",\n    (int)DIGIT_BIT,\n\n    &init,\n    &init_copy,\n    &deinit,\n\n    &neg,\n    &copy,\n\n    &set_int,\n    &get_int,\n    &get_digit,\n    &get_digit_count,\n    &compare,\n    &compare_d,\n    &count_bits,\n    &count_lsb_bits,\n    &twoexpt,\n\n    &read_radix,\n    &write_radix,\n    &unsigned_size,\n    &unsigned_write,\n    &unsigned_read,\n\n    &add,\n    &addi,\n    &sub,\n    &subi,\n    &mul,\n    &muli,\n    &sqr,\n    &divide,\n    &div_2,\n    &modi,\n    &gcd,\n    &lcm,\n\n    &mulmod,\n    &sqrmod,\n    &invmod,\n\n    &montgomery_setup,\n    &montgomery_normalization,\n    &montgomery_reduce,\n    &montgomery_deinit,\n\n    &exptmod,\n    &isprime,\n\n #ifdef LTC_MECC\n  #ifdef LTC_MECC_FP\n    &ltc_ecc_fp_mulmod,\n  #else\n    &ltc_ecc_mulmod,\n  #endif\n    &ltc_ecc_projective_add_point,\n    &ltc_ecc_projective_dbl_point,\n    &ltc_ecc_map,\n  #ifdef LTC_ECC_SHAMIR\n   #ifdef LTC_MECC_FP\n    &ltc_ecc_fp_mul2add,\n   #else\n    &ltc_ecc_mul2add,\n   #endif /* LTC_MECC_FP */\n  #else\n    NULL,\n  #endif /* LTC_ECC_SHAMIR */\n #else\n    NULL,                         NULL,NULL, NULL, NULL,\n #endif /* LTC_MECC */\n\n #ifdef LTC_MRSA\n    &rsa_make_key,\n    &rsa_exptmod,\n #else\n    NULL,                         NULL\n #endif\n};\n\n #define mp_init(a)                           ltc_mp.init(a)\n #define mp_init_multi     ltc_init_multi\n #define mp_clear(a)                          ltc_mp.deinit(a)\n #define mp_clear_multi    ltc_deinit_multi\n #define mp_init_copy(a, b)                   ltc_mp.init_copy(a, b)\n\n #define mp_neg(a, b)                         ltc_mp.neg(a, b)\n #define mp_copy(a, b)                        ltc_mp.copy(a, b)\n\n #define mp_set(a, b)                         ltc_mp.set_int(a, b)\n #define mp_set_int(a, b)                     ltc_mp.set_int(a, b)\n #define mp_get_int(a)                        ltc_mp.get_int(a)\n #define mp_get_digit(a, n)                   ltc_mp.get_digit(a, n)\n #define mp_get_digit_count(a)                ltc_mp.get_digit_count(a)\n #define mp_cmp(a, b)                         ltc_mp.compare(a, b)\n #define mp_cmp_d(a, b)                       ltc_mp.compare_d(a, b)\n #define mp_count_bits(a)                     ltc_mp.count_bits(a)\n #define mp_cnt_lsb(a)                        ltc_mp.count_lsb_bits(a)\n #define mp_2expt(a, b)                       ltc_mp.twoexpt(a, b)\n\n #define mp_read_radix(a, b, c)               ltc_mp.read_radix(a, b, c)\n #define mp_toradix(a, b, c)                  ltc_mp.write_radix(a, b, c)\n #define mp_unsigned_bin_size(a)              ltc_mp.unsigned_size(a)\n #define mp_to_unsigned_bin(a, b)             ltc_mp.unsigned_write(a, b)\n #define mp_read_unsigned_bin(a, b, c)        ltc_mp.unsigned_read(a, b, c)\n\n #define mp_add(a, b, c)                      ltc_mp.add(a, b, c)\n #define mp_add_d(a, b, c)                    ltc_mp.addi(a, b, c)\n #define mp_sub(a, b, c)                      ltc_mp.sub(a, b, c)\n #define mp_sub_d(a, b, c)                    ltc_mp.subi(a, b, c)\n #define mp_mul(a, b, c)                      ltc_mp.mul(a, b, c)\n #define mp_mul_d(a, b, c)                    ltc_mp.muli(a, b, c)\n #define mp_sqr(a, b)                         ltc_mp.sqr(a, b)\n #define mp_div(a, b, c, d)                   ltc_mp.mpdiv(a, b, c, d)\n #define mp_div_2(a, b)                       ltc_mp.div_2(a, b)\n #define mp_mod(a, b, c)                      ltc_mp.mpdiv(a, b, NULL, c)\n #define mp_mod_d(a, b, c)                    ltc_mp.modi(a, b, c)\n #define mp_gcd(a, b, c)                      ltc_mp.gcd(a, b, c)\n #define mp_lcm(a, b, c)                      ltc_mp.lcm(a, b, c)\n\n #define mp_mulmod(a, b, c, d)                ltc_mp.mulmod(a, b, c, d)\n #define mp_sqrmod(a, b, c)                   ltc_mp.sqrmod(a, b, c)\n #define mp_invmod(a, b, c)                   ltc_mp.invmod(a, b, c)\n\n #define mp_montgomery_setup(a, b)            ltc_mp.montgomery_setup(a, b)\n #define mp_montgomery_normalization(a, b)    ltc_mp.montgomery_normalization(a, b)\n #define mp_montgomery_reduce(a, b, c)        ltc_mp.montgomery_reduce(a, b, c)\n #define mp_montgomery_free(a)                ltc_mp.montgomery_deinit(a)\n\n #define mp_exptmod(a, b, c, d)               ltc_mp.exptmod(a, b, c, d)\n #define mp_prime_is_prime(a, b, c)           ltc_mp.isprime(a, c)\n\n #define mp_iszero(a)                         (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO)\n #define mp_isodd(a)                          (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO)\n #define mp_exch(a, b)                        do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while (0);\n\n #define mp_tohex(a, b)                       mp_toradix(a, b, 16)\n\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/math/ltm_desc.c,v $ */\n/* $Revision: 1.31 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n#ifdef MPI\n\nint ltc_init_multi(void **a, ...) {\n    void    **cur = a;\n    int     np    = 0;\n    va_list args;\n\n    va_start(args, a);\n    while (cur != NULL) {\n        if (mp_init(cur) != CRYPT_OK) {\n            /* failed */\n            va_list clean_list;\n\n            va_start(clean_list, a);\n            cur = a;\n            while (np--) {\n                mp_clear(*cur);\n                cur = va_arg(clean_list, void **);\n            }\n            va_end(clean_list);\n            return CRYPT_MEM;\n        }\n        ++np;\n        cur = va_arg(args, void **);\n    }\n    va_end(args);\n    return CRYPT_OK;\n}\n\nvoid ltc_deinit_multi(void *a, ...) {\n    void    *cur = a;\n    va_list args;\n\n    va_start(args, a);\n    while (cur != NULL) {\n        mp_clear(cur);\n        cur = va_arg(args, void *);\n    }\n    va_end(args);\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/math/multi.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:23 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file pkcs_1_i2osp.c\n   Integer to Octet I2OSP, Tom St Denis\n */\n\n#ifdef LTC_PKCS_1\n\n/* always stores the same # of bytes, pads with leading zero bytes\n   as required\n */\n\n/**\n   LTC_PKCS #1 Integer to binary\n   @param n             The integer to store\n   @param modulus_len   The length of the RSA modulus\n   @param out           [out] The destination for the integer\n   @return CRYPT_OK if successful\n */\nint pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out) {\n    unsigned long size;\n\n    size = mp_unsigned_bin_size(n);\n\n    if (size > modulus_len) {\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    /* store it */\n    zeromem(out, modulus_len);\n    return mp_to_unsigned_bin(n, out + (modulus_len - size));\n}\n#endif /* LTC_PKCS_1 */\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file pkcs_1_mgf1.c\n   The Mask Generation Function (MGF1) for LTC_PKCS #1, Tom St Denis\n */\n\n#ifdef LTC_PKCS_1\n\n/**\n   Perform LTC_PKCS #1 MGF1 (internal)\n   @param seed        The seed for MGF1\n   @param seedlen     The length of the seed\n   @param hash_idx    The index of the hash desired\n   @param mask        [out] The destination\n   @param masklen     The length of the mask desired\n   @return CRYPT_OK if successful\n */\nint pkcs_1_mgf1(int hash_idx,\n                const unsigned char *seed, unsigned long seedlen,\n                unsigned char *mask, unsigned long masklen) {\n    unsigned long hLen, x;\n    ulong32       counter;\n    int           err;\n    hash_state    *md;\n    unsigned char *buf;\n\n    LTC_ARGCHK(seed != NULL);\n    LTC_ARGCHK(mask != NULL);\n\n    /* ensure valid hash */\n    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* get hash output size */\n    hLen = hash_descriptor[hash_idx].hashsize;\n\n    /* allocate memory */\n    md  = XMALLOC(sizeof(hash_state));\n    buf = XMALLOC(hLen);\n    if ((md == NULL) || (buf == NULL)) {\n        if (md != NULL) {\n            XFREE(md);\n        }\n        if (buf != NULL) {\n            XFREE(buf);\n        }\n        return CRYPT_MEM;\n    }\n\n    /* start counter */\n    counter = 0;\n\n    while (masklen > 0) {\n        /* handle counter */\n        STORE32H(counter, buf);\n        ++counter;\n\n        /* get hash of seed || counter */\n        if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n        if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n        if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n        if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n\n        /* store it */\n        for (x = 0; x < hLen && masklen > 0; x++, masklen--) {\n            *mask++ = buf[x];\n        }\n    }\n\n    err = CRYPT_OK;\nLBL_ERR:\n #ifdef LTC_CLEAN_STACK\n    zeromem(buf, hLen);\n    zeromem(md, sizeof(hash_state));\n #endif\n\n    XFREE(buf);\n    XFREE(md);\n\n    return err;\n}\n#endif /* LTC_PKCS_1 */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c,v $ */\n/* $Revision: 1.8 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file pkcs_1_oaep_decode.c\n   OAEP Padding for LTC_PKCS #1, Tom St Denis\n */\n\n#ifdef LTC_PKCS_1\n\n/**\n   LTC_PKCS #1 v2.00 OAEP decode\n   @param msg              The encoded data to decode\n   @param msglen           The length of the encoded data (octets)\n   @param lparam           The session or system data (can be NULL)\n   @param lparamlen        The length of the lparam\n   @param modulus_bitlen   The bit length of the RSA modulus\n   @param hash_idx         The index of the hash desired\n   @param out              [out] Destination of decoding\n   @param outlen           [in/out] The max size and resulting size of the decoding\n   @param res              [out] Result of decoding, 1==valid, 0==invalid\n   @return CRYPT_OK if successful (even if invalid)\n */\nint pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,\n                       const unsigned char *lparam, unsigned long lparamlen,\n                       unsigned long modulus_bitlen, int hash_idx,\n                       unsigned char *out, unsigned long *outlen,\n                       int *res) {\n    unsigned char *DB, *seed, *mask;\n    unsigned long hLen, x, y, modulus_len;\n    int           err;\n\n    LTC_ARGCHK(msg != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(res != NULL);\n\n    /* default to invalid packet */\n    *res = 0;\n\n    /* test valid hash */\n    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n        return err;\n    }\n    hLen        = hash_descriptor[hash_idx].hashsize;\n    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);\n\n    /* test hash/message size */\n    if ((2 * hLen >= (modulus_len - 2)) || (msglen != modulus_len)) {\n        return CRYPT_PK_INVALID_SIZE;\n    }\n\n    /* allocate ram for DB/mask/salt of size modulus_len */\n    DB   = XMALLOC(modulus_len);\n    mask = XMALLOC(modulus_len);\n    seed = XMALLOC(hLen);\n    if ((DB == NULL) || (mask == NULL) || (seed == NULL)) {\n        if (DB != NULL) {\n            XFREE(DB);\n        }\n        if (mask != NULL) {\n            XFREE(mask);\n        }\n        if (seed != NULL) {\n            XFREE(seed);\n        }\n        return CRYPT_MEM;\n    }\n\n    /* ok so it's now in the form\n\n       0x00  || maskedseed || maskedDB\n\n        1    ||   hLen     ||  modulus_len - hLen - 1\n\n     */\n\n    /* must have leading 0x00 byte */\n    if (msg[0] != 0x00) {\n        err = CRYPT_OK;\n        goto LBL_ERR;\n    }\n\n    /* now read the masked seed */\n    x = 1;\n    XMEMCPY(seed, msg + x, hLen);\n    x += hLen;\n\n    /* now read the masked DB */\n    XMEMCPY(DB, msg + x, modulus_len - hLen - 1);\n    x += modulus_len - hLen - 1;\n\n    /* compute MGF1 of maskedDB (hLen) */\n    if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* XOR against seed */\n    for (y = 0; y < hLen; y++) {\n        seed[y] ^= mask[y];\n    }\n\n    /* compute MGF1 of seed (k - hlen - 1) */\n    if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* xor against DB */\n    for (y = 0; y < (modulus_len - hLen - 1); y++) {\n        DB[y] ^= mask[y];\n    }\n\n    /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */\n\n    /* compute lhash and store it in seed [reuse temps!] */\n    x = modulus_len;\n    if (lparam != NULL) {\n        if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n    } else {\n        /* can't pass hash_memory a NULL so use DB with zero length */\n        if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* compare the lhash'es */\n    if (XMEMCMP(seed, DB, hLen) != 0) {\n        err = CRYPT_OK;\n        goto LBL_ERR;\n    }\n\n    /* now zeroes before a 0x01 */\n    for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) {\n        /* step... */\n    }\n\n    /* error out if wasn't 0x01 */\n    if ((x == (modulus_len - hLen - 1)) || (DB[x] != 0x01)) {\n        err = CRYPT_INVALID_PACKET;\n        goto LBL_ERR;\n    }\n\n    /* rest is the message (and skip 0x01) */\n    if ((modulus_len - hLen - 1 - ++x) > *outlen) {\n        *outlen = modulus_len - hLen - 1 - x;\n        err     = CRYPT_BUFFER_OVERFLOW;\n        goto LBL_ERR;\n    }\n\n    /* copy message */\n    *outlen = modulus_len - hLen - 1 - x;\n    XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);\n    x += modulus_len - hLen - 1;\n\n    /* valid packet */\n    *res = 1;\n\n    err = CRYPT_OK;\nLBL_ERR:\n #ifdef LTC_CLEAN_STACK\n    zeromem(DB, modulus_len);\n    zeromem(seed, hLen);\n    zeromem(mask, modulus_len);\n #endif\n\n    XFREE(seed);\n    XFREE(mask);\n    XFREE(DB);\n\n    return err;\n}\n#endif /* LTC_PKCS_1 */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c,v $ */\n/* $Revision: 1.13 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file pkcs_1_oaep_encode.c\n   OAEP Padding for LTC_PKCS #1, Tom St Denis\n */\n\n#ifdef LTC_PKCS_1\n\n/**\n   LTC_PKCS #1 v2.00 OAEP encode\n   @param msg             The data to encode\n   @param msglen          The length of the data to encode (octets)\n   @param lparam          A session or system parameter (can be NULL)\n   @param lparamlen       The length of the lparam data\n   @param modulus_bitlen  The bit length of the RSA modulus\n   @param prng            An active PRNG state\n   @param prng_idx        The index of the PRNG desired\n   @param hash_idx        The index of the hash desired\n   @param out             [out] The destination for the encoded data\n   @param outlen          [in/out] The max size and resulting size of the encoded data\n   @return CRYPT_OK if successful\n */\nint pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,\n                       const unsigned char *lparam, unsigned long lparamlen,\n                       unsigned long modulus_bitlen, prng_state *prng,\n                       int prng_idx, int hash_idx,\n                       unsigned char *out, unsigned long *outlen) {\n    unsigned char *DB, *seed, *mask;\n    unsigned long hLen, x, y, modulus_len;\n    int           err;\n\n    LTC_ARGCHK(msg != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* test valid hash */\n    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* valid prng */\n    if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {\n        return err;\n    }\n\n    hLen        = hash_descriptor[hash_idx].hashsize;\n    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);\n\n    /* test message size */\n    if ((2 * hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2 * hLen - 2))) {\n        return CRYPT_PK_INVALID_SIZE;\n    }\n\n    /* allocate ram for DB/mask/salt of size modulus_len */\n    DB   = XMALLOC(modulus_len);\n    mask = XMALLOC(modulus_len);\n    seed = XMALLOC(hLen);\n    if ((DB == NULL) || (mask == NULL) || (seed == NULL)) {\n        if (DB != NULL) {\n            XFREE(DB);\n        }\n        if (mask != NULL) {\n            XFREE(mask);\n        }\n        if (seed != NULL) {\n            XFREE(seed);\n        }\n        return CRYPT_MEM;\n    }\n\n    /* get lhash */\n    /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */\n    x = modulus_len;\n    if (lparam != NULL) {\n        if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n    } else {\n        /* can't pass hash_memory a NULL so use DB with zero length */\n        if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n    }\n\n    /* append PS then 0x01 (to lhash)  */\n    x = hLen;\n    y = modulus_len - msglen - 2 * hLen - 2;\n    XMEMSET(DB + x, 0, y);\n    x += y;\n\n    /* 0x01 byte */\n    DB[x++] = 0x01;\n\n    /* message (length = msglen) */\n    XMEMCPY(DB + x, msg, msglen);\n    x += msglen;\n\n    /* now choose a random seed */\n    if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) {\n        err = CRYPT_ERROR_READPRNG;\n        goto LBL_ERR;\n    }\n\n    /* compute MGF1 of seed (k - hlen - 1) */\n    if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* xor against DB */\n    for (y = 0; y < (modulus_len - hLen - 1); y++) {\n        DB[y] ^= mask[y];\n    }\n\n    /* compute MGF1 of maskedDB (hLen) */\n    if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* XOR against seed */\n    for (y = 0; y < hLen; y++) {\n        seed[y] ^= mask[y];\n    }\n\n    /* create string of length modulus_len */\n    if (*outlen < modulus_len) {\n        *outlen = modulus_len;\n        err     = CRYPT_BUFFER_OVERFLOW;\n        goto LBL_ERR;\n    }\n\n    /* start output which is 0x00 || maskedSeed || maskedDB */\n    x        = 0;\n    out[x++] = 0x00;\n    XMEMCPY(out + x, seed, hLen);\n    x += hLen;\n    XMEMCPY(out + x, DB, modulus_len - hLen - 1);\n    x += modulus_len - hLen - 1;\n\n    *outlen = x;\n\n    err = CRYPT_OK;\nLBL_ERR:\n #ifdef LTC_CLEAN_STACK\n    zeromem(DB, modulus_len);\n    zeromem(seed, hLen);\n    zeromem(mask, modulus_len);\n #endif\n\n    XFREE(seed);\n    XFREE(mask);\n    XFREE(DB);\n\n    return err;\n}\n#endif /* LTC_PKCS_1 */\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c,v $ */\n/* $Revision: 1.9 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file pkcs_1_os2ip.c\n   Octet to Integer OS2IP, Tom St Denis\n */\n#ifdef LTC_PKCS_1\n\n/**\n   Read a binary string into an mp_int\n   @param n          [out] The mp_int destination\n   @param in         The binary string to read\n   @param inlen      The length of the binary string\n   @return CRYPT_OK if successful\n */\nint pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen) {\n    return mp_read_unsigned_bin(n, in, inlen);\n}\n#endif /* LTC_PKCS_1 */\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file pkcs_1_pss_decode.c\n   LTC_PKCS #1 PSS Signature Padding, Tom St Denis\n */\n\n#ifdef LTC_PKCS_1\n\n/**\n   LTC_PKCS #1 v2.00 PSS decode\n   @param  msghash         The hash to verify\n   @param  msghashlen      The length of the hash (octets)\n   @param  sig             The signature data (encoded data)\n   @param  siglen          The length of the signature data (octets)\n   @param  saltlen         The length of the salt used (octets) (0==auto)\n   @param  hash_idx        The index of the hash desired\n   @param  modulus_bitlen  The bit length of the RSA modulus\n   @param  res             [out] The result of the comparison, 1==valid, 0==invalid\n   @return CRYPT_OK if successful (even if the comparison failed)\n */\nint pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,\n                      const unsigned char *sig, unsigned long siglen,\n                      unsigned long saltlen, int hash_idx,\n                      unsigned long modulus_bitlen, int *res) {\n    unsigned char *DB, *mask, *salt, *hash, *saltpos;\n    unsigned long x, y, hLen, modulus_len;\n    int           err;\n    hash_state    md;\n\n    LTC_ARGCHK(msghash != NULL);\n    LTC_ARGCHK(res != NULL);\n\n    /* default to invalid */\n    *res = 0;\n\n    /* ensure hash is valid */\n    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n        return err;\n    }\n\n    hLen        = hash_descriptor[hash_idx].hashsize;\n    modulus_bitlen--;\n    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);\n\n    /* check sizes */\n    if ((saltlen > modulus_len) ||\n        (modulus_len < hLen + saltlen + 2)) {\n        return CRYPT_PK_INVALID_SIZE;\n    }\n\n    /* allocate ram for DB/mask/salt/hash of size modulus_len */\n    DB   = XMALLOC(modulus_len);\n    mask = XMALLOC(modulus_len);\n    salt = XMALLOC(modulus_len);\n    hash = XMALLOC(modulus_len);\n    if ((DB == NULL) || (mask == NULL) || (salt == NULL) || (hash == NULL)) {\n        if (DB != NULL) {\n            XFREE(DB);\n        }\n        if (mask != NULL) {\n            XFREE(mask);\n        }\n        if (salt != NULL) {\n            XFREE(salt);\n        }\n        if (hash != NULL) {\n            XFREE(hash);\n        }\n        return CRYPT_MEM;\n    }\n\n    /* ensure the 0xBC byte */\n    if (sig[siglen - 1] != 0xBC) {\n        err = CRYPT_INVALID_PACKET;\n        goto LBL_ERR;\n    }\n\n    /* copy out the DB */\n    x = 0;\n    XMEMCPY(DB, sig + x, modulus_len - hLen - 1);\n    x += modulus_len - hLen - 1;\n\n    /* copy out the hash */\n    XMEMCPY(hash, sig + x, hLen);\n    /* x += hLen; */\n\n    /* check the MSB */\n    if ((sig[0] & ~(0xFF >> ((modulus_len << 3) - (modulus_bitlen)))) != 0) {\n        err = CRYPT_INVALID_PACKET;\n        goto LBL_ERR;\n    }\n\n    /* generate mask of length modulus_len - hLen - 1 from hash */\n    if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* xor against DB */\n    for (y = 0; y < (modulus_len - hLen - 1); y++) {\n        DB[y] ^= mask[y];\n    }\n\n    /* now clear the first byte [make sure smaller than modulus] */\n    DB[0] &= 0xFF >> ((modulus_len << 3) - (modulus_bitlen));\n\n    /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */\n\n    /* CK: if saltlen is 0, then we need to find the salt length ourselves */\n    if (saltlen == 0) {\n        for(saltlen = modulus_len - (hLen + 2); saltlen >= 0; saltlen--) {\n            switch (DB[modulus_len - hLen - saltlen - 2]) {\n                case 1: goto END_SALT;\n                case 0: continue;\n                default:\n                    err = CRYPT_INVALID_PACKET;\n                    goto LBL_ERR;\n            }\n        }\n        END_SALT: if (saltlen < 0) {\n            err = CRYPT_INVALID_PACKET;\n            goto LBL_ERR;\n        }\n\n        saltpos = DB + (modulus_len - hLen - 1 - saltlen);\n    } else {\n        /* check for zeroes and 0x01 */\n        for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) {\n            if (DB[x] != 0x00) {\n                err = CRYPT_INVALID_PACKET;\n                goto LBL_ERR;\n            }\n        }\n\n        /* check for the 0x01 */\n        if (DB[x++] != 0x01) {\n            err = CRYPT_INVALID_PACKET;\n            goto LBL_ERR;\n        }\n\n        saltpos = DB + x;\n    }\n\n    /* M = (eight) 0x00 || msghash || salt, mask = H(M) */\n    if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    zeromem(mask, 8);\n    if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash_idx].process(&md, saltpos, saltlen)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* mask == hash means valid signature */\n    if (XMEMCMP(mask, hash, hLen) == 0) {\n        *res = 1;\n    }\n\n    err = CRYPT_OK;\nLBL_ERR:\n #ifdef LTC_CLEAN_STACK\n    zeromem(DB, modulus_len);\n    zeromem(mask, modulus_len);\n    zeromem(salt, modulus_len);\n    zeromem(hash, modulus_len);\n #endif\n\n    XFREE(hash);\n    XFREE(salt);\n    XFREE(mask);\n    XFREE(DB);\n\n    return err;\n}\n#endif /* LTC_PKCS_1 */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c,v $ */\n/* $Revision: 1.11 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file pkcs_1_pss_encode.c\n   LTC_PKCS #1 PSS Signature Padding, Tom St Denis\n */\n\n#ifdef LTC_PKCS_1\n\n/**\n   LTC_PKCS #1 v2.00 Signature Encoding\n   @param msghash          The hash to encode\n   @param msghashlen       The length of the hash (octets)\n   @param saltlen          The length of the salt desired (octets)\n   @param prng             An active PRNG context\n   @param prng_idx         The index of the PRNG desired\n   @param hash_idx         The index of the hash desired\n   @param modulus_bitlen   The bit length of the RSA modulus\n   @param out              [out] The destination of the encoding\n   @param outlen           [in/out] The max size and resulting size of the encoded data\n   @return CRYPT_OK if successful\n */\nint pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,\n                      unsigned long saltlen, prng_state *prng,\n                      int prng_idx, int hash_idx,\n                      unsigned long modulus_bitlen,\n                      unsigned char *out, unsigned long *outlen) {\n    unsigned char *DB, *mask, *salt, *hash;\n    unsigned long x, y, hLen, modulus_len;\n    int           err;\n    hash_state    md;\n\n    LTC_ARGCHK(msghash != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n\n    /* ensure hash and PRNG are valid */\n    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n        return err;\n    }\n    if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {\n        return err;\n    }\n\n    hLen        = hash_descriptor[hash_idx].hashsize;\n    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);\n\n    /* check sizes */\n    if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) {\n        return CRYPT_PK_INVALID_SIZE;\n    }\n\n    /* allocate ram for DB/mask/salt/hash of size modulus_len */\n    DB   = XMALLOC(modulus_len);\n    mask = XMALLOC(modulus_len);\n    salt = XMALLOC(modulus_len);\n    hash = XMALLOC(modulus_len);\n    if ((DB == NULL) || (mask == NULL) || (salt == NULL) || (hash == NULL)) {\n        if (DB != NULL) {\n            XFREE(DB);\n        }\n        if (mask != NULL) {\n            XFREE(mask);\n        }\n        if (salt != NULL) {\n            XFREE(salt);\n        }\n        if (hash != NULL) {\n            XFREE(hash);\n        }\n        return CRYPT_MEM;\n    }\n\n\n    /* generate random salt */\n    if (saltlen > 0) {\n        if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) {\n            err = CRYPT_ERROR_READPRNG;\n            goto LBL_ERR;\n        }\n    }\n\n    /* M = (eight) 0x00 || msghash || salt, hash = H(M) */\n    if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    zeromem(DB, 8);\n    if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */\n    x = 0;\n    XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2);\n    x      += modulus_len - saltlen - hLen - 2;\n    DB[x++] = 0x01;\n    XMEMCPY(DB + x, salt, saltlen);\n    x += saltlen;\n\n    /* generate mask of length modulus_len - hLen - 1 from hash */\n    if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    /* xor against DB */\n    for (y = 0; y < (modulus_len - hLen - 1); y++) {\n        DB[y] ^= mask[y];\n    }\n\n    /* output is DB || hash || 0xBC */\n    if (*outlen < modulus_len) {\n        *outlen = modulus_len;\n        err     = CRYPT_BUFFER_OVERFLOW;\n        goto LBL_ERR;\n    }\n\n    /* DB len = modulus_len - hLen - 1 */\n    y = 0;\n    XMEMCPY(out + y, DB, modulus_len - hLen - 1);\n    y += modulus_len - hLen - 1;\n\n    /* hash */\n    XMEMCPY(out + y, hash, hLen);\n    y += hLen;\n\n    /* 0xBC */\n    out[y] = 0xBC;\n\n    /* now clear the 8*modulus_len - modulus_bitlen most significant bits */\n    out[0] &= 0xFF >> ((modulus_len << 3) - (modulus_bitlen - 1));\n\n    /* store output size */\n    *outlen = modulus_len;\n    err     = CRYPT_OK;\nLBL_ERR:\n #ifdef LTC_CLEAN_STACK\n    zeromem(DB, modulus_len);\n    zeromem(mask, modulus_len);\n    zeromem(salt, modulus_len);\n    zeromem(hash, modulus_len);\n #endif\n\n    XFREE(hash);\n    XFREE(salt);\n    XFREE(mask);\n    XFREE(DB);\n\n    return err;\n}\n#endif /* LTC_PKCS_1 */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c,v $ */\n/* $Revision: 1.9 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/** @file pkcs_1_v1_5_decode.c\n *\n *  LTC_PKCS #1 v1.5 Padding. (Andreas Lange)\n */\n\n#ifdef LTC_PKCS_1\n\n/** @brief LTC_PKCS #1 v1.5 decode.\n *\n *  @param msg              The encoded data to decode\n *  @param msglen           The length of the encoded data (octets)\n *  @param block_type       Block type to use in padding (\\sa ltc_pkcs_1_v1_5_blocks)\n *  @param modulus_bitlen   The bit length of the RSA modulus\n *  @param out              [out] Destination of decoding\n *  @param outlen           [in/out] The max size and resulting size of the decoding\n *  @param is_valid         [out] Boolean whether the padding was valid\n *\n *  @return CRYPT_OK if successful (even if invalid)\n */\nint pkcs_1_v1_5_decode(const unsigned char *msg,\n                       unsigned long       msglen,\n                       int                 block_type,\n                       unsigned long       modulus_bitlen,\n                       unsigned char       *out,\n                       unsigned long       *outlen,\n                       int                 *is_valid) {\n    unsigned long modulus_len, ps_len, i;\n    int           result;\n\n    /* default to invalid packet */\n    *is_valid = 0;\n\n    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);\n\n    /* test message size */\n\n    if ((msglen > modulus_len) || (modulus_len < 11)) {\n        return CRYPT_PK_INVALID_SIZE;\n    }\n\n    /* separate encoded message */\n\n    if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {\n        result = CRYPT_INVALID_PACKET;\n        goto bail;\n    }\n\n    if (block_type == LTC_LTC_PKCS_1_EME) {\n        for (i = 2; i < modulus_len; i++) {\n            /* separator */\n            if (msg[i] == 0x00) {\n                break;\n            }\n        }\n        ps_len = i++ - 2;\n\n        if ((i >= modulus_len) || (ps_len < 8)) {\n            /* There was no octet with hexadecimal value 0x00 to separate ps from m,\n             * or the length of ps is less than 8 octets.\n             */\n            result = CRYPT_INVALID_PACKET;\n            goto bail;\n        }\n    } else {\n        for (i = 2; i < modulus_len - 1; i++) {\n            if (msg[i] != 0xFF) {\n                break;\n            }\n        }\n\n        /* separator check */\n        if (msg[i] != 0) {\n            /* There was no octet with hexadecimal value 0x00 to separate ps from m. */\n            result = CRYPT_INVALID_PACKET;\n            goto bail;\n        }\n\n        ps_len = i - 2;\n    }\n\n    if (*outlen < (msglen - (2 + ps_len + 1))) {\n        *outlen = msglen - (2 + ps_len + 1);\n        result  = CRYPT_BUFFER_OVERFLOW;\n        goto bail;\n    }\n\n    *outlen = (msglen - (2 + ps_len + 1));\n    XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);\n\n    /* valid packet */\n    *is_valid = 1;\n    result    = CRYPT_OK;\nbail:\n    return result;\n} /* pkcs_1_v1_5_decode */\n#endif /* #ifdef LTC_PKCS_1 */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/*! \\file pkcs_1_v1_5_encode.c\n *\n *  LTC_PKCS #1 v1.5 Padding (Andreas Lange)\n */\n\n#ifdef LTC_PKCS_1\n\n/*! \\brief LTC_PKCS #1 v1.5 encode.\n *\n *  \\param msg              The data to encode\n *  \\param msglen           The length of the data to encode (octets)\n *  \\param block_type       Block type to use in padding (\\sa ltc_pkcs_1_v1_5_blocks)\n *  \\param modulus_bitlen   The bit length of the RSA modulus\n *  \\param prng             An active PRNG state (only for LTC_LTC_PKCS_1_EME)\n *  \\param prng_idx         The index of the PRNG desired (only for LTC_LTC_PKCS_1_EME)\n *  \\param out              [out] The destination for the encoded data\n *  \\param outlen           [in/out] The max size and resulting size of the encoded data\n *\n *  \\return CRYPT_OK if successful\n */\nint pkcs_1_v1_5_encode(const unsigned char *msg,\n                       unsigned long       msglen,\n                       int                 block_type,\n                       unsigned long       modulus_bitlen,\n                       prng_state          *prng,\n                       int                 prng_idx,\n                       unsigned char       *out,\n                       unsigned long       *outlen) {\n    unsigned long modulus_len, ps_len, i;\n    unsigned char *ps;\n    int           result;\n\n    /* valid block_type? */\n    if ((block_type != LTC_LTC_PKCS_1_EMSA) &&\n        (block_type != LTC_LTC_PKCS_1_EME)) {\n        return CRYPT_PK_INVALID_PADDING;\n    }\n\n    if (block_type == LTC_LTC_PKCS_1_EME) {  /* encryption padding, we need a valid PRNG */\n        if ((result = prng_is_valid(prng_idx)) != CRYPT_OK) {\n            return result;\n        }\n    }\n\n    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);\n\n    /* test message size */\n    if ((msglen + 11) > modulus_len) {\n        return CRYPT_PK_INVALID_SIZE;\n    }\n\n    if (*outlen < modulus_len) {\n        *outlen = modulus_len;\n        result  = CRYPT_BUFFER_OVERFLOW;\n        goto bail;\n    }\n\n    /* generate an octets string PS */\n    ps     = &out[2];\n    ps_len = modulus_len - msglen - 3;\n\n    if (block_type == LTC_LTC_PKCS_1_EME) {\n        /* now choose a random ps */\n        if (prng_descriptor[prng_idx].read(ps, ps_len, prng) != ps_len) {\n            result = CRYPT_ERROR_READPRNG;\n            goto bail;\n        }\n\n        /* transform zero bytes (if any) to non-zero random bytes */\n        for (i = 0; i < ps_len; i++) {\n            while (ps[i] == 0) {\n                if (prng_descriptor[prng_idx].read(&ps[i], 1, prng) != 1) {\n                    result = CRYPT_ERROR_READPRNG;\n                    goto bail;\n                }\n            }\n        }\n    } else {\n        XMEMSET(ps, 0xFF, ps_len);\n    }\n\n    /* create string of length modulus_len */\n    out[0]          = 0x00;\n    out[1]          = (unsigned char)block_type;/* block_type 1 or 2 */\n    out[2 + ps_len] = 0x00;\n    XMEMCPY(&out[2 + ps_len + 1], msg, msglen);\n    *outlen = modulus_len;\n\n    result = CRYPT_OK;\nbail:\n    return result;\n} /* pkcs_1_v1_5_encode */\n#endif /* #ifdef LTC_PKCS_1 */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c,v $ */\n/* $Revision: 1.4 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rand_prime.c\n   Generate a random prime, Tom St Denis\n */\n\n#define USE_BBS    1\n\nint rand_prime(void *N, long len, prng_state *prng, int wprng) {\n    int           err, res, type;\n    unsigned char *buf;\n\n    LTC_ARGCHK(N != NULL);\n\n    /* get type */\n    if (len < 0) {\n        type = USE_BBS;\n        len  = -len;\n    } else {\n        type = 0;\n    }\n\n    /* allow sizes between 2 and 512 bytes for a prime size */\n    if ((len < 2) || (len > 512)) {\n        return CRYPT_INVALID_PRIME_SIZE;\n    }\n\n    /* valid PRNG? Better be! */\n    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* allocate buffer to work with */\n    buf = XCALLOC(1, len);\n    if (buf == NULL) {\n        return CRYPT_MEM;\n    }\n\n    do {\n        /* generate value */\n        if (prng_descriptor[wprng].read(buf, len, prng) != (unsigned long)len) {\n            XFREE(buf);\n            return CRYPT_ERROR_READPRNG;\n        }\n\n        /* munge bits */\n        buf[0]       |= 0x80 | 0x40;\n        buf[len - 1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);\n\n        /* load value */\n        if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) {\n            XFREE(buf);\n            return err;\n        }\n\n        /* test */\n        if ((err = mp_prime_is_prime(N, 8, &res)) != CRYPT_OK) {\n            XFREE(buf);\n            return err;\n        }\n    } while (res == LTC_MP_NO);\n\n#ifdef LTC_CLEAN_STACK\n    zeromem(buf, len);\n#endif\n\n    XFREE(buf);\n    return CRYPT_OK;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/math/rand_prime.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:23 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rng_get_bytes.c\n   portable way to get secure random bits to feed a PRNG (Tom St Denis)\n */\n\n#ifdef LTC_DEVRANDOM\n/* on *NIX read /dev/random */\nstatic unsigned long rng_nix(unsigned char *buf, unsigned long len,\n                             void (*callback)(void)) {\n #ifdef LTC_NO_FILE\n    return 0;\n #else\n    FILE          *f;\n    unsigned long x;\n  #ifdef TRY_URANDOM_FIRST\n    f = fopen(\"/dev/urandom\", \"rb\");\n    if (f == NULL)\n  #endif /* TRY_URANDOM_FIRST */\n    f = fopen(\"/dev/random\", \"rb\");\n\n    if (f == NULL) {\n        return 0;\n    }\n\n    /* disable buffering */\n    if (setvbuf(f, NULL, _IONBF, 0) != 0) {\n        fclose(f);\n        return 0;\n    }\n\n    x = (unsigned long)fread(buf, 1, (size_t)len, f);\n    fclose(f);\n    return x;\n #endif /* LTC_NO_FILE */\n}\n#endif  /* LTC_DEVRANDOM */\n\n/* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */\n/* We don't need this, because we have arc4, allegedly, and some systems\n   strangely will compile it when it is very inefficent. Left here in case\n   we find a system we DO need it for. -- ck */\n#if(0)\n#if defined(CLOCKS_PER_SEC) && !defined(WINCE)\n\n #define ANSI_RNG\n\nstatic unsigned long rng_ansic(unsigned char *buf, unsigned long len,\n                               void (*callback)(void)) {\n    clock_t t1;\n    int     l, acc, bits, a, b;\n\n    if ((XCLOCKS_PER_SEC < 100) || (XCLOCKS_PER_SEC > 10000)) {\n        return 0;\n    }\n\n    l    = len;\n    bits = 8;\n    acc  = a = b = 0;\n    while (len--) {\n        if (callback != NULL) callback();\n        while (bits--) {\n            do {\n                t1 = XCLOCK();\n                while (t1 == XCLOCK()) a ^= 1;\n                t1 = XCLOCK();\n                while (t1 == XCLOCK()) b ^= 1;\n            } while (a == b);\n            acc = (acc << 1) | a;\n        }\n        *buf++ = acc;\n        acc    = 0;\n        bits   = 8;\n    }\n    acc = bits = a = b = 0;\n    return l;\n}\n#endif\n#endif\n\n/* Try the Microsoft CSP */\n#if defined(WIN32) || defined(WINCE)\n #define _WIN32_WINNT    0x0400\n #ifdef WINCE\n  #define UNDER_CE\n  #define ARM\n #endif\n#include <windows.h>\n#include <wincrypt.h>\n\nstatic unsigned long rng_win32(unsigned char *buf, unsigned long len,\n                               void (*callback)(void)) {\n    HCRYPTPROV hProv = 0;\n\n    if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,\n                             (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&\n        !CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,\n                             CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))\n        return 0;\n\n    if (CryptGenRandom(hProv, len, buf) == TRUE) {\n        CryptReleaseContext(hProv, 0);\n        return len;\n    } else {\n        CryptReleaseContext(hProv, 0);\n        return 0;\n    }\n}\n#endif /* WIN32 */\n\n/* Use our alleged internal source, allegedly */\n\nstatic unsigned long rng_alleged(unsigned char *out, unsigned long outlen,\n                                 void (*callback)(void)) {\n   return aarc4random_batch_maybe(out, outlen);\n}\n\n/**\n   Read the system RNG\n   @param out       Destination\n   @param outlen    Length desired (octets)\n   @param callback  Pointer to void function to act as \"callback\" when RNG is slow.  This can be NULL\n   @return Number of octets read\n */\nunsigned long rng_get_bytes(unsigned char *out, unsigned long outlen,\n                            void (*callback)(void)) {\n    unsigned long x;\n\n    LTC_ARGCHK(out != NULL);\n\n#if defined(LTC_DEVRANDOM)\n    x = rng_nix(out, outlen, callback);\n    if (x != 0) {\n        return x;\n    }\n#endif\n#ifdef WIN32\n    x = rng_win32(out, outlen, callback);\n    if (x != 0) {\n        return x;\n    }\n#endif\n#ifdef ANSI_RNG\n    x = rng_ansic(out, outlen, callback);\n    if (x != 0) {\n        return x;\n    }\n#endif\n    /* Fallback */\n    x = rng_alleged(out, outlen, callback);\n    return x;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/prngs/rng_get_bytes.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rng_make_prng.c\n   portable way to get secure random bits to feed a PRNG  (Tom St Denis)\n */\n\n/**\n   Create a PRNG from a RNG\n   @param bits     Number of bits of entropy desired (64 ... 1024)\n   @param wprng    Index of which PRNG to setup\n   @param prng     [out] PRNG state to initialize\n   @param callback A pointer to a void function for when the RNG is slow, this can be NULL\n   @return CRYPT_OK if successful\n */\nint rng_make_prng(int bits, int wprng, prng_state *prng,\n                  void (*callback)(void)) {\n    unsigned char buf[256];\n    int           err;\n\n    LTC_ARGCHK(prng != NULL);\n\n    /* check parameter */\n    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {\n        return err;\n    }\n\n    if ((bits < 64) || (bits > 1024)) {\n        return CRYPT_INVALID_PRNGSIZE;\n    }\n\n    if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) {\n        return err;\n    }\n\n    bits = ((bits / 8) + ((bits & 7) != 0 ? 1 : 0)) * 2;\n    if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) {\n        return CRYPT_ERROR_READPRNG;\n    }\n\n    if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) {\n        return err;\n    }\n\n    if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) {\n        return err;\n    }\n\n#ifdef LTC_CLEAN_STACK\n    zeromem(buf, sizeof(buf));\n#endif\n    return CRYPT_OK;\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/prngs/rng_make_prng.c,v $ */\n/* $Revision: 1.5 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rsa_decrypt_key.c\n   RSA LTC_PKCS #1 Decryption, Tom St Denis and Andreas Lange\n */\n\n#ifdef LTC_MRSA\n\n/**\n   LTC_PKCS #1 decrypt then v1.5 or OAEP depad\n   @param in          The ciphertext\n   @param inlen       The length of the ciphertext (octets)\n   @param out         [out] The plaintext\n   @param outlen      [in/out] The max size and resulting size of the plaintext (octets)\n   @param lparam      The system \"lparam\" value\n   @param lparamlen   The length of the lparam value (octets)\n   @param hash_idx    The index of the hash desired\n   @param padding     Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5)\n   @param stat        [out] Result of the decryption, 1==valid, 0==invalid\n   @param key         The corresponding private RSA key\n   @return CRYPT_OK if succcessul (even if invalid)\n */\nint rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,\n                       unsigned char *out, unsigned long *outlen,\n                       const unsigned char *lparam, unsigned long lparamlen,\n                       int hash_idx, int padding,\n                       int *stat, rsa_key *key) {\n    unsigned long modulus_bitlen, modulus_bytelen, x;\n    int           err;\n    unsigned char *tmp;\n\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(key != NULL);\n    LTC_ARGCHK(stat != NULL);\n\n    /* default to invalid */\n    *stat = 0;\n\n    /* valid padding? */\n\n    if ((padding != LTC_LTC_PKCS_1_V1_5) &&\n        (padding != LTC_LTC_PKCS_1_OAEP)) {\n        return CRYPT_PK_INVALID_PADDING;\n    }\n\n    if (padding == LTC_LTC_PKCS_1_OAEP) {\n        /* valid hash ? */\n        if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n            return err;\n        }\n    }\n\n    /* get modulus len in bits */\n    modulus_bitlen = mp_count_bits((key->N));\n\n    /* outlen must be at least the size of the modulus */\n    modulus_bytelen = mp_unsigned_bin_size((key->N));\n    if (modulus_bytelen != inlen) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* allocate ram */\n    tmp = XMALLOC(inlen);\n    if (tmp == NULL) {\n        return CRYPT_MEM;\n    }\n\n    /* rsa decode the packet */\n    x = inlen;\n    if ((err = ltc_mp.rsa_me(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) {\n        XFREE(tmp);\n        return err;\n    }\n\n    if (padding == LTC_LTC_PKCS_1_OAEP) {\n        /* now OAEP decode the packet */\n        err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx,\n                                 out, outlen, stat);\n    } else {\n        /* now LTC_PKCS #1 v1.5 depad the packet */\n        err = pkcs_1_v1_5_decode(tmp, x, LTC_LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);\n    }\n\n    XFREE(tmp);\n    return err;\n}\n#endif /* LTC_MRSA */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c,v $ */\n/* $Revision: 1.10 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rsa_encrypt_key.c\n   RSA LTC_PKCS #1 encryption, Tom St Denis and Andreas Lange\n */\n\n#ifdef LTC_MRSA\n\n/**\n    (LTC_PKCS #1 v2.0) OAEP pad then encrypt\n    @param in          The plaintext\n    @param inlen       The length of the plaintext (octets)\n    @param out         [out] The ciphertext\n    @param outlen      [in/out] The max size and resulting size of the ciphertext\n    @param lparam      The system \"lparam\" for the encryption\n    @param lparamlen   The length of lparam (octets)\n    @param prng        An active PRNG\n    @param prng_idx    The index of the desired prng\n    @param hash_idx    The index of the desired hash\n    @param padding     Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5)\n    @param key         The RSA key to encrypt to\n    @return CRYPT_OK if successful\n */\nint rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,\n                       unsigned char *out, unsigned long *outlen,\n                       const unsigned char *lparam, unsigned long lparamlen,\n                       prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key) {\n    unsigned long modulus_bitlen, modulus_bytelen, x;\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* valid padding? */\n    if ((padding != LTC_LTC_PKCS_1_V1_5) &&\n        (padding != LTC_LTC_PKCS_1_OAEP)) {\n        return CRYPT_PK_INVALID_PADDING;\n    }\n\n    /* valid prng? */\n    if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {\n        return err;\n    }\n\n    if (padding == LTC_LTC_PKCS_1_OAEP) {\n        /* valid hash? */\n        if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n            return err;\n        }\n    }\n\n    /* get modulus len in bits */\n    modulus_bitlen = mp_count_bits((key->N));\n\n    /* outlen must be at least the size of the modulus */\n    modulus_bytelen = mp_unsigned_bin_size((key->N));\n    if (modulus_bytelen > *outlen) {\n        *outlen = modulus_bytelen;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    if (padding == LTC_LTC_PKCS_1_OAEP) {\n        /* OAEP pad the key */\n        x = *outlen;\n        if ((err = pkcs_1_oaep_encode(in, inlen, lparam,\n                                      lparamlen, modulus_bitlen, prng, prng_idx, hash_idx,\n                                      out, &x)) != CRYPT_OK) {\n            return err;\n        }\n    } else {\n        /* LTC_PKCS #1 v1.5 pad the key */\n        x = *outlen;\n        if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_LTC_PKCS_1_EME,\n                                      modulus_bitlen, prng, prng_idx,\n                                      out, &x)) != CRYPT_OK) {\n            return err;\n        }\n    }\n\n    /* rsa exptmod the OAEP or LTC_PKCS #1 v1.5 pad */\n    return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key);\n}\n#endif /* LTC_MRSA */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c,v $ */\n/* $Revision: 1.10 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rsa_exptmod.c\n   RSA LTC_PKCS exptmod, Tom St Denis\n */\n\n#ifdef LTC_MRSA\n\n/**\n   Compute an RSA modular exponentiation\n   @param in         The input data to send into RSA\n   @param inlen      The length of the input (octets)\n   @param out        [out] The destination\n   @param outlen     [in/out] The max size and resulting size of the output\n   @param which      Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC\n   @param key        The RSA key to use\n   @return CRYPT_OK if successful\n */\nint rsa_exptmod(const unsigned char *in, unsigned long inlen,\n                unsigned char *out, unsigned long *outlen, int which,\n                rsa_key *key) {\n    void          *tmp, *tmpa, *tmpb;\n    unsigned long x;\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* is the key of the right type for the operation? */\n    if ((which == PK_PRIVATE) && (key->type != PK_PRIVATE)) {\n        return CRYPT_PK_NOT_PRIVATE;\n    }\n\n    /* must be a private or public operation */\n    if ((which != PK_PRIVATE) && (which != PK_PUBLIC)) {\n        return CRYPT_PK_INVALID_TYPE;\n    }\n\n    /* init and copy into tmp */\n    if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != CRYPT_OK) {\n        return err;\n    }\n    if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* sanity check on the input */\n    if (mp_cmp(key->N, tmp) == LTC_MP_LT) {\n        err = CRYPT_PK_INVALID_SIZE;\n        goto error;\n    }\n\n    /* are we using the private exponent and is the key optimized? */\n    if (which == PK_PRIVATE) {\n        /* tmpa = tmp^dP mod p */\n        if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) {\n            goto error;\n        }\n\n        /* tmpb = tmp^dQ mod q */\n        if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) {\n            goto error;\n        }\n\n        /* tmp = (tmpa - tmpb) * qInv (mod p) */\n        if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) {\n            goto error;\n        }\n        if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) {\n            goto error;\n        }\n\n        /* tmp = tmpb + q * tmp */\n        if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) {\n            goto error;\n        }\n        if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) {\n            goto error;\n        }\n    } else {\n        /* exptmod it */\n        if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) {\n            goto error;\n        }\n    }\n\n    /* read it back */\n    x = (unsigned long)mp_unsigned_bin_size(key->N);\n    if (x > *outlen) {\n        *outlen = x;\n        err     = CRYPT_BUFFER_OVERFLOW;\n        goto error;\n    }\n\n    /* this should never happen ... */\n    if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) {\n        err = CRYPT_ERROR;\n        goto error;\n    }\n    *outlen = x;\n\n    /* convert it */\n    zeromem(out, x);\n    if ((err = mp_to_unsigned_bin(tmp, out + (x - mp_unsigned_bin_size(tmp)))) != CRYPT_OK) {\n        goto error;\n    }\n\n    /* clean up and return */\n    err = CRYPT_OK;\nerror:\n    mp_clear_multi(tmp, tmpa, tmpb, NULL);\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_exptmod.c,v $ */\n/* $Revision: 1.18 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rsa_free.c\n   Free an RSA key, Tom St Denis\n */\n\n#ifdef LTC_MRSA\n\n/**\n   Free an RSA key from memory\n   @param key   The RSA key to free\n */\nvoid rsa_free(rsa_key *key) {\n    LTC_ARGCHKVD(key != NULL);\n    mp_clear_multi(key->e, key->d, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_free.c,v $ */\n/* $Revision: 1.10 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rsa_import.c\n   Import a LTC_PKCS RSA key, Tom St Denis\n */\n\n#ifdef LTC_MRSA\n\n/**\n   Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1]\n   @param in      The packet to import from\n   @param inlen   It's length (octets)\n   @param key     [out] Destination for newly imported key\n   @return CRYPT_OK if successful, upon error allocated memory is freed\n */\nint rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) {\n#ifdef __MRC__\n/* Disable optimizations for this function so MrC will compile it correctly. */\n#pragma options opt off\n#endif\n\n    int           err;\n    void          *zero;\n    unsigned char *tmpbuf;\n    unsigned long t, x, y, z, tmpoid[16];\n    ltc_asn1_list ssl_pubkey_hashoid[2];\n    ltc_asn1_list ssl_pubkey[2];\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(key != NULL);\n    LTC_ARGCHK(ltc_mp.name != NULL);\n\n    /* init key */\n    if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,\n                             &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* see if the OpenSSL DER format RSA public key will work */\n    tmpbuf = XCALLOC(1, MAX_RSA_SIZE * 8);\n    if (tmpbuf == NULL) {\n        err = CRYPT_MEM;\n        goto LBL_ERR;\n    }\n\n    /* this includes the internal hash ID and optional params (NULL in this case) */\n    LTC_SET_ASN1(ssl_pubkey_hashoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid) / sizeof(tmpoid[0]));\n    LTC_SET_ASN1(ssl_pubkey_hashoid, 1, LTC_ASN1_NULL, NULL, 0);\n\n    /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it\n       then proceed to convert bit to octet\n     */\n    LTC_SET_ASN1(ssl_pubkey, 0, LTC_ASN1_SEQUENCE, &ssl_pubkey_hashoid, 2);\n    LTC_SET_ASN1(ssl_pubkey, 1, LTC_ASN1_BIT_STRING, tmpbuf, MAX_RSA_SIZE * 8);\n\n    if (der_decode_sequence(in, inlen,\n                            ssl_pubkey, 2UL) == CRYPT_OK) {\n        /* ok now we have to reassemble the BIT STRING to an OCTET STRING.  Thanks OpenSSL... */\n        for (t = y = z = x = 0; x < ssl_pubkey[1].size; x++) {\n            y = (y << 1) | tmpbuf[x];\n            if (++z == 8) {\n                tmpbuf[t++] = (unsigned char)y;\n                y           = 0;\n                z           = 0;\n            }\n        }\n\n        /* now it should be SEQUENCE { INTEGER, INTEGER } */\n        if ((err = der_decode_sequence_multi(tmpbuf, t,\n                                             LTC_ASN1_INTEGER, 1UL, key->N,\n                                             LTC_ASN1_INTEGER, 1UL, key->e,\n                                             LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {\n            XFREE(tmpbuf);\n            goto LBL_ERR;\n        }\n        XFREE(tmpbuf);\n        key->type = PK_PUBLIC;\n        return CRYPT_OK;\n    }\n    XFREE(tmpbuf);\n\n    /* not SSL public key, try to match against LTC_PKCS #1 standards */\n    if ((err = der_decode_sequence_multi(in, inlen,\n                                         LTC_ASN1_INTEGER, 1UL, key->N,\n                                         LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {\n        goto LBL_ERR;\n    }\n\n    if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) {\n        if ((err = mp_init(&zero)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n        /* it's a private key */\n        if ((err = der_decode_sequence_multi(in, inlen,\n                                             LTC_ASN1_INTEGER, 1UL, zero,\n                                             LTC_ASN1_INTEGER, 1UL, key->N,\n                                             LTC_ASN1_INTEGER, 1UL, key->e,\n                                             LTC_ASN1_INTEGER, 1UL, key->d,\n                                             LTC_ASN1_INTEGER, 1UL, key->p,\n                                             LTC_ASN1_INTEGER, 1UL, key->q,\n                                             LTC_ASN1_INTEGER, 1UL, key->dP,\n                                             LTC_ASN1_INTEGER, 1UL, key->dQ,\n                                             LTC_ASN1_INTEGER, 1UL, key->qP,\n                                             LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {\n            mp_clear(zero);\n            goto LBL_ERR;\n        }\n        mp_clear(zero);\n        key->type = PK_PRIVATE;\n    } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) {\n        /* we don't support multi-prime RSA */\n        err = CRYPT_PK_INVALID_TYPE;\n        goto LBL_ERR;\n    } else {\n        /* it's a public key and we lack e */\n        if ((err = der_decode_sequence_multi(in, inlen,\n                                             LTC_ASN1_INTEGER, 1UL, key->N,\n                                             LTC_ASN1_INTEGER, 1UL, key->e,\n                                             LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {\n            goto LBL_ERR;\n        }\n        key->type = PK_PUBLIC;\n    }\n    return CRYPT_OK;\nLBL_ERR:\n    mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);\n    return err;\n}\n#endif /* LTC_MRSA */\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_import.c,v $ */\n/* $Revision: 1.23 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rsa_make_key.c\n   RSA key generation, Tom St Denis\n */\n\n#ifdef LTC_MRSA\n\n/**\n   Create an RSA key\n   @param prng     An active PRNG state\n   @param wprng    The index of the PRNG desired\n   @param size     The size of the modulus (key size) desired (octets)\n   @param e        The \"e\" value (public key).  e==65537 is a good choice\n   @param key      [out] Destination of a newly created private key pair\n   @return CRYPT_OK if successful, upon error all allocated ram is freed\n */\nint rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) {\n    void *p, *q, *tmp1, *tmp2, *tmp3;\n    int  err;\n\n    LTC_ARGCHK(ltc_mp.name != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    if ((size < (MIN_RSA_SIZE / 8)) || (size > (MAX_RSA_SIZE / 8))) {\n        return CRYPT_INVALID_KEYSIZE;\n    }\n\n    if ((e < 3) || ((e & 1) == 0)) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {\n        return err;\n    }\n\n    if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* make primes p and q (optimization provided by Wayne Scott) */\n    if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                  /* tmp3 = e */\n\n    /* make prime \"p\" */\n    do {\n        if ((err = rand_prime(p, size / 2, prng, wprng)) != CRYPT_OK) {\n            goto errkey;\n        }\n        if ((err = mp_sub_d(p, 1, tmp1)) != CRYPT_OK) {\n            goto errkey;\n        }                                                                              /* tmp1 = p-1 */\n        if ((err = mp_gcd(tmp1, tmp3, tmp2)) != CRYPT_OK) {\n            goto errkey;\n        }                                                                              /* tmp2 = gcd(p-1, e) */\n    } while (mp_cmp_d(tmp2, 1) != 0);                                                  /* while e divides p-1 */\n\n    /* make prime \"q\" */\n    do {\n        if ((err = rand_prime(q, size / 2, prng, wprng)) != CRYPT_OK) {\n            goto errkey;\n        }\n        if ((err = mp_sub_d(q, 1, tmp1)) != CRYPT_OK) {\n            goto errkey;\n        }                                                                             /* tmp1 = q-1 */\n        if ((err = mp_gcd(tmp1, tmp3, tmp2)) != CRYPT_OK) {\n            goto errkey;\n        }                                                                             /* tmp2 = gcd(q-1, e) */\n    } while (mp_cmp_d(tmp2, 1) != 0);                                                 /* while e divides q-1 */\n\n    /* tmp1 = lcm(p-1, q-1) */\n    if ((err = mp_sub_d(p, 1, tmp2)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                 /* tmp2 = p-1 */\n                                                                                      /* tmp1 = q-1 (previous do/while loop) */\n    if ((err = mp_lcm(tmp1, tmp2, tmp1)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                 /* tmp1 = lcm(p-1, q-1) */\n\n    /* make key */\n    if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {\n        goto errkey;\n    }\n\n    if ((err = mp_set_int(key->e, e)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                   /* key->e =  e */\n    if ((err = mp_invmod(key->e, tmp1, key->d)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                   /* key->d = 1/e mod lcm(p-1,q-1) */\n    if ((err = mp_mul(p, q, key->N)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                   /* key->N = pq */\n\n    /* optimize for CRT now */\n    /* find d mod q-1 and d mod p-1 */\n    if ((err = mp_sub_d(p, 1, tmp1)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                   /* tmp1 = q-1 */\n    if ((err = mp_sub_d(q, 1, tmp2)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                   /* tmp2 = p-1 */\n    if ((err = mp_mod(key->d, tmp1, key->dP)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                   /* dP = d mod p-1 */\n    if ((err = mp_mod(key->d, tmp2, key->dQ)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                   /* dQ = d mod q-1 */\n    if ((err = mp_invmod(q, p, key->qP)) != CRYPT_OK) {\n        goto errkey;\n    }                                                                                   /* qP = 1/q mod p */\n\n    if ((err = mp_copy(p, key->p)) != CRYPT_OK) {\n        goto errkey;\n    }\n    if ((err = mp_copy(q, key->q)) != CRYPT_OK) {\n        goto errkey;\n    }\n\n    /* set key type (in this case it's CRT optimized) */\n    key->type = PK_PRIVATE;\n\n    /* return ok and free temps */\n    err = CRYPT_OK;\n    goto cleanup;\nerrkey:\n    mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);\ncleanup:\n    mp_clear_multi(tmp3, tmp2, tmp1, p, q, NULL);\n    return err;\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_make_key.c,v $ */\n/* $Revision: 1.16 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rsa_sign_hash.c\n   RSA LTC_PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange\n */\n\n#ifdef LTC_MRSA\n\n/**\n   LTC_PKCS #1 pad then sign\n   @param in        The hash to sign\n   @param inlen     The length of the hash to sign (octets)\n   @param out       [out] The signature\n   @param outlen    [in/out] The max size and resulting size of the signature\n   @param padding   Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5)\n   @param prng      An active PRNG state\n   @param prng_idx  The index of the PRNG desired\n   @param hash_idx  The index of the hash desired\n   @param saltlen   The length of the salt desired (octets)\n   @param key       The private RSA key to use\n   @return CRYPT_OK if successful\n */\nint rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,\n                     unsigned char *out, unsigned long *outlen,\n                     int padding,\n                     prng_state *prng, int prng_idx,\n                     int hash_idx, unsigned long saltlen,\n                     rsa_key *key) {\n    unsigned long modulus_bitlen, modulus_bytelen, x, y;\n    int           err;\n\n    LTC_ARGCHK(in != NULL);\n    LTC_ARGCHK(out != NULL);\n    LTC_ARGCHK(outlen != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* valid padding? */\n    if ((padding != LTC_LTC_PKCS_1_V1_5) && (padding != LTC_LTC_PKCS_1_PSS)) {\n        return CRYPT_PK_INVALID_PADDING;\n    }\n\n    if (padding == LTC_LTC_PKCS_1_PSS) {\n        /* valid prng and hash ? */\n        if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {\n            return err;\n        }\n        if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n            return err;\n        }\n    }\n\n    /* get modulus len in bits */\n    modulus_bitlen = mp_count_bits((key->N));\n\n    /* outlen must be at least the size of the modulus */\n    modulus_bytelen = mp_unsigned_bin_size((key->N));\n    if (modulus_bytelen > *outlen) {\n        *outlen = modulus_bytelen;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n\n    if (padding == LTC_LTC_PKCS_1_PSS) {\n        /* PSS pad the key */\n        x = *outlen;\n        if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx,\n                                     hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) {\n            return err;\n        }\n    } else {\n        /* LTC_PKCS #1 v1.5 pad the hash */\n        unsigned char *tmpin;\n        ltc_asn1_list digestinfo[2], siginfo[2];\n\n        /* not all hashes have OIDs... so sad */\n        if (hash_descriptor[hash_idx].OIDlen == 0) {\n            return CRYPT_INVALID_ARG;\n        }\n\n        /* construct the SEQUENCE\n           SEQUENCE {\n             SEQUENCE {hashoid OID\n                       blah    NULL\n             }\n             hash    OCTET STRING\n           }\n         */\n        LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen);\n        LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);\n        LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);\n        LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen);\n\n        /* allocate memory for the encoding */\n        y     = mp_unsigned_bin_size(key->N);\n        tmpin = XMALLOC(y);\n        if (tmpin == NULL) {\n            return CRYPT_MEM;\n        }\n\n        if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) {\n            XFREE(tmpin);\n            return err;\n        }\n\n        x = *outlen;\n        if ((err = pkcs_1_v1_5_encode(tmpin, y, LTC_LTC_PKCS_1_EMSA,\n                                      modulus_bitlen, NULL, 0,\n                                      out, &x)) != CRYPT_OK) {\n            XFREE(tmpin);\n            return err;\n        }\n        XFREE(tmpin);\n    }\n\n    /* RSA encode it */\n    return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key);\n}\n#endif /* LTC_MRSA */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_sign_hash.c,v $ */\n/* $Revision: 1.11 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file rsa_verify_hash.c\n   RSA LTC_PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange\n */\n\n#ifdef LTC_MRSA\n\n/**\n   LTC_PKCS #1 de-sign then v1.5 or PSS depad\n   @param sig              The signature data\n   @param siglen           The length of the signature data (octets)\n   @param hash             The hash of the message that was signed\n   @param hashlen          The length of the hash of the message that was signed (octets)\n   @param padding          Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5)\n   @param hash_idx         The index of the desired hash\n   @param saltlen          The length of the salt used during signature\n   @param stat             [out] The result of the signature comparison, 1==valid, 0==invalid\n   @param key              The public RSA key corresponding to the key that performed the signature\n   @return CRYPT_OK on success (even if the signature is invalid)\n */\nint rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,\n                       const unsigned char *hash, unsigned long hashlen,\n                       int padding,\n                       int hash_idx, unsigned long saltlen,\n                       int *stat, rsa_key *key) {\n    unsigned long modulus_bitlen, modulus_bytelen, x;\n    int           err;\n    unsigned char *tmpbuf;\n\n    LTC_ARGCHK(hash != NULL);\n    LTC_ARGCHK(sig != NULL);\n    LTC_ARGCHK(stat != NULL);\n    LTC_ARGCHK(key != NULL);\n\n    /* default to invalid */\n    *stat = 0;\n\n    /* valid padding? */\n\n    if ((padding != LTC_LTC_PKCS_1_V1_5) &&\n        (padding != LTC_LTC_PKCS_1_PSS)) {\n        return CRYPT_PK_INVALID_PADDING;\n    }\n\n    if (padding == LTC_LTC_PKCS_1_PSS) {\n        /* valid hash ? */\n        if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {\n            return err;\n        }\n    }\n\n    /* get modulus len in bits */\n    modulus_bitlen = mp_count_bits((key->N));\n\n    /* outlen must be at least the size of the modulus */\n    modulus_bytelen = mp_unsigned_bin_size((key->N));\n    if (modulus_bytelen != siglen) {\n        return CRYPT_INVALID_PACKET;\n    }\n\n    /* allocate temp buffer for decoded sig */\n    tmpbuf = XMALLOC(siglen);\n    if (tmpbuf == NULL) {\n        return CRYPT_MEM;\n    }\n\n    /* RSA decode it  */\n    x = siglen;\n    if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {\n        XFREE(tmpbuf);\n        return err;\n    }\n\n    /* make sure the output is the right size */\n    if (x != siglen) {\n        XFREE(tmpbuf);\n        return CRYPT_INVALID_PACKET;\n    }\n\n    if (padding == LTC_LTC_PKCS_1_PSS) {\n        /* PSS decode and verify it */\n        if(modulus_bitlen%8 == 1){\n            err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat);\n        } else {\n            err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);\n        }\n    } else {\n        /* LTC_PKCS #1 v1.5 decode it */\n        unsigned char *out;\n        unsigned long outlen, loid[16];\n        int           decoded;\n        ltc_asn1_list digestinfo[2], siginfo[2];\n\n        /* not all hashes have OIDs... so sad */\n        if (hash_descriptor[hash_idx].OIDlen == 0) {\n            err = CRYPT_INVALID_ARG;\n            goto bail_2;\n        }\n\n        /* allocate temp buffer for decoded hash */\n        outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3;\n        out    = XMALLOC(outlen);\n        if (out == NULL) {\n            err = CRYPT_MEM;\n            goto bail_2;\n        }\n\n        if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) {\n            XFREE(out);\n            goto bail_2;\n        }\n\n        /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */\n\n        /* construct the SEQUENCE\n           SEQUENCE {\n             SEQUENCE {hashoid OID\n                       blah    NULL\n             }\n             hash    OCTET STRING\n           }\n         */\n        LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid) / sizeof(loid[0]));\n        LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);\n        LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);\n        LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);\n\n        if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {\n            XFREE(out);\n            goto bail_2;\n        }\n\n        /* test OID */\n        if ((digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) &&\n            (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) &&\n            (siginfo[1].size == hashlen) &&\n            (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) {\n            *stat = 1;\n        }\n\n #ifdef LTC_CLEAN_STACK\n        zeromem(out, outlen);\n #endif\n        XFREE(out);\n    }\n\nbail_2:\n #ifdef LTC_CLEAN_STACK\n    zeromem(tmpbuf, siglen);\n #endif\n    XFREE(tmpbuf);\n    return err;\n}\n#endif /* LTC_MRSA */\n\n/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_verify_hash.c,v $ */\n/* $Revision: 1.13 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file sprng.c\n   Secure PRNG, Tom St Denis\n */\n\n/* A secure PRNG using the RNG functions.  Basically this is a\n * wrapper that allows you to use a secure RNG as a PRNG\n * in the various other functions.\n */\n\n#ifdef LTC_SPRNG\n\nconst struct ltc_prng_descriptor sprng_desc =\n{\n    \"sprng\",            0,\n    &sprng_start,\n    &sprng_add_entropy,\n    &sprng_ready,\n    &sprng_read,\n    &sprng_done,\n    &sprng_export,\n    &sprng_import,\n    &sprng_test\n};\n\n/**\n   Start the PRNG\n   @param prng     [out] The PRNG state to initialize\n   @return CRYPT_OK if successful\n */\nint sprng_start(prng_state *prng) {\n    return CRYPT_OK;\n}\n\n/**\n   Add entropy to the PRNG state\n   @param in       The data to add\n   @param inlen    Length of the data to add\n   @param prng     PRNG state to update\n   @return CRYPT_OK if successful\n */\nint sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) {\n    return CRYPT_OK;\n}\n\n/**\n   Make the PRNG ready to read from\n   @param prng   The PRNG to make active\n   @return CRYPT_OK if successful\n */\nint sprng_ready(prng_state *prng) {\n    return CRYPT_OK;\n}\n\n/**\n   Read from the PRNG\n   @param out      Destination\n   @param outlen   Length of output\n   @param prng     The active PRNG to read from\n   @return Number of octets read\n */\nunsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng) {\n    LTC_ARGCHK(out != NULL);\n    return rng_get_bytes(out, outlen, NULL);\n}\n\n/**\n   Terminate the PRNG\n   @param prng   The PRNG to terminate\n   @return CRYPT_OK if successful\n */\nint sprng_done(prng_state *prng) {\n    return CRYPT_OK;\n}\n\n/**\n   Export the PRNG state\n   @param out       [out] Destination\n   @param outlen    [in/out] Max size and resulting size of the state\n   @param prng      The PRNG to export\n   @return CRYPT_OK if successful\n */\nint sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) {\n    LTC_ARGCHK(outlen != NULL);\n\n    *outlen = 0;\n    return CRYPT_OK;\n}\n\n/**\n   Import a PRNG state\n   @param in       The PRNG state\n   @param inlen    Size of the state\n   @param prng     The PRNG to import\n   @return CRYPT_OK if successful\n */\nint sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) {\n    return CRYPT_OK;\n}\n\n/**\n   PRNG self-test\n   @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled\n */\nint sprng_test(void) {\n    return CRYPT_OK;\n}\n#endif\n\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/prngs/sprng.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file zeromem.c\n   Zero a block of memory, Tom St Denis\n */\n\n/**\n   Zero a block of memory\n   @param out    The destination of the area to zero\n   @param outlen The length of the area to zero (octets)\n */\nvoid zeromem(void *out, size_t outlen) {\n    unsigned char *mem = out;\n\n    LTC_ARGCHKVD(out != NULL);\n    while (outlen-- > 0) {\n        *mem++ = 0;\n    }\n}\n\n/* $Source: /cvs/libtom/libtomcrypt/src/misc/zeromem.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file sha1.c\n   LTC_SHA1 code by Tom St Denis\n */\n\n\n#ifdef LTC_SHA1\n\nconst struct ltc_hash_descriptor sha1_desc =\n{\n    \"sha1\",\n    2,\n    20,\n    64,\n\n    /* OID */\n    { 1,        3, 14, 3, 2, 26, },\n    6,\n\n    &sha1_init,\n    &sha1_process,\n    &sha1_done,\n    &sha1_test,\n    NULL\n};\n\n #define F0(x, y, z)    (z ^ (x & (y ^ z)))\n #define F1(x, y, z)    (x ^ y ^ z)\n #define F2(x, y, z)    ((x & y) | (z & (x | y)))\n #define F3(x, y, z)    (x ^ y ^ z)\n\n #ifdef LTC_CLEAN_STACK\nstatic int _sha1_compress(hash_state *md, unsigned char *buf)\n #else\nstatic int  sha1_compress(hash_state *md, unsigned char *buf)\n #endif\n{\n    ulong32 a, b, c, d, e, W[80], i;\n\n #ifdef LTC_SMALL_CODE\n    ulong32 t;\n #endif\n\n    /* copy the state into 512-bits into W[0..15] */\n    for (i = 0; i < 16; i++) {\n        LOAD32H(W[i], buf + (4 * i));\n    }\n\n    /* copy state */\n    a = md->sha1.state[0];\n    b = md->sha1.state[1];\n    c = md->sha1.state[2];\n    d = md->sha1.state[3];\n    e = md->sha1.state[4];\n\n    /* expand it */\n    for (i = 16; i < 80; i++) {\n        W[i] = ROL(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);\n    }\n\n    /* compress */\n    /* round one */\n #define FF0(a, b, c, d, e, i)    e = (ROLc(a, 5) + F0(b, c, d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);\n #define FF1(a, b, c, d, e, i)    e = (ROLc(a, 5) + F1(b, c, d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);\n #define FF2(a, b, c, d, e, i)    e = (ROLc(a, 5) + F2(b, c, d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);\n #define FF3(a, b, c, d, e, i)    e = (ROLc(a, 5) + F3(b, c, d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);\n\n #ifdef LTC_SMALL_CODE\n    for (i = 0; i < 20; ) {\n        FF0(a, b, c, d, e, i++);\n        t = e;\n        e = d;\n        d = c;\n        c = b;\n        b = a;\n        a = t;\n    }\n\n    for ( ; i < 40; ) {\n        FF1(a, b, c, d, e, i++);\n        t = e;\n        e = d;\n        d = c;\n        c = b;\n        b = a;\n        a = t;\n    }\n\n    for ( ; i < 60; ) {\n        FF2(a, b, c, d, e, i++);\n        t = e;\n        e = d;\n        d = c;\n        c = b;\n        b = a;\n        a = t;\n    }\n\n    for ( ; i < 80; ) {\n        FF3(a, b, c, d, e, i++);\n        t = e;\n        e = d;\n        d = c;\n        c = b;\n        b = a;\n        a = t;\n    }\n\n #else\n    for (i = 0; i < 20; ) {\n        FF0(a, b, c, d, e, i++);\n        FF0(e, a, b, c, d, i++);\n        FF0(d, e, a, b, c, i++);\n        FF0(c, d, e, a, b, i++);\n        FF0(b, c, d, e, a, i++);\n    }\n\n    /* round two */\n    for ( ; i < 40; ) {\n        FF1(a, b, c, d, e, i++);\n        FF1(e, a, b, c, d, i++);\n        FF1(d, e, a, b, c, i++);\n        FF1(c, d, e, a, b, i++);\n        FF1(b, c, d, e, a, i++);\n    }\n\n    /* round three */\n    for ( ; i < 60; ) {\n        FF2(a, b, c, d, e, i++);\n        FF2(e, a, b, c, d, i++);\n        FF2(d, e, a, b, c, i++);\n        FF2(c, d, e, a, b, i++);\n        FF2(b, c, d, e, a, i++);\n    }\n\n    /* round four */\n    for ( ; i < 80; ) {\n        FF3(a, b, c, d, e, i++);\n        FF3(e, a, b, c, d, i++);\n        FF3(d, e, a, b, c, i++);\n        FF3(c, d, e, a, b, i++);\n        FF3(b, c, d, e, a, i++);\n    }\n #endif\n\n #undef FF0\n #undef FF1\n #undef FF2\n #undef FF3\n\n    /* store */\n    md->sha1.state[0] = md->sha1.state[0] + a;\n    md->sha1.state[1] = md->sha1.state[1] + b;\n    md->sha1.state[2] = md->sha1.state[2] + c;\n    md->sha1.state[3] = md->sha1.state[3] + d;\n    md->sha1.state[4] = md->sha1.state[4] + e;\n\n    return CRYPT_OK;\n}\n\n #ifdef LTC_CLEAN_STACK\nstatic int sha1_compress(hash_state *md, unsigned char *buf) {\n    int err;\n\n    err = _sha1_compress(md, buf);\n    burn_stack(sizeof(ulong32) * 87);\n    return err;\n}\n #endif\n\n/**\n   Initialize the hash state\n   @param md   The hash state you wish to initialize\n   @return CRYPT_OK if successful\n */\nint sha1_init(hash_state *md) {\n    LTC_ARGCHK(md != NULL);\n    md->sha1.state[0] = 0x67452301UL;\n    md->sha1.state[1] = 0xefcdab89UL;\n    md->sha1.state[2] = 0x98badcfeUL;\n    md->sha1.state[3] = 0x10325476UL;\n    md->sha1.state[4] = 0xc3d2e1f0UL;\n    md->sha1.curlen   = 0;\n    md->sha1.length   = 0;\n    return CRYPT_OK;\n}\n\n/**\n   Process a block of memory though the hash\n   @param md     The hash state\n   @param in     The data to hash\n   @param inlen  The length of the data (octets)\n   @return CRYPT_OK if successful\n */\nHASH_PROCESS(sha1_process, sha1_compress, sha1, 64)\n\n/**\n   Terminate the hash to get the digest\n   @param md  The hash state\n   @param out [out] The destination of the hash (20 bytes)\n   @return CRYPT_OK if successful\n */\nint sha1_done(hash_state *md, unsigned char *out) {\n    int i;\n\n    LTC_ARGCHK(md != NULL);\n    LTC_ARGCHK(out != NULL);\n\n    if (md->sha1.curlen >= sizeof(md->sha1.buf)) {\n        return CRYPT_INVALID_ARG;\n    }\n\n    /* increase the length of the message */\n    md->sha1.length += md->sha1.curlen * 8;\n\n    /* append the '1' bit */\n    md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;\n\n    /* if the length is currently above 56 bytes we append zeros\n     * then compress.  Then we can fall back to padding zeros and length\n     * encoding like normal.\n     */\n    if (md->sha1.curlen > 56) {\n        while (md->sha1.curlen < 64) {\n            md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;\n        }\n        sha1_compress(md, md->sha1.buf);\n        md->sha1.curlen = 0;\n    }\n\n    /* pad upto 56 bytes of zeroes */\n    while (md->sha1.curlen < 56) {\n        md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;\n    }\n\n    /* store length */\n    STORE64H(md->sha1.length, md->sha1.buf + 56);\n    sha1_compress(md, md->sha1.buf);\n\n    /* copy output */\n    for (i = 0; i < 5; i++) {\n        STORE32H(md->sha1.state[i], out + (4 * i));\n    }\n #ifdef LTC_CLEAN_STACK\n    zeromem(md, sizeof(hash_state));\n #endif\n    return CRYPT_OK;\n}\n\n/**\n   Self-test the hash\n   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled\n */\nint  sha1_test(void) {\n #ifndef LTC_TEST\n    return CRYPT_NOP;\n #else\n    static const struct {\n        char          *msg;\n        unsigned char hash[20];\n    } tests[] = {\n        { \"abc\",\n            {                                                       0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,\n                                                                  0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,\n                                                                  0x9c, 0xd0, 0xd8, 0x9d } },\n        { \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\",\n            {                                                       0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,\n                                                                  0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,\n                                                                  0xE5, 0x46, 0x70, 0xF1 } }\n    };\n\n    int           i;\n    unsigned char tmp[20];\n    hash_state    md;\n\n    for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {\n        sha1_init(&md);\n        sha1_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));\n        sha1_done(&md, tmp);\n        if (XMEMCMP(tmp, tests[i].hash, 20) != 0) {\n            return CRYPT_FAIL_TESTVECTOR;\n        }\n    }\n    return CRYPT_OK;\n #endif\n}\n#endif\n\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */\n/* $Revision: 1.10 $ */\n/* $Date: 2007/05/12 14:25:28 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n  @file sha256.c\n  LTC_SHA256 by Tom St Denis \n*/\n\n#ifdef LTC_SHA256 \n\nconst struct ltc_hash_descriptor sha256_desc =\n{\n    \"sha256\",\n    0,\n    32,\n    64,\n\n    /* OID */\n   { 2, 16, 840, 1, 101, 3, 4, 2, 1,  },\n   9,\n    \n    &sha256_init,\n    &sha256_process,\n    &sha256_done,\n    &sha256_test,\n    NULL\n};\n\n#ifdef LTC_SMALL_CODE\n/* the K array */\nstatic const ulong32 K[64] = {\n    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,\n    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,\n    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,\n    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,\n    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,\n    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,\n    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,\n    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,\n    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,\n    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,\n    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,\n    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,\n    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL\n};\n#endif\n\n/* Various logical functions */\n#define Ch(x,y,z)       (z ^ (x & (y ^ z)))\n#define Maj(x,y,z)      (((x | y) & z) | (x & y)) \n#define S(x, n)         RORc((x),(n))\n#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))\n#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))\n#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))\n#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))\n#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))\n\n/* compress 512-bits */\n#ifdef LTC_CLEAN_STACK\nstatic int _sha256_compress(hash_state * md, unsigned char *buf)\n#else\nstatic int  sha256_compress(hash_state * md, unsigned char *buf)\n#endif\n{\n#ifdef __MRC__\n/* MrC hangs while optimizing the code for this function. */\n#pragma options opt off\n#endif\n\n    ulong32 S[8], W[64], t0, t1;\n#ifdef LTC_SMALL_CODE\n    ulong32 t;\n#endif\n    int i;\n\n    /* copy state into S */\n    for (i = 0; i < 8; i++) {\n        S[i] = md->sha256.state[i];\n    }\n\n    /* copy the state into 512-bits into W[0..15] */\n    for (i = 0; i < 16; i++) {\n        LOAD32H(W[i], buf + (4*i));\n    }\n\n    /* fill W[16..63] */\n    for (i = 16; i < 64; i++) {\n        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];\n    }        \n\n    /* Compress */\n#ifdef LTC_SMALL_CODE   \n#define RND(a,b,c,d,e,f,g,h,i)                         \\\n     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \\\n     t1 = Sigma0(a) + Maj(a, b, c);                    \\\n     d += t0;                                          \\\n     h  = t0 + t1;\n\n     for (i = 0; i < 64; ++i) {\n         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);\n         t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; \n         S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;\n     }  \n#else \n#define RND(a,b,c,d,e,f,g,h,i,ki)                    \\\n     t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];   \\\n     t1 = Sigma0(a) + Maj(a, b, c);                  \\\n     d += t0;                                        \\\n     h  = t0 + t1;\n\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);\n\n#undef RND     \n    \n#endif     \n\n    /* feedback */\n    for (i = 0; i < 8; i++) {\n        md->sha256.state[i] = md->sha256.state[i] + S[i];\n    }\n    return CRYPT_OK;\n}\n\n#ifdef LTC_CLEAN_STACK\nstatic int sha256_compress(hash_state * md, unsigned char *buf)\n{\n    int err;\n    err = _sha256_compress(md, buf);\n    burn_stack(sizeof(ulong32) * 74);\n    return err;\n}\n#endif\n\n/**\n   Initialize the hash state\n   @param md   The hash state you wish to initialize\n   @return CRYPT_OK if successful\n*/\nint sha256_init(hash_state * md)\n{\n    LTC_ARGCHK(md != NULL);\n\n    md->sha256.curlen = 0;\n    md->sha256.length = 0;\n    md->sha256.state[0] = 0x6A09E667UL;\n    md->sha256.state[1] = 0xBB67AE85UL;\n    md->sha256.state[2] = 0x3C6EF372UL;\n    md->sha256.state[3] = 0xA54FF53AUL;\n    md->sha256.state[4] = 0x510E527FUL;\n    md->sha256.state[5] = 0x9B05688CUL;\n    md->sha256.state[6] = 0x1F83D9ABUL;\n    md->sha256.state[7] = 0x5BE0CD19UL;\n    return CRYPT_OK;\n}\n\n/**\n   Process a block of memory though the hash\n   @param md     The hash state\n   @param in     The data to hash\n   @param inlen  The length of the data (octets)\n   @return CRYPT_OK if successful\n*/\nHASH_PROCESS(sha256_process, sha256_compress, sha256, 64)\n\n/**\n   Terminate the hash to get the digest\n   @param md  The hash state\n   @param out [out] The destination of the hash (32 bytes)\n   @return CRYPT_OK if successful\n*/\nint sha256_done(hash_state * md, unsigned char *out)\n{\n    int i;\n\n    LTC_ARGCHK(md  != NULL);\n    LTC_ARGCHK(out != NULL);\n\n    if (md->sha256.curlen >= sizeof(md->sha256.buf)) {\n       return CRYPT_INVALID_ARG;\n    }\n\n\n    /* increase the length of the message */\n    md->sha256.length += md->sha256.curlen * 8;\n\n    /* append the '1' bit */\n    md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;\n\n    /* if the length is currently above 56 bytes we append zeros\n     * then compress.  Then we can fall back to padding zeros and length\n     * encoding like normal.\n     */\n    if (md->sha256.curlen > 56) {\n        while (md->sha256.curlen < 64) {\n            md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;\n        }\n        sha256_compress(md, md->sha256.buf);\n        md->sha256.curlen = 0;\n    }\n\n    /* pad upto 56 bytes of zeroes */\n    while (md->sha256.curlen < 56) {\n        md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;\n    }\n\n    /* store length */\n    STORE64H(md->sha256.length, md->sha256.buf+56);\n    sha256_compress(md, md->sha256.buf);\n\n    /* copy output */\n    for (i = 0; i < 8; i++) {\n        STORE32H(md->sha256.state[i], out+(4*i));\n    }\n#ifdef LTC_CLEAN_STACK\n    zeromem(md, sizeof(hash_state));\n#endif\n    return CRYPT_OK;\n}\n\n/**\n  Self-test the hash\n  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled\n*/  \nint  sha256_test(void)\n{\n #ifndef LTC_TEST\n    return CRYPT_NOP;\n #else    \n  static const struct {\n      char *msg;\n      unsigned char hash[32];\n  } tests[] = {\n    { \"abc\",\n      { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,\n        0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,\n        0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,\n        0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }\n    },\n    { \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\",\n      { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, \n        0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,\n        0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, \n        0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }\n    },\n  };\n\n  int i;\n  unsigned char tmp[32];\n  hash_state md;\n\n  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {\n      sha256_init(&md);\n      sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));\n      sha256_done(&md, tmp);\n      if (XMEMCMP(tmp, tests[i].hash, 32) != 0) {\n         return CRYPT_FAIL_TESTVECTOR;\n      }\n  }\n  return CRYPT_OK;\n #endif\n}\n\n#endif\n\n\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n/**\n   @param sha384.c\n   LTC_SHA384 hash included in sha512.c, Tom St Denis\n*/\n\n\n\n#if defined(LTC_SHA384) && defined(LTC_SHA512)\n\nconst struct ltc_hash_descriptor sha384_desc =\n{\n    \"sha384\",\n    4,\n    48,\n    128,\n\n    /* OID */\n   { 2, 16, 840, 1, 101, 3, 4, 2, 2,  },\n   9,\n\n    &sha384_init,\n    &sha512_process,\n    &sha384_done,\n    &sha384_test,\n    NULL\n};\n\n/**\n   Initialize the hash state\n   @param md   The hash state you wish to initialize\n   @return CRYPT_OK if successful\n*/\nint sha384_init(hash_state * md)\n{\n    LTC_ARGCHK(md != NULL);\n\n    md->sha512.curlen = 0;\n    md->sha512.length = 0;\n    md->sha512.state[0] = CONST64(0xcbbb9d5dc1059ed8);\n    md->sha512.state[1] = CONST64(0x629a292a367cd507);\n    md->sha512.state[2] = CONST64(0x9159015a3070dd17);\n    md->sha512.state[3] = CONST64(0x152fecd8f70e5939);\n    md->sha512.state[4] = CONST64(0x67332667ffc00b31);\n    md->sha512.state[5] = CONST64(0x8eb44a8768581511);\n    md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7);\n    md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4);\n    return CRYPT_OK;\n}\n\n/**\n   Terminate the hash to get the digest\n   @param md  The hash state\n   @param out [out] The destination of the hash (48 bytes)\n   @return CRYPT_OK if successful\n*/\nint sha384_done(hash_state * md, unsigned char *out)\n{\n   unsigned char buf[64];\n\n   LTC_ARGCHK(md  != NULL);\n   LTC_ARGCHK(out != NULL);\n\n    if (md->sha512.curlen >= sizeof(md->sha512.buf)) {\n       return CRYPT_INVALID_ARG;\n    }\n\n   sha512_done(md, buf);\n   XMEMCPY(out, buf, 48);\n#ifdef LTC_CLEAN_STACK\n   zeromem(buf, sizeof(buf));\n#endif\n   return CRYPT_OK;\n}\n\n/**\n  Self-test the hash\n  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled\n*/\nint  sha384_test(void)\n{\n #ifndef LTC_TEST\n    return CRYPT_NOP;\n #else\n  static const struct {\n      char *msg;\n      unsigned char hash[48];\n  } tests[] = {\n    { \"abc\",\n      { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,\n        0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,\n        0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,\n        0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,\n        0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,\n        0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 }\n    },\n    { \"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu\",\n      { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,\n        0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,\n        0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,\n        0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,\n        0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,\n        0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 }\n    },\n  };\n\n  int i;\n  unsigned char tmp[48];\n  hash_state md;\n\n  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {\n      sha384_init(&md);\n      sha384_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));\n      sha384_done(&md, tmp);\n      if (XMEMCMP(tmp, tests[i].hash, 48) != 0) {\n         return CRYPT_FAIL_TESTVECTOR;\n      }\n  }\n  return CRYPT_OK;\n #endif\n}\n\n#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @param sha512.c\n   LTC_SHA512 by Tom St Denis \n*/\n\n#ifdef LTC_SHA512\n\nconst struct ltc_hash_descriptor sha512_desc =\n{\n    \"sha512\",\n    5,\n    64,\n    128,\n\n    /* OID */\n   { 2, 16, 840, 1, 101, 3, 4, 2, 3,  },\n   9,\n\n    &sha512_init,\n    &sha512_process,\n    &sha512_done,\n    &sha512_test,\n    NULL\n};\n\n/* the K array */\nstatic const ulong64 K[80] = {\nCONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), \nCONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),\nCONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), \nCONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),\nCONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), \nCONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),\nCONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), \nCONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),\nCONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), \nCONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),\nCONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), \nCONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),\nCONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), \nCONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),\nCONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), \nCONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),\nCONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), \nCONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),\nCONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), \nCONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),\nCONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),\nCONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),\nCONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), \nCONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),\nCONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), \nCONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),\nCONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), \nCONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),\nCONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), \nCONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),\nCONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), \nCONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),\nCONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), \nCONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),\nCONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), \nCONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),\nCONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), \nCONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),\nCONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), \nCONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)\n};\n\n/* Various logical functions */\n#undef S\n#undef R\n#undef Sigma0\n#undef Sigma1\n#undef Gamma0\n#undef Gamma1\n\n#define Ch(x,y,z)       (z ^ (x & (y ^ z)))\n#define Maj(x,y,z)      (((x | y) & z) | (x & y)) \n#define S(x, n)         ROR64c(x, n)\n#define R(x, n)         (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n))\n#define Sigma0(x)       (S(x, 28) ^ S(x, 34) ^ S(x, 39))\n#define Sigma1(x)       (S(x, 14) ^ S(x, 18) ^ S(x, 41))\n#define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))\n#define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))\n\n/* compress 1024-bits */\n#ifdef LTC_CLEAN_STACK\nstatic int _sha512_compress(hash_state * md, unsigned char *buf)\n#else\nstatic int  sha512_compress(hash_state * md, unsigned char *buf)\n#endif\n{\n#ifdef __MRC__\n/* MrC hangs while optimizing the code for this function. */\n#pragma options opt off\n#endif\n\n    ulong64 S[8], W[80], t0, t1;\n    int i;\n\n    /* copy state into S */\n    for (i = 0; i < 8; i++) {\n        S[i] = md->sha512.state[i];\n    }\n\n    /* copy the state into 1024-bits into W[0..15] */\n    for (i = 0; i < 16; i++) {\n        LOAD64H(W[i], buf + (8*i));\n    }\n\n    /* fill W[16..79] */\n    for (i = 16; i < 80; i++) {\n        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];\n    }        \n\n    /* Compress */\n#ifdef LTC_SMALL_CODE\n    for (i = 0; i < 80; i++) {\n        t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];\n        t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);\n        S[7] = S[6];\n        S[6] = S[5];\n        S[5] = S[4];\n        S[4] = S[3] + t0;\n        S[3] = S[2];\n        S[2] = S[1];\n        S[1] = S[0];\n        S[0] = t0 + t1;\n    }\n#else\n#define RND(a,b,c,d,e,f,g,h,i)                    \\\n     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \\\n     t1 = Sigma0(a) + Maj(a, b, c);                  \\\n     d += t0;                                        \\\n     h  = t0 + t1;\n\n     for (i = 0; i < 80; i += 8) {\n         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);\n         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);\n         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);\n         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);\n         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);\n         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);\n         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);\n         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);\n     }\n#endif     \n\n\n    /* feedback */\n    for (i = 0; i < 8; i++) {\n        md->sha512.state[i] = md->sha512.state[i] + S[i];\n    }\n\n    return CRYPT_OK;\n}\n\n/* compress 1024-bits */\n#ifdef LTC_CLEAN_STACK\nstatic int sha512_compress(hash_state * md, unsigned char *buf)\n{\n    int err;\n    err = _sha512_compress(md, buf);\n    burn_stack(sizeof(ulong64) * 90 + sizeof(int));\n    return err;\n}\n#endif\n\n/**\n   Initialize the hash state\n   @param md   The hash state you wish to initialize\n   @return CRYPT_OK if successful\n*/\nint sha512_init(hash_state * md)\n{\n    LTC_ARGCHK(md != NULL);\n    md->sha512.curlen = 0;\n    md->sha512.length = 0;\n    md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);\n    md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);\n    md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);\n    md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);\n    md->sha512.state[4] = CONST64(0x510e527fade682d1);\n    md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);\n    md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);\n    md->sha512.state[7] = CONST64(0x5be0cd19137e2179);\n    return CRYPT_OK;\n}\n\n/**\n   Process a block of memory though the hash\n   @param md     The hash state\n   @param in     The data to hash\n   @param inlen  The length of the data (octets)\n   @return CRYPT_OK if successful\n*/\nHASH_PROCESS(sha512_process, sha512_compress, sha512, 128)\n\n/**\n   Terminate the hash to get the digest\n   @param md  The hash state\n   @param out [out] The destination of the hash (64 bytes)\n   @return CRYPT_OK if successful\n*/\nint sha512_done(hash_state * md, unsigned char *out)\n{\n#ifdef __MRC__\n/* Disable optimizations for this function so MrC will compile it correctly. */\n#pragma options opt off\n#endif\n\n    int i;\n\n    LTC_ARGCHK(md  != NULL);\n    LTC_ARGCHK(out != NULL);\n\n    if (md->sha512.curlen >= sizeof(md->sha512.buf)) {\n       return CRYPT_INVALID_ARG;\n    }\n\n    /* increase the length of the message */\n    md->sha512.length += md->sha512.curlen * CONST64(8);\n\n    /* append the '1' bit */\n    md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;\n\n    /* if the length is currently above 112 bytes we append zeros\n     * then compress.  Then we can fall back to padding zeros and length\n     * encoding like normal.\n     */\n    if (md->sha512.curlen > 112) {\n        while (md->sha512.curlen < 128) {\n            md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;\n        }\n        sha512_compress(md, md->sha512.buf);\n        md->sha512.curlen = 0;\n    }\n\n    /* pad upto 120 bytes of zeroes \n     * note: that from 112 to 120 is the 64 MSB of the length.  We assume that you won't hash\n     * > 2^64 bits of data... :-)\n     */\n    while (md->sha512.curlen < 120) {\n        md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;\n    }\n\n    /* store length */\n    STORE64H(md->sha512.length, md->sha512.buf+120);\n    sha512_compress(md, md->sha512.buf);\n\n    /* copy output */\n    for (i = 0; i < 8; i++) {\n        STORE64H(md->sha512.state[i], out+(8*i));\n    }\n#ifdef LTC_CLEAN_STACK\n    zeromem(md, sizeof(hash_state));\n#endif\n    return CRYPT_OK;\n}\n\n/**\n  Self-test the hash\n  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled\n*/  \nint  sha512_test(void)\n{\n #ifndef LTC_TEST\n    return CRYPT_NOP;\n #else    \n  static const struct {\n      char *msg;\n      unsigned char hash[64];\n  } tests[] = {\n    { \"abc\",\n     { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,\n       0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,\n       0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,\n       0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,\n       0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,\n       0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,\n       0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,\n       0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }\n    },\n    { \"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu\",\n     { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,\n       0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,\n       0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,\n       0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,\n       0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,\n       0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,\n       0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,\n       0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }\n    },\n  };\n\n  int i;\n  unsigned char tmp[64];\n  hash_state md;\n\n  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {\n      sha512_init(&md);\n      sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));\n      sha512_done(&md, tmp);\n      if (XMEMCMP(tmp, tests[i].hash, 64) != 0) {\n         return CRYPT_FAIL_TESTVECTOR;\n      }\n  }\n  return CRYPT_OK;\n  #endif\n}\n\n#endif\n\n\n\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n  @file hmac_init.c\n  HMAC support, initialize state, Tom St Denis/Dobes Vandermeer\n*/\n\n#ifdef LTC_HMAC\n\n#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize\n\n/**\n   Initialize an HMAC context.\n   @param hmac     The HMAC state\n   @param hash     The index of the hash you want to use\n   @param key      The secret key\n   @param keylen   The length of the secret key (octets)\n   @return CRYPT_OK if successful\n*/\nint hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen)\n{\n    unsigned char *buf;\n    unsigned long hashsize;\n    unsigned long i, z;\n    int err;\n\n    LTC_ARGCHK(hmac != NULL);\n    LTC_ARGCHK(key  != NULL);\n\n    /* valid hash? */\n    if ((err = hash_is_valid(hash)) != CRYPT_OK) {\n        return err;\n    }\n    hmac->hash = hash;\n    hashsize   = hash_descriptor[hash].hashsize;\n\n    /* valid key length? */\n    if (keylen == 0) {\n        return CRYPT_INVALID_KEYSIZE;\n    }\n\n    /* allocate ram for buf */\n    buf = XMALLOC(LTC_HMAC_BLOCKSIZE);\n    if (buf == NULL) {\n       return CRYPT_MEM;\n    }\n\n    /* allocate memory for key */\n    hmac->key = XMALLOC(LTC_HMAC_BLOCKSIZE);\n    if (hmac->key == NULL) {\n       XFREE(buf);\n       return CRYPT_MEM;\n    }\n\n    /* (1) make sure we have a large enough key */\n    if(keylen > LTC_HMAC_BLOCKSIZE) {\n        z = LTC_HMAC_BLOCKSIZE;\n        if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) {\n           goto LBL_ERR;\n        }\n        keylen = hashsize;\n    } else {\n        XMEMCPY(hmac->key, key, (size_t)keylen);\n    }\n\n    if(keylen < LTC_HMAC_BLOCKSIZE) {\n       zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen));\n    }\n\n    /* Create the initial vector for step (3) */\n    for(i=0; i < LTC_HMAC_BLOCKSIZE;   i++) {\n       buf[i] = hmac->key[i] ^ 0x36;\n    }\n\n    /* Pre-pend that to the hash data */\n    if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) {\n       goto LBL_ERR;\n    }\n\n    if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) {\n       goto LBL_ERR;\n    }\n    goto done;\nLBL_ERR:\n    /* free the key since we failed */\n    XFREE(hmac->key);\ndone:\n#ifdef LTC_CLEAN_STACK\n   zeromem(buf, LTC_HMAC_BLOCKSIZE);\n#endif\n\n   XFREE(buf);\n   return err;\n}\n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n  @file hmac_process.c\n  HMAC support, process data, Tom St Denis/Dobes Vandermeer\n*/\n\n#ifdef LTC_HMAC\n\n/**\n  Process data through HMAC\n  @param hmac    The hmac state\n  @param in      The data to send through HMAC\n  @param inlen   The length of the data to HMAC (octets)\n  @return CRYPT_OK if successful\n*/\nint hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen)\n{\n    int err;\n    LTC_ARGCHK(hmac != NULL);\n    LTC_ARGCHK(in != NULL);\n    if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) {\n        return err;\n    }\n    return hash_descriptor[hmac->hash].process(&hmac->md, in, inlen);\n}\n\n#endif\n\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n  @file hmac_done.c\n  HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer\n*/\n\n#ifdef LTC_HMAC\n\n#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize\n\n/**\n   Terminate an HMAC session\n   @param hmac    The HMAC state\n   @param out     [out] The destination of the HMAC authentication tag\n   @param outlen  [in/out]  The max size and resulting size of the HMAC authentication tag\n   @return CRYPT_OK if successful\n*/\nint hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen)\n{\n    unsigned char *buf, *isha;\n    unsigned long hashsize, i;\n    int hash, err;\n\n    LTC_ARGCHK(hmac  != NULL);\n    LTC_ARGCHK(out   != NULL);\n\n    /* test hash */\n    hash = hmac->hash;\n    if((err = hash_is_valid(hash)) != CRYPT_OK) {\n        return err;\n    }\n\n    /* get the hash message digest size */\n    hashsize = hash_descriptor[hash].hashsize;\n\n    /* allocate buffers */\n    buf  = XMALLOC(LTC_HMAC_BLOCKSIZE);\n    isha = XMALLOC(hashsize);\n    if (buf == NULL || isha == NULL) {\n       if (buf != NULL) {\n          XFREE(buf);\n       }\n       if (isha != NULL) {\n          XFREE(isha);\n       }\n       return CRYPT_MEM;\n    }\n\n    /* Get the hash of the first HMAC vector plus the data */\n    if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) {\n       goto LBL_ERR;\n    }\n\n    /* Create the second HMAC vector vector for step (3) */\n    for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) {\n        buf[i] = hmac->key[i] ^ 0x5C;\n    }\n\n    /* Now calculate the \"outer\" hash for step (5), (6), and (7) */\n    if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) {\n       goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) {\n       goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) {\n       goto LBL_ERR;\n    }\n    if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) {\n       goto LBL_ERR;\n    }\n\n    /* copy to output  */\n    for (i = 0; i < hashsize && i < *outlen; i++) {\n        out[i] = buf[i];\n    }\n    *outlen = i;\n\n    err = CRYPT_OK;\nLBL_ERR:\n    XFREE(hmac->key);\n#ifdef LTC_CLEAN_STACK\n    zeromem(isha, hashsize);\n    zeromem(buf,  hashsize);\n    zeromem(hmac, sizeof(*hmac));\n#endif\n\n    XFREE(isha);\n    XFREE(buf);\n\n    return err;\n}\n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n#define __LTC_AES_TAB_C__\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n/* The precomputed tables for AES */\n/*\nTe0[x] = S [x].[02, 01, 01, 03];\nTe1[x] = S [x].[03, 02, 01, 01];\nTe2[x] = S [x].[01, 03, 02, 01];\nTe3[x] = S [x].[01, 01, 03, 02];\nTe4[x] = S [x].[01, 01, 01, 01];\n\nTd0[x] = Si[x].[0e, 09, 0d, 0b];\nTd1[x] = Si[x].[0b, 0e, 09, 0d];\nTd2[x] = Si[x].[0d, 0b, 0e, 09];\nTd3[x] = Si[x].[09, 0d, 0b, 0e];\nTd4[x] = Si[x].[01, 01, 01, 01];\n*/\n\n#ifdef __LTC_AES_TAB_C__\n\n/**\n  @file aes_tab.c\n  AES tables\n*/\nstatic const ulong32 TE0[256] = {\n    0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,\n    0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,\n    0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,\n    0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,\n    0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,\n    0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,\n    0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,\n    0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,\n    0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,\n    0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,\n    0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,\n    0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,\n    0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,\n    0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,\n    0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,\n    0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,\n    0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,\n    0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,\n    0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,\n    0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,\n    0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,\n    0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,\n    0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,\n    0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,\n    0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,\n    0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,\n    0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,\n    0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,\n    0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,\n    0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,\n    0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,\n    0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,\n    0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,\n    0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,\n    0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,\n    0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,\n    0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,\n    0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,\n    0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,\n    0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,\n    0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,\n    0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,\n    0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,\n    0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,\n    0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,\n    0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,\n    0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,\n    0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,\n    0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,\n    0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,\n    0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,\n    0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,\n    0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,\n    0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,\n    0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,\n    0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,\n    0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,\n    0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,\n    0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,\n    0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,\n    0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,\n    0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,\n    0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,\n    0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL,\n};\n\n#ifndef PELI_TAB\nstatic const ulong32 Te4[256] = {\n    0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL,\n    0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL,\n    0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL,\n    0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL,\n    0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL,\n    0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL,\n    0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL,\n    0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL,\n    0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL,\n    0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL,\n    0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL,\n    0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL,\n    0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL,\n    0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL,\n    0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL,\n    0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL,\n    0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL,\n    0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL,\n    0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL,\n    0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL,\n    0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL,\n    0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL,\n    0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL,\n    0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL,\n    0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL,\n    0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL,\n    0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL,\n    0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL,\n    0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL,\n    0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL,\n    0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL,\n    0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL,\n    0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL,\n    0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL,\n    0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL,\n    0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL,\n    0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL,\n    0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL,\n    0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL,\n    0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL,\n    0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL,\n    0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL,\n    0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL,\n    0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL,\n    0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL,\n    0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL,\n    0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL,\n    0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL,\n    0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL,\n    0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL,\n    0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL,\n    0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL,\n    0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL,\n    0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL,\n    0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL,\n    0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL,\n    0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL,\n    0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL,\n    0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL,\n    0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL,\n    0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL,\n    0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL,\n    0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL,\n    0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,\n};\n#endif\n\n#ifndef ENCRYPT_ONLY\n\nstatic const ulong32 TD0[256] = {\n    0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,\n    0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,\n    0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,\n    0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,\n    0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,\n    0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,\n    0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,\n    0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,\n    0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,\n    0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,\n    0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,\n    0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,\n    0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,\n    0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,\n    0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,\n    0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,\n    0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,\n    0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,\n    0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,\n    0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,\n    0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,\n    0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,\n    0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,\n    0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,\n    0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,\n    0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,\n    0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,\n    0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,\n    0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,\n    0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,\n    0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,\n    0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,\n    0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,\n    0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,\n    0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,\n    0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,\n    0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,\n    0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,\n    0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,\n    0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,\n    0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,\n    0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,\n    0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,\n    0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,\n    0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,\n    0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,\n    0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,\n    0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,\n    0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,\n    0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,\n    0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,\n    0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,\n    0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,\n    0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,\n    0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,\n    0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,\n    0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,\n    0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,\n    0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,\n    0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,\n    0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,\n    0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,\n    0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,\n    0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL,\n};\n\nstatic const ulong32 Td4[256] = {\n    0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL,\n    0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL,\n    0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL,\n    0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL,\n    0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL,\n    0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL,\n    0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL,\n    0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL,\n    0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL,\n    0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL,\n    0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL,\n    0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL,\n    0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL,\n    0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL,\n    0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL,\n    0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL,\n    0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL,\n    0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL,\n    0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL,\n    0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL,\n    0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL,\n    0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL,\n    0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL,\n    0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL,\n    0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL,\n    0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL,\n    0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL,\n    0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL,\n    0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL,\n    0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL,\n    0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL,\n    0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL,\n    0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL,\n    0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL,\n    0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL,\n    0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL,\n    0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL,\n    0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL,\n    0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL,\n    0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL,\n    0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL,\n    0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL,\n    0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL,\n    0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL,\n    0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL,\n    0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL,\n    0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL,\n    0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL,\n    0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL,\n    0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL,\n    0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL,\n    0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL,\n    0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL,\n    0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL,\n    0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL,\n    0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL,\n    0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL,\n    0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL,\n    0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL,\n    0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL,\n    0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL,\n    0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL,\n    0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL,\n    0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,\n};\n\n#endif /* ENCRYPT_ONLY */\n\n#ifdef LTC_SMALL_CODE\n\n#define Te0(x) TE0[x]\n#define Te1(x) RORc(TE0[x], 8)\n#define Te2(x) RORc(TE0[x], 16)\n#define Te3(x) RORc(TE0[x], 24)\n\n#define Td0(x) TD0[x]\n#define Td1(x) RORc(TD0[x], 8)\n#define Td2(x) RORc(TD0[x], 16)\n#define Td3(x) RORc(TD0[x], 24)\n\n#define Te4_0 0x000000FF & Te4\n#define Te4_1 0x0000FF00 & Te4\n#define Te4_2 0x00FF0000 & Te4\n#define Te4_3 0xFF000000 & Te4\n\n#else\n\n#define Te0(x) TE0[x]\n#define Te1(x) TE1[x]\n#define Te2(x) TE2[x]\n#define Te3(x) TE3[x]\n\n#define Td0(x) TD0[x]\n#define Td1(x) TD1[x]\n#define Td2(x) TD2[x]\n#define Td3(x) TD3[x]\n\nstatic const ulong32 TE1[256] = {\n    0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,\n    0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,\n    0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,\n    0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,\n    0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,\n    0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,\n    0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,\n    0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,\n    0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,\n    0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,\n    0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,\n    0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,\n    0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,\n    0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,\n    0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,\n    0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,\n    0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,\n    0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,\n    0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,\n    0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,\n    0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,\n    0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,\n    0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,\n    0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,\n    0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,\n    0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,\n    0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,\n    0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,\n    0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,\n    0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,\n    0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,\n    0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,\n    0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,\n    0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,\n    0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,\n    0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,\n    0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,\n    0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,\n    0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,\n    0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,\n    0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,\n    0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,\n    0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,\n    0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,\n    0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,\n    0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,\n    0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,\n    0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,\n    0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,\n    0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,\n    0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,\n    0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,\n    0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,\n    0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,\n    0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,\n    0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,\n    0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,\n    0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,\n    0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,\n    0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,\n    0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,\n    0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,\n    0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,\n    0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL,\n};\nstatic const ulong32 TE2[256] = {\n    0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,\n    0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,\n    0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,\n    0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,\n    0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,\n    0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,\n    0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,\n    0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,\n    0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,\n    0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,\n    0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,\n    0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,\n    0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,\n    0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,\n    0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,\n    0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,\n    0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,\n    0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,\n    0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,\n    0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,\n    0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,\n    0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,\n    0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,\n    0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,\n    0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,\n    0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,\n    0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,\n    0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,\n    0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,\n    0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,\n    0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,\n    0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,\n    0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,\n    0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,\n    0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,\n    0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,\n    0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,\n    0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,\n    0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,\n    0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,\n    0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,\n    0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,\n    0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,\n    0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,\n    0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,\n    0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,\n    0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,\n    0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,\n    0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,\n    0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,\n    0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,\n    0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,\n    0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,\n    0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,\n    0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,\n    0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,\n    0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,\n    0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,\n    0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,\n    0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,\n    0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,\n    0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,\n    0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,\n    0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL,\n};\nstatic const ulong32 TE3[256] = {\n\n    0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,\n    0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,\n    0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,\n    0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,\n    0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,\n    0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,\n    0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,\n    0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,\n    0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,\n    0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,\n    0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,\n    0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,\n    0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,\n    0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,\n    0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,\n    0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,\n    0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,\n    0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,\n    0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,\n    0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,\n    0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,\n    0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,\n    0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,\n    0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,\n    0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,\n    0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,\n    0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,\n    0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,\n    0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,\n    0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,\n    0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,\n    0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,\n    0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,\n    0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,\n    0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,\n    0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,\n    0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,\n    0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,\n    0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,\n    0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,\n    0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,\n    0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,\n    0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,\n    0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,\n    0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,\n    0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,\n    0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,\n    0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,\n    0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,\n    0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,\n    0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,\n    0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,\n    0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,\n    0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,\n    0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,\n    0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,\n    0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,\n    0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,\n    0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,\n    0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,\n    0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,\n    0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,\n    0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,\n    0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL,\n};\n\n#ifndef PELI_TAB\nstatic const ulong32 Te4_0[] = {\n0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL,\n0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL,\n0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL,\n0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL,\n0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL,\n0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL,\n0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL,\n0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL,\n0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL,\n0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL,\n0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL,\n0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL,\n0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL,\n0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL,\n0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL,\n0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL,\n0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL,\n0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL,\n0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL,\n0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL,\n0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL,\n0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL,\n0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL,\n0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL,\n0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL,\n0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL,\n0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL,\n0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL,\n0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL,\n0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL,\n0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL,\n0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL\n};\n\nstatic const ulong32 Te4_1[] = {\n0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL,\n0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL,\n0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL,\n0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL,\n0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL,\n0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL,\n0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL,\n0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL,\n0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL,\n0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL,\n0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL,\n0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL,\n0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL,\n0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL,\n0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL,\n0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL,\n0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL,\n0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL,\n0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL,\n0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL,\n0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL,\n0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL,\n0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL,\n0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL,\n0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL,\n0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL,\n0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL,\n0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL,\n0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL,\n0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL,\n0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL,\n0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL\n};\n\nstatic const ulong32 Te4_2[] = {\n0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL,\n0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL,\n0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL,\n0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL,\n0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL,\n0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL,\n0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL,\n0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL,\n0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL,\n0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL,\n0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL,\n0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL,\n0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL,\n0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL,\n0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL,\n0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL,\n0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL,\n0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL,\n0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL,\n0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL,\n0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL,\n0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL,\n0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL,\n0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL,\n0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL,\n0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL,\n0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL,\n0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL,\n0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL,\n0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL,\n0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL,\n0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL\n};\n\nstatic const ulong32 Te4_3[] = {\n0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL,\n0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL,\n0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL,\n0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL,\n0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL,\n0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL,\n0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL,\n0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL,\n0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL,\n0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL,\n0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL,\n0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL,\n0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL,\n0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL,\n0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL,\n0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL,\n0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL,\n0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL,\n0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL,\n0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL,\n0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL,\n0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL,\n0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL,\n0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL,\n0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL,\n0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL,\n0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL,\n0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL,\n0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL,\n0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL,\n0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL,\n0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL\n};\n#endif /* pelimac */\n\n#ifndef ENCRYPT_ONLY\n\nstatic const ulong32 TD1[256] = {\n    0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,\n    0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,\n    0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,\n    0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,\n    0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,\n    0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,\n    0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,\n    0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,\n    0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,\n    0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,\n    0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,\n    0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,\n    0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,\n    0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,\n    0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,\n    0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,\n    0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,\n    0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,\n    0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,\n    0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,\n    0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,\n    0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,\n    0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,\n    0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,\n    0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,\n    0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,\n    0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,\n    0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,\n    0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,\n    0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,\n    0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,\n    0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,\n    0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,\n    0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,\n    0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,\n    0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,\n    0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,\n    0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,\n    0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,\n    0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,\n    0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,\n    0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,\n    0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,\n    0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,\n    0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,\n    0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,\n    0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,\n    0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,\n    0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,\n    0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,\n    0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,\n    0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,\n    0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,\n    0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,\n    0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,\n    0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,\n    0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,\n    0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,\n    0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,\n    0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,\n    0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,\n    0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,\n    0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,\n    0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL,\n};\nstatic const ulong32 TD2[256] = {\n    0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,\n    0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,\n    0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,\n    0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,\n    0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,\n    0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,\n    0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,\n    0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,\n    0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,\n    0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,\n    0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,\n    0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,\n    0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,\n    0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,\n    0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,\n    0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,\n    0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,\n    0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,\n    0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,\n    0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,\n    0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,\n    0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,\n    0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,\n    0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,\n    0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,\n    0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,\n    0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,\n    0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,\n    0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,\n    0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,\n    0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,\n    0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,\n    0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,\n    0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,\n    0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,\n    0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,\n    0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,\n    0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,\n    0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,\n    0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,\n    0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,\n    0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,\n    0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,\n    0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,\n    0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,\n    0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,\n    0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,\n    0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,\n    0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,\n    0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,\n    0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,\n    0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,\n    0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,\n    0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,\n    0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,\n    0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,\n    0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,\n    0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,\n    0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,\n    0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,\n    0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,\n    0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,\n    0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,\n    0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL,\n};\nstatic const ulong32 TD3[256] = {\n    0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,\n    0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,\n    0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,\n    0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,\n    0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,\n    0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,\n    0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,\n    0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,\n    0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,\n    0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,\n    0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,\n    0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,\n    0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,\n    0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,\n    0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,\n    0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,\n    0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,\n    0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,\n    0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,\n    0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,\n    0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,\n    0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,\n    0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,\n    0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,\n    0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,\n    0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,\n    0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,\n    0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,\n    0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,\n    0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,\n    0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,\n    0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,\n    0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,\n    0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,\n    0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,\n    0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,\n    0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,\n    0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,\n    0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,\n    0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,\n    0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,\n    0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,\n    0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,\n    0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,\n    0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,\n    0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,\n    0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,\n    0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,\n    0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,\n    0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,\n    0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,\n    0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,\n    0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,\n    0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,\n    0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,\n    0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,\n    0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,\n    0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,\n    0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,\n    0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,\n    0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,\n    0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,\n    0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,\n    0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL,\n};\n\nstatic const ulong32 Tks0[] = {\n0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL,\n0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL,\n0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL,\n0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL,\n0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL,\n0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL,\n0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL,\n0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL,\n0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL,\n0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL,\n0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL,\n0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL,\n0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL,\n0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL,\n0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL,\n0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL,\n0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL,\n0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL,\n0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL,\n0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL,\n0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL,\n0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL,\n0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL,\n0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL,\n0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL,\n0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL,\n0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL,\n0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL,\n0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL,\n0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL,\n0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL,\n0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL\n};\n\nstatic const ulong32 Tks1[] = {\n0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL,\n0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL,\n0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL,\n0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL,\n0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL,\n0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL,\n0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL,\n0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL,\n0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL,\n0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL,\n0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL,\n0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL,\n0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL,\n0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL,\n0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL,\n0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL,\n0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL,\n0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL,\n0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL,\n0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL,\n0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL,\n0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL,\n0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL,\n0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL,\n0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL,\n0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL,\n0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL,\n0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL,\n0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL,\n0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL,\n0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL,\n0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL\n};\n\nstatic const ulong32 Tks2[] = {\n0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL,\n0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL,\n0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL,\n0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL,\n0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL,\n0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL,\n0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL,\n0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL,\n0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL,\n0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL,\n0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL,\n0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL,\n0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL,\n0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL,\n0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL,\n0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL,\n0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL,\n0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL,\n0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL,\n0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL,\n0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL,\n0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL,\n0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL,\n0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL,\n0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL,\n0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL,\n0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL,\n0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL,\n0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL,\n0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL,\n0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL,\n0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL\n};\n\nstatic const ulong32 Tks3[] = {\n0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL,\n0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL,\n0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL,\n0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL,\n0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL,\n0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL,\n0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL,\n0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL,\n0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL,\n0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL,\n0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL,\n0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL,\n0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL,\n0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL,\n0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL,\n0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL,\n0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL,\n0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL,\n0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL,\n0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL,\n0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL,\n0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL,\n0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL,\n0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL,\n0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL,\n0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL,\n0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL,\n0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL,\n0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL,\n0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL,\n0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL,\n0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL\n};\n\n#endif /* ENCRYPT_ONLY */\n\n#endif /* SMALL CODE */\n\nstatic const ulong32 rcon[] = {\n    0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,\n    0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,\n    0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */\n};\n\n#endif /* __LTC_AES_TAB_C__ */\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/* AES implementation by Tom St Denis\n *\n * Derived from the Public Domain source code by\n\n---\n  * rijndael-alg-fst.c\n  *\n  * @version 3.0 (December 2000)\n  *\n  * Optimised ANSI C code for the Rijndael cipher (now AES)\n  *\n  * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>\n  * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>\n  * @author Paulo Barreto <paulo.barreto@terra.com.br>\n---\n */\n/**\n  @file aes.c\n  Implementation of AES\n*/\n\n\n\n#ifdef LTC_RIJNDAEL\n\n#ifndef ENCRYPT_ONLY\n\n#define SETUP    rijndael_setup\n#define ECB_ENC  rijndael_ecb_encrypt\n#define ECB_DEC  rijndael_ecb_decrypt\n#define ECB_DONE rijndael_done\n#define ECB_TEST rijndael_test\n#define ECB_KS   rijndael_keysize\n\nconst struct ltc_cipher_descriptor rijndael_desc =\n{\n    \"rijndael\",\n    6,\n    16, 32, 16, 10,\n    SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\nconst struct ltc_cipher_descriptor aes_desc =\n{\n    \"aes\",\n    6,\n    16, 32, 16, 10,\n    SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\n#else\n\n#define SETUP    rijndael_enc_setup\n#define ECB_ENC  rijndael_enc_ecb_encrypt\n#define ECB_KS   rijndael_enc_keysize\n#define ECB_DONE rijndael_enc_done\n\nconst struct ltc_cipher_descriptor rijndael_enc_desc =\n{\n    \"rijndael\",\n    6,\n    16, 32, 16, 10,\n    SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\nconst struct ltc_cipher_descriptor aes_enc_desc =\n{\n    \"aes\",\n    6,\n    16, 32, 16, 10,\n    SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS,\n    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\n#endif\n\n#define __LTC_AES_TAB_C__\n\n\nstatic ulong32 setup_mix(ulong32 temp)\n{\n   return (Te4_3[byte(temp, 2)]) ^\n          (Te4_2[byte(temp, 1)]) ^\n          (Te4_1[byte(temp, 0)]) ^\n          (Te4_0[byte(temp, 3)]);\n}\n\n#ifndef ENCRYPT_ONLY\n#ifdef LTC_SMALL_CODE\nstatic ulong32 setup_mix2(ulong32 temp)\n{\n   return Td0(255 & Te4[byte(temp, 3)]) ^\n          Td1(255 & Te4[byte(temp, 2)]) ^\n          Td2(255 & Te4[byte(temp, 1)]) ^\n          Td3(255 & Te4[byte(temp, 0)]);\n}\n#endif\n#endif\n\n /**\n    Initialize the AES (Rijndael) block cipher\n    @param key The symmetric key you wish to pass\n    @param keylen The key length in bytes\n    @param num_rounds The number of rounds desired (0 for default)\n    @param skey The key in as scheduled by this function.\n    @return CRYPT_OK if successful\n */\nint SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)\n{\n    int i;\n    ulong32 temp, *rk;\n#ifndef ENCRYPT_ONLY\n    ulong32 *rrk;\n#endif\n    LTC_ARGCHK(key  != NULL);\n    LTC_ARGCHK(skey != NULL);\n\n    if (keylen != 16 && keylen != 24 && keylen != 32) {\n       return CRYPT_INVALID_KEYSIZE;\n    }\n\n    if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) {\n       return CRYPT_INVALID_ROUNDS;\n    }\n\n    skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;\n\n    /* setup the forward key */\n    i                 = 0;\n    rk                = skey->rijndael.eK;\n    LOAD32H(rk[0], key     );\n    LOAD32H(rk[1], key +  4);\n    LOAD32H(rk[2], key +  8);\n    LOAD32H(rk[3], key + 12);\n    if (keylen == 16) {\n        for (;;) {\n            temp  = rk[3];\n            rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];\n            rk[5] = rk[1] ^ rk[4];\n            rk[6] = rk[2] ^ rk[5];\n            rk[7] = rk[3] ^ rk[6];\n            if (++i == 10) {\n               break;\n            }\n            rk += 4;\n        }\n    } else if (keylen == 24) {\n        LOAD32H(rk[4], key + 16);\n        LOAD32H(rk[5], key + 20);\n        for (;;) {\n        #ifdef _MSC_VER\n            temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5];\n        #else\n            temp = rk[5];\n        #endif\n            rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];\n            rk[ 7] = rk[ 1] ^ rk[ 6];\n            rk[ 8] = rk[ 2] ^ rk[ 7];\n            rk[ 9] = rk[ 3] ^ rk[ 8];\n            if (++i == 8) {\n                break;\n            }\n            rk[10] = rk[ 4] ^ rk[ 9];\n            rk[11] = rk[ 5] ^ rk[10];\n            rk += 6;\n        }\n    } else if (keylen == 32) {\n        LOAD32H(rk[4], key + 16);\n        LOAD32H(rk[5], key + 20);\n        LOAD32H(rk[6], key + 24);\n        LOAD32H(rk[7], key + 28);\n        for (;;) {\n        #ifdef _MSC_VER\n            temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7];\n        #else\n            temp = rk[7];\n        #endif\n            rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];\n            rk[ 9] = rk[ 1] ^ rk[ 8];\n            rk[10] = rk[ 2] ^ rk[ 9];\n            rk[11] = rk[ 3] ^ rk[10];\n            if (++i == 7) {\n                break;\n            }\n            temp = rk[11];\n            rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8));\n            rk[13] = rk[ 5] ^ rk[12];\n            rk[14] = rk[ 6] ^ rk[13];\n            rk[15] = rk[ 7] ^ rk[14];\n            rk += 8;\n        }\n    } else {\n       /* this can't happen */\n       /* coverity[dead_error_line] */\n       return CRYPT_ERROR;\n    }\n\n#ifndef ENCRYPT_ONLY\n    /* setup the inverse key now */\n    rk   = skey->rijndael.dK;\n    rrk  = skey->rijndael.eK + (28 + keylen) - 4;\n\n    /* apply the inverse MixColumn transform to all round keys but the first and the last: */\n    /* copy first */\n    *rk++ = *rrk++;\n    *rk++ = *rrk++;\n    *rk++ = *rrk++;\n    *rk   = *rrk;\n    rk -= 3; rrk -= 3;\n\n    for (i = 1; i < skey->rijndael.Nr; i++) {\n        rrk -= 4;\n        rk  += 4;\n    #ifdef LTC_SMALL_CODE\n        temp = rrk[0];\n        rk[0] = setup_mix2(temp);\n        temp = rrk[1];\n        rk[1] = setup_mix2(temp);\n        temp = rrk[2];\n        rk[2] = setup_mix2(temp);\n        temp = rrk[3];\n        rk[3] = setup_mix2(temp);\n     #else\n        temp = rrk[0];\n        rk[0] =\n            Tks0[byte(temp, 3)] ^\n            Tks1[byte(temp, 2)] ^\n            Tks2[byte(temp, 1)] ^\n            Tks3[byte(temp, 0)];\n        temp = rrk[1];\n        rk[1] =\n            Tks0[byte(temp, 3)] ^\n            Tks1[byte(temp, 2)] ^\n            Tks2[byte(temp, 1)] ^\n            Tks3[byte(temp, 0)];\n        temp = rrk[2];\n        rk[2] =\n            Tks0[byte(temp, 3)] ^\n            Tks1[byte(temp, 2)] ^\n            Tks2[byte(temp, 1)] ^\n            Tks3[byte(temp, 0)];\n        temp = rrk[3];\n        rk[3] =\n            Tks0[byte(temp, 3)] ^\n            Tks1[byte(temp, 2)] ^\n            Tks2[byte(temp, 1)] ^\n            Tks3[byte(temp, 0)];\n      #endif\n\n    }\n\n    /* copy last */\n    rrk -= 4;\n    rk  += 4;\n    *rk++ = *rrk++;\n    *rk++ = *rrk++;\n    *rk++ = *rrk++;\n    *rk   = *rrk;\n#endif /* ENCRYPT_ONLY */\n\n    return CRYPT_OK;\n}\n\n/**\n  Encrypts a block of text with AES\n  @param pt The input plaintext (16 bytes)\n  @param ct The output ciphertext (16 bytes)\n  @param skey The key as scheduled\n  @return CRYPT_OK if successful\n*/\n#ifdef LTC_CLEAN_STACK\nstatic int _rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)\n#else\nint ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)\n#endif\n{\n    ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;\n    int Nr, r;\n\n    LTC_ARGCHK(pt != NULL);\n    LTC_ARGCHK(ct != NULL);\n    LTC_ARGCHK(skey != NULL);\n\n    Nr = skey->rijndael.Nr;\n    rk = skey->rijndael.eK;\n\n    /*\n     * map byte array block to cipher state\n     * and add initial round key:\n     */\n    LOAD32H(s0, pt      ); s0 ^= rk[0];\n    LOAD32H(s1, pt  +  4); s1 ^= rk[1];\n    LOAD32H(s2, pt  +  8); s2 ^= rk[2];\n    LOAD32H(s3, pt  + 12); s3 ^= rk[3];\n\n#ifdef LTC_SMALL_CODE\n\n    for (r = 0; ; r++) {\n        rk += 4;\n        t0 =\n            Te0(byte(s0, 3)) ^\n            Te1(byte(s1, 2)) ^\n            Te2(byte(s2, 1)) ^\n            Te3(byte(s3, 0)) ^\n            rk[0];\n        t1 =\n            Te0(byte(s1, 3)) ^\n            Te1(byte(s2, 2)) ^\n            Te2(byte(s3, 1)) ^\n            Te3(byte(s0, 0)) ^\n            rk[1];\n        t2 =\n            Te0(byte(s2, 3)) ^\n            Te1(byte(s3, 2)) ^\n            Te2(byte(s0, 1)) ^\n            Te3(byte(s1, 0)) ^\n            rk[2];\n        t3 =\n            Te0(byte(s3, 3)) ^\n            Te1(byte(s0, 2)) ^\n            Te2(byte(s1, 1)) ^\n            Te3(byte(s2, 0)) ^\n            rk[3];\n        if (r == Nr-2) {\n           break;\n        }\n        s0 = t0; s1 = t1; s2 = t2; s3 = t3;\n    }\n    rk += 4;\n\n#else\n\n    /*\n     * Nr - 1 full rounds:\n     */\n    r = Nr >> 1;\n    for (;;) {\n        t0 =\n            Te0(byte(s0, 3)) ^\n            Te1(byte(s1, 2)) ^\n            Te2(byte(s2, 1)) ^\n            Te3(byte(s3, 0)) ^\n            rk[4];\n        t1 =\n            Te0(byte(s1, 3)) ^\n            Te1(byte(s2, 2)) ^\n            Te2(byte(s3, 1)) ^\n            Te3(byte(s0, 0)) ^\n            rk[5];\n        t2 =\n            Te0(byte(s2, 3)) ^\n            Te1(byte(s3, 2)) ^\n            Te2(byte(s0, 1)) ^\n            Te3(byte(s1, 0)) ^\n            rk[6];\n        t3 =\n            Te0(byte(s3, 3)) ^\n            Te1(byte(s0, 2)) ^\n            Te2(byte(s1, 1)) ^\n            Te3(byte(s2, 0)) ^\n            rk[7];\n\n        rk += 8;\n        if (--r == 0) {\n            break;\n        }\n\n        s0 =\n            Te0(byte(t0, 3)) ^\n            Te1(byte(t1, 2)) ^\n            Te2(byte(t2, 1)) ^\n            Te3(byte(t3, 0)) ^\n            rk[0];\n        s1 =\n            Te0(byte(t1, 3)) ^\n            Te1(byte(t2, 2)) ^\n            Te2(byte(t3, 1)) ^\n            Te3(byte(t0, 0)) ^\n            rk[1];\n        s2 =\n            Te0(byte(t2, 3)) ^\n            Te1(byte(t3, 2)) ^\n            Te2(byte(t0, 1)) ^\n            Te3(byte(t1, 0)) ^\n            rk[2];\n        s3 =\n            Te0(byte(t3, 3)) ^\n            Te1(byte(t0, 2)) ^\n            Te2(byte(t1, 1)) ^\n            Te3(byte(t2, 0)) ^\n            rk[3];\n    }\n\n#endif\n\n    /*\n     * apply last round and\n     * map cipher state to byte array block:\n     */\n    s0 =\n        (Te4_3[byte(t0, 3)]) ^\n        (Te4_2[byte(t1, 2)]) ^\n        (Te4_1[byte(t2, 1)]) ^\n        (Te4_0[byte(t3, 0)]) ^\n        rk[0];\n    STORE32H(s0, ct);\n    s1 =\n        (Te4_3[byte(t1, 3)]) ^\n        (Te4_2[byte(t2, 2)]) ^\n        (Te4_1[byte(t3, 1)]) ^\n        (Te4_0[byte(t0, 0)]) ^\n        rk[1];\n    STORE32H(s1, ct+4);\n    s2 =\n        (Te4_3[byte(t2, 3)]) ^\n        (Te4_2[byte(t3, 2)]) ^\n        (Te4_1[byte(t0, 1)]) ^\n        (Te4_0[byte(t1, 0)]) ^\n        rk[2];\n    STORE32H(s2, ct+8);\n    s3 =\n        (Te4_3[byte(t3, 3)]) ^\n        (Te4_2[byte(t0, 2)]) ^\n        (Te4_1[byte(t1, 1)]) ^\n        (Te4_0[byte(t2, 0)]) ^\n        rk[3];\n    STORE32H(s3, ct+12);\n\n    return CRYPT_OK;\n}\n\n#ifdef LTC_CLEAN_STACK\nint ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)\n{\n   int err = _rijndael_ecb_encrypt(pt, ct, skey);\n   burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);\n   return err;\n}\n#endif\n\n#ifndef ENCRYPT_ONLY\n\n/**\n  Decrypts a block of text with AES\n  @param ct The input ciphertext (16 bytes)\n  @param pt The output plaintext (16 bytes)\n  @param skey The key as scheduled\n  @return CRYPT_OK if successful\n*/\n#ifdef LTC_CLEAN_STACK\nstatic int _rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)\n#else\nint ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)\n#endif\n{\n    ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;\n    int Nr, r;\n\n    LTC_ARGCHK(pt != NULL);\n    LTC_ARGCHK(ct != NULL);\n    LTC_ARGCHK(skey != NULL);\n\n    Nr = skey->rijndael.Nr;\n    rk = skey->rijndael.dK;\n\n    /*\n     * map byte array block to cipher state\n     * and add initial round key:\n     */\n    LOAD32H(s0, ct      ); s0 ^= rk[0];\n    LOAD32H(s1, ct  +  4); s1 ^= rk[1];\n    LOAD32H(s2, ct  +  8); s2 ^= rk[2];\n    LOAD32H(s3, ct  + 12); s3 ^= rk[3];\n\n#ifdef LTC_SMALL_CODE\n    for (r = 0; ; r++) {\n        rk += 4;\n        t0 =\n            Td0(byte(s0, 3)) ^\n            Td1(byte(s3, 2)) ^\n            Td2(byte(s2, 1)) ^\n            Td3(byte(s1, 0)) ^\n            rk[0];\n        t1 =\n            Td0(byte(s1, 3)) ^\n            Td1(byte(s0, 2)) ^\n            Td2(byte(s3, 1)) ^\n            Td3(byte(s2, 0)) ^\n            rk[1];\n        t2 =\n            Td0(byte(s2, 3)) ^\n            Td1(byte(s1, 2)) ^\n            Td2(byte(s0, 1)) ^\n            Td3(byte(s3, 0)) ^\n            rk[2];\n        t3 =\n            Td0(byte(s3, 3)) ^\n            Td1(byte(s2, 2)) ^\n            Td2(byte(s1, 1)) ^\n            Td3(byte(s0, 0)) ^\n            rk[3];\n        if (r == Nr-2) {\n           break;\n        }\n        s0 = t0; s1 = t1; s2 = t2; s3 = t3;\n    }\n    rk += 4;\n\n#else\n\n    /*\n     * Nr - 1 full rounds:\n     */\n    r = Nr >> 1;\n    for (;;) {\n\n        t0 =\n            Td0(byte(s0, 3)) ^\n            Td1(byte(s3, 2)) ^\n            Td2(byte(s2, 1)) ^\n            Td3(byte(s1, 0)) ^\n            rk[4];\n        t1 =\n            Td0(byte(s1, 3)) ^\n            Td1(byte(s0, 2)) ^\n            Td2(byte(s3, 1)) ^\n            Td3(byte(s2, 0)) ^\n            rk[5];\n        t2 =\n            Td0(byte(s2, 3)) ^\n            Td1(byte(s1, 2)) ^\n            Td2(byte(s0, 1)) ^\n            Td3(byte(s3, 0)) ^\n            rk[6];\n        t3 =\n            Td0(byte(s3, 3)) ^\n            Td1(byte(s2, 2)) ^\n            Td2(byte(s1, 1)) ^\n            Td3(byte(s0, 0)) ^\n            rk[7];\n\n        rk += 8;\n        if (--r == 0) {\n            break;\n        }\n\n\n        s0 =\n            Td0(byte(t0, 3)) ^\n            Td1(byte(t3, 2)) ^\n            Td2(byte(t2, 1)) ^\n            Td3(byte(t1, 0)) ^\n            rk[0];\n        s1 =\n            Td0(byte(t1, 3)) ^\n            Td1(byte(t0, 2)) ^\n            Td2(byte(t3, 1)) ^\n            Td3(byte(t2, 0)) ^\n            rk[1];\n        s2 =\n            Td0(byte(t2, 3)) ^\n            Td1(byte(t1, 2)) ^\n            Td2(byte(t0, 1)) ^\n            Td3(byte(t3, 0)) ^\n            rk[2];\n        s3 =\n            Td0(byte(t3, 3)) ^\n            Td1(byte(t2, 2)) ^\n            Td2(byte(t1, 1)) ^\n            Td3(byte(t0, 0)) ^\n            rk[3];\n    }\n#endif\n\n    /*\n     * apply last round and\n     * map cipher state to byte array block:\n     */\n    s0 =\n        (Td4[byte(t0, 3)] & 0xff000000) ^\n        (Td4[byte(t3, 2)] & 0x00ff0000) ^\n        (Td4[byte(t2, 1)] & 0x0000ff00) ^\n        (Td4[byte(t1, 0)] & 0x000000ff) ^\n        rk[0];\n    STORE32H(s0, pt);\n    s1 =\n        (Td4[byte(t1, 3)] & 0xff000000) ^\n        (Td4[byte(t0, 2)] & 0x00ff0000) ^\n        (Td4[byte(t3, 1)] & 0x0000ff00) ^\n        (Td4[byte(t2, 0)] & 0x000000ff) ^\n        rk[1];\n    STORE32H(s1, pt+4);\n    s2 =\n        (Td4[byte(t2, 3)] & 0xff000000) ^\n        (Td4[byte(t1, 2)] & 0x00ff0000) ^\n        (Td4[byte(t0, 1)] & 0x0000ff00) ^\n        (Td4[byte(t3, 0)] & 0x000000ff) ^\n        rk[2];\n    STORE32H(s2, pt+8);\n    s3 =\n        (Td4[byte(t3, 3)] & 0xff000000) ^\n        (Td4[byte(t2, 2)] & 0x00ff0000) ^\n        (Td4[byte(t1, 1)] & 0x0000ff00) ^\n        (Td4[byte(t0, 0)] & 0x000000ff) ^\n        rk[3];\n    STORE32H(s3, pt+12);\n\n    return CRYPT_OK;\n}\n\n\n#ifdef LTC_CLEAN_STACK\nint ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)\n{\n   int err = _rijndael_ecb_decrypt(ct, pt, skey);\n   burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);\n   return err;\n}\n#endif\n\n/**\n  Performs a self-test of the AES block cipher\n  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled\n*/\nint ECB_TEST(void)\n{\n #ifndef LTC_TEST\n    return CRYPT_NOP;\n #else\n int err;\n static const struct {\n     int keylen;\n     unsigned char key[32], pt[16], ct[16];\n } tests[] = {\n    { 16,\n      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },\n      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,\n        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },\n      { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,\n        0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }\n    }, {\n      24,\n      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\n        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },\n      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,\n        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },\n      { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,\n        0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }\n    }, {\n      32,\n      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\n        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },\n      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,\n        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },\n      { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,\n        0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }\n    }\n };\n\n symmetric_key key;\n unsigned char tmp[2][16];\n int i, y;\n\n for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {\n    zeromem(&key, sizeof(key));\n    if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {\n       return err;\n    }\n\n    rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key);\n    rijndael_ecb_decrypt(tmp[0], tmp[1], &key);\n    if (XMEMCMP(tmp[0], tests[i].ct, 16) || XMEMCMP(tmp[1], tests[i].pt, 16)) {\n#if 0\n       printf(\"\\n\\nTest %d failed\\n\", i);\n       if (XMEMCMP(tmp[0], tests[i].ct, 16)) {\n          printf(\"CT: \");\n          for (i = 0; i < 16; i++) {\n             printf(\"%02x \", tmp[0][i]);\n          }\n          printf(\"\\n\");\n       } else {\n          printf(\"PT: \");\n          for (i = 0; i < 16; i++) {\n             printf(\"%02x \", tmp[1][i]);\n          }\n          printf(\"\\n\");\n       }\n#endif\n        return CRYPT_FAIL_TESTVECTOR;\n    }\n\n      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */\n      for (y = 0; y < 16; y++) tmp[0][y] = 0;\n      for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key);\n      for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key);\n      for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;\n }\n return CRYPT_OK;\n #endif\n}\n\n#endif /* ENCRYPT_ONLY */\n\n\n/** Terminate the context\n   @param skey    The scheduled key\n*/\nvoid ECB_DONE(symmetric_key *skey)\n{\n  /* LTC_UNUSED_PARAM(skey); */\n}\n\n\n/**\n  Gets suitable key size\n  @param keysize [in/out] The length of the recommended key (in bytes).  This function will store the suitable size back in this variable.\n  @return CRYPT_OK if the input key size is acceptable.\n*/\nint ECB_KS(int *keysize)\n{\n   LTC_ARGCHK(keysize != NULL);\n\n   if (*keysize < 16)\n      return CRYPT_INVALID_KEYSIZE;\n   if (*keysize < 24) {\n      *keysize = 16;\n      return CRYPT_OK;\n   } else if (*keysize < 32) {\n      *keysize = 24;\n      return CRYPT_OK;\n   } else {\n      *keysize = 32;\n      return CRYPT_OK;\n   }\n}\n\n#endif\n\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file cbc_decrypt.c\n   CBC implementation, encrypt block, Tom St Denis\n*/\n\n\n#ifdef LTC_CBC_MODE\n\n/**\n  CBC decrypt\n  @param ct     Ciphertext\n  @param pt     [out] Plaintext\n  @param len    The number of bytes to process (must be multiple of block length)\n  @param cbc    CBC state\n  @return CRYPT_OK if successful\n*/\nint cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc)\n{\n   int x, err;\n   unsigned char tmp[16];\n#ifdef LTC_FAST\n   LTC_FAST_TYPE tmpy;\n#else\n   unsigned char tmpy;\n#endif\n\n   LTC_ARGCHK(pt  != NULL);\n   LTC_ARGCHK(ct  != NULL);\n   LTC_ARGCHK(cbc != NULL);\n\n   if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {\n       return err;\n   }\n\n   /* is blocklen valid? */\n   if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   if (len % cbc->blocklen) {\n      return CRYPT_INVALID_ARG;\n   }\n#ifdef LTC_FAST\n   if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) {\n      return CRYPT_INVALID_ARG;\n   }\n#endif\n\n   if (cipher_descriptor[cbc->cipher].accel_cbc_decrypt != NULL) {\n      return cipher_descriptor[cbc->cipher].accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key);\n   } else {\n      while (len) {\n         /* decrypt */\n         if ((err = cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) {\n            return err;\n         }\n\n         /* xor IV against plaintext */\n         #if defined(LTC_FAST)\n        for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) {\n            tmpy = *((LTC_FAST_TYPE*)((unsigned char *)cbc->IV + x)) ^ *((LTC_FAST_TYPE*)((unsigned char *)tmp + x));\n       *((LTC_FAST_TYPE*)((unsigned char *)cbc->IV + x)) = *((LTC_FAST_TYPE*)((unsigned char *)ct + x));\n       *((LTC_FAST_TYPE*)((unsigned char *)pt + x)) = tmpy;\n        }\n    #else\n            for (x = 0; x < cbc->blocklen; x++) {\n               tmpy       = tmp[x] ^ cbc->IV[x];\n               cbc->IV[x] = ct[x];\n               pt[x]      = tmpy;\n            }\n    #endif\n\n         ct  += cbc->blocklen;\n         pt  += cbc->blocklen;\n         len -= cbc->blocklen;\n      }\n   }\n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file cbc_done.c\n   CBC implementation, finish chain, Tom St Denis\n*/\n\n#ifdef LTC_CBC_MODE\n\n/** Terminate the chain\n  @param cbc    The CBC chain to terminate\n  @return CRYPT_OK on success\n*/\nint cbc_done(symmetric_CBC *cbc)\n{\n   int err;\n   LTC_ARGCHK(cbc != NULL);\n\n   if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {\n      return err;\n   }\n   cipher_descriptor[cbc->cipher].done(&cbc->key);\n   return CRYPT_OK;\n}\n\n   \n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file cbc_encrypt.c\n   CBC implementation, encrypt block, Tom St Denis\n*/\n\n\n#ifdef LTC_CBC_MODE\n\n/**\n  CBC encrypt\n  @param pt     Plaintext\n  @param ct     [out] Ciphertext\n  @param len    The number of bytes to process (must be multiple of block length)\n  @param cbc    CBC state\n  @return CRYPT_OK if successful\n*/\nint cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc)\n{\n   int x, err;\n\n   LTC_ARGCHK(pt != NULL);\n   LTC_ARGCHK(ct != NULL);\n   LTC_ARGCHK(cbc != NULL);\n\n   if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {\n       return err;\n   }\n\n   /* is blocklen valid? */\n   if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   if (len % cbc->blocklen) {\n      return CRYPT_INVALID_ARG;\n   }\n#ifdef LTC_FAST\n   if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) {\n      return CRYPT_INVALID_ARG;\n   }\n#endif\n\n   if (cipher_descriptor[cbc->cipher].accel_cbc_encrypt != NULL) {\n      return cipher_descriptor[cbc->cipher].accel_cbc_encrypt(pt, ct, len / cbc->blocklen, cbc->IV, &cbc->key);\n   } else {\n      while (len) {\n         /* xor IV against plaintext */\n         #if defined(LTC_FAST)\n        for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) {\n            *((LTC_FAST_TYPE*)((unsigned char *)cbc->IV + x)) ^= *((LTC_FAST_TYPE*)((unsigned char *)pt + x));\n        }\n    #else\n            for (x = 0; x < cbc->blocklen; x++) {\n               cbc->IV[x] ^= pt[x];\n            }\n    #endif\n\n         /* encrypt */\n         if ((err = cipher_descriptor[cbc->cipher].ecb_encrypt(cbc->IV, ct, &cbc->key)) != CRYPT_OK) {\n            return err;\n         }\n\n        /* store IV [ciphertext] for a future block */\n         #if defined(LTC_FAST)\n        for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) {\n            *((LTC_FAST_TYPE*)((unsigned char *)cbc->IV + x)) = *((LTC_FAST_TYPE*)((unsigned char *)ct + x));\n        }\n    #else\n             for (x = 0; x < cbc->blocklen; x++) {\n                cbc->IV[x] = ct[x];\n             }\n    #endif\n\n        ct  += cbc->blocklen;\n        pt  += cbc->blocklen;\n        len -= cbc->blocklen;\n     }\n   }\n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file cbc_getiv.c\n   CBC implementation, get IV, Tom St Denis\n*/\n\n#ifdef LTC_CBC_MODE\n\n/**\n   Get the current initial vector\n   @param IV   [out] The destination of the initial vector\n   @param len  [in/out]  The max size and resulting size of the initial vector\n   @param cbc  The CBC state\n   @return CRYPT_OK if successful\n*/\nint cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc)\n{\n   LTC_ARGCHK(IV  != NULL);\n   LTC_ARGCHK(len != NULL);\n   LTC_ARGCHK(cbc != NULL);\n   if ((unsigned long)cbc->blocklen > *len) {\n      *len = cbc->blocklen;\n      return CRYPT_BUFFER_OVERFLOW;\n   }\n   XMEMCPY(IV, cbc->IV, cbc->blocklen);\n   *len = cbc->blocklen;\n\n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file cbc_setiv.c\n   CBC implementation, set IV, Tom St Denis\n*/\n\n\n#ifdef LTC_CBC_MODE\n\n/**\n   Set an initial vector\n   @param IV   The initial vector\n   @param len  The length of the vector (in octets)\n   @param cbc  The CBC state\n   @return CRYPT_OK if successful\n*/\nint cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc)\n{\n   LTC_ARGCHK(IV  != NULL);\n   LTC_ARGCHK(cbc != NULL);\n   if (len != (unsigned long)cbc->blocklen) {\n      return CRYPT_INVALID_ARG;\n   }\n   XMEMCPY(cbc->IV, IV, len);\n   return CRYPT_OK;\n}\n\n#endif \n\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n/**\n   @file cbc_start.c\n   CBC implementation, start chain, Tom St Denis\n*/\n\n#ifdef LTC_CBC_MODE\n\n/**\n   Initialize a CBC context\n   @param cipher      The index of the cipher desired\n   @param IV          The initial vector\n   @param key         The secret key \n   @param keylen      The length of the secret key (octets)\n   @param num_rounds  Number of rounds in the cipher desired (0 for default)\n   @param cbc         The CBC state to initialize\n   @return CRYPT_OK if successful\n*/\nint cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, \n              int keylen, int num_rounds, symmetric_CBC *cbc)\n{\n   int x, err;\n \n   LTC_ARGCHK(IV != NULL);\n   LTC_ARGCHK(key != NULL);\n   LTC_ARGCHK(cbc != NULL);\n\n   /* bad param? */\n   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {\n      return err;\n   }\n\n   /* setup cipher */\n   if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) {\n      return err;\n   }\n\n   /* copy IV */\n   cbc->blocklen = cipher_descriptor[cipher].block_length;\n   cbc->cipher   = cipher;\n   for (x = 0; x < cbc->blocklen; x++) {\n       cbc->IV[x] = IV[x];\n   }\n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file gcm_add_iv.c\n   GCM implementation, add IV data to the state, by Tom St Denis\n*/\n\n\n#ifdef LTC_GCM_MODE\n\n/**\n  Add IV data to the GCM state\n  @param gcm    The GCM state\n  @param IV     The initial value data to add\n  @param IVlen  The length of the IV\n  @return CRYPT_OK on success\n */\nint gcm_add_iv(gcm_state *gcm, \n               const unsigned char *IV,     unsigned long IVlen)\n{\n   unsigned long x, y;\n   int           err;\n\n   LTC_ARGCHK(gcm != NULL);\n   if (IVlen > 0) {\n      LTC_ARGCHK(IV  != NULL);\n   }\n\n   /* must be in IV mode */\n   if (gcm->mode != LTC_GCM_MODE_IV) {\n      return CRYPT_INVALID_ARG;\n   }\n \n   if (gcm->buflen >= 16 || gcm->buflen < 0) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {\n      return err;\n   }\n\n\n   /* trip the ivmode flag */\n   if (IVlen + gcm->buflen > 12) {\n      gcm->ivmode |= 1;\n   }\n\n   x = 0;\n#ifdef LTC_FAST\n   if (gcm->buflen == 0) {\n      for (x = 0; x < (IVlen & ~15); x += 16) {\n          for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {\n              *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&IV[x + y]));\n          }\n          gcm_mult_h(gcm, gcm->X);\n          gcm->totlen += 128;\n      }\n      IV += x;\n   }\n#endif\n\n   /* start adding IV data to the state */\n   for (; x < IVlen; x++) {\n       gcm->buf[gcm->buflen++] = *IV++;\n\n       if (gcm->buflen == 16) {\n         /* GF mult it */\n         for (y = 0; y < 16; y++) {\n             gcm->X[y] ^= gcm->buf[y];\n         }\n         gcm_mult_h(gcm, gcm->X);\n         gcm->buflen = 0;\n         gcm->totlen += 128;\n      }\n   }\n\n   return CRYPT_OK;\n}\n\n#endif\n   \n\n/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_add_iv.c,v $ */\n/* $Revision: 1.9 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file gcm_done.c\n   GCM implementation, Terminate the stream, by Tom St Denis\n*/\n\n\n#ifdef LTC_GCM_MODE\n\n/**\n  Terminate a GCM stream\n  @param gcm     The GCM state\n  @param tag     [out] The destination for the MAC tag\n  @param taglen  [in/out]  The length of the MAC tag\n  @return CRYPT_OK on success\n */\nint gcm_done(gcm_state *gcm, \n                     unsigned char *tag,    unsigned long *taglen)\n{\n#ifdef __MRC__\n/* Disable optimizations for this function so MrC will compile it correctly. */\n#pragma options opt off\n#endif\n\n   unsigned long x;\n   int err;\n\n   LTC_ARGCHK(gcm     != NULL);\n   LTC_ARGCHK(tag     != NULL);\n   LTC_ARGCHK(taglen  != NULL);\n\n   if (gcm->buflen > 16 || gcm->buflen < 0) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {\n      return err;\n   }\n\n\n   if (gcm->mode != LTC_GCM_MODE_TEXT) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   /* handle remaining ciphertext */\n   if (gcm->buflen) {\n      gcm->pttotlen += gcm->buflen * CONST64(8);\n      gcm_mult_h(gcm, gcm->X);\n   }\n\n   /* length */\n   STORE64H(gcm->totlen, gcm->buf);\n   STORE64H(gcm->pttotlen, gcm->buf+8);\n   for (x = 0; x < 16; x++) {\n       gcm->X[x] ^= gcm->buf[x];\n   }\n   gcm_mult_h(gcm, gcm->X);\n\n   /* encrypt original counter */\n   if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) {\n      return err;\n   }\n   for (x = 0; x < 16 && x < *taglen; x++) {\n       tag[x] = gcm->buf[x] ^ gcm->X[x];\n   }\n   *taglen = x;\n\n   cipher_descriptor[gcm->cipher].done(&gcm->K);\n\n   return CRYPT_OK;\n}\n\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_done.c,v $ */\n/* $Revision: 1.11 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file gcm_init.c\n   GCM implementation, initialize state, by Tom St Denis\n*/\n\n\n#ifdef LTC_GCM_MODE\n\n/**\n  Initialize a GCM state\n  @param gcm     The GCM state to initialize\n  @param cipher  The index of the cipher to use\n  @param key     The secret key\n  @param keylen  The length of the secret key\n  @return CRYPT_OK on success\n */\nint gcm_init(gcm_state *gcm, int cipher, \n             const unsigned char *key,  int keylen)\n{\n   int           err;\n   unsigned char B[16];\n#ifdef LTC_GCM_TABLES\n   int           x, y, z, t;\n#endif\n\n   LTC_ARGCHK(gcm != NULL);\n   LTC_ARGCHK(key != NULL);\n\n#ifdef LTC_FAST\n   if (16 % sizeof(LTC_FAST_TYPE)) {\n      return CRYPT_INVALID_ARG;\n   }\n#endif\n\n   /* is cipher valid? */\n   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {\n      return err;\n   }\n   if (cipher_descriptor[cipher].block_length != 16) {\n      return CRYPT_INVALID_CIPHER;\n   }\n\n   /* schedule key */\n   if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &gcm->K)) != CRYPT_OK) {\n      return err;\n   }\n\n   /* H = E(0) */\n   zeromem(B, 16);\n   if ((err = cipher_descriptor[cipher].ecb_encrypt(B, gcm->H, &gcm->K)) != CRYPT_OK) {\n      return err;\n   }\n\n   /* setup state */\n   zeromem(gcm->buf, sizeof(gcm->buf));\n   zeromem(gcm->X,   sizeof(gcm->X));\n   gcm->cipher   = cipher;\n   gcm->mode     = LTC_GCM_MODE_IV;\n   gcm->ivmode   = 0;\n   gcm->buflen   = 0;\n   gcm->totlen   = 0;\n   gcm->pttotlen = 0;\n\n#ifdef LTC_GCM_TABLES\n   /* setup tables */\n\n   /* generate the first table as it has no shifting (from which we make the other tables) */\n   zeromem(B, 16);\n   for (y = 0; y < 256; y++) {\n        B[0] = y;\n        gcm_gf_mult(gcm->H, B, &gcm->PC[0][y][0]);\n   }\n\n   /* now generate the rest of the tables based the previous table */\n   for (x = 1; x < 16; x++) {\n      for (y = 0; y < 256; y++) {\n         /* now shift it right by 8 bits */\n         t = gcm->PC[x-1][y][15];\n         for (z = 15; z > 0; z--) {\n             gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1];\n         }\n         gcm->PC[x][y][0] = gcm_shift_table[t<<1];\n         gcm->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1];\n     }\n  }\n\n#endif\n\n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_init.c,v $ */\n/* $Revision: 1.20 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file gcm_process.c\n   GCM implementation, process message data, by Tom St Denis\n*/\n\n\n#ifdef LTC_GCM_MODE\n\n/** \n  Process plaintext/ciphertext through GCM\n  @param gcm       The GCM state \n  @param pt        The plaintext\n  @param ptlen     The plaintext length (ciphertext length is the same)\n  @param ct        The ciphertext\n  @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)\n  @return CRYPT_OK on success\n */\nint gcm_process(gcm_state *gcm,\n                     unsigned char *pt,     unsigned long ptlen,\n                     unsigned char *ct,\n                     int direction)\n{\n#ifdef __MRC__\n/* Selectively enable optimization. */\n#pragma options opt local\n#endif\n\n   unsigned long x;\n   int           y, err;\n   unsigned char b;\n\n   LTC_ARGCHK(gcm != NULL);\n   if (ptlen > 0) {\n      LTC_ARGCHK(pt  != NULL);\n      LTC_ARGCHK(ct  != NULL);\n   }\n\n   if (gcm->buflen > 16 || gcm->buflen < 0) {\n      return CRYPT_INVALID_ARG;\n   }\n \n   if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {\n      return err;\n   }\n\n   /* in AAD mode? */\n   if (gcm->mode == LTC_GCM_MODE_AAD) {\n      /* let's process the AAD */\n      if (gcm->buflen) {\n         gcm->totlen += gcm->buflen * CONST64(8);\n         gcm_mult_h(gcm, gcm->X);\n      }\n\n      /* increment counter */\n      for (y = 15; y >= 12; y--) {\n          if (++gcm->Y[y] & 255) { break; }\n      }\n      /* encrypt the counter */\n      if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {\n         return err;\n      }\n\n      gcm->buflen = 0;\n      gcm->mode   = LTC_GCM_MODE_TEXT;\n   }\n\n   if (gcm->mode != LTC_GCM_MODE_TEXT) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   x = 0;\n#ifdef LTC_FAST\n   if (gcm->buflen == 0) {\n      if (direction == GCM_ENCRYPT) { \n         for (x = 0; x < (ptlen & ~15); x += 16) {\n             /* ctr encrypt */\n             for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {\n                 *((LTC_FAST_TYPE*)(&ct[x + y])) = *((LTC_FAST_TYPE*)(&pt[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y]));\n                 *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y]));\n             }\n             /* GMAC it */\n             gcm->pttotlen += 128;\n             gcm_mult_h(gcm, gcm->X);\n             /* increment counter */\n             for (y = 15; y >= 12; y--) {\n                 if (++gcm->Y[y] & 255) { break; }\n             }\n             if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {\n                return err;\n             }\n         }\n      } else {\n         for (x = 0; x < (ptlen & ~15); x += 16) {\n             /* ctr encrypt */\n             for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {\n                 *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y]));\n                 *((LTC_FAST_TYPE*)(&pt[x + y])) = *((LTC_FAST_TYPE*)(&ct[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y]));\n             }\n             /* GMAC it */\n             gcm->pttotlen += 128;\n             gcm_mult_h(gcm, gcm->X);\n             /* increment counter */\n             for (y = 15; y >= 12; y--) {\n                 if (++gcm->Y[y] & 255) { break; }\n             }\n             if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {\n                return err;\n             }\n         }\n     }\n   }\n#endif        \n\n   /* process text */\n   for (; x < ptlen; x++) {\n       if (gcm->buflen == 16) {\n          gcm->pttotlen += 128;\n          gcm_mult_h(gcm, gcm->X);\n          \n          /* increment counter */\n          for (y = 15; y >= 12; y--) {\n              if (++gcm->Y[y] & 255) { break; }\n          }\n          if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {\n             return err;\n          }\n          gcm->buflen = 0;\n       }\n\n       if (direction == GCM_ENCRYPT) {\n          b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen]; \n       } else {\n          b = ct[x];\n          pt[x] = ct[x] ^ gcm->buf[gcm->buflen];\n       }\n       gcm->X[gcm->buflen++] ^= b;          \n   }\n\n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_process.c,v $ */\n/* $Revision: 1.16 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file gcm_mult_h.c\n   GCM implementation, do the GF mult, by Tom St Denis\n*/\n\n\n#if defined(LTC_GCM_MODE)\n/**\n  GCM multiply by H\n  @param gcm   The GCM state which holds the H value\n  @param I     The value to multiply H by\n */\nvoid gcm_mult_h(gcm_state *gcm, unsigned char *I)\n{\n   unsigned char T[16];\n#ifdef LTC_GCM_TABLES\n   int x, y;\n#ifdef LTC_GCM_TABLES_SSE2\n   asm(\"movdqa (%0),%%xmm0\"::\"r\"(&gcm->PC[0][I[0]][0]));\n   for (x = 1; x < 16; x++) {\n      asm(\"pxor (%0),%%xmm0\"::\"r\"(&gcm->PC[x][I[x]][0]));\n   }\n   asm(\"movdqa %%xmm0,(%0)\"::\"r\"(&T));\n#else\n   XMEMCPY(T, &gcm->PC[0][I[0]][0], 16);\n   for (x = 1; x < 16; x++) {\n#ifdef LTC_FAST\n       for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {\n           *((LTC_FAST_TYPE *)(T + y)) ^= *((LTC_FAST_TYPE *)(&gcm->PC[x][I[x]][y]));\n       }\n#else\n       for (y = 0; y < 16; y++) {\n           T[y] ^= gcm->PC[x][I[x]][y];\n       }\n#endif /* LTC_FAST */\n   }\n#endif /* LTC_GCM_TABLES_SSE2 */\n#else     \n   gcm_gf_mult(gcm->H, I, T); \n#endif\n   XMEMCPY(I, T, 16);\n}\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_mult_h.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file gcm_gf_mult.c\n   GCM implementation, do the GF mult, by Tom St Denis\n*/\n\n\n#if defined(LTC_GCM_TABLES) || defined(LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST))\n\n/* this is x*2^128 mod p(x) ... the results are 16 bytes each stored in a packed format.  Since only the \n * lower 16 bits are not zero'ed I removed the upper 14 bytes */\nconst unsigned char gcm_shift_table[256*2] = {\n0x00, 0x00, 0x01, 0xc2, 0x03, 0x84, 0x02, 0x46, 0x07, 0x08, 0x06, 0xca, 0x04, 0x8c, 0x05, 0x4e,\n0x0e, 0x10, 0x0f, 0xd2, 0x0d, 0x94, 0x0c, 0x56, 0x09, 0x18, 0x08, 0xda, 0x0a, 0x9c, 0x0b, 0x5e,\n0x1c, 0x20, 0x1d, 0xe2, 0x1f, 0xa4, 0x1e, 0x66, 0x1b, 0x28, 0x1a, 0xea, 0x18, 0xac, 0x19, 0x6e,\n0x12, 0x30, 0x13, 0xf2, 0x11, 0xb4, 0x10, 0x76, 0x15, 0x38, 0x14, 0xfa, 0x16, 0xbc, 0x17, 0x7e,\n0x38, 0x40, 0x39, 0x82, 0x3b, 0xc4, 0x3a, 0x06, 0x3f, 0x48, 0x3e, 0x8a, 0x3c, 0xcc, 0x3d, 0x0e,\n0x36, 0x50, 0x37, 0x92, 0x35, 0xd4, 0x34, 0x16, 0x31, 0x58, 0x30, 0x9a, 0x32, 0xdc, 0x33, 0x1e,\n0x24, 0x60, 0x25, 0xa2, 0x27, 0xe4, 0x26, 0x26, 0x23, 0x68, 0x22, 0xaa, 0x20, 0xec, 0x21, 0x2e,\n0x2a, 0x70, 0x2b, 0xb2, 0x29, 0xf4, 0x28, 0x36, 0x2d, 0x78, 0x2c, 0xba, 0x2e, 0xfc, 0x2f, 0x3e,\n0x70, 0x80, 0x71, 0x42, 0x73, 0x04, 0x72, 0xc6, 0x77, 0x88, 0x76, 0x4a, 0x74, 0x0c, 0x75, 0xce,\n0x7e, 0x90, 0x7f, 0x52, 0x7d, 0x14, 0x7c, 0xd6, 0x79, 0x98, 0x78, 0x5a, 0x7a, 0x1c, 0x7b, 0xde,\n0x6c, 0xa0, 0x6d, 0x62, 0x6f, 0x24, 0x6e, 0xe6, 0x6b, 0xa8, 0x6a, 0x6a, 0x68, 0x2c, 0x69, 0xee,\n0x62, 0xb0, 0x63, 0x72, 0x61, 0x34, 0x60, 0xf6, 0x65, 0xb8, 0x64, 0x7a, 0x66, 0x3c, 0x67, 0xfe,\n0x48, 0xc0, 0x49, 0x02, 0x4b, 0x44, 0x4a, 0x86, 0x4f, 0xc8, 0x4e, 0x0a, 0x4c, 0x4c, 0x4d, 0x8e,\n0x46, 0xd0, 0x47, 0x12, 0x45, 0x54, 0x44, 0x96, 0x41, 0xd8, 0x40, 0x1a, 0x42, 0x5c, 0x43, 0x9e,\n0x54, 0xe0, 0x55, 0x22, 0x57, 0x64, 0x56, 0xa6, 0x53, 0xe8, 0x52, 0x2a, 0x50, 0x6c, 0x51, 0xae,\n0x5a, 0xf0, 0x5b, 0x32, 0x59, 0x74, 0x58, 0xb6, 0x5d, 0xf8, 0x5c, 0x3a, 0x5e, 0x7c, 0x5f, 0xbe,\n0xe1, 0x00, 0xe0, 0xc2, 0xe2, 0x84, 0xe3, 0x46, 0xe6, 0x08, 0xe7, 0xca, 0xe5, 0x8c, 0xe4, 0x4e,\n0xef, 0x10, 0xee, 0xd2, 0xec, 0x94, 0xed, 0x56, 0xe8, 0x18, 0xe9, 0xda, 0xeb, 0x9c, 0xea, 0x5e,\n0xfd, 0x20, 0xfc, 0xe2, 0xfe, 0xa4, 0xff, 0x66, 0xfa, 0x28, 0xfb, 0xea, 0xf9, 0xac, 0xf8, 0x6e,\n0xf3, 0x30, 0xf2, 0xf2, 0xf0, 0xb4, 0xf1, 0x76, 0xf4, 0x38, 0xf5, 0xfa, 0xf7, 0xbc, 0xf6, 0x7e,\n0xd9, 0x40, 0xd8, 0x82, 0xda, 0xc4, 0xdb, 0x06, 0xde, 0x48, 0xdf, 0x8a, 0xdd, 0xcc, 0xdc, 0x0e,\n0xd7, 0x50, 0xd6, 0x92, 0xd4, 0xd4, 0xd5, 0x16, 0xd0, 0x58, 0xd1, 0x9a, 0xd3, 0xdc, 0xd2, 0x1e,\n0xc5, 0x60, 0xc4, 0xa2, 0xc6, 0xe4, 0xc7, 0x26, 0xc2, 0x68, 0xc3, 0xaa, 0xc1, 0xec, 0xc0, 0x2e,\n0xcb, 0x70, 0xca, 0xb2, 0xc8, 0xf4, 0xc9, 0x36, 0xcc, 0x78, 0xcd, 0xba, 0xcf, 0xfc, 0xce, 0x3e,\n0x91, 0x80, 0x90, 0x42, 0x92, 0x04, 0x93, 0xc6, 0x96, 0x88, 0x97, 0x4a, 0x95, 0x0c, 0x94, 0xce,\n0x9f, 0x90, 0x9e, 0x52, 0x9c, 0x14, 0x9d, 0xd6, 0x98, 0x98, 0x99, 0x5a, 0x9b, 0x1c, 0x9a, 0xde,\n0x8d, 0xa0, 0x8c, 0x62, 0x8e, 0x24, 0x8f, 0xe6, 0x8a, 0xa8, 0x8b, 0x6a, 0x89, 0x2c, 0x88, 0xee,\n0x83, 0xb0, 0x82, 0x72, 0x80, 0x34, 0x81, 0xf6, 0x84, 0xb8, 0x85, 0x7a, 0x87, 0x3c, 0x86, 0xfe,\n0xa9, 0xc0, 0xa8, 0x02, 0xaa, 0x44, 0xab, 0x86, 0xae, 0xc8, 0xaf, 0x0a, 0xad, 0x4c, 0xac, 0x8e,\n0xa7, 0xd0, 0xa6, 0x12, 0xa4, 0x54, 0xa5, 0x96, 0xa0, 0xd8, 0xa1, 0x1a, 0xa3, 0x5c, 0xa2, 0x9e,\n0xb5, 0xe0, 0xb4, 0x22, 0xb6, 0x64, 0xb7, 0xa6, 0xb2, 0xe8, 0xb3, 0x2a, 0xb1, 0x6c, 0xb0, 0xae,\n0xbb, 0xf0, 0xba, 0x32, 0xb8, 0x74, 0xb9, 0xb6, 0xbc, 0xf8, 0xbd, 0x3a, 0xbf, 0x7c, 0xbe, 0xbe };\n\n#endif\n\n\n#if defined(LTC_GCM_MODE) || defined(LRW_MODE)\n\n#ifndef LTC_FAST\n/* right shift */\nstatic void gcm_rightshift(unsigned char *a)\n{\n   int x;\n   for (x = 15; x > 0; x--) {\n       a[x] = (a[x]>>1) | ((a[x-1]<<7)&0x80);\n   }\n   a[0] >>= 1;\n}\n\n/* c = b*a */\nstatic const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\nstatic const unsigned char poly[] = { 0x00, 0xE1 };\n\n     \n/**\n  GCM GF multiplier (internal use only)  bitserial\n  @param a   First value\n  @param b   Second value\n  @param c   Destination for a * b\n */  \nvoid gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c)\n{\n   unsigned char Z[16], V[16];\n   unsigned char x, y, z;\n\n   zeromem(Z, 16);\n   XMEMCPY(V, a, 16);\n   for (x = 0; x < 128; x++) {\n       if (b[x>>3] & mask[x&7]) {\n          for (y = 0; y < 16; y++) {\n              Z[y] ^= V[y]; \n          }\n       }\n       z     = V[15] & 0x01;\n       gcm_rightshift(V);\n       V[0] ^= poly[z];\n   }\n   XMEMCPY(c, Z, 16);\n}\n\n#else\n\n/* map normal numbers to \"ieee\" way ... e.g. bit reversed */\n#define M(x) ( ((x&8)>>3) | ((x&4)>>1) | ((x&2)<<1) | ((x&1)<<3) )\n\n#define BPD (sizeof(LTC_FAST_TYPE) * 8)\n#define WPV (1 + (16 / sizeof(LTC_FAST_TYPE)))\n\n/**\n  GCM GF multiplier (internal use only)  word oriented\n  @param a   First value\n  @param b   Second value\n  @param c   Destination for a * b\n */  \nvoid gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c)\n{\n   int i, j, k, u;\n   LTC_FAST_TYPE B[16][WPV], tmp[32 / sizeof(LTC_FAST_TYPE)], pB[16 / sizeof(LTC_FAST_TYPE)], zz, z;\n   unsigned char pTmp[32];\n\n   /* create simple tables */\n   zeromem(B[0],       sizeof(B[0]));\n   zeromem(B[M(1)],    sizeof(B[M(1)]));\n\n#ifdef ENDIAN_32BITWORD\n   for (i = 0; i < 4; i++) {\n       LOAD32H(B[M(1)][i], a + (i<<2));\n       LOAD32L(pB[i],      b + (i<<2));\n   }\n#else \n   for (i = 0; i < 2; i++) {\n       LOAD64H(B[M(1)][i], a + (i<<3));\n       LOAD64L(pB[i],      b + (i<<3));\n   }\n#endif\n\n   /* now create 2, 4 and 8 */\n   B[M(2)][0] = B[M(1)][0] >> 1;\n   B[M(4)][0] = B[M(1)][0] >> 2;\n   B[M(8)][0] = B[M(1)][0] >> 3;\n   for (i = 1; i < (int)WPV; i++) {\n      B[M(2)][i] = (B[M(1)][i-1] << (BPD-1)) | (B[M(1)][i] >> 1);\n      B[M(4)][i] = (B[M(1)][i-1] << (BPD-2)) | (B[M(1)][i] >> 2);\n      B[M(8)][i] = (B[M(1)][i-1] << (BPD-3)) | (B[M(1)][i] >> 3);\n   }\n\n   /*  now all values with two bits which are 3, 5, 6, 9, 10, 12 */\n   for (i = 0; i < (int)WPV; i++) {\n      B[M(3)][i]  = B[M(1)][i] ^ B[M(2)][i];\n      B[M(5)][i]  = B[M(1)][i] ^ B[M(4)][i];\n      B[M(6)][i]  = B[M(2)][i] ^ B[M(4)][i];\n      B[M(9)][i]  = B[M(1)][i] ^ B[M(8)][i];\n      B[M(10)][i] = B[M(2)][i] ^ B[M(8)][i];\n      B[M(12)][i] = B[M(8)][i] ^ B[M(4)][i];\n   \n   /*  now all 3 bit values and the only 4 bit value: 7, 11, 13, 14, 15 */\n      B[M(7)][i]  = B[M(3)][i] ^ B[M(4)][i];\n      B[M(11)][i] = B[M(3)][i] ^ B[M(8)][i];\n      B[M(13)][i] = B[M(1)][i] ^ B[M(12)][i];\n      B[M(14)][i] = B[M(6)][i] ^ B[M(8)][i];\n      B[M(15)][i] = B[M(7)][i] ^ B[M(8)][i];\n   }\n\n   zeromem(tmp, sizeof(tmp));\n\n   /* compute product four bits of each word at a time */\n   /* for each nibble */\n   for (i = (BPD/4)-1; i >= 0; i--) {\n       /* for each word */\n       for (j = 0; j < (int)(WPV-1); j++) {\n        /* grab the 4 bits recall the nibbles are backwards so it's a shift by (i^1)*4 */\n           u = (pB[j] >> ((i^1)<<2)) & 15;\n\n        /* add offset by the word count the table looked up value to the result */\n           for (k = 0; k < (int)WPV; k++) {\n               tmp[k+j] ^= B[u][k];\n           }\n       }\n     /* shift result up by 4 bits */\n       if (i != 0) {\n          for (z = j = 0; j < (int)(32 / sizeof(LTC_FAST_TYPE)); j++) {\n              zz = tmp[j] << (BPD-4);\n              tmp[j] = (tmp[j] >> 4) | z;\n              z = zz;\n          }\n       }\n   }\n\n   /* store product */\n#ifdef ENDIAN_32BITWORD\n   for (i = 0; i < 8; i++) {\n       STORE32H(tmp[i], pTmp + (i<<2));\n   }\n#else \n   for (i = 0; i < 4; i++) {\n       STORE64H(tmp[i], pTmp + (i<<3));\n   }\n#endif\n\n   /* reduce by taking most significant byte and adding the appropriate two byte sequence 16 bytes down */\n   for (i = 31; i >= 16; i--) {\n       pTmp[i-16] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)];\n       pTmp[i-15] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)+1];\n   }\n\n   for (i = 0; i < 16; i++) {\n       c[i] = pTmp[i];\n   }\n\n}\n\n#endif\n\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c,v $ */\n/* $Revision: 1.25 $ */\n/* $Date: 2007/05/12 14:32:35 $ */\n \n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file gcm_add_aad.c\n   GCM implementation, Add AAD data to the stream, by Tom St Denis\n*/\n\n\n#ifdef LTC_GCM_MODE\n\n/**\n  Add AAD to the GCM state\n  @param gcm       The GCM state\n  @param adata     The additional authentication data to add to the GCM state\n  @param adatalen  The length of the AAD data.\n  @return CRYPT_OK on success\n */\nint gcm_add_aad(gcm_state *gcm,\n               const unsigned char *adata,  unsigned long adatalen)\n{\n   unsigned long x;\n   int           err;\n#ifdef LTC_FAST\n   unsigned long y;\n#endif\n\n   LTC_ARGCHK(gcm    != NULL);\n   if (adatalen > 0) {\n      LTC_ARGCHK(adata  != NULL);\n   }\n\n   if (gcm->buflen > 16 || gcm->buflen < 0) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {\n      return err;\n   }\n\n   /* in IV mode? */\n   if (gcm->mode == LTC_GCM_MODE_IV) {\n      /* let's process the IV */\n      if (gcm->ivmode || gcm->buflen != 12) {\n         for (x = 0; x < (unsigned long)gcm->buflen; x++) {\n             gcm->X[x] ^= gcm->buf[x];\n         }\n         if (gcm->buflen) {\n            gcm->totlen += gcm->buflen * CONST64(8);\n            gcm_mult_h(gcm, gcm->X);\n         }\n\n         /* mix in the length */\n         zeromem(gcm->buf, 8);\n         STORE64H(gcm->totlen, gcm->buf+8);\n         for (x = 0; x < 16; x++) {\n             gcm->X[x] ^= gcm->buf[x];\n         }\n         gcm_mult_h(gcm, gcm->X);\n\n         /* copy counter out */\n         XMEMCPY(gcm->Y, gcm->X, 16);\n         zeromem(gcm->X, 16);\n      } else {\n         XMEMCPY(gcm->Y, gcm->buf, 12);\n         gcm->Y[12] = 0;\n         gcm->Y[13] = 0;\n         gcm->Y[14] = 0;\n         gcm->Y[15] = 1;\n      }\n      XMEMCPY(gcm->Y_0, gcm->Y, 16);\n      zeromem(gcm->buf, 16);\n      gcm->buflen = 0;\n      gcm->totlen = 0;\n      gcm->mode   = LTC_GCM_MODE_AAD;\n   }\n\n   if (gcm->mode != LTC_GCM_MODE_AAD || gcm->buflen >= 16) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   x = 0;\n#ifdef LTC_FAST\n   if (gcm->buflen == 0) {\n      for (x = 0; x < (adatalen & ~15); x += 16) {\n          for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {\n              *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&adata[x + y]));\n          }\n          gcm_mult_h(gcm, gcm->X);\n          gcm->totlen += 128;\n      }\n      adata += x;\n   }\n#endif\n\n\n   /* start adding AAD data to the state */\n   for (; x < adatalen; x++) {\n       gcm->X[gcm->buflen++] ^= *adata++;\n\n       if (gcm->buflen == 16) {\n         /* GF mult it */\n         gcm_mult_h(gcm, gcm->X);\n         gcm->buflen = 0;\n         gcm->totlen += 128;\n      }\n   }\n\n   return CRYPT_OK;\n}\n#endif\n\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file gcm_reset.c\n   GCM implementation, reset a used state so it can accept IV data, by Tom St Denis\n*/\n\n\n#ifdef LTC_GCM_MODE\n\n/**\n  Reset a GCM state to as if you just called gcm_init().  This saves the initialization time.\n  @param gcm   The GCM state to reset\n  @return CRYPT_OK on success\n*/\nint gcm_reset(gcm_state *gcm)\n{\n   LTC_ARGCHK(gcm != NULL);\n\n   zeromem(gcm->buf, sizeof(gcm->buf));\n   zeromem(gcm->X,   sizeof(gcm->X));\n   gcm->mode     = LTC_GCM_MODE_IV;\n   gcm->ivmode   = 0;\n   gcm->buflen   = 0;\n   gcm->totlen   = 0;\n   gcm->pttotlen = 0;\n  \n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */\n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n\n\n/**\n  @file md5.c\n  LTC_MD5 hash function by Tom St Denis \n*/\n\n#ifdef LTC_MD5\n\nconst struct ltc_hash_descriptor md5_desc =\n{\n    \"md5\",\n    3,\n    16,\n    64,\n\n    /* OID */\n   { 1, 2, 840, 113549, 2, 5,  },\n   6,\n\n    &md5_init,\n    &md5_process,\n    &md5_done,\n    &md5_test,\n    NULL\n};\n\n#define F(x,y,z)  (z ^ (x & (y ^ z)))\n#define G(x,y,z)  (y ^ (z & (y ^ x)))\n#define H(x,y,z)  (x^y^z)\n#define I(x,y,z)  (y^(x|(~z)))\n\n#ifdef LTC_SMALL_CODE\n\n#define FF(a,b,c,d,M,s,t) \\\n    a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b;\n\n#define GG(a,b,c,d,M,s,t) \\\n    a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b;\n\n#define HH(a,b,c,d,M,s,t) \\\n    a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b;\n\n#define II(a,b,c,d,M,s,t) \\\n    a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;\n\nstatic const unsigned char Worder[64] = {\n   0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n   1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,\n   5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,\n   0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9\n};\n\nstatic const unsigned char Rorder[64] = {\n   7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,\n   5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,\n   4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,\n   6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21\n};\n\nstatic const ulong32 Korder[64] = {\n0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,\n0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,\n0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,\n0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,\n0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,\n0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,\n0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,\n0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL\n};\n\n#else\n\n#define FF(a,b,c,d,M,s,t) \\\n    a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b;\n\n#define GG(a,b,c,d,M,s,t) \\\n    a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b;\n\n#define HH(a,b,c,d,M,s,t) \\\n    a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b;\n\n#define II(a,b,c,d,M,s,t) \\\n    a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b;\n\n\n#endif   \n\n#ifdef LTC_CLEAN_STACK\nstatic int _md5_compress(hash_state *md, unsigned char *buf)\n#else\nstatic int  md5_compress(hash_state *md, unsigned char *buf)\n#endif\n{\n    ulong32 i, W[16], a, b, c, d;\n#ifdef LTC_SMALL_CODE\n    ulong32 t;\n#endif\n\n    /* copy the state into 512-bits into W[0..15] */\n    for (i = 0; i < 16; i++) {\n        LOAD32L(W[i], buf + (4*i));\n    }\n \n    /* copy state */\n    a = md->md5.state[0];\n    b = md->md5.state[1];\n    c = md->md5.state[2];\n    d = md->md5.state[3];\n\n#ifdef LTC_SMALL_CODE\n    for (i = 0; i < 16; ++i) {\n        FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);\n        t = d; d = c; c = b; b = a; a = t;\n    }\n\n    for (; i < 32; ++i) {\n        GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);\n        t = d; d = c; c = b; b = a; a = t;\n    }\n\n    for (; i < 48; ++i) {\n        HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);\n        t = d; d = c; c = b; b = a; a = t;\n    }\n\n    for (; i < 64; ++i) {\n        II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);\n        t = d; d = c; c = b; b = a; a = t;\n    }\n\n#else\n    FF(a,b,c,d,W[0],7,0xd76aa478UL)\n    FF(d,a,b,c,W[1],12,0xe8c7b756UL)\n    FF(c,d,a,b,W[2],17,0x242070dbUL)\n    FF(b,c,d,a,W[3],22,0xc1bdceeeUL)\n    FF(a,b,c,d,W[4],7,0xf57c0fafUL)\n    FF(d,a,b,c,W[5],12,0x4787c62aUL)\n    FF(c,d,a,b,W[6],17,0xa8304613UL)\n    FF(b,c,d,a,W[7],22,0xfd469501UL)\n    FF(a,b,c,d,W[8],7,0x698098d8UL)\n    FF(d,a,b,c,W[9],12,0x8b44f7afUL)\n    FF(c,d,a,b,W[10],17,0xffff5bb1UL)\n    FF(b,c,d,a,W[11],22,0x895cd7beUL)\n    FF(a,b,c,d,W[12],7,0x6b901122UL)\n    FF(d,a,b,c,W[13],12,0xfd987193UL)\n    FF(c,d,a,b,W[14],17,0xa679438eUL)\n    FF(b,c,d,a,W[15],22,0x49b40821UL)\n    GG(a,b,c,d,W[1],5,0xf61e2562UL)\n    GG(d,a,b,c,W[6],9,0xc040b340UL)\n    GG(c,d,a,b,W[11],14,0x265e5a51UL)\n    GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)\n    GG(a,b,c,d,W[5],5,0xd62f105dUL)\n    GG(d,a,b,c,W[10],9,0x02441453UL)\n    GG(c,d,a,b,W[15],14,0xd8a1e681UL)\n    GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)\n    GG(a,b,c,d,W[9],5,0x21e1cde6UL)\n    GG(d,a,b,c,W[14],9,0xc33707d6UL)\n    GG(c,d,a,b,W[3],14,0xf4d50d87UL)\n    GG(b,c,d,a,W[8],20,0x455a14edUL)\n    GG(a,b,c,d,W[13],5,0xa9e3e905UL)\n    GG(d,a,b,c,W[2],9,0xfcefa3f8UL)\n    GG(c,d,a,b,W[7],14,0x676f02d9UL)\n    GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)\n    HH(a,b,c,d,W[5],4,0xfffa3942UL)\n    HH(d,a,b,c,W[8],11,0x8771f681UL)\n    HH(c,d,a,b,W[11],16,0x6d9d6122UL)\n    HH(b,c,d,a,W[14],23,0xfde5380cUL)\n    HH(a,b,c,d,W[1],4,0xa4beea44UL)\n    HH(d,a,b,c,W[4],11,0x4bdecfa9UL)\n    HH(c,d,a,b,W[7],16,0xf6bb4b60UL)\n    HH(b,c,d,a,W[10],23,0xbebfbc70UL)\n    HH(a,b,c,d,W[13],4,0x289b7ec6UL)\n    HH(d,a,b,c,W[0],11,0xeaa127faUL)\n    HH(c,d,a,b,W[3],16,0xd4ef3085UL)\n    HH(b,c,d,a,W[6],23,0x04881d05UL)\n    HH(a,b,c,d,W[9],4,0xd9d4d039UL)\n    HH(d,a,b,c,W[12],11,0xe6db99e5UL)\n    HH(c,d,a,b,W[15],16,0x1fa27cf8UL)\n    HH(b,c,d,a,W[2],23,0xc4ac5665UL)\n    II(a,b,c,d,W[0],6,0xf4292244UL)\n    II(d,a,b,c,W[7],10,0x432aff97UL)\n    II(c,d,a,b,W[14],15,0xab9423a7UL)\n    II(b,c,d,a,W[5],21,0xfc93a039UL)\n    II(a,b,c,d,W[12],6,0x655b59c3UL)\n    II(d,a,b,c,W[3],10,0x8f0ccc92UL)\n    II(c,d,a,b,W[10],15,0xffeff47dUL)\n    II(b,c,d,a,W[1],21,0x85845dd1UL)\n    II(a,b,c,d,W[8],6,0x6fa87e4fUL)\n    II(d,a,b,c,W[15],10,0xfe2ce6e0UL)\n    II(c,d,a,b,W[6],15,0xa3014314UL)\n    II(b,c,d,a,W[13],21,0x4e0811a1UL)\n    II(a,b,c,d,W[4],6,0xf7537e82UL)\n    II(d,a,b,c,W[11],10,0xbd3af235UL)\n    II(c,d,a,b,W[2],15,0x2ad7d2bbUL)\n    II(b,c,d,a,W[9],21,0xeb86d391UL)\n#endif\n\n    md->md5.state[0] = md->md5.state[0] + a;\n    md->md5.state[1] = md->md5.state[1] + b;\n    md->md5.state[2] = md->md5.state[2] + c;\n    md->md5.state[3] = md->md5.state[3] + d;\n\n    return CRYPT_OK;\n}\n\n#ifdef LTC_CLEAN_STACK\nstatic int md5_compress(hash_state *md, unsigned char *buf)\n{\n   int err;\n   err = _md5_compress(md, buf);\n   burn_stack(sizeof(ulong32) * 21);\n   return err;\n}\n#endif\n\n/**\n   Initialize the hash state\n   @param md   The hash state you wish to initialize\n   @return CRYPT_OK if successful\n*/\nint md5_init(hash_state * md)\n{\n   LTC_ARGCHK(md != NULL);\n   md->md5.state[0] = 0x67452301UL;\n   md->md5.state[1] = 0xefcdab89UL;\n   md->md5.state[2] = 0x98badcfeUL;\n   md->md5.state[3] = 0x10325476UL;\n   md->md5.curlen = 0;\n   md->md5.length = 0;\n   return CRYPT_OK;\n}\n\n/**\n   Process a block of memory though the hash\n   @param md     The hash state\n   @param in     The data to hash\n   @param inlen  The length of the data (octets)\n   @return CRYPT_OK if successful\n*/\nHASH_PROCESS(md5_process, md5_compress, md5, 64)\n\n/**\n   Terminate the hash to get the digest\n   @param md  The hash state\n   @param out [out] The destination of the hash (16 bytes)\n   @return CRYPT_OK if successful\n*/\nint md5_done(hash_state * md, unsigned char *out)\n{\n    int i;\n\n    LTC_ARGCHK(md  != NULL);\n    LTC_ARGCHK(out != NULL);\n\n    if (md->md5.curlen >= sizeof(md->md5.buf)) {\n       return CRYPT_INVALID_ARG;\n    }\n\n\n    /* increase the length of the message */\n    md->md5.length += md->md5.curlen * 8;\n\n    /* append the '1' bit */\n    md->md5.buf[md->md5.curlen++] = (unsigned char)0x80;\n\n    /* if the length is currently above 56 bytes we append zeros\n     * then compress.  Then we can fall back to padding zeros and length\n     * encoding like normal.\n     */\n    if (md->md5.curlen > 56) {\n        while (md->md5.curlen < 64) {\n            md->md5.buf[md->md5.curlen++] = (unsigned char)0;\n        }\n        md5_compress(md, md->md5.buf);\n        md->md5.curlen = 0;\n    }\n\n    /* pad upto 56 bytes of zeroes */\n    while (md->md5.curlen < 56) {\n        md->md5.buf[md->md5.curlen++] = (unsigned char)0;\n    }\n\n    /* store length */\n    STORE64L(md->md5.length, md->md5.buf+56);\n    md5_compress(md, md->md5.buf);\n\n    /* copy output */\n    for (i = 0; i < 4; i++) {\n        STORE32L(md->md5.state[i], out+(4*i));\n    }\n#ifdef LTC_CLEAN_STACK\n    zeromem(md, sizeof(hash_state));\n#endif\n    return CRYPT_OK;\n}\n\n/**\n  Self-test the hash\n  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled\n*/  \nint  md5_test(void)\n{\n #ifndef LTC_TEST\n    return CRYPT_NOP;\n #else    \n  static const struct {\n      char *msg;\n      unsigned char hash[16];\n  } tests[] = {\n    { \"\",\n      { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, \n        0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },\n    { \"a\",\n      {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, \n       0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },\n    { \"abc\",\n      { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, \n        0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },\n    { \"message digest\", \n      { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, \n        0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, \n    { \"abcdefghijklmnopqrstuvwxyz\",\n      { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, \n        0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },\n    { \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\",\n      { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, \n        0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },\n    { \"12345678901234567890123456789012345678901234567890123456789012345678901234567890\",\n      { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, \n        0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, \n    { NULL, { 0 } }\n  };\n\n  int i;\n  unsigned char tmp[16];\n  hash_state md;\n\n  for (i = 0; tests[i].msg != NULL; i++) {\n      md5_init(&md);\n      md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));\n      md5_done(&md, tmp);\n      if (XMEMCMP(tmp, tests[i].hash, 16) != 0) {\n         return CRYPT_FAIL_TESTVECTOR;\n      }\n  }\n  return CRYPT_OK;\n #endif\n}\n\n#endif\n\n/* $Source$ */\n/* $Revision$ */\n/* $Date$ */ \n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n  @file ctr_encrypt.c\n  CTR implementation, encrypt data, Tom St Denis\n*/\n\n\n#ifdef LTC_CTR_MODE\n\n/**\n  CTR encrypt\n  @param pt     Plaintext\n  @param ct     [out] Ciphertext\n  @param len    Length of plaintext (octets)\n  @param ctr    CTR state\n  @return CRYPT_OK if successful\n*/\nint ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)\n{\n   int x, err;\n\n   LTC_ARGCHK(pt != NULL);\n   LTC_ARGCHK(ct != NULL);\n   LTC_ARGCHK(ctr != NULL);\n\n   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {\n       return err;\n   }\n   \n   /* is blocklen/padlen valid? */\n   if (ctr->blocklen < 1 || ctr->blocklen > (int)sizeof(ctr->ctr) ||\n       ctr->padlen   < 0 || ctr->padlen   > (int)sizeof(ctr->pad)) {\n      return CRYPT_INVALID_ARG;\n   }\n\n#ifdef LTC_FAST\n   if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) {\n      return CRYPT_INVALID_ARG;\n   }\n#endif\n   \n   /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */\n   if ((ctr->padlen == ctr->blocklen) && cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL && (len >= (unsigned long)ctr->blocklen)) {\n      if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) {\n         return err;\n      }\n      len %= ctr->blocklen;\n   }\n\n   while (len) {\n      /* is the pad empty? */\n      if (ctr->padlen == ctr->blocklen) {\n         /* increment counter */\n         if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {\n            /* little-endian */\n            for (x = 0; x < ctr->ctrlen; x++) {\n               ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;\n               if (ctr->ctr[x] != (unsigned char)0) {\n                  break;\n               }\n            }\n         } else {\n            /* big-endian */\n            for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {\n               ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;\n               if (ctr->ctr[x] != (unsigned char)0) {\n                  break;\n               }\n            }\n         }\n\n         /* encrypt it */\n         if ((err = cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) {\n            return err;\n         }\n         ctr->padlen = 0;\n      }\n#ifdef LTC_FAST\n      if (ctr->padlen == 0 && len >= (unsigned long)ctr->blocklen) {\n         for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) {\n            *((LTC_FAST_TYPE*)((unsigned char *)ct + x)) = *((LTC_FAST_TYPE*)((unsigned char *)pt + x)) ^\n                                                           *((LTC_FAST_TYPE*)((unsigned char *)ctr->pad + x));\n         }\n       pt         += ctr->blocklen;\n       ct         += ctr->blocklen;\n       len        -= ctr->blocklen;\n       ctr->padlen = ctr->blocklen;\n       continue;\n      }\n#endif    \n      *ct++ = *pt++ ^ ctr->pad[ctr->padlen++];\n      --len;\n   }\n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_encrypt.c,v $ */\n/* $Revision: 1.22 $ */\n/* $Date: 2007/02/22 20:26:05 $ */ \n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file ctr_done.c\n   CTR implementation, finish chain, Tom St Denis\n*/\n\n#ifdef LTC_CTR_MODE\n\n/** Terminate the chain\n  @param ctr    The CTR chain to terminate\n  @return CRYPT_OK on success\n*/\nint ctr_done(symmetric_CTR *ctr)\n{\n   int err;\n   LTC_ARGCHK(ctr != NULL);\n\n   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {\n      return err;\n   }\n   cipher_descriptor[ctr->cipher].done(&ctr->key);\n   return CRYPT_OK;\n}\n\n   \n\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_done.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */ \n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n  @file ctr_decrypt.c\n  CTR implementation, decrypt data, Tom St Denis\n*/\n\n#ifdef LTC_CTR_MODE\n\n/**\n   CTR decrypt\n   @param ct      Ciphertext\n   @param pt      [out] Plaintext\n   @param len     Length of ciphertext (octets)\n   @param ctr     CTR state\n   @return CRYPT_OK if successful\n*/\nint ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr)\n{\n   LTC_ARGCHK(pt != NULL);\n   LTC_ARGCHK(ct != NULL);\n   LTC_ARGCHK(ctr != NULL);\n\n   return ctr_encrypt(ct, pt, len, ctr);\n}\n\n#endif\n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_decrypt.c,v $ */\n/* $Revision: 1.6 $ */\n/* $Date: 2006/12/28 01:27:24 $ */ \n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file ctr_start.c\n   CTR implementation, start chain, Tom St Denis\n*/\n\n\n#ifdef LTC_CTR_MODE\n\n/**\n   Initialize a CTR context\n   @param cipher      The index of the cipher desired\n   @param IV          The initial vector\n   @param key         The secret key \n   @param keylen      The length of the secret key (octets)\n   @param num_rounds  Number of rounds in the cipher desired (0 for default)\n   @param ctr_mode    The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN)\n   @param ctr         The CTR state to initialize\n   @return CRYPT_OK if successful\n*/\nint ctr_start(               int   cipher, \n              const unsigned char *IV, \n              const unsigned char *key,       int keylen, \n                             int  num_rounds, int ctr_mode,\n                   symmetric_CTR *ctr)\n{\n   int x, err;\n\n   LTC_ARGCHK(IV  != NULL);\n   LTC_ARGCHK(key != NULL);\n   LTC_ARGCHK(ctr != NULL);\n\n   /* bad param? */\n   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {\n      return err;\n   }\n\n   /* ctrlen == counter width */\n   ctr->ctrlen   = (ctr_mode & 255) ? (ctr_mode & 255) : cipher_descriptor[cipher].block_length;\n   if (ctr->ctrlen > cipher_descriptor[cipher].block_length) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) {\n      ctr->ctrlen = cipher_descriptor[cipher].block_length - ctr->ctrlen;\n   }\n\n   /* setup cipher */\n   if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) {\n      return err;\n   }\n\n   /* copy ctr */\n   ctr->blocklen = cipher_descriptor[cipher].block_length;\n   ctr->cipher   = cipher;\n   ctr->padlen   = 0;\n   ctr->mode     = ctr_mode & 0x1000;\n   for (x = 0; x < ctr->blocklen; x++) {\n       ctr->ctr[x] = IV[x];\n   }\n\n   if (ctr_mode & LTC_CTR_RFC3686) {\n      /* increment the IV as per RFC 3686 */\n      if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {\n         /* little-endian */\n         for (x = 0; x < ctr->ctrlen; x++) {\n             ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;\n             if (ctr->ctr[x] != (unsigned char)0) {\n                break;\n             }\n         }\n      } else {\n         /* big-endian */\n         for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {\n             ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;\n             if (ctr->ctr[x] != (unsigned char)0) {\n                break;\n             }\n         }\n      }\n   }\n\n   return cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key); \n}\n\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_start.c,v $ */\n/* $Revision: 1.15 $ */\n/* $Date: 2007/02/23 14:18:37 $ */ \n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n  @file ctr_setiv.c\n  CTR implementation, set IV, Tom St Denis\n*/\n  \n#ifdef LTC_CTR_MODE\n\n/**\n   Set an initial vector\n   @param IV   The initial vector\n   @param len  The length of the vector (in octets)\n   @param ctr  The CTR state\n   @return CRYPT_OK if successful\n*/\nint ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr)\n{\n   int err;\n   \n   LTC_ARGCHK(IV  != NULL);\n   LTC_ARGCHK(ctr != NULL);\n\n   /* bad param? */\n   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {\n      return err;\n   }\n   \n   if (len != (unsigned long)ctr->blocklen) {\n      return CRYPT_INVALID_ARG;\n   }\n\n   /* set IV */\n   XMEMCPY(ctr->ctr, IV, len);\n   \n   /* force next block */\n   ctr->padlen = 0;\n   return cipher_descriptor[ctr->cipher].ecb_encrypt(IV, ctr->pad, &ctr->key);\n}\n\n#endif \n\n\n/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_setiv.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */ \n\n/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n\n/**\n   @file ctr_getiv.c\n   CTR implementation, get IV, Tom St Denis\n*/\n\n#ifdef LTC_CTR_MODE\n\n/**\n   Get the current initial vector\n   @param IV   [out] The destination of the initial vector\n   @param len  [in/out]  The max size and resulting size of the initial vector\n   @param ctr  The CTR state\n   @return CRYPT_OK if successful\n*/\nint ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr)\n{\n   LTC_ARGCHK(IV  != NULL);\n   LTC_ARGCHK(len != NULL);\n   LTC_ARGCHK(ctr != NULL);\n   if ((unsigned long)ctr->blocklen > *len) {\n      *len = ctr->blocklen;\n      return CRYPT_BUFFER_OVERFLOW;\n   }\n   XMEMCPY(IV, ctr->ctr, ctr->blocklen);\n   *len = ctr->blocklen;\n\n   return CRYPT_OK;\n}\n\n#endif\n\n/* $Source: /cvs/libtom/libtomcrypt/src/modes/ctr/ctr_getiv.c,v $ */\n/* $Revision: 1.7 $ */\n/* $Date: 2006/12/28 01:27:24 $ */ \n/* per nuTLS this doesn't work properly yet */\n#define IGNORE_SESSION_ID\n\n#if (CRYPT <= 0x0117)\n    #define LTC_PKCS_1_EMSA LTC_LTC_PKCS_1_EMSA\n    #define LTC_PKCS_1_V1_5 LTC_LTC_PKCS_1_V1_5\n    #define LTC_PKCS_1_PSS LTC_LTC_PKCS_1_PSS\n#endif\n\n#ifdef WITH_KTLS\n    #include <sys/types.h>\n    #include <sys/socket.h>\n    #include <netinet/tcp.h>\n    /* should get uapi/linux/tls.h (linux headers)\n    // rename it to ktls.h and add it to your project\n    // or just include tls.h instead of ktls.h */\n    #include \"ktls.h\"\n#endif\n\n#include \"cryanc.h\"\n#ifdef TLS_CURVE25519\n\n/* Copyright 2008, Google Inc.\n * All rights reserved.\n * Minimally modified for Crypto Ancienne (C)2020 Cameron Kaiser.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *     * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n *     * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * curve25519-donna: Curve25519 elliptic curve, public key function\n *\n * http://code.google.com/p/curve25519-donna/\n *\n * Adam Langley <agl@imperialviolet.org>\n *\n * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>\n *\n * More information about curve25519 can be found here\n *   http://cr.yp.to/ecdh.html\n *\n * djb's sample implementation of curve25519 is written in a special assembly\n * language called qhasm and uses the floating point registers.\n *\n * This is, almost, a clean room reimplementation from the curve25519 paper. It\n * uses many of the tricks described therein. Only the crecip function is taken\n * from the sample implementation.\n */\n\n/* Field element representation:\n *\n * Field elements are written as an array of signed, 64-bit limbs, least\n * significant first. The value of the field element is:\n *   x[0] + 2^26B7x[1] + x^51B7x[2] + 2^102B7x[3] + ...\n *\n * i.e. the limbs are 26, 25, 26, 25, ... bits wide.\n */\n\n/* Sum two numbers: output += in */\nstatic void fsum(int64_t *output, const int64_t *in) {\n  unsigned i;\n  for (i = 0; i < 10; i += 2) {\n    output[0+i] = (output[0+i] + in[0+i]);\n    output[1+i] = (output[1+i] + in[1+i]);\n  }\n}\n\n/* Find the difference of two numbers: output = in - output\n * (note the order of the arguments!)\n */\nstatic void fdifference(int64_t *output, const int64_t *in) {\n  unsigned i;\n  for (i = 0; i < 10; ++i) {\n    output[i] = (in[i] - output[i]);\n  }\n}\n\n/* Multiply a number by a scalar: output = in * scalar */\nstatic void fscalar_product(int64_t *output, const int64_t *in, const int64_t scalar) {\n  unsigned i;\n  for (i = 0; i < 10; ++i) {\n    output[i] = in[i] * scalar;\n  }\n}\n\n/* Multiply two numbers: output = in2 * in\n *\n * output must be distinct to both inputs. The inputs are reduced coefficient\n * form, the output is not.\n */\nstatic void fproduct(int64_t *output, const int64_t *in2, const int64_t *in) {\n  output[0] =       ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[0]);\n  output[1] =       ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[1]) +\n                    ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[0]);\n  output[2] =  2 *  ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[1]) +\n                    ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[2]) +\n                    ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[0]);\n  output[3] =       ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[2]) +\n                    ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[1]) +\n                    ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[3])) * ((int32_t) in[0]);\n  output[4] =       ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[2]) +\n               2 * (((int64_t) ((int32_t) in2[1])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[3])) * ((int32_t) in[1])) +\n                    ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[0]);\n  output[5] =       ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[3])) * ((int32_t) in[2]) +\n                    ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[1]) +\n                    ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[5])) * ((int32_t) in[0]);\n  output[6] =  2 * (((int64_t) ((int32_t) in2[3])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[5])) * ((int32_t) in[1])) +\n                    ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[2]) +\n                    ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[0]);\n  output[7] =       ((int64_t) ((int32_t) in2[3])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[5])) * ((int32_t) in[2]) +\n                    ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[1]) +\n                    ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[7])) * ((int32_t) in[0]);\n  output[8] =       ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[4]) +\n               2 * (((int64_t) ((int32_t) in2[3])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[5])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[7])) * ((int32_t) in[1])) +\n                    ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[2]) +\n                    ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[0]);\n  output[9] =       ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[5])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in2[3])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[7])) * ((int32_t) in[2]) +\n                    ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[1]) +\n                    ((int64_t) ((int32_t) in2[0])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[0]);\n  output[10] = 2 * (((int64_t) ((int32_t) in2[5])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[3])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[7])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[1])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[1])) +\n                    ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[2]);\n  output[11] =      ((int64_t) ((int32_t) in2[5])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[7])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in2[3])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in2[2])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[2]);\n  output[12] =      ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[6]) +\n               2 * (((int64_t) ((int32_t) in2[5])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[7])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[3])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[3])) +\n                    ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[4]);\n  output[13] =      ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[7])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in2[5])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in2[4])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[4]);\n  output[14] = 2 * (((int64_t) ((int32_t) in2[7])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[5])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[5])) +\n                    ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[6]);\n  output[15] =      ((int64_t) ((int32_t) in2[7])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in2[6])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[6]);\n  output[16] =      ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[8]) +\n               2 * (((int64_t) ((int32_t) in2[7])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[7]));\n  output[17] =      ((int64_t) ((int32_t) in2[8])) * ((int32_t) in[9]) +\n                    ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[8]);\n  output[18] = 2 *  ((int64_t) ((int32_t) in2[9])) * ((int32_t) in[9]);\n}\n\n/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */\nstatic void freduce_degree(int64_t *output) {\n  /* Each of these shifts and adds ends up multiplying the value by 19. */\n  output[8] += output[18] << 4;\n  output[8] += output[18] << 1;\n  output[8] += output[18];\n  output[7] += output[17] << 4;\n  output[7] += output[17] << 1;\n  output[7] += output[17];\n  output[6] += output[16] << 4;\n  output[6] += output[16] << 1;\n  output[6] += output[16];\n  output[5] += output[15] << 4;\n  output[5] += output[15] << 1;\n  output[5] += output[15];\n  output[4] += output[14] << 4;\n  output[4] += output[14] << 1;\n  output[4] += output[14];\n  output[3] += output[13] << 4;\n  output[3] += output[13] << 1;\n  output[3] += output[13];\n  output[2] += output[12] << 4;\n  output[2] += output[12] << 1;\n  output[2] += output[12];\n  output[1] += output[11] << 4;\n  output[1] += output[11] << 1;\n  output[1] += output[11];\n  output[0] += output[10] << 4;\n  output[0] += output[10] << 1;\n  output[0] += output[10];\n}\n\n\n/* return v / 2^26, using only shifts and adds. */\nstatic inline int64_t div_by_2_26(const int64_t v) {\n  /* High word of v; no shift needed*/\n  const uint32_t highword = (uint32_t)(((uint64_t) v) >> 32);\n  /* Set to all 1s if v was negative; else set to 0s. */\n  const int32_t sign = ((int32_t) highword) >> 31;\n  /* Set to 0x3ffffff if v was negative; else set to 0. */\n  const int32_t roundoff = ((uint32_t) sign) >> 6;\n  /* Should return v / (1<<26) */\n  return (v + roundoff) >> 26;\n}\n\n/* return v / (2^25), using only shifts and adds. */\nstatic inline int64_t div_by_2_25(const int64_t v) {\n  /* High word of v; no shift needed*/\n  const uint32_t highword = (uint32_t)(((uint64_t) v) >> 32);\n  /* Set to all 1s if v was negative; else set to 0s. */\n  const int32_t sign = ((int32_t) highword) >> 31;\n  /* Set to 0x1ffffff if v was negative; else set to 0. */\n  const int32_t roundoff = ((uint32_t) sign) >> 7;\n  /* Should return v / (1<<25) */\n  return (v + roundoff) >> 25;\n}\n\nstatic inline int32_t div_s32_by_2_25(const int32_t v) {\n   const int32_t roundoff = ((uint32_t)(v >> 31)) >> 7;\n   return (v + roundoff) >> 25;\n}\n\n/* Reduce all coefficients of the short form input so that |x| < 2^26.\n *\n * On entry: |output[i]| < 2^62\n */\nstatic void freduce_coefficients(int64_t *output) {\n  unsigned i;\n\n  output[10] = 0;\n\n  for (i = 0; i < 10; i += 2) {\n    int64_t over = div_by_2_26(output[i]);\n    output[i] -= over << 26;\n    output[i+1] += over;\n\n    over = div_by_2_25(output[i+1]);\n    output[i+1] -= over << 25;\n    output[i+2] += over;\n  }\n  /* Now |output[10]| < 2 ^ 38 and all other coefficients are reduced. */\n  output[0] += output[10] << 4;\n  output[0] += output[10] << 1;\n  output[0] += output[10];\n\n  output[10] = 0;\n\n  /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19 * 2^38\n   * So |over| will be no more than 77825  */\n  {\n    int64_t over = div_by_2_26(output[0]);\n    output[0] -= over << 26;\n    output[1] += over;\n  }\n\n  /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 77825\n   * So |over| will be no more than 1. */\n  {\n    /* output[1] fits in 32 bits, so we can use div_s32_by_2_25 here. */\n    int32_t over32 = div_s32_by_2_25((int32_t)output[1]);\n    output[1] -= over32 << 25;\n    output[2] += over32;\n  }\n\n  /* Finally, output[0,1,3..9] are reduced, and output[2] is \"nearly reduced\":\n   * we have |output[2]| <= 2^26.  This is good enough for all of our math,\n   * but it will require an extra freduce_coefficients before fcontract. */\n}\n\n/* A helpful wrapper around fproduct: output = in * in2.\n *\n * output must be distinct to both inputs. The output is reduced degree and\n * reduced coefficient.\n */\nstatic void fmul(int64_t *output, const int64_t *in, const int64_t *in2) {\n  int64_t t[19];\n  fproduct(t, in, in2);\n  freduce_degree(t);\n  freduce_coefficients(t);\n  memcpy(output, t, sizeof(int64_t) * 10);\n}\n\nstatic void fsquare_inner(int64_t *output, const int64_t *in) {\n  output[0] =       ((int64_t) ((int32_t) in[0])) * ((int32_t) in[0]);\n  output[1] =  2 *  ((int64_t) ((int32_t) in[0])) * ((int32_t) in[1]);\n  output[2] =  2 * (((int64_t) ((int32_t) in[1])) * ((int32_t) in[1]) +\n                    ((int64_t) ((int32_t) in[0])) * ((int32_t) in[2]));\n  output[3] =  2 * (((int64_t) ((int32_t) in[1])) * ((int32_t) in[2]) +\n                    ((int64_t) ((int32_t) in[0])) * ((int32_t) in[3]));\n  output[4] =       ((int64_t) ((int32_t) in[2])) * ((int32_t) in[2]) +\n               4 *  ((int64_t) ((int32_t) in[1])) * ((int32_t) in[3]) +\n               2 *  ((int64_t) ((int32_t) in[0])) * ((int32_t) in[4]);\n  output[5] =  2 * (((int64_t) ((int32_t) in[2])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in[1])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in[0])) * ((int32_t) in[5]));\n  output[6] =  2 * (((int64_t) ((int32_t) in[3])) * ((int32_t) in[3]) +\n                    ((int64_t) ((int32_t) in[2])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in[0])) * ((int32_t) in[6]) +\n               2 *  ((int64_t) ((int32_t) in[1])) * ((int32_t) in[5]));\n  output[7] =  2 * (((int64_t) ((int32_t) in[3])) * ((int32_t) in[4]) +\n                    ((int64_t) ((int32_t) in[2])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in[1])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in[0])) * ((int32_t) in[7]));\n  output[8] =       ((int64_t) ((int32_t) in[4])) * ((int32_t) in[4]) +\n               2 * (((int64_t) ((int32_t) in[2])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in[0])) * ((int32_t) in[8]) +\n               2 * (((int64_t) ((int32_t) in[1])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in[3])) * ((int32_t) in[5])));\n  output[9] =  2 * (((int64_t) ((int32_t) in[4])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in[3])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in[2])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in[1])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in[0])) * ((int32_t) in[9]));\n  output[10] = 2 * (((int64_t) ((int32_t) in[5])) * ((int32_t) in[5]) +\n                    ((int64_t) ((int32_t) in[4])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in[2])) * ((int32_t) in[8]) +\n               2 * (((int64_t) ((int32_t) in[3])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in[1])) * ((int32_t) in[9])));\n  output[11] = 2 * (((int64_t) ((int32_t) in[5])) * ((int32_t) in[6]) +\n                    ((int64_t) ((int32_t) in[4])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in[3])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in[2])) * ((int32_t) in[9]));\n  output[12] =      ((int64_t) ((int32_t) in[6])) * ((int32_t) in[6]) +\n               2 * (((int64_t) ((int32_t) in[4])) * ((int32_t) in[8]) +\n               2 * (((int64_t) ((int32_t) in[5])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in[3])) * ((int32_t) in[9])));\n  output[13] = 2 * (((int64_t) ((int32_t) in[6])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in[5])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in[4])) * ((int32_t) in[9]));\n  output[14] = 2 * (((int64_t) ((int32_t) in[7])) * ((int32_t) in[7]) +\n                    ((int64_t) ((int32_t) in[6])) * ((int32_t) in[8]) +\n               2 *  ((int64_t) ((int32_t) in[5])) * ((int32_t) in[9]));\n  output[15] = 2 * (((int64_t) ((int32_t) in[7])) * ((int32_t) in[8]) +\n                    ((int64_t) ((int32_t) in[6])) * ((int32_t) in[9]));\n  output[16] =      ((int64_t) ((int32_t) in[8])) * ((int32_t) in[8]) +\n               4 *  ((int64_t) ((int32_t) in[7])) * ((int32_t) in[9]);\n  output[17] = 2 *  ((int64_t) ((int32_t) in[8])) * ((int32_t) in[9]);\n  output[18] = 2 *  ((int64_t) ((int32_t) in[9])) * ((int32_t) in[9]);\n}\n\nstatic void fsquare(int64_t *output, const int64_t *in) {\n  int64_t t[19];\n  fsquare_inner(t, in);\n  freduce_degree(t);\n  freduce_coefficients(t);\n  memcpy(output, t, sizeof(int64_t) * 10);\n}\n\n/* Take a little-endian, 32-byte number and expand it into polynomial form */\nstatic void fexpand(int64_t *output, const uint8_t *input) {\n  output[0] = ((((int64_t) input[0 + 0]) | ((int64_t) input[0 + 1]) << 8 | ((int64_t) input[0 + 2]) << 16 | ((int64_t) input[0 + 3]) << 24) >> 0) & 0x3ffffff;;\n  output[1] = ((((int64_t) input[3 + 0]) | ((int64_t) input[3 + 1]) << 8 | ((int64_t) input[3 + 2]) << 16 | ((int64_t) input[3 + 3]) << 24) >> 2) & 0x1ffffff;;\n  output[2] = ((((int64_t) input[6 + 0]) | ((int64_t) input[6 + 1]) << 8 | ((int64_t) input[6 + 2]) << 16 | ((int64_t) input[6 + 3]) << 24) >> 3) & 0x3ffffff;;\n  output[3] = ((((int64_t) input[9 + 0]) | ((int64_t) input[9 + 1]) << 8 | ((int64_t) input[9 + 2]) << 16 | ((int64_t) input[9 + 3]) << 24) >> 5) & 0x1ffffff;;\n  output[4] = ((((int64_t) input[12 + 0]) | ((int64_t) input[12 + 1]) << 8 | ((int64_t) input[12 + 2]) << 16 | ((int64_t) input[12 + 3]) << 24) >> 6) & 0x3ffffff;;\n  output[5] = ((((int64_t) input[16 + 0]) | ((int64_t) input[16 + 1]) << 8 | ((int64_t) input[16 + 2]) << 16 | ((int64_t) input[16 + 3]) << 24) >> 0) & 0x1ffffff;;\n  output[6] = ((((int64_t) input[19 + 0]) | ((int64_t) input[19 + 1]) << 8 | ((int64_t) input[19 + 2]) << 16 | ((int64_t) input[19 + 3]) << 24) >> 1) & 0x3ffffff;;\n  output[7] = ((((int64_t) input[22 + 0]) | ((int64_t) input[22 + 1]) << 8 | ((int64_t) input[22 + 2]) << 16 | ((int64_t) input[22 + 3]) << 24) >> 3) & 0x1ffffff;;\n  output[8] = ((((int64_t) input[25 + 0]) | ((int64_t) input[25 + 1]) << 8 | ((int64_t) input[25 + 2]) << 16 | ((int64_t) input[25 + 3]) << 24) >> 4) & 0x3ffffff;;\n  output[9] = ((((int64_t) input[28 + 0]) | ((int64_t) input[28 + 1]) << 8 | ((int64_t) input[28 + 2]) << 16 | ((int64_t) input[28 + 3]) << 24) >> 6) & 0x1ffffff;;\n}\n\n/* Take a fully reduced polynomial form number and contract it into a\n * little-endian, 32-byte array\n */\nstatic void fcontract(uint8_t *output, int64_t *input) {\n  int i;\n  int j;\n  int32_t mask;\n  int32_t carry;\n\n  for (j = 0; j < 2; ++j) {\n    for (i = 0; i < 9; ++i) {\n      if ((i & 1) == 1) {\n        /* This calculation is a time-invariant way to make input[i] positive\n           by borrowing from the next-larger int64_t.\n        */\n        const int32_t mask = (int32_t)(input[i]) >> 31;\n        const int32_t carry = -(((int32_t)(input[i]) & mask) >> 25);\n        input[i] = (int32_t)(input[i]) + (carry << 25);\n        input[i+1] = (int32_t)(input[i+1]) - carry;\n      } else {\n        const int32_t mask = (int32_t)(input[i]) >> 31;\n        const int32_t carry = -(((int32_t)(input[i]) & mask) >> 26);\n        input[i] = (int32_t)(input[i]) + (carry << 26);\n        input[i+1] = (int32_t)(input[i+1]) - carry;\n      }\n    }\n    mask = (int32_t)(input[9]) >> 31;\n    carry = -(((int32_t)(input[9]) & mask) >> 25);\n    input[9] = (int32_t)(input[9]) + (carry << 25);\n    input[0] = (int32_t)(input[0]) - (carry * 19);\n  }\n\n  /* The first borrow-propagation pass above ended with every int64_t\n     except (possibly) input[0] non-negative.\n\n     Since each input int64_t except input[0] is decreased by at most 1\n     by a borrow-propagation pass, the second borrow-propagation pass\n     could only have wrapped around to decrease input[0] again if the\n     first pass left input[0] negative *and* input[1] through input[9]\n     were all zero.  In that case, input[1] is now 2^25 - 1, and this\n     last borrow-propagation step will leave input[1] non-negative.\n  */\n  mask = (int32_t)(input[0]) >> 31;\n  carry = -(((int32_t)(input[0]) & mask) >> 26);\n  input[0] = (int32_t)(input[0]) + (carry << 26);\n  input[1] = (int32_t)(input[1]) - carry;\n\n  /* Both passes through the above loop, plus the last 0-to-1 step, are\n     necessary: if input[9] is -1 and input[0] through input[8] are 0,\n     negative values will remain in the array until the end.\n   */\n\n  input[1] <<= 2;\n  input[2] <<= 3;\n  input[3] <<= 5;\n  input[4] <<= 6;\n  input[6] <<= 1;\n  input[7] <<= 3;\n  input[8] <<= 4;\n  input[9] <<= 6;\n  output[0] = 0;\n  output[16] = 0;\n  output[0+0] |= input[0] & 0xff; output[0+1] = (input[0] >> 8) & 0xff; output[0+2] = (input[0] >> 16) & 0xff; output[0+3] = (input[0] >> 24) & 0xff;;\n  output[3+0] |= input[1] & 0xff; output[3+1] = (input[1] >> 8) & 0xff; output[3+2] = (input[1] >> 16) & 0xff; output[3+3] = (input[1] >> 24) & 0xff;;\n  output[6+0] |= input[2] & 0xff; output[6+1] = (input[2] >> 8) & 0xff; output[6+2] = (input[2] >> 16) & 0xff; output[6+3] = (input[2] >> 24) & 0xff;;\n  output[9+0] |= input[3] & 0xff; output[9+1] = (input[3] >> 8) & 0xff; output[9+2] = (input[3] >> 16) & 0xff; output[9+3] = (input[3] >> 24) & 0xff;;\n  output[12+0] |= input[4] & 0xff; output[12+1] = (input[4] >> 8) & 0xff; output[12+2] = (input[4] >> 16) & 0xff; output[12+3] = (input[4] >> 24) & 0xff;;\n  output[16+0] |= input[5] & 0xff; output[16+1] = (input[5] >> 8) & 0xff; output[16+2] = (input[5] >> 16) & 0xff; output[16+3] = (input[5] >> 24) & 0xff;;\n  output[19+0] |= input[6] & 0xff; output[19+1] = (input[6] >> 8) & 0xff; output[19+2] = (input[6] >> 16) & 0xff; output[19+3] = (input[6] >> 24) & 0xff;;\n  output[22+0] |= input[7] & 0xff; output[22+1] = (input[7] >> 8) & 0xff; output[22+2] = (input[7] >> 16) & 0xff; output[22+3] = (input[7] >> 24) & 0xff;;\n  output[25+0] |= input[8] & 0xff; output[25+1] = (input[8] >> 8) & 0xff; output[25+2] = (input[8] >> 16) & 0xff; output[25+3] = (input[8] >> 24) & 0xff;;\n  output[28+0] |= input[9] & 0xff; output[28+1] = (input[9] >> 8) & 0xff; output[28+2] = (input[9] >> 16) & 0xff; output[28+3] = (input[9] >> 24) & 0xff;;\n}\n\n/* Input: Q, Q', Q-Q'\n * Output: 2Q, Q+Q'\n *\n *   x2 z3: long form\n *   x3 z3: long form\n *   x z: short form, destroyed\n *   xprime zprime: short form, destroyed\n *   qmqp: short form, preserved\n */\nstatic void fmonty(int64_t *x2, int64_t *z2,  /* output 2Q */\n                   int64_t *x3, int64_t *z3,  /* output Q + Q' */\n                   int64_t *x, int64_t *z,    /* input Q */\n                   int64_t *xprime, int64_t *zprime,  /* input Q' */\n                   const int64_t *qmqp /* input Q - Q' */) {\n  int64_t origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],\n        zzprime[19], zzzprime[19], xxxprime[19];\n\n  memcpy(origx, x, 10 * sizeof(int64_t));\n  fsum(x, z);\n  fdifference(z, origx);  /* does x - z */\n\n  memcpy(origxprime, xprime, sizeof(int64_t) * 10);\n  fsum(xprime, zprime);\n  fdifference(zprime, origxprime);\n  fproduct(xxprime, xprime, z);\n  fproduct(zzprime, x, zprime);\n  freduce_degree(xxprime);\n  freduce_coefficients(xxprime);\n  freduce_degree(zzprime);\n  freduce_coefficients(zzprime);\n  memcpy(origxprime, xxprime, sizeof(int64_t) * 10);\n  fsum(xxprime, zzprime);\n  fdifference(zzprime, origxprime);\n  fsquare(xxxprime, xxprime);\n  fsquare(zzzprime, zzprime);\n  fproduct(zzprime, zzzprime, qmqp);\n  freduce_degree(zzprime);\n  freduce_coefficients(zzprime);\n  memcpy(x3, xxxprime, sizeof(int64_t) * 10);\n  memcpy(z3, zzprime, sizeof(int64_t) * 10);\n\n  fsquare(xx, x);\n  fsquare(zz, z);\n  fproduct(x2, xx, zz);\n  freduce_degree(x2);\n  freduce_coefficients(x2);\n  fdifference(zz, xx);  /* does zz = xx - zz */\n  memset(zzz + 10, 0, sizeof(int64_t) * 9);\n  fscalar_product(zzz, zz, 121665);\n  /* No need to call freduce_degree here:\n     fscalar_product doesn't increase the degree of its input. */\n  freduce_coefficients(zzz);\n  fsum(zzz, xx);\n  fproduct(z2, zz, zzz);\n  freduce_degree(z2);\n  freduce_coefficients(z2);\n}\n\n/* Conditionally swap two reduced-form int64_t arrays if 'iswap' is 1, but leave\n * them unchanged if 'iswap' is 0.  Runs in data-invariant time to avoid\n * side-channel attacks.\n *\n * NOTE that this function requires that 'iswap' be 1 or 0; other values give\n * wrong results.  Also, the two int64_t arrays must be in reduced-coefficient,\n * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped,\n * and all all values in a[0..9],b[0..9] must have magnitude less than\n * INT32_MAX.\n */\nstatic void swap_conditional(int64_t a[19], int64_t b[19], int64_t iswap) {\n  unsigned i;\n  const int32_t swap = (int32_t)-iswap;\n\n  for (i = 0; i < 10; ++i) {\n    const int32_t x = swap & ( ((int32_t)a[i]) ^ ((int32_t)b[i]) );\n    a[i] = ((int32_t)a[i]) ^ x;\n    b[i] = ((int32_t)b[i]) ^ x;\n  }\n}\n\n/* Calculates nQ where Q is the x-coordinate of a point on the curve\n *\n *   resultx/resultz: the x coordinate of the resulting curve point (short form)\n *   n: a little endian, 32-byte number\n *   q: a point of the curve (short form)\n */\nstatic void cmult(int64_t *resultx, int64_t *resultz, const uint8_t *n, const int64_t *q) {\n  int64_t a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};\n  int64_t *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;\n  int64_t e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};\n  int64_t *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;\n\n  unsigned i, j;\n\n  memcpy(nqpqx, q, sizeof(int64_t) * 10);\n\n  for (i = 0; i < 32; ++i) {\n    uint8_t byte = n[31 - i];\n    for (j = 0; j < 8; ++j) {\n      const int64_t bit = byte >> 7;\n\n      swap_conditional(nqx, nqpqx, bit);\n      swap_conditional(nqz, nqpqz, bit);\n      fmonty(nqx2, nqz2,\n             nqpqx2, nqpqz2,\n             nqx, nqz,\n             nqpqx, nqpqz,\n             q);\n      swap_conditional(nqx2, nqpqx2, bit);\n      swap_conditional(nqz2, nqpqz2, bit);\n\n      t = nqx;\n      nqx = nqx2;\n      nqx2 = t;\n      t = nqz;\n      nqz = nqz2;\n      nqz2 = t;\n      t = nqpqx;\n      nqpqx = nqpqx2;\n      nqpqx2 = t;\n      t = nqpqz;\n      nqpqz = nqpqz2;\n      nqpqz2 = t;\n\n      byte <<= 1;\n    }\n  }\n\n  memcpy(resultx, nqx, sizeof(int64_t) * 10);\n  memcpy(resultz, nqz, sizeof(int64_t) * 10);\n}\n\n/* -----------------------------------------------------------------------------\n// Shamelessly copied from djb's code\n// -------------------------------------------------------------------------- */\nstatic void crecip(int64_t *out, const int64_t *z) {\n  int64_t z2[10];\n  int64_t z9[10];\n  int64_t z11[10];\n  int64_t z2_5_0[10];\n  int64_t z2_10_0[10];\n  int64_t z2_20_0[10];\n  int64_t z2_50_0[10];\n  int64_t z2_100_0[10];\n  int64_t t0[10];\n  int64_t t1[10];\n  int i;\n\n  /* 2 */ fsquare(z2,z);\n  /* 4 */ fsquare(t1,z2);\n  /* 8 */ fsquare(t0,t1);\n  /* 9 */ fmul(z9,t0,z);\n  /* 11 */ fmul(z11,z9,z2);\n  /* 22 */ fsquare(t0,z11);\n  /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9);\n\n  /* 2^6 - 2^1 */ fsquare(t0,z2_5_0);\n  /* 2^7 - 2^2 */ fsquare(t1,t0);\n  /* 2^8 - 2^3 */ fsquare(t0,t1);\n  /* 2^9 - 2^4 */ fsquare(t1,t0);\n  /* 2^10 - 2^5 */ fsquare(t0,t1);\n  /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0);\n\n  /* 2^11 - 2^1 */ fsquare(t0,z2_10_0);\n  /* 2^12 - 2^2 */ fsquare(t1,t0);\n  /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }\n  /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0);\n\n  /* 2^21 - 2^1 */ fsquare(t0,z2_20_0);\n  /* 2^22 - 2^2 */ fsquare(t1,t0);\n  /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }\n  /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0);\n\n  /* 2^41 - 2^1 */ fsquare(t1,t0);\n  /* 2^42 - 2^2 */ fsquare(t0,t1);\n  /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }\n  /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0);\n\n  /* 2^51 - 2^1 */ fsquare(t0,z2_50_0);\n  /* 2^52 - 2^2 */ fsquare(t1,t0);\n  /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }\n  /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0);\n\n  /* 2^101 - 2^1 */ fsquare(t1,z2_100_0);\n  /* 2^102 - 2^2 */ fsquare(t0,t1);\n  /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }\n  /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0);\n\n  /* 2^201 - 2^1 */ fsquare(t0,t1);\n  /* 2^202 - 2^2 */ fsquare(t1,t0);\n  /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }\n  /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0);\n\n  /* 2^251 - 2^1 */ fsquare(t1,t0);\n  /* 2^252 - 2^2 */ fsquare(t0,t1);\n  /* 2^253 - 2^3 */ fsquare(t1,t0);\n  /* 2^254 - 2^4 */ fsquare(t0,t1);\n  /* 2^255 - 2^5 */ fsquare(t1,t0);\n  /* 2^255 - 21 */ fmul(out,t1,z11);\n}\n\nstatic const unsigned char kCurve25519BasePoint[ 32 ] = { 9 };\n\nvoid curve25519(uint8_t *mypublic, const uint8_t *secret, const uint8_t *basepoint) {\n  int64_t bp[10], x[10], z[11], zmone[10];\n  uint8_t e[32];\n  int i;\n\n  if (basepoint == 0) basepoint = kCurve25519BasePoint;\n\n  for (i = 0; i < 32; ++i) e[i] = secret[i];\n  e[0] &= 248;\n  e[31] &= 127;\n  e[31] |= 64;\n\n  fexpand(bp, basepoint);\n  cmult(x, z, e, bp);\n  crecip(zmone, z);\n  fmul(z, x, zmone);\n  freduce_coefficients(z);\n  fcontract(mypublic, z);\n}\n\n#endif\n/* using ChaCha20 implementation by D. J. Bernstein */\n\n#ifndef TLS_FORWARD_SECRECY\n#undef TLS_ECDSA_SUPPORTED\n#endif\n\n#ifndef TLS_ECDSA_SUPPORTED\n/* disable client ECDSA if not supported */\n#undef TLS_CLIENT_ECDSA\n#endif\n\n#define TLS_DH_DEFAULT_P            \"87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597\"\n#define TLS_DH_DEFAULT_G            \"3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659\"\n#define TLS_DHE_KEY_SIZE          2048\n\n#if(0)\n/* you should never use weak DH groups (1024 bits)\n// but if you have old devices (like grandstream ip phones)\n// that can't handle 2048bit DHE, uncomment next lines\n// and define TLS_WEAK_DH_LEGACY_DEVICES\n// #ifdef TLS_WEAK_DH_LEGACY_DEVICES\n//     #define TLS_DH_DEFAULT_P            \"B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371\"\n//     #define TLS_DH_DEFAULT_G            \"A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5\"\n//     #define TLS_DHE_KEY_SIZE          1024\n// #endif */\n#endif\n\n#ifndef TLS_MALLOC\n    #define TLS_MALLOC(size)        malloc(size)\n#endif\n#ifndef TLS_REALLOC\n    #define TLS_REALLOC(ptr, size)  realloc(ptr, size)\n#endif\n#ifndef TLS_FREE\n    #define TLS_FREE(ptr)           if (ptr) free(ptr)\n#endif\n\n#define TLS_ERROR(err, statement)   if (err) statement;\n\n/* No variadic macros in c89. Using the (a...) method doesn't work on all\n   versions of gcc 2.7. */\n#ifdef DEBUG\n#define DEBUG_PRINT0(a)            fprintf(stderr, a)\n#define DEBUG_PRINT1(a, b)         fprintf(stderr, a, b)\n#define DEBUG_PRINT2(a, b, c)      fprintf(stderr, a, b, c)\n#define DEBUG_PRINT3(a, b, c, d)   fprintf(stderr, a, b, c, d)\n#define DEBUG_PRINT4(a, b, c, d, e) fprintf(stderr, a, b, c, d, e)\n#define DEBUG_DUMP_HEX(buf, len)    {if (buf) { int _i_; for (_i_ = 0; _i_ < len; _i_++) { DEBUG_PRINT1(\"%02X \", (unsigned int)(buf)[_i_]); } } else { fprintf(stderr, \"(null)\"); } }\n#define DEBUG_INDEX(fields)         print_index(fields)\n#define DEBUG_DUMP(buf, length)     fwrite(buf, 1, length, stderr);\n#define DEBUG_DUMP_HEX_LABEL(title, buf, len)    {fprintf(stderr, \"%s (%i): \", title, (int)len); DEBUG_DUMP_HEX(buf, len); fprintf(stderr, \"\\n\");}\n#else\n#define DEBUG_PRINT0(a)             { }\n#define DEBUG_PRINT1(a,b)           { }\n#define DEBUG_PRINT2(a,b,c)         { }\n#define DEBUG_PRINT3(a,b,c,d)       { }\n#define DEBUG_PRINT4(a,b,c,d,e)     { }\n#define DEBUG_DUMP_HEX(buf, len)    { }\n#define DEBUG_INDEX(fields)         { }\n#define DEBUG_DUMP(buf, length)     { }\n#define DEBUG_DUMP_HEX_LABEL(title, buf, len) { }\n#endif\n\n#ifndef htonll\n#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))\n#endif\n\n#ifndef ntohll\n#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))\n#endif\n\n#define TLS_CHANGE_CIPHER       0x14\n#define TLS_ALERT               0x15\n#define TLS_HANDSHAKE           0x16\n#define TLS_APPLICATION_DATA    0x17\n\n#define TLS_SERIALIZED_OBJECT   0xFE\n\n#define TLS_CLIENT_HELLO_MINSIZE    41\n#define TLS_CLIENT_RANDOM_SIZE      32\n#define TLS_SERVER_RANDOM_SIZE      32\n#define TLS_MAX_SESSION_ID          32\n#define TLS_SHA256_MAC_SIZE         32\n#define TLS_SHA1_MAC_SIZE           20\n#define TLS_SHA384_MAC_SIZE         48\n#define TLS_MAX_MAC_SIZE            TLS_SHA384_MAC_SIZE\n /* 160 */\n#define TLS_MAX_KEY_EXPANSION_SIZE  192\n/* 512bits (sha256) = 64 bytes */\n#define TLS_MAX_HASH_LEN            64\n#define TLS_AES_IV_LENGTH           16\n#define TLS_AES_BLOCK_SIZE          16\n#define TLS_AES_GCM_IV_LENGTH       4\n#define TLS_13_AES_GCM_IV_LENGTH    12\n#define TLS_GCM_TAG_LEN             16\n#define TLS_MAX_TAG_LEN             16\n#define TLS_MIN_FINISHED_OPAQUE_LEN 12\n\n#define TLS_BLOB_INCREMENT        0xFFF\n#define TLS_ASN1_MAXLEVEL         0xFF\n\n#define DTLS_COOKIE_SIZE          32\n\n#define TLS_MAX_SHA_SIZE 48\n/* 16(md5) + 20(sha1) */\n#define TLS_V11_HASH_SIZE 36\n#define TLS_MAX_HASH_SIZE TLS_MAX_SHA_SIZE\n/* 16(md5) + 20(sha1) */\n#define TLS_MAX_RSA_KEY   2048\n\n#define TLS_MAXTLS_APP_SIZE      0x4000\n/* max 1 second sleep */\n#define TLS_MAX_ERROR_SLEEP_uS    1000000\n/* max 5 seconds context sleep */\n#define TLS_MAX_ERROR_IDLE_S      5\n\n#define TLS_V13_MAX_KEY_SIZE      32\n#define TLS_V13_MAX_IV_SIZE       12\n\n#define VERSION_SUPPORTED(version, err)  if ((version != TLS_V13) && (version != TLS_V12) && (version != TLS_V11) && (version != TLS_V10) && (version != DTLS_V13) && (version != DTLS_V12) && (version != DTLS_V10)) { if ((version == SSL_V30) && (context->connection_status == 0)) { version = TLS_V12; } else { DEBUG_PRINT1(\"UNSUPPORTED TLS VERSION %x\\n\", (int)version); return err;} }\n#define CHECK_SIZE(size, buf_size, err)  if (((int)(size) > (int)(buf_size)) || ((int)(buf_size) < 0)) return err;\n#define TLS_IMPORT_CHECK_SIZE(buf_pos, size, buf_size) if (((int)size > (int)buf_size - buf_pos) || ((int)buf_pos > (int)buf_size)) { DEBUG_PRINT0(\"IMPORT ELEMENT SIZE ERROR\\n\"); tls_destroy_context(context); return NULL; }\n#define CHECK_HANDSHAKE_STATE(context, n, limit)  { if (context->hs_messages[n] >= limit) { DEBUG_PRINT1(\"* UNEXPECTED MESSAGE (%i)\\n\", (int)n); payload_res = TLS_UNEXPECTED_MESSAGE; break; } context->hs_messages[n]++; }\n\n#ifdef TLS_WITH_CHACHA20_POLY1305\n#define TLS_CHACHA20_IV_LENGTH    12\n\n/* ChaCha20 implementation by D. J. Bernstein\n   Public domain. */\n\n#define CHACHA_MINKEYLEN    16\n#define CHACHA_NONCELEN     8\n#define CHACHA_NONCELEN_96  12\n#define CHACHA_CTRLEN       8\n#define CHACHA_CTRLEN_96    4\n#define CHACHA_STATELEN     (CHACHA_NONCELEN+CHACHA_CTRLEN)\n#define CHACHA_BLOCKLEN     64\n\n#define POLY1305_MAX_AAD    32\n#define POLY1305_KEYLEN     32\n#define POLY1305_TAGLEN     16\n\n#define u_int   unsigned int\n#define uint8_t unsigned char\n#define u_char  unsigned char\n#ifndef NULL\n#define NULL (void *)0\n#endif\n\n#if (CRYPT >= 0x0117) && (0)\n    /* to do: use ltc chacha/poly1305 implementation (working on big-endian machines) */\n    #define chacha_ctx                                  chacha20poly1305_state\n    #define poly1305_context                            poly1305_state\n\n    #define _private_tls_poly1305_init(ctx, key, len)  poly1305_init(ctx, key, len)\n    #define _private_tls_poly1305_update(ctx, in, len) poly1305_process(ctx, in, len)\n    #define _private_tls_poly1305_finish(ctx, mac)     poly1305_done(ctx, mac, 16)\n#else\nstruct chacha_ctx {\n    u_int input[16];\n    uint8_t ks[CHACHA_BLOCKLEN];\n    uint8_t unused;\n};\n\nstatic inline void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits);\nstatic inline void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr);\nstatic inline void chacha_ivsetup_96bitnonce(struct chacha_ctx *x, const u_char *iv, const u_char *ctr);\nstatic inline void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m, u_char *c, u_int bytes);\nstatic inline int poly1305_generate_key(unsigned char *key256, unsigned char *nonce, unsigned int noncelen, unsigned char *poly_key, unsigned int counter);\n\n#define poly1305_block_size 16\n#define poly1305_context poly1305_state_internal_t\n\n/*\n//========== ChaCha20 from D. J. Bernstein ========= //\n// Source available at https://cr.yp.to/chacha.html  //\n*/\n\ntypedef unsigned char u8;\ntypedef unsigned int u32;\n\ntypedef struct chacha_ctx chacha_ctx;\n\n#define U8C(v) (v##U)\n#define U32C(v) (v##U)\n\n#define U8V(v) ((u8)(v) & U8C(0xFF))\n#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))\n\n/* egcs barfs on the macros if the lines end in ^M. */\n#define ROTL32(v, n) \\\n  (U32V((v) << (n)) | ((v) >> (32 - (n))))\n\n#if __BIG_ENDIAN__\n#define _private_tls_U8TO32_BIG(p) \\\n  (((u32)((p)[3])) | \\\n   ((u32)((p)[2]) <<  8) | \\\n   ((u32)((p)[1]) << 16) | \\\n   ((u32)((p)[0]) << 24))\n#endif\n\n#define _private_tls_U8TO32_LITTLE(p) \\\n  (((u32)((p)[0])) | \\\n   ((u32)((p)[1]) <<  8) | \\\n   ((u32)((p)[2]) << 16) | \\\n   ((u32)((p)[3]) << 24))\n\n#define _private_tls_U32TO8_LITTLE(p, v) \\\n  do { \\\n    (p)[0] = U8V((v)); \\\n    (p)[1] = U8V((v) >>  8); \\\n    (p)[2] = U8V((v) >> 16); \\\n    (p)[3] = U8V((v) >> 24); \\\n  } while (0)\n\n#define ROTATE(v,c) (ROTL32(v,c))\n#define XOR(v,w) ((v) ^ (w))\n#define PLUS(v,w) (U32V((v) + (w)))\n#define PLUSONE(v) (PLUS((v),1))\n\n#define QUARTERROUND(a,b,c,d) \\\n  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \\\n  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \\\n  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \\\n  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);\n\nstatic const char sigma[] = \"expand 32-byte k\";\nstatic const char tau[] = \"expand 16-byte k\";\n\nstatic inline void chacha_keysetup(chacha_ctx *x, const u8 *k, u32 kbits) {\n    const char *constants;\n\n    x->input[4] = _private_tls_U8TO32_LITTLE(k + 0);\n    x->input[5] = _private_tls_U8TO32_LITTLE(k + 4);\n    x->input[6] = _private_tls_U8TO32_LITTLE(k + 8);\n    x->input[7] = _private_tls_U8TO32_LITTLE(k + 12);\n    if (kbits == 256) { /* recommended */\n        k += 16;\n        constants = sigma;\n    } else { /* kbits == 128 */\n        constants = tau;\n    }\n    x->input[8] = _private_tls_U8TO32_LITTLE(k + 0);\n    x->input[9] = _private_tls_U8TO32_LITTLE(k + 4);\n    x->input[10] = _private_tls_U8TO32_LITTLE(k + 8);\n    x->input[11] = _private_tls_U8TO32_LITTLE(k + 12);\n#if __BIG_ENDIAN__\n    if (kbits == 256) {\n        x->input[0] = 0x61707865; /* apxe */\n        x->input[1] = 0x3320646e; /* 3 dn */\n        x->input[2] = 0x79622d32; /* yb-2 */\n        x->input[3] = 0x6b206574; /* k et */\n    } else {\n        x->input[0] = 0x61707865; /* apxe */\n        x->input[1] = 0x3120646e; /* 1 dn */\n        x->input[2] = 0x79622d36; /* yb-6 */\n        x->input[3] = 0x6b206574; /* k et */\n    }\n#else\n    x->input[0] = _private_tls_U8TO32_LITTLE(constants + 0);\n    x->input[1] = _private_tls_U8TO32_LITTLE(constants + 4);\n    x->input[2] = _private_tls_U8TO32_LITTLE(constants + 8);\n    x->input[3] = _private_tls_U8TO32_LITTLE(constants + 12);\n#endif\n}\n\nstatic inline void chacha_key(chacha_ctx *x, u8 *k) {\n    _private_tls_U32TO8_LITTLE(k, x->input[4]);\n    _private_tls_U32TO8_LITTLE(k + 4, x->input[5]);\n    _private_tls_U32TO8_LITTLE(k + 8, x->input[6]);\n    _private_tls_U32TO8_LITTLE(k + 12, x->input[7]);\n\n    _private_tls_U32TO8_LITTLE(k + 16, x->input[8]);\n    _private_tls_U32TO8_LITTLE(k + 20, x->input[9]);\n    _private_tls_U32TO8_LITTLE(k + 24, x->input[10]);\n    _private_tls_U32TO8_LITTLE(k + 28, x->input[11]);\n}\n\nstatic inline void chacha_nonce(chacha_ctx *x, u8 *nonce) {\n    _private_tls_U32TO8_LITTLE(nonce + 0, x->input[13]);\n    _private_tls_U32TO8_LITTLE(nonce + 4, x->input[14]);\n    _private_tls_U32TO8_LITTLE(nonce + 8, x->input[15]);\n}\n\nstatic inline void chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) {\n#if __BIG_ENDIAN__\n    /* incoming int is native endian */\n    x->input[12] = counter == NULL ? 0 : _private_tls_U8TO32_BIG(counter + 0);\n    x->input[13] = counter == NULL ? 0 : _private_tls_U8TO32_BIG(counter + 4);\n#else\n    x->input[12] = counter == NULL ? 0 : _private_tls_U8TO32_LITTLE(counter + 0);\n    x->input[13] = counter == NULL ? 0 : _private_tls_U8TO32_LITTLE(counter + 4);\n#endif\n    if (iv) {\n        x->input[14] = _private_tls_U8TO32_LITTLE(iv + 0);\n        x->input[15] = _private_tls_U8TO32_LITTLE(iv + 4);\n    }\n}\n\nstatic inline void chacha_ivsetup_96bitnonce(chacha_ctx *x, const u8 *iv, const u8 *counter) {\n#if __BIG_ENDIAN__\n    x->input[12] = counter == NULL ? 0 : _private_tls_U8TO32_BIG(counter + 0);\n#else\n    x->input[12] = counter == NULL ? 0 : _private_tls_U8TO32_LITTLE(counter + 0);\n#endif\n    if (iv) {\n        x->input[13] = _private_tls_U8TO32_LITTLE(iv + 0);\n        x->input[14] = _private_tls_U8TO32_LITTLE(iv + 4);\n        x->input[15] = _private_tls_U8TO32_LITTLE(iv + 8);\n    }\n}\n\nstatic inline void chacha_ivupdate(chacha_ctx *x, const u8 *iv, const u8 *aad, const u8 *counter) {\n#if __BIG_ENDIAN__\n    x->input[12] = counter == NULL ? 0 : _private_tls_U8TO32_BIG(counter + 0);\n#else\n    x->input[12] = counter == NULL ? 0 : _private_tls_U8TO32_LITTLE(counter + 0);\n#endif\n    x->input[13] = _private_tls_U8TO32_LITTLE(iv + 0);\n    x->input[14] = _private_tls_U8TO32_LITTLE(iv + 4) ^ _private_tls_U8TO32_LITTLE(aad);\n    x->input[15] = _private_tls_U8TO32_LITTLE(iv + 8) ^ _private_tls_U8TO32_LITTLE(aad + 4);\n}\n\nstatic inline void chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes) {\n    u32 x0, x1, x2, x3, x4, x5, x6, x7;\n    u32 x8, x9, x10, x11, x12, x13, x14, x15;\n    u32 j0, j1, j2, j3, j4, j5, j6, j7;\n    u32 j8, j9, j10, j11, j12, j13, j14, j15;\n    u8 *ctarget = NULL;\n    u8 tmp[64];\n    u_int i;\n\n    if (!bytes)\n        return;\n\n    j0 = x->input[0];\n    j1 = x->input[1];\n    j2 = x->input[2];\n    j3 = x->input[3];\n    j4 = x->input[4];\n    j5 = x->input[5];\n    j6 = x->input[6];\n    j7 = x->input[7];\n    j8 = x->input[8];\n    j9 = x->input[9];\n    j10 = x->input[10];\n    j11 = x->input[11];\n    j12 = x->input[12];\n    j13 = x->input[13];\n    j14 = x->input[14];\n    j15 = x->input[15];\n\n    for (;;) {\n        if (bytes < 64) {\n            for (i = 0; i < bytes; ++i)\n                tmp[i] = m[i];\n            m = tmp;\n            ctarget = c;\n            c = tmp;\n        }\n        x0 = j0;\n        x1 = j1;\n        x2 = j2;\n        x3 = j3;\n        x4 = j4;\n        x5 = j5;\n        x6 = j6;\n        x7 = j7;\n        x8 = j8;\n        x9 = j9;\n        x10 = j10;\n        x11 = j11;\n        x12 = j12;\n        x13 = j13;\n        x14 = j14;\n        x15 = j15;\n        for (i = 20; i > 0; i -= 2) {\n            QUARTERROUND(x0, x4, x8, x12)\n            QUARTERROUND(x1, x5, x9, x13)\n            QUARTERROUND(x2, x6, x10, x14)\n            QUARTERROUND(x3, x7, x11, x15)\n            QUARTERROUND(x0, x5, x10, x15)\n            QUARTERROUND(x1, x6, x11, x12)\n            QUARTERROUND(x2, x7, x8, x13)\n            QUARTERROUND(x3, x4, x9, x14)\n        }\n        x0 = PLUS(x0, j0);\n        x1 = PLUS(x1, j1);\n        x2 = PLUS(x2, j2);\n        x3 = PLUS(x3, j3);\n        x4 = PLUS(x4, j4);\n        x5 = PLUS(x5, j5);\n        x6 = PLUS(x6, j6);\n        x7 = PLUS(x7, j7);\n        x8 = PLUS(x8, j8);\n        x9 = PLUS(x9, j9);\n        x10 = PLUS(x10, j10);\n        x11 = PLUS(x11, j11);\n        x12 = PLUS(x12, j12);\n        x13 = PLUS(x13, j13);\n        x14 = PLUS(x14, j14);\n        x15 = PLUS(x15, j15);\n\n        if (bytes < 64) {\n            _private_tls_U32TO8_LITTLE(x->ks + 0, x0);\n            _private_tls_U32TO8_LITTLE(x->ks + 4, x1);\n            _private_tls_U32TO8_LITTLE(x->ks + 8, x2);\n            _private_tls_U32TO8_LITTLE(x->ks + 12, x3);\n            _private_tls_U32TO8_LITTLE(x->ks + 16, x4);\n            _private_tls_U32TO8_LITTLE(x->ks + 20, x5);\n            _private_tls_U32TO8_LITTLE(x->ks + 24, x6);\n            _private_tls_U32TO8_LITTLE(x->ks + 28, x7);\n            _private_tls_U32TO8_LITTLE(x->ks + 32, x8);\n            _private_tls_U32TO8_LITTLE(x->ks + 36, x9);\n            _private_tls_U32TO8_LITTLE(x->ks + 40, x10);\n            _private_tls_U32TO8_LITTLE(x->ks + 44, x11);\n            _private_tls_U32TO8_LITTLE(x->ks + 48, x12);\n            _private_tls_U32TO8_LITTLE(x->ks + 52, x13);\n            _private_tls_U32TO8_LITTLE(x->ks + 56, x14);\n            _private_tls_U32TO8_LITTLE(x->ks + 60, x15);\n        }\n\n        x0 = XOR(x0, _private_tls_U8TO32_LITTLE(m + 0));\n        x1 = XOR(x1, _private_tls_U8TO32_LITTLE(m + 4));\n        x2 = XOR(x2, _private_tls_U8TO32_LITTLE(m + 8));\n        x3 = XOR(x3, _private_tls_U8TO32_LITTLE(m + 12));\n        x4 = XOR(x4, _private_tls_U8TO32_LITTLE(m + 16));\n        x5 = XOR(x5, _private_tls_U8TO32_LITTLE(m + 20));\n        x6 = XOR(x6, _private_tls_U8TO32_LITTLE(m + 24));\n        x7 = XOR(x7, _private_tls_U8TO32_LITTLE(m + 28));\n        x8 = XOR(x8, _private_tls_U8TO32_LITTLE(m + 32));\n        x9 = XOR(x9, _private_tls_U8TO32_LITTLE(m + 36));\n        x10 = XOR(x10, _private_tls_U8TO32_LITTLE(m + 40));\n        x11 = XOR(x11, _private_tls_U8TO32_LITTLE(m + 44));\n        x12 = XOR(x12, _private_tls_U8TO32_LITTLE(m + 48));\n        x13 = XOR(x13, _private_tls_U8TO32_LITTLE(m + 52));\n        x14 = XOR(x14, _private_tls_U8TO32_LITTLE(m + 56));\n        x15 = XOR(x15, _private_tls_U8TO32_LITTLE(m + 60));\n\n        j12 = PLUSONE(j12);\n        if (!j12) {\n            j13 = PLUSONE(j13);\n            /*\n             * Stopping at 2^70 bytes per nonce is the user's\n             * responsibility.\n             */\n        }\n\n        _private_tls_U32TO8_LITTLE(c + 0, x0);\n        _private_tls_U32TO8_LITTLE(c + 4, x1);\n        _private_tls_U32TO8_LITTLE(c + 8, x2);\n        _private_tls_U32TO8_LITTLE(c + 12, x3);\n        _private_tls_U32TO8_LITTLE(c + 16, x4);\n        _private_tls_U32TO8_LITTLE(c + 20, x5);\n        _private_tls_U32TO8_LITTLE(c + 24, x6);\n        _private_tls_U32TO8_LITTLE(c + 28, x7);\n        _private_tls_U32TO8_LITTLE(c + 32, x8);\n        _private_tls_U32TO8_LITTLE(c + 36, x9);\n        _private_tls_U32TO8_LITTLE(c + 40, x10);\n        _private_tls_U32TO8_LITTLE(c + 44, x11);\n        _private_tls_U32TO8_LITTLE(c + 48, x12);\n        _private_tls_U32TO8_LITTLE(c + 52, x13);\n        _private_tls_U32TO8_LITTLE(c + 56, x14);\n        _private_tls_U32TO8_LITTLE(c + 60, x15);\n\n        if (bytes <= 64) {\n            if (bytes < 64) {\n                for (i = 0; i < bytes; ++i)\n                    ctarget[i] = c[i];\n            }\n            x->input[12] = j12;\n            x->input[13] = j13;\n            x->unused = 64 - bytes;\n            return;\n        }\n        bytes -= 64;\n        c += 64;\n        m += 64;\n    }\n}\n\nstatic inline void chacha20_block(chacha_ctx *x, unsigned char *c, u_int len) {\n    u_int i;\n\n    unsigned int state[16];\n    for (i = 0; i < 16; i++)\n        state[i] = x->input[i];\n    for (i = 20; i > 0; i -= 2) {\n        QUARTERROUND(state[0], state[4], state[8], state[12])\n        QUARTERROUND(state[1], state[5], state[9], state[13])\n        QUARTERROUND(state[2], state[6], state[10], state[14])\n        QUARTERROUND(state[3], state[7], state[11], state[15])\n        QUARTERROUND(state[0], state[5], state[10], state[15])\n        QUARTERROUND(state[1], state[6], state[11], state[12])\n        QUARTERROUND(state[2], state[7], state[8], state[13])\n        QUARTERROUND(state[3], state[4], state[9], state[14])\n    }\n\n    for (i = 0; i < 16; i++)\n        x->input[i] = PLUS(x->input[i], state[i]);\n\n    for (i = 0; i < len; i += 4) {\n        _private_tls_U32TO8_LITTLE(c + i, x->input[i/4]);\n    }\n}\n\nstatic inline int poly1305_generate_key(unsigned char *key256, unsigned char *nonce, unsigned int noncelen, unsigned char *poly_key, unsigned int counter) {\n    struct chacha_ctx ctx;\n    uint64_t ctr;\n    memset(&ctx, 0, sizeof(ctx));\n    chacha_keysetup(&ctx, key256, 256);\n    switch (noncelen) {\n        case 8:\n            ctr = counter;\n            chacha_ivsetup(&ctx, nonce, (unsigned char *)&ctr);\n            break;\n        case 12:\n            chacha_ivsetup_96bitnonce(&ctx, nonce, (unsigned char *)&counter);\n            break;\n        default:\n            return -1;\n    }\n    chacha20_block(&ctx, poly_key, POLY1305_KEYLEN);\n    return 0;\n}\n\n/* 17 + sizeof(size_t) + 14*sizeof(unsigned long) */\ntypedef struct poly1305_state_internal_t {\n    unsigned long r[5];\n    unsigned long h[5];\n    unsigned long pad[4];\n    size_t leftover;\n    unsigned char buffer[poly1305_block_size];\n    unsigned char final;\n} poly1305_state_internal_t;\n\n/* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */\nstatic unsigned long _private_tls_U8TO32(const unsigned char *p) {\n    return\n        (((unsigned long)(p[0] & 0xff)      ) |\n         ((unsigned long)(p[1] & 0xff) <<  8) |\n         ((unsigned long)(p[2] & 0xff) << 16) |\n         ((unsigned long)(p[3] & 0xff) << 24));\n}\n\n/* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */\nstatic void _private_tls_U32TO8(unsigned char *p, unsigned long v) {\n    p[0] = (v      ) & 0xff;\n    p[1] = (v >>  8) & 0xff;\n    p[2] = (v >> 16) & 0xff;\n    p[3] = (v >> 24) & 0xff;\n}\n\nvoid _private_tls_poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {\n    poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;\n\n    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */\n    st->r[0] = (_private_tls_U8TO32(&key[ 0])     ) & 0x3ffffff;\n    st->r[1] = (_private_tls_U8TO32(&key[ 3]) >> 2) & 0x3ffff03;\n    st->r[2] = (_private_tls_U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff;\n    st->r[3] = (_private_tls_U8TO32(&key[ 9]) >> 6) & 0x3f03fff;\n    st->r[4] = (_private_tls_U8TO32(&key[12]) >> 8) & 0x00fffff;\n\n    /* h = 0 */\n    st->h[0] = 0;\n    st->h[1] = 0;\n    st->h[2] = 0;\n    st->h[3] = 0;\n    st->h[4] = 0;\n\n    /* save pad for later */\n    st->pad[0] = _private_tls_U8TO32(&key[16]);\n    st->pad[1] = _private_tls_U8TO32(&key[20]);\n    st->pad[2] = _private_tls_U8TO32(&key[24]);\n    st->pad[3] = _private_tls_U8TO32(&key[28]);\n\n    st->leftover = 0;\n    st->final = 0;\n}\n\nstatic void _private_tls_poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) {\n#ifdef __MRC__\n/* MrC quits with a code generator error here at higher optimization levels. */\n#pragma options opt local\n#endif\n\n    const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */\n    unsigned long r0,r1,r2,r3,r4;\n    unsigned long s1,s2,s3,s4;\n    unsigned long h0,h1,h2,h3,h4;\n    unsigned long long d0,d1,d2,d3,d4;\n    unsigned long c;\n\n    r0 = st->r[0];\n    r1 = st->r[1];\n    r2 = st->r[2];\n    r3 = st->r[3];\n    r4 = st->r[4];\n\n    s1 = r1 * 5;\n    s2 = r2 * 5;\n    s3 = r3 * 5;\n    s4 = r4 * 5;\n\n    h0 = st->h[0];\n    h1 = st->h[1];\n    h2 = st->h[2];\n    h3 = st->h[3];\n    h4 = st->h[4];\n\n    while (bytes >= poly1305_block_size) {\n        /* h += m[i] */\n        h0 += (_private_tls_U8TO32(m+ 0)     ) & 0x3ffffff;\n        h1 += (_private_tls_U8TO32(m+ 3) >> 2) & 0x3ffffff;\n        h2 += (_private_tls_U8TO32(m+ 6) >> 4) & 0x3ffffff;\n        h3 += (_private_tls_U8TO32(m+ 9) >> 6) & 0x3ffffff;\n        h4 += (_private_tls_U8TO32(m+12) >> 8) | hibit;\n\n        /* h *= r */\n        d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);\n        d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);\n        d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);\n        d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);\n        d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);\n\n        /* (partial) h %= p */\n                      c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff;\n        d1 += c;      c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff;\n        d2 += c;      c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff;\n        d3 += c;      c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff;\n        d4 += c;      c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff;\n        h0 += c * 5;  c =                (h0 >> 26); h0 =                h0 & 0x3ffffff;\n        h1 += c;\n\n        m += poly1305_block_size;\n        bytes -= poly1305_block_size;\n    }\n\n    st->h[0] = h0;\n    st->h[1] = h1;\n    st->h[2] = h2;\n    st->h[3] = h3;\n    st->h[4] = h4;\n}\n\nvoid _private_tls_poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {\n    poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;\n    unsigned long h0,h1,h2,h3,h4,c;\n    unsigned long g0,g1,g2,g3,g4;\n    unsigned long long f;\n    unsigned long mask;\n\n    /* process the remaining block */\n    if (st->leftover) {\n        size_t i = st->leftover;\n        st->buffer[i++] = 1;\n        for (; i < poly1305_block_size; i++)\n            st->buffer[i] = 0;\n        st->final = 1;\n        _private_tls_poly1305_blocks(st, st->buffer, poly1305_block_size);\n    }\n\n    /* fully carry h */\n    h0 = st->h[0];\n    h1 = st->h[1];\n    h2 = st->h[2];\n    h3 = st->h[3];\n    h4 = st->h[4];\n\n                 c = h1 >> 26; h1 = h1 & 0x3ffffff;\n    h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;\n    h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;\n    h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;\n    h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;\n    h1 +=     c;\n\n    /* compute h + -p */\n    g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;\n    g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;\n    g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;\n    g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;\n    g4 = h4 + c - (1UL << 26);\n\n    /* select h if h < p, or h + -p if h >= p */\n    mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;\n    g0 &= mask;\n    g1 &= mask;\n    g2 &= mask;\n    g3 &= mask;\n    g4 &= mask;\n    mask = ~mask;\n    h0 = (h0 & mask) | g0;\n    h1 = (h1 & mask) | g1;\n    h2 = (h2 & mask) | g2;\n    h3 = (h3 & mask) | g3;\n    h4 = (h4 & mask) | g4;\n\n    /* h = h % (2^128) */\n    h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;\n    h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;\n    h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;\n    h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;\n\n    /* mac = (h + pad) % (2^128) */\n    f = (unsigned long long)h0 + st->pad[0]            ; h0 = (unsigned long)f;\n    f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f;\n    f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f;\n    f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f;\n\n    _private_tls_U32TO8(mac +  0, h0);\n    _private_tls_U32TO8(mac +  4, h1);\n    _private_tls_U32TO8(mac +  8, h2);\n    _private_tls_U32TO8(mac + 12, h3);\n\n    /* zero out the state */\n    st->h[0] = 0;\n    st->h[1] = 0;\n    st->h[2] = 0;\n    st->h[3] = 0;\n    st->h[4] = 0;\n    st->r[0] = 0;\n    st->r[1] = 0;\n    st->r[2] = 0;\n    st->r[3] = 0;\n    st->r[4] = 0;\n    st->pad[0] = 0;\n    st->pad[1] = 0;\n    st->pad[2] = 0;\n    st->pad[3] = 0;\n}\n\nvoid _private_tls_poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) {\n    poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;\n    size_t i;\n    /* handle leftover */\n    if (st->leftover) {\n        size_t want = (poly1305_block_size - st->leftover);\n        if (want > bytes)\n            want = bytes;\n        for (i = 0; i < want; i++)\n            st->buffer[st->leftover + i] = m[i];\n        bytes -= want;\n        m += want;\n        st->leftover += want;\n        if (st->leftover < poly1305_block_size)\n            return;\n        _private_tls_poly1305_blocks(st, st->buffer, poly1305_block_size);\n        st->leftover = 0;\n    }\n\n    /* process full blocks */\n    if (bytes >= poly1305_block_size) {\n        size_t want = (bytes & ~(poly1305_block_size - 1));\n        _private_tls_poly1305_blocks(st, m, want);\n        m += want;\n        bytes -= want;\n    }\n\n    /* store leftover */\n    if (bytes) {\n        for (i = 0; i < bytes; i++)\n            st->buffer[st->leftover + i] = m[i];\n        st->leftover += bytes;\n    }\n}\n\nint poly1305_verify(const unsigned char mac1[16], const unsigned char mac2[16]) {\n    size_t i;\n    unsigned int dif = 0;\n    for (i = 0; i < 16; i++)\n        dif |= (mac1[i] ^ mac2[i]);\n    dif = (dif - 1) >> ((sizeof(unsigned int) * 8) - 1);\n    return (dif & 1);\n}\n\nvoid chacha20_poly1305_key(struct chacha_ctx *ctx, unsigned char *poly1305_key) {\n    unsigned char key[32];\n    unsigned char nonce[12];\n    chacha_key(ctx, key);\n    chacha_nonce(ctx, nonce);\n    poly1305_generate_key(key, nonce, sizeof(nonce), poly1305_key, 0);\n}\n\n/* many of these functions embed declarations later in the function.\n   egcs doesn't like that. */\n\nint chacha20_poly1305_aead(struct chacha_ctx *ctx,  unsigned char *pt, unsigned int len, unsigned char *aad, unsigned int aad_len, unsigned char *poly_key, unsigned char *out) {\n    int rem;\n    poly1305_context aead_ctx;\n    unsigned int counter = 1;\n    unsigned char trail[16];\n    static unsigned char zeropad[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n    if (aad_len > POLY1305_MAX_AAD)\n        return -1;\n\n    chacha_ivsetup_96bitnonce(ctx, NULL, (unsigned char *)&counter);\n    chacha_encrypt_bytes(ctx, pt, out, len);\n    \n    _private_tls_poly1305_init(&aead_ctx, poly_key);\n    _private_tls_poly1305_update(&aead_ctx, aad, aad_len);\n    rem = aad_len % 16;\n    if (rem)\n        _private_tls_poly1305_update(&aead_ctx, zeropad, 16 - rem);\n    _private_tls_poly1305_update(&aead_ctx, out, len);\n    rem = len % 16;\n    if (rem)\n        _private_tls_poly1305_update(&aead_ctx, zeropad, 16 - rem);\n\n    _private_tls_U32TO8(trail, aad_len);\n    *(int *)(trail + 4) = 0;\n    _private_tls_U32TO8(trail + 8, len);\n    *(int *)(trail + 12) = 0;\n\n    _private_tls_poly1305_update(&aead_ctx, trail, 16);\n    _private_tls_poly1305_finish(&aead_ctx, out + len);\n    \n    return len + POLY1305_TAGLEN;\n}\n#endif\n#endif\n\ntypedef enum {\n    KEA_dhe_dss,\n    KEA_dhe_rsa,\n    KEA_dh_anon,\n    KEA_rsa,\n    KEA_dh_dss,\n    KEA_dh_rsa,\n    KEA_ec_diffie_hellman\n} KeyExchangeAlgorithm;\n\ntypedef enum {\n    rsa_sign = 1,\n    dss_sign = 2,\n    rsa_fixed_dh = 3,\n    dss_fixed_dh = 4,\n    rsa_ephemeral_dh_RESERVED = 5,\n    dss_ephemeral_dh_RESERVED = 6,\n    fortezza_dms_RESERVED = 20,\n    ecdsa_sign = 64,\n    rsa_fixed_ecdh = 65,\n    ecdsa_fixed_ecdh = 66\n} TLSClientCertificateType;\n\ntypedef enum {\n    none = 0,\n    md5 = 1,\n    sha1 = 2,\n    sha224 = 3,\n    sha256 = 4,\n    sha384 = 5,\n    sha512 = 6,\n    _md5_sha1 = 255\n} TLSHashAlgorithm;\n\ntypedef enum {\n    anonymous = 0,\n    rsa = 1,\n    dsa = 2,\n    ecdsa = 3,\n    pss_rsae = 8\n} TLSSignatureAlgorithm;\n\nstruct _private_OID_chain {\n    void *top;\n    unsigned char *oid;\n};\n\nstruct TLSCertificate {\n    unsigned short version;\n    unsigned int algorithm;\n    unsigned int key_algorithm;\n    unsigned int ec_algorithm;\n    unsigned char *exponent;\n    unsigned int exponent_len;\n    unsigned char *pk;\n    unsigned int pk_len;\n    unsigned char *priv;\n    unsigned int priv_len;\n    unsigned char *issuer_country;\n    unsigned char *issuer_state;\n    unsigned char *issuer_location;\n    unsigned char *issuer_entity;\n    unsigned char *issuer_subject;\n    unsigned char *not_before;\n    unsigned char *not_after;\n    unsigned char *country;\n    unsigned char *state;\n    unsigned char *location;\n    unsigned char *entity;\n    unsigned char *subject;\n    unsigned char **san;\n    unsigned short san_length;\n    unsigned char *ocsp;\n    unsigned char *serial_number;\n    unsigned int serial_len;\n    unsigned char *sign_key;\n    unsigned int sign_len;\n    unsigned char *fingerprint;\n    unsigned char *der_bytes;\n    unsigned int der_len;\n    unsigned char *bytes;\n    unsigned int len;\n};\n\ntypedef struct {\n    union {\n        symmetric_CBC aes_local;\n        gcm_state aes_gcm_local;\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        chacha_ctx chacha_local;\n#endif\n    } ctx_local;\n    union {\n        symmetric_CBC aes_remote;\n        gcm_state aes_gcm_remote;\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        chacha_ctx chacha_remote;\n#endif\n    } ctx_remote;\n    union {\n        unsigned char local_mac[TLS_MAX_MAC_SIZE];\n        unsigned char local_aead_iv[TLS_AES_GCM_IV_LENGTH];\n#ifdef WITH_TLS_13\n        unsigned char local_iv[TLS_13_AES_GCM_IV_LENGTH];\n#endif\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        unsigned char local_nonce[TLS_CHACHA20_IV_LENGTH];\n#endif\n    } ctx_local_mac;\n    union {\n        unsigned char remote_aead_iv[TLS_AES_GCM_IV_LENGTH];\n        unsigned char remote_mac[TLS_MAX_MAC_SIZE];\n#ifdef WITH_TLS_13\n        unsigned char remote_iv[TLS_13_AES_GCM_IV_LENGTH];\n#endif\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        unsigned char remote_nonce[TLS_CHACHA20_IV_LENGTH];\n#endif\n    } ctx_remote_mac;\n    unsigned char created;\n} TLSCipher;\n\ntypedef struct {\n    hash_state hash32;\n    hash_state hash48;\n#ifdef TLS_LEGACY_SUPPORT\n    hash_state hash2;\n#endif\n    unsigned char created;\n} TLSHash;\n\n#ifdef TLS_FORWARD_SECRECY\n#define mp_init(a)                           ltc_mp.init(a)\n#define mp_init_multi                        ltc_init_multi\n#define mp_clear(a)                          ltc_mp.deinit(a)\n#define mp_clear_multi                       ltc_deinit_multi\n#define mp_count_bits(a)                     ltc_mp.count_bits(a)\n#define mp_read_radix(a, b, c)               ltc_mp.read_radix(a, b, c)\n#define mp_unsigned_bin_size(a)              ltc_mp.unsigned_size(a)\n#define mp_to_unsigned_bin(a, b)             ltc_mp.unsigned_write(a, b)\n#define mp_read_unsigned_bin(a, b, c)        ltc_mp.unsigned_read(a, b, c)\n#define mp_exptmod(a, b, c, d)               ltc_mp.exptmod(a, b, c, d)\n#define mp_add(a, b, c)                      ltc_mp.add(a, b, c)\n#define mp_mul(a, b, c)                      ltc_mp.mul(a, b, c)\n#define mp_cmp(a, b)                         ltc_mp.compare(a, b)\n#define mp_cmp_d(a, b)                       ltc_mp.compare_d(a, b)\n#define mp_sqr(a, b)                         ltc_mp.sqr(a, b)\n#define mp_mod(a, b, c)                      ltc_mp.mpdiv(a, b, NULL, c)\n#define mp_sub(a, b, c)                      ltc_mp.sub(a, b, c)\n#define mp_set(a, b)                         ltc_mp.set_int(a, b)\n\ntypedef struct {\n    int iana;\n    void *x;\n    void *y;\n    void *p;\n    void *g;\n} DHKey;\n\n#ifdef WITH_TLS_13\nstatic DHKey ffdhe2048 = {\n    0x0100,\n    NULL,\n    NULL,\n    (void *)\"FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B423861285C97FFFFFFFFFFFFFFFF\",\n    (void *)\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002\"\n};\n\nstatic DHKey ffdhe3072 = {\n    0x0101,\n    NULL,\n    NULL,\n    (void *)\"FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF\",\n    (void *)\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002\"\n};\n\nstatic DHKey ffdhe4096 = {\n    0x0102,\n    NULL,\n    NULL,\n    (void *)\"FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6AFFFFFFFFFFFFFFFF\",\n    (void *)\"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002\"\n};\n\nstatic DHKey ffdhe6144 = {\n    0x0103,\n    NULL,\n    NULL,\n    (void *)\"FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF\",\n    (void *)\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002\"\n};\n\nstatic DHKey ffdhe8192 = {\n    0x0104,\n    NULL,\n    NULL,\n    (void *)\"FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C8381E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665CB2C0F1CC01BD70229388839D2AF05E454504AC78B7582822846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA4571EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88CD68C8BB7C5C6424CFFFFFFFFFFFFFFFF\",\n    (void *)\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002\"\n};\n#endif\n\nstruct ECCCurveParameters {\n    int size;\n    int iana;\n    const char *name;\n    const char *P;\n    const char *A;\n    const char *B;\n    const char *Gx;\n    const char *Gy;\n    const char *order;\n    ltc_ecc_set_type dp;\n};\n\nstatic struct ECCCurveParameters secp192r1 = {\n    24,\n    19,\n    \"secp192r1\",\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF\", /* P */\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC\", /* A */\n    \"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1\", /* B */\n    \"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012\", /* Gx */\n    \"07192B95FFC8DA78631011ED6B24CDD573F977A11E794811\", /* Gy */\n    \"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831\"  /* order (n) */\n};\n\n\nstatic struct ECCCurveParameters secp224r1 = {\n    28,\n    21,\n    \"secp224r1\",\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001\", /* P */\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE\", /* A */\n    \"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4\", /* B */\n    \"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21\", /* Gx */\n    \"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34\", /* Gy */\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D\"  /* order (n) */\n};\n\nstatic struct ECCCurveParameters secp224k1 = {\n    28,\n    20,\n    \"secp224k1\",\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D\", /* P */\n    \"00000000000000000000000000000000000000000000000000000000\", /* A */\n    \"00000000000000000000000000000000000000000000000000000005\", /* B */\n    \"A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C\", /* Gx */\n    \"7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5\", /* Gy */\n    \"0000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7\"  /* order (n) */\n};\n\nstatic struct ECCCurveParameters secp256r1 = {\n    32,\n    23,\n    \"secp256r1\",\n    \"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF\", /* P */\n    \"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC\", /* A */\n    \"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B\", /* B */\n    \"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296\", /* Gx */\n    \"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5\", /* Gy */\n    \"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551\"  /* order (n) */\n};\n\nstatic struct ECCCurveParameters secp256k1 = {\n    32,\n    22,\n    \"secp256k1\",\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F\", /* P */\n    \"0000000000000000000000000000000000000000000000000000000000000000\", /* A */\n    \"0000000000000000000000000000000000000000000000000000000000000007\", /* B */\n    \"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798\", /* Gx */\n    \"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8\", /* Gy */\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141\"  /* order (n) */\n};\n\nstatic struct ECCCurveParameters secp384r1 = {\n    48,\n    24,\n    \"secp384r1\",\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF\", /* P */\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC\", /* A */\n    \"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF\", /* B */\n    \"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7\", /* Gx */\n    \"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F\", /* Gy */\n    \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973\"  /* order (n) */\n};\n\nstatic struct ECCCurveParameters secp521r1 = {\n    66,\n    25,\n    \"secp521r1\",\n    \"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\", /* P */\n    \"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC\", /* A */\n    \"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00\", /* B */\n    \"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66\", /* Gx */\n    \"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650\", /* Gy */\n    \"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409\"  /* order (n) */\n};\n\n#ifdef TLS_CURVE25519\n/* XXX: dummy */\nstatic struct ECCCurveParameters x25519 = {\n    32,\n    29,\n    \"x25519\",\n    \"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED\", /* P */\n    \"0000000000000000000000000000000000000000000000000000000000076D06\", /* A */\n    \"0000000000000000000000000000000000000000000000000000000000000000\", /* B */\n    \"0000000000000000000000000000000000000000000000000000000000000009\", /* Gx */\n    \"20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9\", /* Gy */\n    \"1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED\"  /* order (n) */\n};\n#endif\n\nstatic struct ECCCurveParameters * const default_curve = &secp256r1;\n\nvoid init_curve(struct ECCCurveParameters *curve) {\n    curve->dp.size = curve->size;\n    curve->dp.name = (char *)curve->name;\n    curve->dp.B = (char *)curve->B;\n    curve->dp.prime = (char *)curve->P;\n    curve->dp.Gx = (char *)curve->Gx;\n    curve->dp.Gy = (char *)curve->Gy;\n    curve->dp.order = (char *)curve->order;\n}\n\nvoid init_curves() {\n    init_curve(&secp192r1);\n    init_curve(&secp224r1);\n    init_curve(&secp224k1);\n    init_curve(&secp256r1);\n    init_curve(&secp256k1);\n    init_curve(&secp384r1);\n    init_curve(&secp521r1);\n}\n#endif\n\nstruct TLSContext {\n    unsigned char remote_random[TLS_CLIENT_RANDOM_SIZE];\n    unsigned char local_random[TLS_SERVER_RANDOM_SIZE];\n    unsigned char session[TLS_MAX_SESSION_ID];\n    unsigned char session_size;\n    unsigned short cipher;\n    unsigned short version;\n    unsigned char is_server;\n    struct TLSCertificate **certificates;\n    struct TLSCertificate *private_key;\n#ifdef TLS_ECDSA_SUPPORTED\n    struct TLSCertificate *ec_private_key;\n#endif\n#ifdef TLS_FORWARD_SECRECY\n    DHKey *dhe;\n    ecc_key *ecc_dhe;\n    char *default_dhe_p;\n    char *default_dhe_g;\n    const struct ECCCurveParameters *curve;\n#endif\n    struct TLSCertificate **client_certificates;\n    unsigned int certificates_count;\n    unsigned int client_certificates_count;\n    unsigned char *master_key;\n    unsigned int master_key_len;\n    unsigned char *premaster_key;\n    unsigned int premaster_key_len;\n    unsigned char cipher_spec_set;\n    TLSCipher crypto;\n    TLSHash *handshake_hash;\n    \n    unsigned char *message_buffer;\n    unsigned int message_buffer_len;\n    uint64_t remote_sequence_number;\n    uint64_t local_sequence_number;\n    \n    unsigned char connection_status;\n    unsigned char critical_error;\n    unsigned char error_code;\n    \n    unsigned char *tls_buffer;\n    unsigned int tls_buffer_len;\n    \n    unsigned char *application_buffer;\n    unsigned int application_buffer_len;\n    unsigned char is_child;\n    unsigned char exportable;\n    unsigned char *exportable_keys;\n    unsigned char exportable_size;\n    char *sni;\n    unsigned char request_client_certificate;\n    unsigned char dtls;\n    unsigned short dtls_epoch_local;\n    unsigned short dtls_epoch_remote;\n    unsigned char *dtls_cookie;\n    unsigned char dtls_cookie_len;\n    unsigned char dtls_seq;\n    unsigned char *cached_handshake;\n    unsigned int cached_handshake_len;\n    unsigned char client_verified;\n    /* handshake messages flags */\n    unsigned char hs_messages[11];\n    void *user_data;\n    struct TLSCertificate **root_certificates;\n    unsigned int root_count;\n#ifdef TLS_ACCEPT_SECURE_RENEGOTIATION\n    unsigned char *verify_data;\n    unsigned char verify_len;\n#endif\n#ifdef WITH_TLS_13\n    unsigned char *finished_key;\n    unsigned char *remote_finished_key;\n    unsigned char *server_finished_hash;\n#endif\n#ifdef TLS_CURVE25519\n    unsigned char *client_secret;\n#endif\n    char **alpn;\n    unsigned char alpn_count;\n    char *negotiated_alpn;\n    unsigned int sleep_until;\n    unsigned short tls13_version;\n#ifdef TLS_12_FALSE_START\n    unsigned char false_start;\n#endif\n};\n\nstruct TLSPacket {\n    unsigned char *buf;\n    unsigned int len;\n    unsigned int size;\n    unsigned char broken;\n    struct TLSContext *context;\n};\n\n#ifdef SSL_COMPATIBLE_INTERFACE\n\ntypedef int (*SOCKET_RECV_CALLBACK)(int socket, void *buffer, size_t length, int flags);\ntypedef int (*SOCKET_SEND_CALLBACK)(int socket, const void *buffer, size_t length, int flags);\n\n#ifndef _WIN32\n#include <sys/socket.h>\n#endif\n#endif\n\nstatic const unsigned int version_id[] = {1, 1, 1, 0};\nstatic const unsigned int pk_id[] = {1, 1, 7, 0};\nstatic const unsigned int serial_id[] = {1, 1, 2, 1, 0};\nstatic const unsigned int issurer_id[] = {1, 1, 4, 0};\nstatic const unsigned int owner_id[] = {1, 1, 6, 0};\nstatic const unsigned int validity_id[] = {1, 1, 5, 0};\nstatic const unsigned int algorithm_id[] = {1, 1, 3, 0};\nstatic const unsigned int sign_id[] = {1, 3, 2, 1, 0};\nstatic const unsigned int priv_id[] = {1, 4, 0};\nstatic const unsigned int priv_der_id[] = {1, 3, 1, 0};\nstatic const unsigned int ecc_priv_id[] = {1, 2, 0};\n\nstatic const unsigned char country_oid[] = {0x55, 0x04, 0x06, 0x00};\nstatic const unsigned char state_oid[] = {0x55, 0x04, 0x08, 0x00};\nstatic const unsigned char location_oid[] = {0x55, 0x04, 0x07, 0x00};\nstatic const unsigned char entity_oid[] = {0x55, 0x04, 0x0A, 0x00};\nstatic const unsigned char subject_oid[] = {0x55, 0x04, 0x03, 0x00};\nstatic const unsigned char san_oid[] = {0x55, 0x1D, 0x11, 0x00};\nstatic const unsigned char ocsp_oid[] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x00};\n\nstatic const unsigned char TLS_RSA_SIGN_RSA_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x00};\nstatic const unsigned char TLS_RSA_SIGN_MD5_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x00};\nstatic const unsigned char TLS_RSA_SIGN_SHA1_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x00};\nstatic const unsigned char TLS_RSA_SIGN_SHA256_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x00};\nstatic const unsigned char TLS_RSA_SIGN_SHA384_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C, 0x00};\nstatic const unsigned char TLS_RSA_SIGN_SHA512_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D, 0x00};\n\n#if(0)\nstatic const unsigned char TLS_ECDSA_SIGN_SHA1_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01, 0x05, 0x00, 0x00};\nstatic const unsigned char TLS_ECDSA_SIGN_SHA224_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01, 0x05, 0x00, 0x00};\nstatic const unsigned char TLS_ECDSA_SIGN_SHA384_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x05, 0x00, 0x00};\nstatic const unsigned char TLS_ECDSA_SIGN_SHA512_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04, 0x05, 0x00, 0x00};\n#endif\nstatic const unsigned char TLS_ECDSA_SIGN_SHA256_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x00};\n\nstatic const unsigned char TLS_EC_PUBLIC_KEY_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x00};\n\nstatic const unsigned char TLS_EC_prime192v1_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x01, 0x00};\nstatic const unsigned char TLS_EC_prime192v2_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x02, 0x00};\nstatic const unsigned char TLS_EC_prime192v3_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x03, 0x00};\nstatic const unsigned char TLS_EC_prime239v1_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x04, 0x00};\nstatic const unsigned char TLS_EC_prime239v2_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x05, 0x00};\nstatic const unsigned char TLS_EC_prime239v3_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x06, 0x00};\nstatic const unsigned char TLS_EC_prime256v1_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x00};\n\n#define TLS_EC_secp256r1_OID    TLS_EC_prime256v1_OID\nstatic const unsigned char TLS_EC_secp224r1_OID[] = {0x2B, 0x81, 0x04, 0x00, 0x21, 0x00};\nstatic const unsigned char TLS_EC_secp384r1_OID[] = {0x2B, 0x81, 0x04, 0x00, 0x22, 0x00};\nstatic const unsigned char TLS_EC_secp521r1_OID[] = {0x2B, 0x81, 0x04, 0x00, 0x23, 0x00};\n\nstruct TLSCertificate *asn1_parse(struct TLSContext *context, const unsigned char *buffer, unsigned int size, int client_cert);\nint _private_tls_update_hash(struct TLSContext *context, const unsigned char *in, unsigned int len);\nstruct TLSPacket *tls_build_finished(struct TLSContext *context);\nunsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *context, const unsigned char *buf, int buf_len, const unsigned char *buf2, int buf_len2, unsigned char *out, unsigned int outlen, uint64_t remote_sequence_number);\nint tls_random(unsigned char *key, int len);\nvoid tls_destroy_packet(struct TLSPacket *packet);\nstruct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrade);\nstruct TLSPacket *tls_build_certificate(struct TLSContext *context);\nstruct TLSPacket *tls_build_done(struct TLSContext *context);\nstruct TLSPacket *tls_build_alert(struct TLSContext *context, char critical, unsigned char code);\nstruct TLSPacket *tls_build_change_cipher_spec(struct TLSContext *context);\nstruct TLSPacket *tls_build_verify_request(struct TLSContext *context);\nint _private_tls_crypto_create(struct TLSContext *context, int key_length, unsigned char *localkey, unsigned char *localiv, unsigned char *remotekey, unsigned char *remoteiv);\nint _private_tls_get_hash(struct TLSContext *context, unsigned char *hout);\nint _private_tls_done_hash(struct TLSContext *context, unsigned char *hout);\nint _private_tls_get_hash_idx(struct TLSContext *context);\nint _private_tls_build_random(struct TLSPacket *packet);\nunsigned int _private_tls_mac_length(struct TLSContext *context);\nvoid _private_dtls_handshake_data(struct TLSContext *context, struct TLSPacket *packet, unsigned int dataframe);\n#ifdef TLS_FORWARD_SECRECY\nvoid _private_tls_dhe_free(struct TLSContext *context);\nvoid _private_tls_ecc_dhe_free(struct TLSContext *context);\nvoid _private_tls_dh_clear_key(DHKey *key);\n#endif\n\n#ifdef WITH_TLS_13\nstruct TLSPacket *tls_build_encrypted_extensions(struct TLSContext *context);\nstruct TLSPacket *tls_build_certificate_verify(struct TLSContext *context);\n#endif\n\n/* dtls base secret */\nstatic unsigned char dtls_secret[32];\n\nstatic unsigned char dependecies_loaded = 0;\n/* not supported */\n/* static unsigned char TLS_DSA_SIGN_SHA1_OID[] = {0x2A, 0x86, 0x52, 0xCE, 0x38, 0x04, 0x03, 0x00}; */\n\n/* base64 stuff */\nstatic const char cd64[] = \"|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\\\]^_`abcdefghijklmnopq\";\n\nvoid _private_b64_decodeblock(unsigned char in[4], unsigned char out[3]) {\n    out[0] = (unsigned char )(in[0] << 2 | in[1] >> 4);\n    out[1] = (unsigned char )(in[1] << 4 | in[2] >> 2);\n    out[2] = (unsigned char )(((in[2] << 6) & 0xc0) | in[3]);\n}\n\nint _private_b64_decode(const char *in_buffer, int in_buffer_size, unsigned char *out_buffer) {\n    unsigned char in[4], out[3], v;\n    int           i, len;\n    \n    const char *ptr     = in_buffer;\n    char *out_ptr = (char *)out_buffer;\n    \n    while (ptr <= in_buffer + in_buffer_size) {\n        for (len = 0, i = 0; i < 4 && (ptr <= in_buffer + in_buffer_size); i++) {\n            v = 0;\n            while ((ptr <= in_buffer + in_buffer_size) && v == 0) {\n                v = (unsigned char)ptr[0];\n                ptr++;\n                v = (unsigned char)((v < 43 || v > 122) ? 0 : cd64[v - 43]);\n                if (v)\n                    v = (unsigned char)((v == '$') ? 0 : v - 61);\n            }\n            if (ptr <= in_buffer + in_buffer_size) {\n                len++;\n                if (v)\n                    in[i] = (unsigned char)(v - 1);\n            } else {\n                in[i] = 0;\n            }\n        }\n        if (len) {\n            _private_b64_decodeblock(in, out);\n            for (i = 0; i < len - 1; i++) {\n                out_ptr[0] = out[i];\n                out_ptr++;\n            }\n        }\n    }\n    return (int)((intptr_t)out_ptr - (intptr_t)out_buffer);\n}\n\nvoid dtls_reset_cookie_secret() {\n    tls_random(dtls_secret, sizeof(dtls_secret));\n}\n\nvoid tls_init() {\n    if (dependecies_loaded)\n        return;\n    DEBUG_PRINT0(\"Initializing dependencies\\n\");\n    dependecies_loaded = 1;\n#ifdef LTM_DESC\n    ltc_mp = ltm_desc;\n#else\n#ifdef TFM_DESC\n    ltc_mp = tfm_desc;\n#else\n#ifdef GMP_DESC\n    ltc_mp = gmp_desc;\n#endif\n#endif\n#endif\n    register_prng(&sprng_desc);\n    register_hash(&sha256_desc);\n    register_hash(&sha1_desc);\n    register_hash(&sha384_desc);\n    register_hash(&sha512_desc);\n    register_hash(&md5_desc);\n    register_cipher(&aes_desc);\n#ifdef TLS_FORWARD_SECRECY\n    init_curves();\n#endif\n    dtls_reset_cookie_secret();\n}\n\n#ifdef TLS_FORWARD_SECRECY\nint _private_tls_dh_shared_secret(DHKey *private_key, DHKey *public_key, unsigned char *out, unsigned long *outlen) {\n    void *tmp;\n    unsigned long x;\n    int err;\n    \n    if ((!private_key) || (!public_key) || (!out) || (!outlen))\n        return TLS_GENERIC_ERROR;\n    \n    /* compute y^x mod p */\n    if ((err = mp_init(&tmp)) != CRYPT_OK)\n        return err;\n    \n    if ((err = mp_exptmod(public_key->y, private_key->x, private_key->p, tmp)) != CRYPT_OK) {\n        mp_clear(tmp);\n        return err;\n    }\n    \n    x = (unsigned long)mp_unsigned_bin_size(tmp);\n    if (*outlen < x) {\n        err = CRYPT_BUFFER_OVERFLOW;\n        mp_clear(tmp);\n        return err;\n    }\n    \n    if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) {\n        mp_clear(tmp);\n        return err;\n    }\n    *outlen = x;\n    mp_clear(tmp);\n    return 0;\n}\n\nunsigned char *_private_tls_decrypt_dhe(struct TLSContext *context, const unsigned char *buffer, unsigned int len, unsigned int *size, int clear_key) {\n    unsigned long out_size;\n    void *Yc = NULL;\n    unsigned char *out;\n    DHKey client_key;\n    int err;\n    \n    *size = 0;\n    if ((!len) || (!context) || (!context->dhe)) {\n        DEBUG_PRINT0(\"No private DHE key set\\n\");\n        return NULL;\n    }\n    \n    out_size = len;\n    \n    if (mp_init(&Yc)) {\n        DEBUG_PRINT0(\"ERROR CREATING Yc\\n\");\n        return NULL;\n    }\n    if (mp_read_unsigned_bin(Yc, (unsigned char *)buffer, len)) {\n        DEBUG_PRINT0(\"ERROR LOADING DHE Yc\\n\");\n        mp_clear(Yc);\n        return NULL;\n    }\n\n    out = (unsigned char *)TLS_MALLOC(len);\n    memset(&client_key, 0, sizeof(DHKey));\n    \n    client_key.p = context->dhe->p;\n    client_key.g = context->dhe->g;\n    client_key.y = Yc;\n    err = _private_tls_dh_shared_secret(context->dhe, &client_key, out, &out_size);\n    /* don't delete p and g */\n    client_key.p = NULL;\n    client_key.g = NULL;\n    _private_tls_dh_clear_key(&client_key);\n    /* not needing the dhe key anymore */\n    if (clear_key)\n        _private_tls_dhe_free(context);\n    if (err) {\n        DEBUG_PRINT1(\"DHE DECRYPT ERROR %i\\n\", err);\n        TLS_FREE(out);\n        return NULL;\n    }\n    DEBUG_PRINT1(\"OUT_SIZE: %lu\\n\", out_size);\n    DEBUG_DUMP_HEX_LABEL(\"DHE\", out, out_size);\n    *size = (unsigned int)out_size;\n    return out;\n}\n\nunsigned char *_private_tls_decrypt_ecc_dhe(struct TLSContext *context, const unsigned char *buffer, unsigned int len, unsigned int *size, int clear_key) {\n    ltc_ecc_set_type *dp;\n    ecc_key client_key;\n    unsigned char *out;\n    unsigned long out_size;\n    int err;\n    const struct ECCCurveParameters *curve;\n\n    *size = 0;\n    if ((!len) || (!context) || (!context->ecc_dhe)) {\n        DEBUG_PRINT0(\"No private ECC DHE key set\\n\");\n        return NULL;\n    }\n    \n    if (context->curve)\n        curve = context->curve;\n    else\n        curve = default_curve;\n    \n    dp = (ltc_ecc_set_type *)&curve->dp;\n    \n    memset(&client_key, 0, sizeof(client_key));\n    if (ecc_ansi_x963_import_ex(buffer, len, &client_key, dp)) {\n        DEBUG_PRINT0(\"Error importing ECC DHE key\\n\");\n        return NULL;\n    }\n    out = (unsigned char *)TLS_MALLOC(len);\n    out_size = len;\n    \n    err = ecc_shared_secret(context->ecc_dhe, &client_key, out, &out_size);\n    ecc_free(&client_key);\n    if (clear_key)\n        _private_tls_ecc_dhe_free(context);\n    if (err) {\n        DEBUG_PRINT1(\"ECC DHE DECRYPT ERROR %i\\n\", err);\n        TLS_FREE(out);\n        return NULL;\n    }\n    DEBUG_PRINT1(\"OUT_SIZE: %lu\\n\", out_size);\n    DEBUG_DUMP_HEX_LABEL(\"ECC DHE\", out, out_size);\n    *size = (unsigned int)out_size;\n    return out;\n}\n#endif\n\nunsigned char *_private_tls_decrypt_rsa(struct TLSContext *context, const unsigned char *buffer, unsigned int len, unsigned int *size) {\n    rsa_key key;\n    int err;\n    unsigned char *out;\n    unsigned long out_size;\n    int res = 0;\n\n    *size = 0;\n    if ((!len) || (!context) || (!context->private_key) || (!context->private_key->der_bytes) || (!context->private_key->der_len)) {\n        DEBUG_PRINT0(\"No private key set\\n\");\n        return NULL;\n    }\n    tls_init();\n    err = rsa_import(context->private_key->der_bytes, context->private_key->der_len, &key);\n    \n    if (err) {\n        DEBUG_PRINT1(\"Error importing RSA key (code: %i)\\n\", err);\n        return NULL;\n    }\n    out = (unsigned char *)TLS_MALLOC(len);\n    out_size = len;\n\n    err = rsa_decrypt_key_ex(buffer, len, out, &out_size, NULL, 0, -1, LTC_PKCS_1_V1_5, &res, &key);\n    rsa_free(&key);\n\n    if ((err) || (out_size != 48) || (ntohs(*(unsigned short *)out) != context->version)) {\n        /* generate a random secret and continue (ROBOT fix), silently ignore and generate a random secret */\n        out_size = 48;\n        tls_random(out, out_size);\n        *(unsigned short *)out = htons(context->version);\n    }\n    *size = (unsigned int)out_size;\n    return out;\n}\n\nunsigned char *_private_tls_encrypt_rsa(struct TLSContext *context, const unsigned char *buffer, unsigned int len, unsigned int *size) {\n    rsa_key key;\n    int err;\n    unsigned long out_size = TLS_MAX_RSA_KEY;\n    unsigned char *out;\n    int hash_idx;\n    int prng_idx;\n\n    *size = 0;\n    if ((!len) || (!context) || (!context->certificates) || (!context->certificates_count) || (!context->certificates[0]) ||\n        (!context->certificates[0]->der_bytes) || (!context->certificates[0]->der_len)) {\n        DEBUG_PRINT0(\"No certificate set\\n\");\n        return NULL;\n    }\n    tls_init();\n    err = rsa_import(context->certificates[0]->der_bytes, context->certificates[0]->der_len, &key);\n    \n    if (err) {\n        DEBUG_PRINT1(\"Error importing RSA certificate (code: %i)\\n\", err);\n        return NULL;\n    }\n    out = (unsigned char *)TLS_MALLOC(out_size);\n    hash_idx = find_hash(\"sha256\");\n    prng_idx = find_prng(\"sprng\");\n    err = rsa_encrypt_key_ex(buffer, len, out, &out_size, (unsigned char *)\"Concept\", 7, NULL, prng_idx, hash_idx, LTC_PKCS_1_V1_5, &key);\n    rsa_free(&key);\n    if ((err) || (!out_size)) {\n        TLS_FREE(out);\n        return NULL;\n    }\n    *size = (unsigned int)out_size;\n    return out;\n}\n\n#ifdef TLS_LEGACY_SUPPORT\nint _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long siglen, unsigned char *hash, unsigned long hashlen, int *stat, rsa_key *key) {\n    unsigned long modulus_bitlen, modulus_bytelen, x;\n    int           err;\n    unsigned char *tmpbuf = NULL;\n    unsigned long out_len = siglen;\n    unsigned char *out;\n    int decoded = 0;\n    \n    if ((hash == NULL) || (sig == NULL) || (stat == NULL) || (key == NULL) || (!siglen) || (!hashlen))\n        return TLS_GENERIC_ERROR;\n    \n    *stat = 0;\n    \n    modulus_bitlen = mp_count_bits((key->N));\n    \n    modulus_bytelen = mp_unsigned_bin_size((key->N));\n    if (modulus_bytelen != siglen)\n        return TLS_GENERIC_ERROR;\n    \n    tmpbuf = (unsigned char *)TLS_MALLOC(siglen);\n    if (!tmpbuf)\n        return TLS_GENERIC_ERROR;\n    \n    x = siglen;\n    if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {\n        TLS_FREE(tmpbuf);\n        return err;\n    }\n    \n    if (x != siglen) {\n        TLS_FREE(tmpbuf);\n        return CRYPT_INVALID_PACKET;\n    }\n\n    out = (unsigned char *)TLS_MALLOC(siglen);\n    if (!out) {\n        TLS_FREE(tmpbuf);\n        return TLS_GENERIC_ERROR;\n    }\n    \n    err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &out_len, &decoded);\n    if (decoded) {\n        if (out_len == hashlen) {\n            if (!memcmp(out, hash, hashlen))\n                *stat = 1;\n        }\n    }\n    \n    TLS_FREE(tmpbuf);\n    TLS_FREE(out);\n    return err;\n}\n#endif\n\nint _private_tls_verify_rsa(struct TLSContext *context, unsigned int hash_type, const unsigned char *buffer, unsigned int len, const unsigned char *message, unsigned int message_len, int force_pss) {\n    rsa_key key;\n    int err;\n    int hash_idx = -1;\n    unsigned char hash[TLS_MAX_HASH_LEN];\n    unsigned int hash_len = 0;\n    hash_state state;\n    int rsa_stat = 0;\n    \n    tls_init();\n    if (context->is_server) {\n        if ((!len) || (!context->client_certificates) || (!context->client_certificates_count) || (!context->client_certificates[0]) ||\n            (!context->client_certificates[0]->der_bytes) || (!context->client_certificates[0]->der_len)) {\n            DEBUG_PRINT0(\"No client certificate set\\n\");\n            return TLS_GENERIC_ERROR;\n        }\n        err = rsa_import(context->client_certificates[0]->der_bytes, context->client_certificates[0]->der_len, &key);\n    } else {\n        if ((!len) || (!context->certificates) || (!context->certificates_count) || (!context->certificates[0]) ||\n            (!context->certificates[0]->der_bytes) || (!context->certificates[0]->der_len)) {\n            DEBUG_PRINT0(\"No server certificate set\\n\");\n            return TLS_GENERIC_ERROR;\n        }\n        err = rsa_import(context->certificates[0]->der_bytes, context->certificates[0]->der_len, &key);\n    }\n    if (err) {\n        DEBUG_PRINT1(\"Error importing RSA certificate (code: %i)\\n\", err);\n        return TLS_GENERIC_ERROR;\n    }\n    switch (hash_type) {\n        case md5:\n            hash_idx = find_hash(\"md5\");\n            err = md5_init(&state);\n            TLS_ERROR(err, break);\n            err = md5_process(&state, message, message_len);\n            TLS_ERROR(err, break);\n            err = md5_done(&state, hash);\n            TLS_ERROR(err, break);\n            hash_len = 16;\n            break;\n        case sha1:\n            hash_idx = find_hash(\"sha1\");\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 20;\n            break;\n        case sha256:\n            hash_idx = find_hash(\"sha256\");\n            err = sha256_init(&state);\n            TLS_ERROR(err, break)\n            err = sha256_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha256_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 32;\n            break;\n        case sha384:\n            hash_idx = find_hash(\"sha384\");\n            err = sha384_init(&state);\n            TLS_ERROR(err, break)\n            err = sha384_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha384_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 48;\n            break;\n        case sha512:\n            hash_idx = find_hash(\"sha512\");\n            err = sha512_init(&state);\n            TLS_ERROR(err, break)\n            err = sha512_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha512_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 64;\n            break;\n#ifdef TLS_LEGACY_SUPPORT\n        case _md5_sha1:\n            hash_idx = find_hash(\"md5\");\n            err = md5_init(&state);\n            TLS_ERROR(err, break)\n            err = md5_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = md5_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_idx = find_hash(\"sha1\");\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash + 16);\n            TLS_ERROR(err, break)\n            hash_len = 36;\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash + 16);\n            TLS_ERROR(err, break)\n            hash_len = 36;\n            break;\n#endif\n    }\n    if ((hash_idx < 0) || (err)) {\n        DEBUG_PRINT1(\"Unsupported hash type: %i\\n\", hash_type);\n        return TLS_GENERIC_ERROR;\n    }\n#ifdef TLS_LEGACY_SUPPORT\n    if (hash_type == _md5_sha1)\n        err = _private_rsa_verify_hash_md5sha1(buffer, len, hash, hash_len, &rsa_stat, &key);\n    else\n#endif\n#ifdef WITH_TLS_13\n    if (((context->version == TLS_V13) || (context->version == DTLS_V13)) || force_pss)\n        err = rsa_verify_hash_ex(buffer, len, hash, hash_len, LTC_PKCS_1_PSS, hash_idx, 0, &rsa_stat, &key);\n    else\n#endif\n        err = rsa_verify_hash_ex(buffer, len, hash, hash_len, LTC_PKCS_1_V1_5, hash_idx, 0, &rsa_stat, &key);\n    rsa_free(&key);\n    if (err)\n        return 0;\n    return rsa_stat;\n}\n\n#ifdef TLS_LEGACY_SUPPORT\nint _private_rsa_sign_hash_md5sha1(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, rsa_key *key) {\n    unsigned long modulus_bitlen, modulus_bytelen, x;\n    int err;\n    \n    if ((in == NULL) || (out == NULL) || (outlen == NULL) || (key == NULL))\n        return TLS_GENERIC_ERROR;\n    \n    modulus_bitlen = mp_count_bits((key->N));\n    \n    modulus_bytelen = mp_unsigned_bin_size((key->N));\n    if (modulus_bytelen > *outlen) {\n        *outlen = modulus_bytelen;\n        return CRYPT_BUFFER_OVERFLOW;\n    }\n    x = modulus_bytelen;\n    err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x);\n    if (err != CRYPT_OK)\n        return err;\n    \n    return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key);\n}\n#endif\n\nint _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, const unsigned char *message, unsigned int message_len, unsigned char *out, unsigned long *outlen) {\n    rsa_key key;\n    int err;\n    int hash_idx = -1;\n    unsigned char hash[TLS_MAX_HASH_LEN];\n    unsigned int hash_len = 0;\n    hash_state state;\n\n    if ((!outlen) || (!context) || (!out) || (!outlen) || (!context->private_key) || (!context->private_key->der_bytes) || (!context->private_key->der_len)) {\n        DEBUG_PRINT0(\"No private key set\\n\");\n        return TLS_GENERIC_ERROR;\n    }\n    tls_init();\n    err = rsa_import(context->private_key->der_bytes, context->private_key->der_len, &key);\n    \n    if (err) {\n        DEBUG_PRINT1(\"Error importing RSA certificate (code: %i)\\n\", err);\n        return TLS_GENERIC_ERROR;\n    }\n    switch (hash_type) {\n        case md5:\n            hash_idx = find_hash(\"md5\");\n            err = md5_init(&state);\n            TLS_ERROR(err, break)\n            err = md5_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = md5_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 16;\n            break;\n        case sha1:\n            hash_idx = find_hash(\"sha1\");\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 20;\n            break;\n        case sha256:\n            hash_idx = find_hash(\"sha256\");\n            err = sha256_init(&state);\n            TLS_ERROR(err, break)\n            err = sha256_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha256_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 32;\n            break;\n        case sha384:\n            hash_idx = find_hash(\"sha384\");\n            err = sha384_init(&state);\n            TLS_ERROR(err, break)\n            err = sha384_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha384_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 48;\n            break;\n        case sha512:\n            hash_idx = find_hash(\"sha512\");\n            err = sha512_init(&state);\n            TLS_ERROR(err, break)\n            err = sha512_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha512_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 64;\n            break;\n        case _md5_sha1:\n            hash_idx = find_hash(\"md5\");\n            err = md5_init(&state);\n            TLS_ERROR(err, break)\n            err = md5_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = md5_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_idx = find_hash(\"sha1\");\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash + 16);\n            TLS_ERROR(err, break)\n            hash_len = 36;\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash + 16);\n            TLS_ERROR(err, break)\n            hash_len = 36;\n            break;\n    }\n#ifdef TLS_LEGACY_SUPPORT\n    if (hash_type == _md5_sha1) {\n        if (err) {\n            DEBUG_PRINT1(\"Unsupported hash type: %i\\n\", hash_type);\n            return TLS_GENERIC_ERROR;\n        }\n        err = _private_rsa_sign_hash_md5sha1(hash, hash_len, out, outlen, &key);\n    } else\n#endif\n    {\n        if ((hash_idx < 0) || (err)) {\n            DEBUG_PRINT1(\"Unsupported hash type: %i\\n\", hash_type);\n            return TLS_GENERIC_ERROR;\n        }\n#ifdef WITH_TLS_13\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n            err = rsa_sign_hash_ex(hash, hash_len, out, outlen, LTC_PKCS_1_PSS, NULL, find_prng(\"sprng\"), hash_idx, hash_type == sha256 ? 32 : 48, &key);\n        else\n#endif\n            err = rsa_sign_hash_ex(hash, hash_len, out, outlen, LTC_PKCS_1_V1_5, NULL, find_prng(\"sprng\"), hash_idx, 0, &key);\n    }\n    rsa_free(&key);\n    if (err)\n        return 0;\n    \n    return 1;\n}\n\n#ifdef TLS_ECDSA_SUPPORTED\nstatic int _private_tls_is_point(ecc_key *key) {\n    void *prime, *b, *t1, *t2;\n    int  err;\n    \n    if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) {\n        return err;\n    }\n    \n    /* load prime and b */\n    if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) {\n        goto error;\n    }\n    \n    /* compute y^2 */\n    if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    \n    /* compute x^3 */\n    if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) {\n        goto error;\n    }\n    \n    /* compute y^2 - x^3 */\n    if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    \n    /* compute y^2 - x^3 + 3x */\n    if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) {\n        goto error;\n    }\n    while (mp_cmp_d(t1, 0) == LTC_MP_LT) {\n        if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) {\n            goto error;\n        }\n    }\n    while (mp_cmp(t1, prime) != LTC_MP_LT) {\n        if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) {\n            goto error;\n        }\n    }\n    \n    /* compare to b */\n    if (mp_cmp(t1, b) != LTC_MP_EQ) {\n        err = CRYPT_INVALID_PACKET;\n    } else {\n        err = CRYPT_OK;\n    }\n    \nerror:\n    mp_clear_multi(prime, b, t1, t2, NULL);\n    return err;\n}\n\nint _private_tls_ecc_import_key(const unsigned char *private_key, int private_len, const unsigned char *public_key, int public_len, ecc_key *key, const ltc_ecc_set_type *dp) {\n    int           err;\n    \n    if ((!key) || (!ltc_mp.name))\n        return CRYPT_MEM;\n        \n    key->type = PK_PRIVATE;\n    \n    if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK)\n        return CRYPT_MEM;\n    \n    if ((public_len) && (!public_key[0])) {\n        public_key++;\n        public_len--;\n    }\n    if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)public_key + 1, (public_len - 1) >> 1)) != CRYPT_OK) {\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)public_key + 1 + ((public_len - 1) >> 1), (public_len - 1) >> 1)) != CRYPT_OK) {\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)private_key, private_len)) != CRYPT_OK) {\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    key->idx = -1;\n    key->dp  = dp;\n    \n    /* set z */\n    if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) {\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    /* is it a point on the curve?  */\n    if ((err = _private_tls_is_point(key)) != CRYPT_OK) {\n        DEBUG_PRINT0(\"KEY IS NOT ON CURVE\\n\");\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    /* we're good */\n    return CRYPT_OK;\n}\n\nint _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, const unsigned char *message, unsigned int message_len, unsigned char *out, unsigned long *outlen) {\n    ecc_key key;\n    int err;\n    ltc_ecc_set_type *dp;\n    unsigned char hash[TLS_MAX_HASH_LEN];\n    unsigned int hash_len = 0;\n    hash_state state;\n    const struct ECCCurveParameters *curve = NULL;\n    \n    if ((!outlen) || (!context) || (!out) || (!outlen) || (!context->ec_private_key) ||\n        (!context->ec_private_key->priv) || (!context->ec_private_key->priv_len) || (!context->ec_private_key->pk) || (!context->ec_private_key->pk_len)) {\n        DEBUG_PRINT0(\"No private ECDSA key set\\n\");\n        return TLS_GENERIC_ERROR;\n    }\n    \n    switch (context->ec_private_key->ec_algorithm) {\n        case 19:\n            curve = &secp192r1;\n            break;\n        case 20:\n            curve = &secp224k1;\n            break;\n        case 21:\n            curve = &secp224r1;\n            break;\n        case 22:\n            curve = &secp256k1;\n            break;\n        case 23:\n            curve = &secp256r1;\n            break;\n        case 24:\n            curve = &secp384r1;\n            break;\n        case 25:\n            curve = &secp521r1;\n            break;\n        default:\n            DEBUG_PRINT0(\"UNSUPPORTED CURVE\\n\");\n    }\n    \n    if (!curve)\n        return TLS_GENERIC_ERROR;\n    \n    tls_init();\n    \n    dp = (ltc_ecc_set_type *)&curve->dp;\n    \n    /* XXX: broken ... fix this */\n    err = _private_tls_ecc_import_key(context->ec_private_key->priv, context->ec_private_key->priv_len, context->ec_private_key->pk, context->ec_private_key->pk_len, &key, dp);\n    if (err) {\n        DEBUG_PRINT1(\"Error importing ECC certificate (code: %i)\\n\", (int)err);\n        return TLS_GENERIC_ERROR;\n    }\n    switch (hash_type) {\n        case md5:\n            err = md5_init(&state);\n            TLS_ERROR(err, break)\n            err = md5_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = md5_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 16;\n            break;\n        case sha1:\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 20;\n            break;\n        case sha256:\n            err = sha256_init(&state);\n            TLS_ERROR(err, break)\n            err = sha256_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha256_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 32;\n            break;\n        case sha384:\n            err = sha384_init(&state);\n            TLS_ERROR(err, break)\n            err = sha384_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha384_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 48;\n            break;\n        case sha512:\n            err = sha512_init(&state);\n            TLS_ERROR(err, break)\n            err = sha512_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha512_done(&state, hash);\n            TLS_ERROR(err, break)\n            hash_len = 64;\n            break;\n        case _md5_sha1:\n            err = md5_init(&state);\n            TLS_ERROR(err, break)\n            err = md5_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = md5_done(&state, hash);\n            TLS_ERROR(err, break)\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash + 16);\n            TLS_ERROR(err, break)\n            hash_len = 36;\n            err = sha1_init(&state);\n            TLS_ERROR(err, break)\n            err = sha1_process(&state, message, message_len);\n            TLS_ERROR(err, break)\n            err = sha1_done(&state, hash + 16);\n            TLS_ERROR(err, break)\n            hash_len = 36;\n            break;\n    }\n    \n    if (err) {\n        DEBUG_PRINT1(\"Unsupported hash type: %i\\n\", hash_type);\n        return TLS_GENERIC_ERROR;\n    }\n    /* \"Let z be the Ln leftmost bits of e, where Ln is the bit length of the group order n.\" */\n    if (hash_len > (unsigned int)curve->size)\n        hash_len = (unsigned int)curve->size;\n    err = ecc_sign_hash(hash, hash_len, out, outlen, NULL, find_prng(\"sprng\"), &key);\n    DEBUG_DUMP_HEX_LABEL(\"ECC SIGNATURE\", out, *outlen);\n    ecc_free(&key);\n    if (err)\n        return 0;\n    \n    return 1;\n}\n\n#if defined(TLS_CLIENT_ECDSA) || defined(WITH_TLS_13)\nint _private_tls_ecc_import_pk(const unsigned char *public_key, int public_len, ecc_key *key, const ltc_ecc_set_type *dp) {\n    int           err;\n    \n    if ((!key) || (!ltc_mp.name))\n        return CRYPT_MEM;\n        \n    key->type = PK_PUBLIC;\n    \n    if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK)\n        return CRYPT_MEM;\n    \n    if ((public_len) && (!public_key[0])) {\n        public_key++;\n        public_len--;\n    }\n    if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)public_key + 1, (public_len - 1) >> 1)) != CRYPT_OK) {\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)public_key + 1 + ((public_len - 1) >> 1), (public_len - 1) >> 1)) != CRYPT_OK) {\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    \n    key->idx = -1;\n    key->dp  = dp;\n    \n    /* set z */\n    if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) {\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    /* is it a point on the curve?  */\n    if ((err = _private_tls_is_point(key)) != CRYPT_OK) {\n        DEBUG_PRINT0(\"KEY IS NOT ON CURVE\\n\");\n        mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);\n        return err;\n    }\n    \n    /* we're good */\n    return CRYPT_OK;\n}\n\nint _private_tls_verify_ecdsa(struct TLSContext *context, unsigned int hash_type, const unsigned char *buffer, unsigned int len, const unsigned char *message, unsigned int message_len, const struct ECCCurveParameters *curve_hint) {\n    ecc_key key;\n    int ecc_stat = 0;\n    int err;\n    int hash_idx = -1;\n    unsigned char hash[TLS_MAX_HASH_LEN];\n    unsigned int hash_len = 0;\n    hash_state state;\n\n    tls_init();\n    if (!curve_hint)\n        curve_hint = context->curve;\n\n    if (context->is_server) {\n        if ((!len) || (!context->client_certificates) || (!context->client_certificates_count) || (!context->client_certificates[0]) ||\n            (!context->client_certificates[0]->pk) || (!context->client_certificates[0]->pk_len) || (!curve_hint)) {\n            DEBUG_PRINT0(\"No client certificate set\\n\");\n            return TLS_GENERIC_ERROR;\n        }\n        err = _private_tls_ecc_import_pk(context->client_certificates[0]->pk, context->client_certificates[0]->pk_len, &key, (ltc_ecc_set_type *)&curve_hint->dp);\n    } else {\n        if ((!len) || (!context->certificates) || (!context->certificates_count) || (!context->certificates[0]) ||\n            (!context->certificates[0]->pk) || (!context->certificates[0]->pk_len) || (!curve_hint)) {\n            DEBUG_PRINT0(\"No server certificate set\\n\");\n            return TLS_GENERIC_ERROR;\n        }\n        err = _private_tls_ecc_import_pk(context->certificates[0]->pk, context->certificates[0]->pk_len, &key, (ltc_ecc_set_type *)&curve_hint->dp);\n    }\n    if (err) {\n        DEBUG_PRINT1(\"Error importing ECC certificate (code: %i)\", err);\n        return TLS_GENERIC_ERROR;\n    }\n    switch (hash_type) {\n        case md5:\n            hash_idx = find_hash(\"md5\");\n            err = md5_init(&state);\n            if (!err) {\n                err = md5_process(&state, message, message_len);\n                if (!err)\n                    err = md5_done(&state, hash);\n            }\n            hash_len = 16;\n            break;\n        case sha1:\n            hash_idx = find_hash(\"sha1\");\n            err = sha1_init(&state);\n            if (!err) {\n                err = sha1_process(&state, message, message_len);\n                if (!err)\n                    err = sha1_done(&state, hash);\n            }\n            hash_len = 20;\n            break;\n        case sha256:\n            hash_idx = find_hash(\"sha256\");\n            err = sha256_init(&state);\n            if (!err) {\n                err = sha256_process(&state, message, message_len);\n                if (!err)\n                    err = sha256_done(&state, hash);\n            }\n            hash_len = 32;\n            break;\n        case sha384:\n            hash_idx = find_hash(\"sha384\");\n            err = sha384_init(&state);\n            if (!err) {\n                err = sha384_process(&state, message, message_len);\n                if (!err)\n                    err = sha384_done(&state, hash);\n            }\n            hash_len = 48;\n            break;\n        case sha512:\n            hash_idx = find_hash(\"sha512\");\n            err = sha512_init(&state);\n            if (!err) {\n                err = sha512_process(&state, message, message_len);\n                if (!err)\n                    err = sha512_done(&state, hash);\n            }\n            hash_len = 64;\n            break;\n#ifdef TLS_LEGACY_SUPPORT\n        case _md5_sha1:\n            hash_idx = find_hash(\"md5\");\n            err = md5_init(&state);\n            if (!err) {\n                err = md5_process(&state, message, message_len);\n                if (!err)\n                    err = md5_done(&state, hash);\n            }\n            hash_idx = find_hash(\"sha1\");\n            err = sha1_init(&state);\n            if (!err) {\n                err = sha1_process(&state, message, message_len);\n                if (!err)\n                    err = sha1_done(&state, hash + 16);\n            }\n            hash_len = 36;\n            err = sha1_init(&state);\n            if (!err) {\n                err = sha1_process(&state, message, message_len);\n                if (!err)\n                    err = sha1_done(&state, hash + 16);\n            }\n            hash_len = 36;\n            break;\n#endif\n    }\n    if ((hash_idx < 0) || (err)) {\n        DEBUG_PRINT1(\"Unsupported hash type: %i\\n\", hash_type);\n        return TLS_GENERIC_ERROR;\n    }\n    err = ecc_verify_hash(buffer, len, hash, hash_len, &ecc_stat, &key);\n    ecc_free(&key);\n    if (err)\n        return 0;\n    return ecc_stat;\n}\n#endif\n\n#endif\n\nunsigned int _private_tls_random_int(int limit) {\n    unsigned int res = 0;\n\n    tls_random((unsigned char *)&res, sizeof(int));\n    if (limit)\n        res %= limit;\n    return res;\n}\n\nvoid _private_tls_sleep(unsigned int microseconds) {\n#ifdef _WIN32\n    Sleep(microseconds/1000);\n#else\n#if(0)\n    /* this is unnecessary: usleep() has uS precision and is on more systems */\n    struct timespec ts;\n    \n    ts.tv_sec = (unsigned int) (microseconds / 1000000);\n    ts.tv_nsec = (unsigned int) (microseconds % 1000000) * 1000ul;\n    \n    nanosleep(&ts, NULL);\n#endif\n    usleep(microseconds);\n#endif\n}\n\nvoid _private_random_sleep(struct TLSContext *context, int max_microseconds) {\n    if (context)\n        context->sleep_until = (unsigned int)time(NULL) + _private_tls_random_int(max_microseconds/1000000 * TLS_MAX_ERROR_IDLE_S);\n    else\n        _private_tls_sleep(_private_tls_random_int(max_microseconds));\n}\n\nvoid _private_tls_prf_helper(int hash_idx, unsigned long dlen, unsigned char *output, unsigned int outlen, const unsigned char *secret, const unsigned int secret_len,\n                              const unsigned char *label, unsigned int label_len, unsigned char *seed, unsigned int seed_len,\n                              unsigned char *seed_b, unsigned int seed_b_len) {\n    unsigned char digest_out0[TLS_MAX_HASH_LEN];\n    unsigned char digest_out1[TLS_MAX_HASH_LEN];\n    unsigned int i;\n    hmac_state hmac;\n    int idx = 0;\n    \n    hmac_init(&hmac, hash_idx, secret, secret_len);\n    hmac_process(&hmac, label, label_len);\n    \n    hmac_process(&hmac, seed, seed_len);\n    if ((seed_b) && (seed_b_len))\n        hmac_process(&hmac, seed_b, seed_b_len);\n    hmac_done(&hmac, digest_out0, &dlen);\n    while (outlen) {\n        unsigned int copylen = outlen;\n\n        hmac_init(&hmac, hash_idx, secret, secret_len);\n        hmac_process(&hmac, digest_out0, dlen);\n        hmac_process(&hmac, label, label_len);\n        hmac_process(&hmac, seed, seed_len);\n        if ((seed_b) && (seed_b_len))\n            hmac_process(&hmac, seed_b, seed_b_len);\n        hmac_done(&hmac, digest_out1, &dlen);\n        \n        if (copylen > dlen)\n            copylen = dlen;\n        \n        for (i = 0; i < copylen; i++) {\n            output[idx++] ^= digest_out1[i];\n            outlen--;\n        }\n        \n        if (!outlen)\n            break;\n        \n        hmac_init(&hmac, hash_idx, secret, secret_len);\n        hmac_process(&hmac, digest_out0, dlen);\n        hmac_done(&hmac, digest_out0, &dlen);\n    }\n}\n\n#ifdef WITH_TLS_13\nint _private_tls_hkdf_label(const char *label, unsigned char label_len, const unsigned char *data, unsigned char data_len, unsigned char *hkdflabel, unsigned short length, const char *prefix) {\n    int prefix_len;\n\n    *(unsigned short *)hkdflabel = htons(length);\n    if (prefix) {\n        prefix_len = (int)strlen(prefix);\n        memcpy(&hkdflabel[3], prefix, prefix_len);\n    } else {\n        memcpy(&hkdflabel[3], \"tls13 \", 6);\n        prefix_len = 6;\n    }\n    hkdflabel[2] = (unsigned char)prefix_len + label_len;\n    memcpy(&hkdflabel[3 + prefix_len], label, label_len);\n    hkdflabel[3 + prefix_len + label_len] = (unsigned char)data_len;\n    if (data_len)\n        memcpy(&hkdflabel[4 + prefix_len + label_len], data, data_len);\n    return 4 + prefix_len + label_len + data_len;\n}\n\nint _private_tls_hkdf_extract(unsigned int mac_length, unsigned char *output, unsigned int outlen, const unsigned char *salt, unsigned int salt_len, const unsigned char *ikm, unsigned char ikm_len) {\n    int hash_idx;\n    unsigned long dlen = outlen;\n    static unsigned char dummy_label[1] = { 0 };\n    hmac_state hmac;\n\n    if ((!salt) || (salt_len == 0)) {\n        salt_len = 1;\n        salt = dummy_label;\n    }\n    if (mac_length == TLS_SHA384_MAC_SIZE) {\n        hash_idx = find_hash(\"sha384\");\n        dlen = mac_length;\n    } else\n        hash_idx = find_hash(\"sha256\");\n\n    hmac_init(&hmac, hash_idx, salt, salt_len);\n    hmac_process(&hmac, ikm, ikm_len);\n    hmac_done(&hmac, output, &dlen);\n    DEBUG_DUMP_HEX_LABEL(\"EXTRACT\", output, dlen);\n    return dlen;\n}\n\nvoid _private_tls_hkdf_expand(unsigned int mac_length, unsigned char *output, unsigned int outlen, const unsigned char *secret, unsigned int secret_len, const unsigned char *info, unsigned char info_len) {\n    unsigned char digest_out[TLS_MAX_HASH_LEN];\n    unsigned long dlen = 32;\n    int hash_idx;\n    unsigned int i;\n    unsigned int idx = 0;\n    hmac_state hmac;\n    unsigned char i2 = 0;\n\n    if (mac_length == TLS_SHA384_MAC_SIZE) {\n        hash_idx = find_hash(\"sha384\");\n        dlen = mac_length;\n    } else\n        hash_idx = find_hash(\"sha256\");\n    while (outlen) {\n        unsigned int copylen = outlen;\n        hmac_init(&hmac, hash_idx, secret, secret_len);\n        if (i2)\n            hmac_process(&hmac, digest_out, dlen);\n        if ((info) && (info_len))\n            hmac_process(&hmac, info, info_len);\n        i2++;\n        hmac_process(&hmac, &i2, 1);\n        hmac_done(&hmac, digest_out, &dlen);\n            \n        if (copylen > dlen)\n            copylen = (unsigned int)dlen;\n            \n        for (i = 0; i < copylen; i++) {\n            output[idx++] = digest_out[i];\n            outlen--;\n        }\n            \n        if (!outlen)\n            break;            \n    }\n}\n\nvoid _private_tls_hkdf_expand_label(unsigned int mac_length, unsigned char *output, unsigned int outlen, const unsigned char *secret, unsigned int secret_len, const char *label, unsigned char label_len, const unsigned char *data, unsigned char data_len) {\n    unsigned char hkdf_label[512];\n    int len = _private_tls_hkdf_label(label, label_len, data, data_len, hkdf_label, outlen, NULL);\n\n    DEBUG_DUMP_HEX_LABEL(\"INFO\", hkdf_label, len);\n    _private_tls_hkdf_expand(mac_length, output, outlen, secret, secret_len, hkdf_label, len);\n}\n#endif\n\nvoid _private_tls_prf(struct TLSContext *context,\n                       unsigned char *output, unsigned int outlen, const unsigned char *secret, const unsigned int secret_len,\n                       const unsigned char *label, unsigned int label_len, unsigned char *seed, unsigned int seed_len,\n                       unsigned char *seed_b, unsigned int seed_b_len) {\n    if ((!secret) || (!secret_len)) {\n        DEBUG_PRINT0(\"NULL SECRET\\n\");\n        return;\n    }\n    if ((context->version != TLS_V12) && (context->version != DTLS_V12)) {\n        int md5_hash_idx = find_hash(\"md5\");\n        int sha1_hash_idx = find_hash(\"sha1\");\n        int half_secret = (secret_len + 1) / 2;\n        \n        memset(output, 0, outlen);\n        _private_tls_prf_helper(md5_hash_idx, 16, output, outlen, secret, half_secret, label, label_len, seed, seed_len, seed_b, seed_b_len);\n        _private_tls_prf_helper(sha1_hash_idx, 20, output, outlen, secret + (secret_len - half_secret), secret_len - half_secret, label, label_len, seed, seed_len, seed_b, seed_b_len);\n    } else {\n        /* sha256_hmac */\n        unsigned char digest_out0[TLS_MAX_HASH_LEN];\n        unsigned char digest_out1[TLS_MAX_HASH_LEN];\n        unsigned long dlen = 32;\n        int hash_idx;\n        unsigned int i;\n        hmac_state hmac;\n        int idx = 0;\n        unsigned int mac_length = _private_tls_mac_length(context);\n\n        if (mac_length == TLS_SHA384_MAC_SIZE) {\n            hash_idx = find_hash(\"sha384\");\n            dlen = mac_length;\n        } else\n            hash_idx = find_hash(\"sha256\");\n        \n        hmac_init(&hmac, hash_idx, secret, secret_len);\n        hmac_process(&hmac, label, label_len);\n        \n        hmac_process(&hmac, seed, seed_len);\n        if ((seed_b) && (seed_b_len))\n            hmac_process(&hmac, seed_b, seed_b_len);\n        hmac_done(&hmac, digest_out0, &dlen);\n        while (outlen) {\n            unsigned int copylen = outlen;\n            hmac_init(&hmac, hash_idx, secret, secret_len);\n            hmac_process(&hmac, digest_out0, dlen);\n            hmac_process(&hmac, label, label_len);\n            hmac_process(&hmac, seed, seed_len);\n            if ((seed_b) && (seed_b_len))\n                hmac_process(&hmac, seed_b, seed_b_len);\n            hmac_done(&hmac, digest_out1, &dlen);\n            \n            if (copylen > dlen)\n                copylen = (unsigned int)dlen;\n            \n            for (i = 0; i < copylen; i++) {\n                output[idx++] = digest_out1[i];\n                outlen--;\n            }\n            \n            if (!outlen)\n                break;\n            \n            hmac_init(&hmac, hash_idx, secret, secret_len);\n            hmac_process(&hmac, digest_out0, dlen);\n            hmac_done(&hmac, digest_out0, &dlen);\n        }\n    }\n}\n\nint _private_tls_key_length(struct TLSContext *context) {\n    switch (context->cipher) {\n        case TLS_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n        case TLS_AES_128_GCM_SHA256:\n            return 16;\n        case TLS_RSA_WITH_AES_256_CBC_SHA:\n        case TLS_RSA_WITH_AES_256_CBC_SHA256:\n        case TLS_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:\n        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:\n        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:\n        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_AES_256_GCM_SHA384:\n        case TLS_CHACHA20_POLY1305_SHA256:\n            return 32;\n    }\n    return 0;\n}\n\nint _private_tls_is_aead(struct TLSContext *context) {\n    switch (context->cipher) {\n        case TLS_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n        case TLS_AES_128_GCM_SHA256:\n        case TLS_AES_256_GCM_SHA384:\n            return 1;\n        case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_CHACHA20_POLY1305_SHA256:\n            return 2;\n    }\n    return 0;\n}\n\n\n\nunsigned int _private_tls_mac_length(struct TLSContext *context) {\n    switch (context->cipher) {\n        case TLS_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_RSA_WITH_AES_256_CBC_SHA:\n        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:\n        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:\n            return TLS_SHA1_MAC_SIZE;\n        case TLS_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_RSA_WITH_AES_256_CBC_SHA256:\n        case TLS_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:\n        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n#ifdef WITH_TLS_13\n        case TLS_AES_128_GCM_SHA256:\n        case TLS_CHACHA20_POLY1305_SHA256:\n        case TLS_AES_128_CCM_SHA256:\n        case TLS_AES_128_CCM_8_SHA256:\n#endif\n            return TLS_SHA256_MAC_SIZE;\n        case TLS_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n#ifdef WITH_TLS_13\n        case TLS_AES_256_GCM_SHA384:\n#endif\n            return TLS_SHA384_MAC_SIZE;\n    }\n    return 0;\n}\n\n#ifdef WITH_TLS_13\nint _private_tls13_key(struct TLSContext *context, int handshake) {\n    int is_aead;\n    unsigned char *clientkey = NULL;\n    unsigned char *serverkey = NULL;\n    unsigned char *clientiv = NULL;\n    unsigned char *serveriv = NULL;\n    unsigned char local_keybuffer[TLS_V13_MAX_KEY_SIZE];\n    unsigned char local_ivbuffer[TLS_V13_MAX_IV_SIZE];\n    unsigned char remote_keybuffer[TLS_V13_MAX_KEY_SIZE];\n    unsigned char remote_ivbuffer[TLS_V13_MAX_IV_SIZE];\n\n    unsigned char prk[TLS_MAX_HASH_SIZE];\n    unsigned char hash[TLS_MAX_HASH_SIZE];\n    static unsigned char earlysecret[TLS_MAX_HASH_SIZE];\n\n    const char *server_key = \"s ap traffic\";\n    const char *client_key = \"c ap traffic\";\n\n    unsigned char salt[TLS_MAX_HASH_SIZE];\n    hash_state md;\n    int key_length;\n    unsigned int mac_length;\n\n    unsigned char secret[TLS_MAX_MAC_SIZE];\n    unsigned char hs_secret[TLS_MAX_HASH_SIZE];\n\n    int hash_size;\n    int iv_length = TLS_13_AES_GCM_IV_LENGTH;\n\n    tls_init();\n\n    key_length = _private_tls_key_length(context);\n    mac_length = _private_tls_mac_length(context);\n\n    if ((!context->premaster_key) || (!context->premaster_key_len))\n        return 0; \n    \n    if ((!key_length) || (!mac_length)) {\n        DEBUG_PRINT2(\"KEY EXPANSION FAILED, KEY LENGTH: %i, MAC LENGTH: %i\\n\", key_length, mac_length);\n        return 0;\n    }\n\n    is_aead = _private_tls_is_aead(context);\n\n    if (handshake) {\n        server_key = \"s hs traffic\";\n        client_key = \"c hs traffic\";\n    }\n\n    if (mac_length == TLS_SHA384_MAC_SIZE) {\n        sha384_init(&md);\n        sha384_done(&md, hash);\n    } else {\n        sha256_init(&md);\n        sha256_done(&md, hash);\n    }\n    /* extract secret \"early\" */\n    if ((context->master_key) && (context->master_key_len) && (!handshake)) {\n        DEBUG_DUMP_HEX_LABEL(\"USING PREVIOUS SECRET\", context->master_key, context->master_key_len);\n        _private_tls_hkdf_expand_label(mac_length, salt, mac_length, context->master_key, context->master_key_len, \"derived\", 7, hash, mac_length);\n        DEBUG_DUMP_HEX_LABEL(\"salt\", salt, mac_length);\n        _private_tls_hkdf_extract(mac_length, prk, mac_length, salt, mac_length, earlysecret, mac_length);\n    } else {\n        _private_tls_hkdf_extract(mac_length, prk, mac_length, NULL, 0, earlysecret, mac_length);\n        /* derive secret for handshake \"tls13 derived\": */\n        DEBUG_DUMP_HEX_LABEL(\"null hash\", hash, mac_length);\n        _private_tls_hkdf_expand_label(mac_length, salt, mac_length, prk, mac_length, \"derived\", 7, hash, mac_length);\n        /* extract secret \"handshake\": */\n        DEBUG_DUMP_HEX_LABEL(\"salt\", salt, mac_length);\n        _private_tls_hkdf_extract(mac_length, prk, mac_length, salt, mac_length, context->premaster_key, context->premaster_key_len);\n    }\n\n    if (!is_aead) {\n        DEBUG_PRINT0(\"KEY EXPANSION FAILED, NON AEAD CIPHER\\n\");\n        return 0;\n    }\n\n    if (handshake)\n        hash_size = _private_tls_get_hash(context, hash);\n    else\n        hash_size = _private_tls_done_hash(context, hash);\n    DEBUG_DUMP_HEX_LABEL(\"messages hash\", hash, hash_size);\n\n    if (context->is_server) {\n        _private_tls_hkdf_expand_label(mac_length, hs_secret, mac_length, prk, mac_length, server_key, 12, context->server_finished_hash ? context->server_finished_hash : hash, hash_size);\n        DEBUG_DUMP_HEX_LABEL(server_key, hs_secret, mac_length);\n        serverkey = local_keybuffer;\n        serveriv = local_ivbuffer;\n        clientkey = remote_keybuffer;\n        clientiv = remote_ivbuffer;\n    } else {\n        _private_tls_hkdf_expand_label(mac_length, hs_secret, mac_length, prk, mac_length, client_key, 12, context->server_finished_hash ? context->server_finished_hash : hash, hash_size);\n        DEBUG_DUMP_HEX_LABEL(client_key, hs_secret, mac_length);\n        serverkey = remote_keybuffer;\n        serveriv = remote_ivbuffer;\n        clientkey = local_keybuffer;\n        clientiv = local_ivbuffer;\n    }\n\n#ifdef TLS_WITH_CHACHA20_POLY1305\n    if (is_aead == 2)\n        iv_length = TLS_CHACHA20_IV_LENGTH;\n#endif\n\n    _private_tls_hkdf_expand_label(mac_length, local_keybuffer, key_length, hs_secret, mac_length, \"key\", 3, NULL, 0);\n    _private_tls_hkdf_expand_label(mac_length, local_ivbuffer, iv_length, hs_secret, mac_length, \"iv\", 2, NULL, 0);\n    if (context->is_server)\n        _private_tls_hkdf_expand_label(mac_length, secret, mac_length, prk, mac_length, client_key, 12, context->server_finished_hash ? context->server_finished_hash : hash, hash_size);\n    else\n        _private_tls_hkdf_expand_label(mac_length, secret, mac_length, prk, mac_length, server_key, 12, context->server_finished_hash ? context->server_finished_hash : hash, hash_size);\n\n    _private_tls_hkdf_expand_label(mac_length, remote_keybuffer, key_length, secret, mac_length, \"key\", 3, NULL, 0);\n    _private_tls_hkdf_expand_label(mac_length, remote_ivbuffer, iv_length, secret, mac_length, \"iv\", 2, NULL, 0);\n\n    DEBUG_DUMP_HEX_LABEL(\"CLIENT KEY\", clientkey, key_length)\n    DEBUG_DUMP_HEX_LABEL(\"CLIENT IV\", clientiv, iv_length)\n    DEBUG_DUMP_HEX_LABEL(\"SERVER KEY\", serverkey, key_length)\n    DEBUG_DUMP_HEX_LABEL(\"SERVER IV\", serveriv, iv_length)\n    \n    TLS_FREE(context->finished_key);\n    TLS_FREE(context->remote_finished_key);\n    if (handshake) {\n        context->finished_key = (unsigned char *)TLS_MALLOC(mac_length);\n        context->remote_finished_key = (unsigned char *)TLS_MALLOC(mac_length);\n\n        if (context->finished_key) {\n            _private_tls_hkdf_expand_label(mac_length, context->finished_key, mac_length, hs_secret, mac_length, \"finished\", 8, NULL, 0);\n            DEBUG_DUMP_HEX_LABEL(\"FINISHED\", context->finished_key, mac_length)\n        }\n\n        if (context->remote_finished_key) {\n            _private_tls_hkdf_expand_label(mac_length, context->remote_finished_key, mac_length, secret, mac_length, \"finished\", 8, NULL, 0);\n            DEBUG_DUMP_HEX_LABEL(\"REMOTE FINISHED\", context->remote_finished_key, mac_length)\n        }\n    } else {\n        context->finished_key = NULL;\n        context->remote_finished_key = NULL;\n        TLS_FREE(context->server_finished_hash);\n        context->server_finished_hash = NULL;\n    }\n\n    if (context->is_server) {\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        if (is_aead == 2) {\n            memcpy(context->crypto.ctx_remote_mac.remote_nonce, clientiv, iv_length);\n            memcpy(context->crypto.ctx_local_mac.local_nonce, serveriv, iv_length);\n        } else\n#endif\n        if (is_aead) {\n            memcpy(context->crypto.ctx_remote_mac.remote_iv, clientiv, iv_length);\n            memcpy(context->crypto.ctx_local_mac.local_iv, serveriv, iv_length);\n        }\n        if (_private_tls_crypto_create(context, key_length, serverkey, serveriv, clientkey, clientiv))\n            return 0;\n    } else {\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        if (is_aead == 2) {\n            memcpy(context->crypto.ctx_local_mac.local_nonce, clientiv, iv_length);\n            memcpy(context->crypto.ctx_remote_mac.remote_nonce, serveriv, iv_length);\n        } else\n#endif\n        if (is_aead) {\n            memcpy(context->crypto.ctx_local_mac.local_iv, clientiv, iv_length);\n            memcpy(context->crypto.ctx_remote_mac.remote_iv, serveriv, iv_length);\n        }\n        if (_private_tls_crypto_create(context, key_length, clientkey, clientiv, serverkey, serveriv))\n            return 0;\n    }\n    context->crypto.created = 1 + is_aead;\n    if (context->exportable) {\n        TLS_FREE(context->exportable_keys);\n        context->exportable_keys = (unsigned char *)TLS_MALLOC(key_length * 2);\n        if (context->exportable_keys) {\n            if (context->is_server) {\n                memcpy(context->exportable_keys, serverkey, key_length);\n                memcpy(context->exportable_keys + key_length, clientkey, key_length);\n            } else {\n                memcpy(context->exportable_keys, clientkey, key_length);\n                memcpy(context->exportable_keys + key_length, serverkey, key_length);\n            }\n            context->exportable_size = key_length * 2;\n        }\n    }\n    TLS_FREE(context->master_key);\n    context->master_key = (unsigned char *)TLS_MALLOC(mac_length);\n    if (context->master_key) {\n        memcpy(context->master_key, prk, mac_length);\n        context->master_key_len = mac_length;\n    }\n    context->local_sequence_number = 0;\n    context->remote_sequence_number = 0;\n    \n    /* extract client_mac_key(mac_key_length)\n    // extract server_mac_key(mac_key_length)\n    // extract client_key(enc_key_length)\n    // extract server_key(enc_key_length)\n    // extract client_iv(fixed_iv_lengh)\n    // extract server_iv(fixed_iv_length) */\n    return 1;\n}\n#endif\n\nint _private_tls_expand_key(struct TLSContext *context) {\n    unsigned char key[TLS_MAX_KEY_EXPANSION_SIZE];\n    unsigned char *clientkey = NULL;\n    unsigned char *serverkey = NULL;\n    unsigned char *clientiv = NULL;\n    unsigned char *serveriv = NULL;\n    int iv_length = TLS_AES_IV_LENGTH;\n    int is_aead, key_length, mac_length;\n    int pos = 0;\n\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n        return 0;\n#endif\n    \n    if ((!context->master_key) || (!context->master_key_len))\n        return 0;\n    \n    key_length = _private_tls_key_length(context);\n    mac_length = _private_tls_mac_length(context);\n    \n    if ((!key_length) || (!mac_length)) {\n        DEBUG_PRINT2(\"KEY EXPANSION FAILED, KEY LENGTH: %i, MAC LENGTH: %i\\n\", key_length, mac_length);\n        return 0;\n    }\n    is_aead = _private_tls_is_aead(context);\n    if (context->is_server)\n        _private_tls_prf(context, key, sizeof(key), context->master_key, context->master_key_len, (unsigned char *)\"key expansion\", 13, context->local_random, TLS_SERVER_RANDOM_SIZE, context->remote_random, TLS_CLIENT_RANDOM_SIZE);\n    else\n        _private_tls_prf(context, key, sizeof(key), context->master_key, context->master_key_len, (unsigned char *)\"key expansion\", 13, context->remote_random, TLS_SERVER_RANDOM_SIZE, context->local_random, TLS_CLIENT_RANDOM_SIZE);\n    \n    DEBUG_DUMP_HEX_LABEL(\"LOCAL RANDOM \", context->local_random, TLS_SERVER_RANDOM_SIZE);\n    DEBUG_DUMP_HEX_LABEL(\"REMOTE RANDOM\", context->remote_random, TLS_CLIENT_RANDOM_SIZE);\n    DEBUG_PRINT0(\"\\n=========== EXPANSION ===========\\n\");\n    DEBUG_DUMP_HEX(key, TLS_MAX_KEY_EXPANSION_SIZE);\n    DEBUG_PRINT0(\"\\n\");\n        \n#ifdef TLS_WITH_CHACHA20_POLY1305\n    if (is_aead == 2) {\n        iv_length = TLS_CHACHA20_IV_LENGTH;\n    } else\n#endif\n    if (is_aead) {\n        iv_length = TLS_AES_GCM_IV_LENGTH;\n    } else {\n        if (context->is_server) {\n            memcpy(context->crypto.ctx_remote_mac.remote_mac, &key[pos], mac_length);\n            pos += mac_length;\n            memcpy(context->crypto.ctx_local_mac.local_mac, &key[pos], mac_length);\n            pos += mac_length;\n        } else {\n            memcpy(context->crypto.ctx_local_mac.local_mac, &key[pos], mac_length);\n            pos += mac_length;\n            memcpy(context->crypto.ctx_remote_mac.remote_mac, &key[pos], mac_length);\n            pos += mac_length;\n        }\n    }\n    \n    clientkey = &key[pos];\n    pos += key_length;\n    serverkey = &key[pos];\n    pos += key_length;\n    clientiv = &key[pos];\n    pos += iv_length;\n    serveriv = &key[pos];\n    pos += iv_length;\n    DEBUG_PRINT2(\"EXPANSION %i/%i\\n\", (int)pos, (int)TLS_MAX_KEY_EXPANSION_SIZE);\n    DEBUG_DUMP_HEX_LABEL(\"CLIENT KEY\", clientkey, key_length)\n    DEBUG_DUMP_HEX_LABEL(\"CLIENT IV\", clientiv, iv_length)\n    DEBUG_DUMP_HEX_LABEL(\"CLIENT MAC KEY\", context->is_server ? context->crypto.ctx_remote_mac.remote_mac : context->crypto.ctx_local_mac.local_mac, mac_length)\n    DEBUG_DUMP_HEX_LABEL(\"SERVER KEY\", serverkey, key_length)\n    DEBUG_DUMP_HEX_LABEL(\"SERVER IV\", serveriv, iv_length)\n    DEBUG_DUMP_HEX_LABEL(\"SERVER MAC KEY\", context->is_server ? context->crypto.ctx_local_mac.local_mac : context->crypto.ctx_remote_mac.remote_mac, mac_length)\n    \n    if (context->is_server) {\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        if (is_aead == 2) {\n            memcpy(context->crypto.ctx_remote_mac.remote_nonce, clientiv, iv_length);\n            memcpy(context->crypto.ctx_local_mac.local_nonce, serveriv, iv_length);\n        } else\n#endif\n        if (is_aead) {\n            memcpy(context->crypto.ctx_remote_mac.remote_aead_iv, clientiv, iv_length);\n            memcpy(context->crypto.ctx_local_mac.local_aead_iv, serveriv, iv_length);\n        }\n        if (_private_tls_crypto_create(context, key_length, serverkey, serveriv, clientkey, clientiv))\n            return 0;\n    } else {\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        if (is_aead == 2) {\n            memcpy(context->crypto.ctx_local_mac.local_nonce, clientiv, iv_length);\n            memcpy(context->crypto.ctx_remote_mac.remote_nonce, serveriv, iv_length);\n        } else\n#endif\n        if (is_aead) {\n            memcpy(context->crypto.ctx_local_mac.local_aead_iv, clientiv, iv_length);\n            memcpy(context->crypto.ctx_remote_mac.remote_aead_iv, serveriv, iv_length);\n        }\n        if (_private_tls_crypto_create(context, key_length, clientkey, clientiv, serverkey, serveriv))\n            return 0;\n    }\n    \n    if (context->exportable) {\n        TLS_FREE(context->exportable_keys);\n        context->exportable_keys = (unsigned char *)TLS_MALLOC(key_length * 2);\n        if (context->exportable_keys) {\n            if (context->is_server) {\n                memcpy(context->exportable_keys, serverkey, key_length);\n                memcpy(context->exportable_keys + key_length, clientkey, key_length);\n            } else {\n                memcpy(context->exportable_keys, clientkey, key_length);\n                memcpy(context->exportable_keys + key_length, serverkey, key_length);\n            }\n            context->exportable_size = key_length * 2;\n        }\n    }\n    \n    /* extract client_mac_key(mac_key_length)\n    // extract server_mac_key(mac_key_length)\n    // extract client_key(enc_key_length)\n    // extract server_key(enc_key_length)\n    // extract client_iv(fixed_iv_lengh)\n    // extract server_iv(fixed_iv_length) */\n    return 1;\n}\n\nint _private_tls_compute_key(struct TLSContext *context, unsigned int key_len) {\n    unsigned char master_secret_label[] = \"master secret\";\n\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n        return 0;\n#endif\n    if ((!context->premaster_key) || (!context->premaster_key_len) || (key_len < 48)) {\n        DEBUG_PRINT0(\"CANNOT COMPUTE MASTER SECRET\\n\");\n        return 0;\n    }\n#ifdef TLS_CHECK_PREMASTER_KEY\n    if (!tls_cipher_is_ephemeral(context)) {\n        unsigned short version = ntohs(*(unsigned short *)context->premaster_key);\n        /*  this check is not true for DHE/ECDHE ciphers */\n        if (context->version > version) {\n            DEBUG_PRINT1(\"Mismatch protocol version 0x(%x)\\n\", version);\n            return 0;\n        }\n    }\n#endif\n    TLS_FREE(context->master_key);\n    context->master_key_len = 0;\n    context->master_key = NULL;\n    if ((context->version == TLS_V13) || (context->version == TLS_V12) || (context->version == TLS_V11) || (context->version == TLS_V10) ||  (context->version == DTLS_V13) || (context->version == DTLS_V12) || (context->version == DTLS_V10)) {\n        context->master_key = (unsigned char *)TLS_MALLOC(key_len);\n        if (!context->master_key)\n            return 0;\n        context->master_key_len = key_len;\n        if (context->is_server) {\n            _private_tls_prf(context,\n                              context->master_key, context->master_key_len,\n                              context->premaster_key, context->premaster_key_len,\n                              master_secret_label, 13,\n                              context->remote_random, TLS_CLIENT_RANDOM_SIZE,\n                              context->local_random, TLS_SERVER_RANDOM_SIZE\n            );\n        } else {\n            _private_tls_prf(context,\n                              context->master_key, context->master_key_len,\n                              context->premaster_key, context->premaster_key_len,\n                              master_secret_label, 13,\n                              context->local_random, TLS_CLIENT_RANDOM_SIZE,\n                              context->remote_random, TLS_SERVER_RANDOM_SIZE\n            );\n        }\n        TLS_FREE(context->premaster_key);\n        context->premaster_key = NULL;\n        context->premaster_key_len = 0;\n        DEBUG_PRINT0(\"\\n=========== Master key ===========\\n\");\n        DEBUG_DUMP_HEX(context->master_key, context->master_key_len);\n        DEBUG_PRINT0(\"\\n\");\n        _private_tls_expand_key(context);\n        return 1;\n    }\n    return 0;\n}\n\nunsigned char *tls_pem_decode(const unsigned char *data_in, unsigned int input_length, int cert_index, unsigned int *output_len) {\n    unsigned int i;\n    int alloc_len = input_length / 4 * 3;\n    unsigned int start_at = 0;\n    unsigned int idx = 0;\n    unsigned char *output = (unsigned char *)TLS_MALLOC(alloc_len);\n\n    *output_len = 0;\n    if (!output)\n        return NULL;\n    for (i = 0; i < input_length; i++) {\n        if ((data_in[i] == '\\n') || (data_in[i] == '\\r'))\n            continue;\n        \n        if (data_in[i] != '-')  {\n            /* read entire line */\n            while ((i < input_length) && (data_in[i] != '\\n'))\n                i++;\n            continue;\n        }\n        \n        if (data_in[i] == '-') {\n            unsigned int end_idx = i;\n            /* read until end of line */\n            while ((i < input_length) && (data_in[i] != '\\n'))\n                i++;\n            if (start_at) {\n                if (cert_index > 0) {\n                    cert_index--;\n                    start_at = 0;\n                } else {\n                    idx = _private_b64_decode((const char *)&data_in[start_at], end_idx - start_at, output);\n                    break;\n                }\n            } else\n                start_at = i + 1;\n        }\n    }\n    *output_len = idx;\n    if (!idx) {\n        TLS_FREE(output);\n        return NULL;\n    }\n    return output;\n}\n\nint _is_oid(const unsigned char *oid, const unsigned char *compare_to, int compare_to_len) {\n    int i = 0;\n    while ((oid[i]) && (i < compare_to_len)) {\n        if (oid[i] != compare_to[i])\n            return 0;\n        \n        i++;\n    }\n    return 1;\n}\n\nint _is_oid2(const unsigned char *oid, const unsigned char *compare_to, int compare_to_len, int oid_len) {\n    int i = 0;\n    if (oid_len < compare_to_len)\n        compare_to_len = oid_len;\n    while (i < compare_to_len) {\n        if (oid[i] != compare_to[i])\n            return 0;\n        \n        i++;\n    }\n    return 1;\n}\n\nstruct TLSCertificate *tls_create_certificate() {\n    struct TLSCertificate *cert = (struct TLSCertificate *)TLS_MALLOC(sizeof(struct TLSCertificate));\n    if (cert)\n        memset(cert, 0, sizeof(struct TLSCertificate));\n    return cert;\n}\n\nint tls_certificate_valid_subject_name(const unsigned char *cert_subject, const char *subject) {\n    const char *wildcard;\n\n    /* no subjects ... */\n    if (((!cert_subject) || (!cert_subject[0])) && ((!subject) || (!subject[0])))\n        return 0;\n    \n    if ((!subject) || (!subject[0]))\n        return bad_certificate;\n    \n    if ((!cert_subject) || (!cert_subject[0]))\n        return bad_certificate;\n    \n    /* exact match */\n    if (!strcmp((const char *)cert_subject, subject))\n        return 0;\n    \n    wildcard = strchr((const char *)cert_subject, '*');\n    if (wildcard) {\n        const char *match;\n\n        /* 6.4.3 (1) The client SHOULD NOT attempt to match a presented identifier in\n           which the wildcard character comprises a label other than the left-most label */\n        if (!wildcard[1]) {\n            /* subject is [*]\n               or\n               subject is [something*] .. invalid */\n            return bad_certificate;\n        }\n        wildcard++;\n        match = strstr(subject, wildcard);\n        if ((!match) && (wildcard[0] == '.')) {\n            /* check *.domain.com agains domain.com */\n            wildcard++;\n            if (!strcasecmp(subject, wildcard))\n                return 0;\n        }\n        if (match) {\n            uintptr_t offset = (uintptr_t)match - (uintptr_t)subject;\n            if (offset) {\n                /* check for foo.*.domain.com against *.domain.com (invalid) */\n                if (memchr(subject, '.', offset))\n                    return bad_certificate;\n            }\n            /* check if exact match */\n            if (!strcasecmp(match, wildcard))\n                return 0;\n        }\n    }\n    \n    return bad_certificate;\n}\n\nint tls_certificate_valid_subject(struct TLSCertificate *cert, const char *subject) {\n    int i, err;\n\n    if (!cert)\n        return certificate_unknown;\n    err = tls_certificate_valid_subject_name(cert->subject, subject);\n    if ((err) && (cert->san)) {\n        for (i = 0; i < cert->san_length; i++) {\n            err = tls_certificate_valid_subject_name(cert->san[i], subject);\n            if (!err)\n                return err;\n        }\n    }\n    return err;\n}\n\nint tls_certificate_is_valid(struct TLSCertificate *cert) {\n    /* 20160224182300Z */\n    char current_time[16];\n    time_t t = time(NULL);\n    struct tm *utct = gmtime(&t);\n\n    if (!cert)\n        return certificate_unknown;\n    if (!cert->not_before)\n        return certificate_unknown;\n    if (!cert->not_after)\n        return certificate_unknown;\n    if (utct) {\n        current_time[0] = 0;\n#ifdef HAS_SNPRINTF\n        snprintf(current_time, sizeof(current_time), \"%04d%02d%02d%02d%02d%02dZ\", 1900 + utct->tm_year, utct->tm_mon + 1, utct->tm_mday, utct->tm_hour, utct->tm_min, utct->tm_sec);\n#else\n        (void)sprintf(current_time, \"%04d%02d%02d%02d%02d%02dZ\", 1900 + utct->tm_year, utct->tm_mon + 1, utct->tm_mday, utct->tm_hour, utct->tm_min, utct->tm_sec);\n#endif\n        if (strcasecmp((char *)cert->not_before, current_time) > 0) {\n            DEBUG_PRINT3(\"Certificate is not yer valid, now: %s (validity: %s - %s)\\n\", current_time, cert->not_before, cert->not_after);\n            return certificate_expired;\n        }\n        if (strcasecmp((char *)cert->not_after, current_time) < 0) {\n            DEBUG_PRINT3(\"Expired certificate, now: %s (validity: %s - %s)\\n\", current_time, cert->not_before, cert->not_after);\n            return certificate_expired;\n        }\n        DEBUG_PRINT3(\"Valid certificate, now: %s (validity: %s - %s)\\n\", current_time, cert->not_before, cert->not_after);\n    }\n    return 0;\n}\n\nvoid tls_certificate_set_copy(unsigned char **member, const unsigned char *val, int len) {\n    if (!member)\n        return;\n    TLS_FREE(*member);\n    if (len) {\n        *member = (unsigned char *)TLS_MALLOC(len + 1);\n        if (*member) {\n            memcpy(*member, val, len);\n            (*member)[len] = 0;\n        }\n    } else\n        *member = NULL;\n}\n\nvoid tls_certificate_set_copy_date(unsigned char **member, const unsigned char *val, int len) {\n    if (!member)\n        return;\n    TLS_FREE(*member);\n    if (len > 4) {\n        *member = (unsigned char *)TLS_MALLOC(len + 3);\n        if (*member) {\n            if (val[0] == '9') {\n                (*member)[0]='1';\n                (*member)[1]='9';\n            } else {\n                (*member)[0]='2';\n                (*member)[1]='0';\n            }\n            memcpy(*member + 2, val, len);\n            (*member)[len] = 0;\n        }\n    } else\n        *member = NULL;\n}\n\nvoid tls_certificate_set_key(struct TLSCertificate *cert, const unsigned char *val, int len) {\n    if ((!val[0]) && (len % 2)) {\n        val++;\n        len--;\n    }\n    tls_certificate_set_copy(&cert->pk, val, len);\n    if (cert->pk)\n        cert->pk_len = len;\n}\n\nvoid tls_certificate_set_priv(struct TLSCertificate *cert, const unsigned char *val, int len) {\n    tls_certificate_set_copy(&cert->priv, val, len);\n    if (cert->priv)\n        cert->priv_len = len;\n}\n\nvoid tls_certificate_set_sign_key(struct TLSCertificate *cert, const unsigned char *val, int len) {\n    if ((!val[0]) && (len % 2)) {\n        val++;\n        len--;\n    }\n    tls_certificate_set_copy(&cert->sign_key, val, len);\n    if (cert->sign_key)\n        cert->sign_len = len;\n}\n\n/* needs snprintf! compile with -DHAS_SNPRINTF if you do. */\n#ifdef DEBUG\nchar *tls_certificate_to_string(struct TLSCertificate *cert, char *buffer, int len) {\n    unsigned int i;\n    if (!buffer)\n        return NULL;\n    buffer[0] = 0;\n#ifdef HAS_SNPRINTF\n    if (cert->version) {\n        int res = snprintf(buffer, len, \"X.509v%i certificate\\n  Issued by: [%s]%s (%s)\\n  Issued to: [%s]%s (%s, %s)\\n  Subject: %s\\n  Validity: %s - %s\\n  OCSP: %s\\n  Serial number: \",\n                           (int)cert->version,\n                           cert->issuer_country, cert->issuer_entity, cert->issuer_subject,\n                           cert->country, cert->entity, cert->state, cert->location,\n                           cert->subject,\n                           cert->not_before, cert->not_after,\n                           cert->ocsp\n                           );\n        if (res > 0) {\n            for (i = 0; i < cert->serial_len; i++)\n                res += snprintf(buffer + res, len - res, \"%02x\", (int)cert->serial_number[i]);\n        }\n        if ((cert->san) && (cert->san_length)) {\n            res += snprintf(buffer + res, len - res, \"\\n  Alternative subjects: \");\n            for (i = 0; i < cert->san_length; i++) {\n                if (i)\n                    res += snprintf(buffer + res, len - res, \", %s\", cert->san[i]);\n                else\n                    res += snprintf(buffer + res, len - res, \"%s\", cert->san[i]);\n            }\n        }\n        res += snprintf(buffer + res, len - res, \"\\n  Key (%i bits, \", cert->pk_len * 8);\n        if (res > 0) {\n            switch (cert->key_algorithm) {\n                case TLS_RSA_SIGN_RSA:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_RSA\");\n                    break;\n                case TLS_RSA_SIGN_MD5:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_MD5\");\n                    break;\n                case TLS_RSA_SIGN_SHA1:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_SHA1\");\n                    break;\n                case TLS_RSA_SIGN_SHA256:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_SHA256\");\n                    break;\n                case TLS_RSA_SIGN_SHA384:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_SHA384\");\n                    break;\n                case TLS_RSA_SIGN_SHA512:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_SHA512\");\n                    break;\n                case TLS_ECDSA_SIGN_SHA256:\n                    res += snprintf(buffer + res, len - res, \"ECDSA_SIGN_SHA512\");\n                    break;\n                case TLS_EC_PUBLIC_KEY:\n                    res += snprintf(buffer + res, len - res, \"EC_PUBLIC_KEY\");\n                    break;\n                default:\n                    res += snprintf(buffer + res, len - res, \"not supported (%i)\", (int)cert->key_algorithm);\n            }\n        }\n        if ((res > 0) && (cert->ec_algorithm)) {\n            switch (cert->ec_algorithm) {\n                case TLS_EC_prime192v1:\n                    res += snprintf(buffer + res, len - res, \" prime192v1\");\n                    break;\n                case TLS_EC_prime192v2:\n                    res += snprintf(buffer + res, len - res, \" prime192v2\");\n                    break;\n                case TLS_EC_prime192v3:\n                    res += snprintf(buffer + res, len - res, \" prime192v3\");\n                    break;\n                case TLS_EC_prime239v2:\n                    res += snprintf(buffer + res, len - res, \" prime239v2\");\n                    break;\n                case TLS_EC_secp256r1:\n                    res += snprintf(buffer + res, len - res, \" EC_secp256r1\");\n                    break;\n                case TLS_EC_secp224r1:\n                    res += snprintf(buffer + res, len - res, \" EC_secp224r1\");\n                    break;\n                case TLS_EC_secp384r1:\n                    res += snprintf(buffer + res, len - res, \" EC_secp384r1\");\n                    break;\n                case TLS_EC_secp521r1:\n                    res += snprintf(buffer + res, len - res, \" EC_secp521r1\");\n                    break;\n                default:\n                    res += snprintf(buffer + res, len - res, \" unknown(%i)\", (int)cert->ec_algorithm);\n            }\n        }\n        res += snprintf(buffer + res, len - res, \"):\\n\");\n        if (res > 0) {\n            for (i = 0; i < cert->pk_len; i++)\n                res += snprintf(buffer + res, len - res, \"%02x\", (int)cert->pk[i]);\n            res += snprintf(buffer + res, len - res, \"\\n  Signature (%i bits, \", cert->sign_len * 8);\n            switch (cert->algorithm) {\n                case TLS_RSA_SIGN_RSA:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_RSA):\\n\");\n                    break;\n                case TLS_RSA_SIGN_MD5:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_MD5):\\n\");\n                    break;\n                case TLS_RSA_SIGN_SHA1:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_SHA1):\\n\");\n                    break;\n                case TLS_RSA_SIGN_SHA256:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_SHA256):\\n\");\n                    break;\n                case TLS_RSA_SIGN_SHA384:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_SHA384):\\n\");\n                    break;\n                case TLS_RSA_SIGN_SHA512:\n                    res += snprintf(buffer + res, len - res, \"RSA_SIGN_SHA512):\\n\");\n                    break;\n                case TLS_EC_PUBLIC_KEY:\n                    res += snprintf(buffer + res, len - res, \"EC_PUBLIC_KEY):\\n\");\n                    break;\n                default:\n                    res += snprintf(buffer + res, len - res, \"not supported):\\n\");\n            }\n            \n            for (i = 0; i < cert->sign_len; i++)\n                res += snprintf(buffer + res, len - res, \"%02x\", (int)cert->sign_key[i]);\n        }\n    } else\n    if ((cert->priv) && (cert->priv_len)) {\n        int res = snprintf(buffer, len, \"X.509 private key\\n\");\n        res += snprintf(buffer + res, len - res, \"  Private Key: \");\n        if (res > 0) {\n            for (i = 0; i < cert->priv_len; i++)\n                res += snprintf(buffer + res, len - res, \"%02x\", (int)cert->priv[i]);\n        }\n    } else\n        snprintf(buffer, len, \"Empty ASN1 file\");\n#else\n    fprintf(stderr, \"certificate display requires snprintf() currently\\n\");\n#endif\n    return buffer;\n}\n#endif\n\nvoid tls_certificate_set_exponent(struct TLSCertificate *cert, const unsigned char *val, int len) {\n    tls_certificate_set_copy(&cert->exponent, val, len);\n    if (cert->exponent)\n        cert->exponent_len = len;\n}\n\nvoid tls_certificate_set_serial(struct TLSCertificate *cert, const unsigned char *val, int len) {\n    tls_certificate_set_copy(&cert->serial_number, val, len);\n    if (cert->serial_number)\n        cert->serial_len = len;\n}\n\nvoid tls_certificate_set_algorithm(struct TLSContext *context, unsigned int *algorithm, const unsigned char *val, int len) {\n    if ((len == 7) && (_is_oid(val, TLS_EC_PUBLIC_KEY_OID, 7))) {\n        *algorithm = TLS_EC_PUBLIC_KEY;\n        return;\n    }\n    if (len == 8) {\n        if (_is_oid(val, TLS_EC_prime192v1_OID, len)) {\n            *algorithm = TLS_EC_prime192v1;\n            return;\n        }\n        if (_is_oid(val, TLS_EC_prime192v2_OID, len)) {\n            *algorithm = TLS_EC_prime192v2;\n            return;\n        }\n        if (_is_oid(val, TLS_EC_prime192v3_OID, len)) {\n            *algorithm = TLS_EC_prime192v3;\n            return;\n        }\n        if (_is_oid(val, TLS_EC_prime239v1_OID, len)) {\n            *algorithm = TLS_EC_prime239v1;\n            return;\n        }\n        if (_is_oid(val, TLS_EC_prime239v2_OID, len)) {\n            *algorithm = TLS_EC_prime239v2;\n            return;\n        }\n        if (_is_oid(val, TLS_EC_prime239v3_OID, len)) {\n            *algorithm = TLS_EC_prime239v3;\n            return;\n        }\n        if (_is_oid(val, TLS_EC_prime256v1_OID, len)) {\n            *algorithm = TLS_EC_prime256v1;\n            return;\n        }\n    }\n    if (len == 5) {\n        if (_is_oid2(val, TLS_EC_secp224r1_OID, len, sizeof(TLS_EC_secp224r1_OID) - 1)) {\n            *algorithm = TLS_EC_secp224r1;\n            return;\n        }\n        if (_is_oid2(val, TLS_EC_secp384r1_OID, len, sizeof(TLS_EC_secp384r1_OID) - 1)) {\n            *algorithm = TLS_EC_secp384r1;\n            return;\n        }\n        if (_is_oid2(val, TLS_EC_secp521r1_OID, len, sizeof(TLS_EC_secp521r1_OID) - 1)) {\n            *algorithm = TLS_EC_secp521r1;\n            return;\n        }\n    }\n    if (len != 9)\n        return;\n    \n    if (_is_oid(val, TLS_RSA_SIGN_SHA256_OID, 9)) {\n        *algorithm = TLS_RSA_SIGN_SHA256;\n        return;\n    }\n    \n    if (_is_oid(val, TLS_RSA_SIGN_RSA_OID, 9)) {\n        *algorithm = TLS_RSA_SIGN_RSA;\n        return;\n    }\n    \n    if (_is_oid(val, TLS_RSA_SIGN_SHA1_OID, 9)) {\n        *algorithm = TLS_RSA_SIGN_SHA1;\n        return;\n    }\n    \n    if (_is_oid(val, TLS_RSA_SIGN_SHA512_OID, 9)) {\n        *algorithm = TLS_RSA_SIGN_SHA512;\n        return;\n    }\n    \n    if (_is_oid(val, TLS_RSA_SIGN_SHA384_OID, 9)) {\n        *algorithm = TLS_RSA_SIGN_SHA384;\n        return;\n    }\n    \n    if (_is_oid(val, TLS_RSA_SIGN_MD5_OID, 9)) {\n        *algorithm = TLS_RSA_SIGN_MD5;\n        return;\n    }\n\n    if (_is_oid(val, TLS_ECDSA_SIGN_SHA256_OID, 9)) {\n        *algorithm = TLS_ECDSA_SIGN_SHA256;\n        return;\n    }\n\n    /* client should fail on unsupported signature */\n    if (!context->is_server) {\n        DEBUG_PRINT0(\"UNSUPPORTED SIGNATURE ALGORITHM\\n\");\n        context->critical_error = 1;\n    }\n}\n\nvoid tls_destroy_certificate(struct TLSCertificate *cert) {\n    if (cert) {\n        int i;\n        TLS_FREE(cert->exponent);\n        TLS_FREE(cert->pk);\n        TLS_FREE(cert->issuer_country);\n        TLS_FREE(cert->issuer_state);\n        TLS_FREE(cert->issuer_location);\n        TLS_FREE(cert->issuer_entity);\n        TLS_FREE(cert->issuer_subject);\n        TLS_FREE(cert->country);\n        TLS_FREE(cert->state);\n        TLS_FREE(cert->location);\n        TLS_FREE(cert->subject);\n        for (i = 0; i < cert->san_length; i++) {\n            TLS_FREE(cert->san[i]);\n        }\n        TLS_FREE(cert->san);\n        TLS_FREE(cert->ocsp);\n        TLS_FREE(cert->serial_number);\n        TLS_FREE(cert->entity);\n        TLS_FREE(cert->not_before);\n        TLS_FREE(cert->not_after);\n        TLS_FREE(cert->sign_key);\n        TLS_FREE(cert->priv);\n        TLS_FREE(cert->der_bytes);\n        TLS_FREE(cert->bytes);\n        TLS_FREE(cert->fingerprint);\n        TLS_FREE(cert);\n    }\n}\n\nstruct TLSPacket *tls_create_packet(struct TLSContext *context, unsigned char type, unsigned short version, int payload_size_hint) {\n    struct TLSPacket *packet = (struct TLSPacket *)TLS_MALLOC(sizeof(struct TLSPacket));\n    if (!packet)\n        return NULL;\n    packet->broken = 0;\n    if (payload_size_hint > 0)\n        packet->size = payload_size_hint + 10;\n    else\n        packet->size = TLS_BLOB_INCREMENT;\n    packet->buf = (unsigned char *)TLS_MALLOC(packet->size);\n    packet->context = context;\n    if (!packet->buf) {\n        TLS_FREE(packet);\n        return NULL;\n    }\n    if ((context) && (context->dtls))\n        packet->len = 13;\n    else\n        packet->len = 5;\n    packet->buf[0] = type;\n#ifdef WITH_TLS_13\n#if NO_FUNNY_ALIGNMENT\n    switch (version) {\n        case TLS_V13:\n            /* check if context is not null. If null, is a tls_export_context call */\n            if (context)\n                __short(packet->buf, 1, 0x0303);\n            else\n                __short(packet->buf, 1, version);\n            break;\n        case DTLS_V13:\n            __short(packet->buf, 1, DTLS_V13);\n            break;\n        default:\n            __short(packet->buf, 1, version);\n#else\n    switch (version) {\n        case TLS_V13:\n            /* check if context is not null. If null, is a tls_export_context call */\n            if (context)\n                *(unsigned short *)(packet->buf + 1) = 0x0303; /* no need to reorder (same bytes) */\n            else\n                *(unsigned short *)(packet->buf + 1) = htons(version);\n            break;\n        case DTLS_V13:\n            *(unsigned short *)(packet->buf + 1) = htons(DTLS_V13);\n            break;\n        default:\n            *(unsigned short *)(packet->buf + 1) = htons(version);\n#endif\n    }\n#else\n#if NO_FUNNY_ALIGNMENT\n    __short(packet->buf, 1, version);\n#else\n    *(unsigned short *)(packet->buf + 1) = htons(version);\n#endif\n#endif\n    return packet;\n}\n\nvoid tls_destroy_packet(struct TLSPacket *packet) {\n    if (packet) {\n        if (packet->buf)\n            TLS_FREE(packet->buf);\n        TLS_FREE(packet);\n    }\n}\n\nint _private_tls_crypto_create(struct TLSContext *context, int key_length, unsigned char *localkey, unsigned char *localiv, unsigned char *remotekey, unsigned char *remoteiv) {\n    int is_aead;\n    int cipherID;\n\n    if (context->crypto.created) {\n        if (context->crypto.created == 1) {\n            cbc_done(&context->crypto.ctx_remote.aes_remote);\n            cbc_done(&context->crypto.ctx_local.aes_local);\n        } else {\n#ifdef TLS_WITH_CHACHA20_POLY1305\n            if (context->crypto.created == 2) {\n#endif\n            unsigned char dummy_buffer[32];\n            unsigned long tag_len = 0;\n            gcm_done(&context->crypto.ctx_remote.aes_gcm_remote, dummy_buffer, &tag_len);\n            gcm_done(&context->crypto.ctx_local.aes_gcm_local, dummy_buffer, &tag_len);\n#ifdef TLS_WITH_CHACHA20_POLY1305\n            }\n#endif\n        }\n        context->crypto.created = 0;\n    }\n    tls_init();\n    is_aead = _private_tls_is_aead(context);\n    cipherID = find_cipher(\"aes\");\n    DEBUG_PRINT1(\"Using cipher ID: %x\\n\", (int)context->cipher);\n#ifdef TLS_WITH_CHACHA20_POLY1305\n    if (is_aead == 2) {\n        unsigned int counter = 1;\n\n        chacha_keysetup(&context->crypto.ctx_local.chacha_local, localkey, key_length * 8);\n        chacha_ivsetup_96bitnonce(&context->crypto.ctx_local.chacha_local, localiv, (unsigned char *)&counter);\n\n        chacha_keysetup(&context->crypto.ctx_remote.chacha_remote, remotekey, key_length * 8);\n        chacha_ivsetup_96bitnonce(&context->crypto.ctx_remote.chacha_remote, remoteiv, (unsigned char *)&counter);\n\n        context->crypto.created = 3;\n    } else\n#endif\n    if (is_aead) {\n        int res1 = gcm_init(&context->crypto.ctx_local.aes_gcm_local, cipherID, localkey, key_length);\n        int res2 = gcm_init(&context->crypto.ctx_remote.aes_gcm_remote, cipherID, remotekey, key_length);\n        \n        if ((res1) || (res2))\n            return TLS_GENERIC_ERROR;\n        context->crypto.created = 2;\n    } else {\n        int res1 = cbc_start(cipherID, localiv, localkey, key_length, 0, &context->crypto.ctx_local.aes_local);\n        int res2 = cbc_start(cipherID, remoteiv, remotekey, key_length, 0, &context->crypto.ctx_remote.aes_remote);\n        \n        if ((res1) || (res2))\n            return TLS_GENERIC_ERROR;\n        context->crypto.created = 1;\n    }\n    return 0;\n}\n\nint _private_tls_crypto_encrypt(struct TLSContext *context, unsigned char *buf, unsigned char *ct, unsigned int len) {\n    if (context->crypto.created == 1)\n        return cbc_encrypt(buf, ct, len, &context->crypto.ctx_local.aes_local);\n\n    memset(ct, 0, len);\n    return TLS_GENERIC_ERROR;\n}\n\nint _private_tls_crypto_decrypt(struct TLSContext *context, unsigned char *buf, unsigned char *pt, unsigned int len) {\n    if (context->crypto.created == 1)\n        return cbc_decrypt(buf, pt, len, &context->crypto.ctx_remote.aes_remote);\n    \n    memset(pt, 0, len);\n    return TLS_GENERIC_ERROR;\n}\n\nvoid _private_tls_crypto_done(struct TLSContext *context) {\n    unsigned char dummy_buffer[32];\n    unsigned long tag_len = 0;\n    switch (context->crypto.created) {\n        case 1:\n            cbc_done(&context->crypto.ctx_remote.aes_remote);\n            cbc_done(&context->crypto.ctx_local.aes_local);\n            break;\n        case 2:\n            gcm_done(&context->crypto.ctx_remote.aes_gcm_remote, dummy_buffer, &tag_len);\n            gcm_done(&context->crypto.ctx_local.aes_gcm_local, dummy_buffer, &tag_len);\n            break;\n    }\n    context->crypto.created = 0;\n}\n\nvoid tls_packet_update(struct TLSPacket *packet) {\n    if ((packet) && (!packet->broken)) {                   \n        int footer_size = 0;\n        unsigned int header_size = 5;\n\n#ifdef WITH_TLS_13\n        if ((packet->context) && ((packet->context->version == TLS_V13) || (packet->context->version == DTLS_V13)) && (packet->context->cipher_spec_set) && (packet->context->crypto.created)) {\n            /* type */\n            tls_packet_uint8(packet, packet->buf[0]);\n            /* no padding */\n            /* tls_packet_uint8(packet, 0); */\n            footer_size = 1;\n        }\n#endif\n        if ((packet->context) && (packet->context->dtls)) {\n            uint64_t sequence_number;\n\n            header_size = 13;\n#if NO_FUNNY_ALIGNMENT\n            __short(packet->buf, 3, packet->context->dtls_epoch_local);\n#else\n            *(unsigned short *)(packet->buf + 3) = htons(packet->context->dtls_epoch_local);\n#endif\n            sequence_number = packet->context->local_sequence_number;\n            packet->buf[5] = (unsigned char)(sequence_number / 0x10000000000LL);\n            sequence_number %= 0x10000000000LL;\n            packet->buf[6] = (unsigned char)(sequence_number / 0x100000000LL);\n            sequence_number %= 0x100000000LL;\n            packet->buf[7] = (unsigned char)(sequence_number / 0x1000000);\n            sequence_number %= 0x1000000;\n            packet->buf[8] = (unsigned char)(sequence_number / 0x10000);\n            sequence_number %= 0x10000;\n            packet->buf[9] = (unsigned char)(sequence_number / 0x100);\n            sequence_number %= 0x100;\n            packet->buf[10] = (unsigned char)sequence_number;\n\n#if NO_FUNNY_ALIGNMENT\n            __short(packet->buf, 11, (packet->len - header_size));\n#else\n            *(unsigned short *)(packet->buf + 11) = htons(packet->len - header_size);\n#endif\n        } else\n#if NO_FUNNY_ALIGNMENT\n            __short(packet->buf, 3, (packet->len - header_size));\n#else\n            *(unsigned short *)(packet->buf + 3) = htons(packet->len - header_size);\n#endif\n        if (packet->context) {\n            if (packet->buf[0] != TLS_CHANGE_CIPHER)  {\n                if ((packet->buf[0] == TLS_HANDSHAKE) && (packet->len > header_size)) {\n                    unsigned char handshake_type = packet->buf[header_size];\n                    if ((handshake_type != 0x00) && (handshake_type != 0x03))\n                        _private_tls_update_hash(packet->context, packet->buf + header_size, packet->len - header_size - footer_size);\n                }\n#ifdef TLS_12_FALSE_START\n                if (((packet->context->cipher_spec_set) || (packet->context->false_start)) && (packet->context->crypto.created)) {\n#else\n                if ((packet->context->cipher_spec_set) && (packet->context->crypto.created)) {\n#endif\n                    int block_size = TLS_AES_BLOCK_SIZE;\n                    int mac_size = 0;\n                    unsigned int length = 0;\n                    unsigned char padding = 0;\n                    unsigned int pt_length = packet->len - header_size;\n                    \n                    if (packet->context->crypto.created == 1) {\n                        mac_size = _private_tls_mac_length(packet->context);\n#ifdef TLS_LEGACY_SUPPORT\n                        if (packet->context->version == TLS_V10)\n                            length = packet->len - header_size + mac_size;\n                        else\n#endif\n                            length = packet->len - header_size + TLS_AES_IV_LENGTH + mac_size;\n                        padding = block_size - length % block_size;\n                        length += padding;\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                    } else\n                    if (packet->context->crypto.created == 3) {\n                        mac_size = POLY1305_TAGLEN;\n                        length = packet->len - header_size + mac_size;\n#endif\n                    } else {\n                        mac_size = TLS_GCM_TAG_LEN;\n                        length = packet->len - header_size + 8 + mac_size;\n                    }\n                    if (packet->context->crypto.created == 1) {\n                        unsigned char *buf = (unsigned char *)TLS_MALLOC(length);\n                        if (buf) {\n                            unsigned char *ct = (unsigned char *)TLS_MALLOC(length + header_size);\n                            if (ct) {\n                                unsigned int buf_pos = 0;\n                                memcpy(ct, packet->buf, header_size - 2);\n                                *(unsigned short *)&ct[header_size - 2] = htons(length);\n#ifdef TLS_LEGACY_SUPPORT\n                                if (packet->context->version != TLS_V10)\n#endif\n                                {\n                                    tls_random(buf, TLS_AES_IV_LENGTH);\n                                    buf_pos += TLS_AES_IV_LENGTH;\n                                }\n                                /* copy payload */\n                                memcpy(buf + buf_pos, packet->buf + header_size, packet->len - header_size);\n                                buf_pos += packet->len - header_size;\n                                if (packet->context->dtls) {\n                                    unsigned char temp_buf[5];\n                                    uint64_t dtls_sequence_number;\n\n                                    memcpy(temp_buf, packet->buf, 3);\n                                    *(unsigned short *)(temp_buf + 3) = *(unsigned short *)&packet->buf[header_size - 2];\n                                    dtls_sequence_number = ntohll(*(uint64_t *)&packet->buf[3]);\n                                    _private_tls_hmac_message(1, packet->context, temp_buf, 5, packet->buf + header_size, packet->len  - header_size, buf + buf_pos, mac_size, dtls_sequence_number);\n                                } else\n                                    _private_tls_hmac_message(1, packet->context, packet->buf, packet->len, NULL, 0, buf + buf_pos, mac_size, 0);\n                                buf_pos += mac_size;\n                                \n                                memset(buf + buf_pos, padding - 1, padding);\n                                buf_pos += padding;\n                                \n                                /* DEBUG_DUMP_HEX_LABEL(\"PT BUFFER\", buf, length); */\n                                _private_tls_crypto_encrypt(packet->context, buf, ct + header_size, length);\n                                TLS_FREE(packet->buf);\n                                packet->buf = ct;\n                                packet->len = length + header_size;\n                                packet->size = packet->len;\n                            } else {\n                                /* invalidate packet */\n                                memset(packet->buf, 0, packet->len);\n                            }\n                            TLS_FREE(buf);\n                        } else {\n                            /* invalidate packet */\n                            memset(packet->buf, 0, packet->len);\n                        }\n                    } else\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                    if (packet->context->crypto.created >= 2) {\n#else\n                    if (packet->context->crypto.created == 2) {\n#endif\n                        unsigned char iv[TLS_13_AES_GCM_IV_LENGTH];\n                        unsigned long taglen = TLS_GCM_TAG_LEN;\n\n                        /* + 1 = type */\n                        int ct_size = length + header_size + 12 + TLS_MAX_TAG_LEN + 1;\n                        unsigned char *ct = (unsigned char *)TLS_MALLOC(ct_size);\n                        if (ct) {\n                            unsigned char aad[13];\n                            unsigned char *sequence = aad;\n                            int aad_size = sizeof(aad);\n                            int ct_pos;\n\n                            memset(ct, 0, ct_size);\n                            /* AEAD\n                               sequence number (8 bytes)\n                               content type (1 byte)\n                               version (2 bytes)\n                               length (2 bytes) */\n#ifdef WITH_TLS_13\n                            if ((packet->context->version == TLS_V13) || (packet->context->version == DTLS_V13)) {\n                                aad[0] = TLS_APPLICATION_DATA;\n                                aad[1] = packet->buf[1];\n                                aad[2] = packet->buf[2];\n#if NO_FUNNY_ALIGNMENT\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                                if (packet->context->crypto.created == 3)\n                                    __short(aad, 3, packet->len + POLY1305_TAGLEN - header_size);\n                                else\n#endif\n                                    __short(aad, 3, packet->len + TLS_GCM_TAG_LEN - header_size);\n#else\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                                if (packet->context->crypto.created == 3)\n                                    *((unsigned short *)(aad + 3)) = htons(packet->len + POLY1305_TAGLEN - header_size);\n                                else\n#endif\n                                    *((unsigned short *)(aad + 3)) = htons(packet->len + TLS_GCM_TAG_LEN - header_size);\n#endif\n                                aad_size = 5;\n                                sequence = aad + 5;\n                                if (packet->context->dtls)\n                                    *((uint64_t *)sequence) = *(uint64_t *)&packet->buf[3];\n                                else\n#if NO_FUNNY_ALIGNMENT\n#if __BIG_ENDIAN__\n                                    memcpy((void *)sequence, (void *)&packet->context->local_sequence_number, sizeof(uint64_t));\n#else\n                                    __llong((void *)sequence, packet->context->local_sequence_number);\n#endif\n#else\n                                    *((uint64_t *)sequence) = htonll(packet->context->local_sequence_number);\n#endif\n                            } else {\n#endif\n                                if (packet->context->dtls)\n                                    *((uint64_t *)aad) = *(uint64_t *)&packet->buf[3];\n                                else\n#if NO_FUNNY_ALIGNMENT\n#if __BIG_ENDIAN__\n                                    memcpy((void *)aad, (void *)&packet->context->local_sequence_number, sizeof(uint64_t));\n#else\n                                    __llong((void *)aad, packet->context->local_sequence_number);\n#endif\n#else\n                                    *((uint64_t *)aad) = htonll(packet->context->local_sequence_number);\n#endif\n                                aad[8] = packet->buf[0];\n                                aad[9] = packet->buf[1];\n                                aad[10] = packet->buf[2];\n#if NO_FUNNY_ALIGNMENT\n                                __short(aad, 11, (packet->len - header_size));\n#else\n                                *((unsigned short *)(aad + 11)) = htons(packet->len - header_size);\n#endif\n#ifdef WITH_TLS_13\n                            }\n#endif\n                            ct_pos = header_size;\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                            if (packet->context->crypto.created == 3) {\n                                unsigned int counter = 1;\n                                unsigned char poly1305_key[POLY1305_KEYLEN];\n\n                                chacha_ivupdate(&packet->context->crypto.ctx_local.chacha_local, packet->context->crypto.ctx_local_mac.local_aead_iv, sequence, (u8 *)&counter);\n                                chacha20_poly1305_key(&packet->context->crypto.ctx_local.chacha_local, poly1305_key);\n                                ct_pos += chacha20_poly1305_aead(&packet->context->crypto.ctx_local.chacha_local, packet->buf + header_size, pt_length, aad, aad_size, poly1305_key, ct + ct_pos);\n                            } else {\n#endif\n#ifdef WITH_TLS_13\n                                if ((packet->context->version == TLS_V13) || (packet->context->version == DTLS_V13)) {\n                                    int i;\n                                    int offset = TLS_13_AES_GCM_IV_LENGTH - 8;\n\n                                    memcpy(iv, packet->context->crypto.ctx_local_mac.local_iv, TLS_13_AES_GCM_IV_LENGTH);\n                                    for (i = 0; i < 8; i++)\n                                        iv[offset + i] = packet->context->crypto.ctx_local_mac.local_iv[offset + i] ^ sequence[i];\n                                } else {\n#endif\n                                    memcpy(iv, packet->context->crypto.ctx_local_mac.local_aead_iv, TLS_AES_GCM_IV_LENGTH);\n                                    tls_random(iv + TLS_AES_GCM_IV_LENGTH, 8);\n                                    memcpy(ct + ct_pos, iv + TLS_AES_GCM_IV_LENGTH, 8);\n                                    ct_pos += 8;\n#ifdef WITH_TLS_13\n                                }\n#endif\n\n                                gcm_reset(&packet->context->crypto.ctx_local.aes_gcm_local);\n                                gcm_add_iv(&packet->context->crypto.ctx_local.aes_gcm_local, iv, 12);\n                                gcm_add_aad(&packet->context->crypto.ctx_local.aes_gcm_local, aad, aad_size);                                \n                                gcm_process(&packet->context->crypto.ctx_local.aes_gcm_local, packet->buf + header_size, pt_length, ct + ct_pos, GCM_ENCRYPT);\n                                ct_pos += pt_length;\n                                \n                                gcm_done(&packet->context->crypto.ctx_local.aes_gcm_local, ct + ct_pos, &taglen);\n                                ct_pos += taglen;\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                            }\n#endif\n#ifdef WITH_TLS_13\n                            if ((packet->context->version == TLS_V13) || (packet->context->version == DTLS_V13)) {\n                                ct[0] = TLS_APPLICATION_DATA;\n#if NO_FUNNY_ALIGNMENT\n                                __short(ct, 1, (packet->context->version == TLS_V13 ? TLS_V12 : DTLS_V12));\n#else\n                                *(unsigned short *)&ct[1] = htons(packet->context->version == TLS_V13 ? TLS_V12 : DTLS_V12);\n#endif\n                                /* is dtls? */\n                                if (header_size != 5)\n                                    memcpy(ct, packet->buf + 3, header_size - 2);\n                            } else\n#endif\n                                memcpy(ct, packet->buf, header_size - 2);\n#if NO_FUNNY_ALIGNMENT\n                            /* uggggh */\n                            ct[header_size - 2] = (ct_pos - header_size) >> 8;\n                            ct[header_size - 1] = (ct_pos - header_size) & 0xff;\n#else\n                            *(unsigned short *)&ct[header_size - 2] = htons(ct_pos - header_size);\n#endif\n                            TLS_FREE(packet->buf);\n                            packet->buf = ct;\n                            packet->len = ct_pos;\n                            packet->size = ct_pos;\n                        } else {\n                            /* invalidate packet */\n                            memset(packet->buf, 0, packet->len);\n                        }\n                    } else {\n                        /* invalidate packet (never reached) */\n                        memset(packet->buf, 0, packet->len);\n                    }\n                }\n            } else\n                packet->context->dtls_epoch_local++;\n            packet->context->local_sequence_number++;\n        }\n    }\n}\n\nint tls_packet_append(struct TLSPacket *packet, const unsigned char *buf, unsigned int len) {\n    unsigned int new_len;\n\n    if ((!packet) || (packet->broken))\n        return -1;\n    \n    if (!len)\n        return 0;\n    \n    new_len = packet->len + len;\n    \n    if (new_len > packet->size) {\n        packet->size = (new_len / TLS_BLOB_INCREMENT + 1) * TLS_BLOB_INCREMENT;\n        packet->buf = (unsigned char *)TLS_REALLOC(packet->buf, packet->size);\n        if (!packet->buf) {\n            packet->size = 0;\n            packet->len = 0;\n            packet->broken = 1;\n            return -1;\n        }\n    }\n    memcpy(packet->buf + packet->len, buf, len);\n    packet->len = new_len;\n    return new_len;\n}\n\nint tls_packet_uint8(struct TLSPacket *packet, unsigned char i) {\n    return tls_packet_append(packet, &i, 1);\n}\n\nint tls_packet_uint16(struct TLSPacket *packet, unsigned short i) {\n    unsigned short ni = htons(i);\n    return tls_packet_append(packet, (unsigned char *)&ni, 2);\n}\n\nint tls_packet_uint32(struct TLSPacket *packet, unsigned int i) {\n    unsigned int ni = htonl(i);\n    return tls_packet_append(packet, (unsigned char *)&ni, 4);\n}\n\nint tls_packet_uint24(struct TLSPacket *packet, unsigned int i) {\n    unsigned char buf[3];\n    buf[0] = i / 0x10000;\n    i %= 0x10000;\n    buf[1] = i / 0x100;\n    i %= 0x100;\n    buf[2] = i;\n    \n    return tls_packet_append(packet, buf, 3);\n}\n\nint tls_random(unsigned char *key, int len) {\n#if(1)\n    /* Use our alleged ARC4 randomizer, allegedly */\n    return aarc4random_batch_maybe(key, len);\n#else\n#ifdef TLS_USE_RANDOM_SOURCE\n    TLS_USE_RANDOM_SOURCE(key, len);\n#else\n#ifdef __APPLE__\n    int i = 0;\n    for (i = 0; i < len; i++) {\n        unsigned int v = arc4random() % 0x100;\n        key[i] = (char)v;\n    }\n    return 1;\n#else\n#ifdef _WIN32\n    HCRYPTPROV hProvider = 0;\n    if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {\n        if (CryptGenRandom(hProvider, len, (BYTE *)key)) {\n            CryptReleaseContext(hProvider, 0);\n            return 1;\n        }\n        CryptReleaseContext(hProvider, 0);\n    }\n#else\n    FILE *fp = fopen(\"/dev/urandom\", \"r\");\n    if (fp) {\n        int key_len = fread(key, 1, len, fp);\n        fclose(fp);\n        if (key_len == len)\n            return 1;\n    }\n#endif\n#endif\n#endif\n#endif\n    return 0;\n}\n\nTLSHash *_private_tls_ensure_hash(struct TLSContext *context) {\n    TLSHash *hash = context->handshake_hash;\n    if (!hash) {\n        hash = (TLSHash *)TLS_MALLOC(sizeof(TLSHash));\n        if (hash)\n            memset(hash, 0, sizeof(TLSHash));\n        context->handshake_hash = hash;\n    }\n    return hash;\n}\n\nvoid _private_tls_destroy_hash(struct TLSContext *context) {\n    if (context) {\n        TLS_FREE(context->handshake_hash);\n        context->handshake_hash = NULL;\n    }\n}\n\nvoid _private_tls_create_hash(struct TLSContext *context) {\n    TLSHash *hash;\n\n    if (!context)\n        return;\n    hash = _private_tls_ensure_hash(context);\n    if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        int hash_size = _private_tls_mac_length(context);\n\n        if (hash->created) {\n            unsigned char temp[TLS_MAX_SHA_SIZE];\n            sha384_done(&hash->hash32, temp);\n            sha256_done(&hash->hash48, temp);\n        }\n        sha384_init(&hash->hash48);\n        sha256_init(&hash->hash32);\n        hash->created = 1;\n    } else {\n#ifdef TLS_LEGACY_SUPPORT\n        /* TLS_V11 */\n        if (hash->created) {\n            unsigned char temp[TLS_V11_HASH_SIZE];\n            md5_done(&hash->hash32, temp);\n            sha1_done(&hash->hash2, temp);\n        }\n        md5_init(&hash->hash32);\n        sha1_init(&hash->hash2);\n        hash->created = 1;\n#endif\n    }\n}\n\nint _private_tls_update_hash(struct TLSContext *context, const unsigned char *in, unsigned int len) {\n    TLSHash *hash;\n\n    if (!context)\n        return 0;\n    hash = _private_tls_ensure_hash(context);\n    if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        int hash_size;\n\n        if (!hash->created) {\n            _private_tls_create_hash(context);\n#ifdef TLS_LEGACY_SUPPORT\n            /* cache first hello in case of protocol downgrade */\n            if ((!context->is_server) && (!context->cached_handshake) && (!context->request_client_certificate) && (len)) {\n                context->cached_handshake = (unsigned char *)TLS_MALLOC(len);\n                if (context->cached_handshake) {\n                    memcpy(context->cached_handshake, in, len);\n                    context->cached_handshake_len = len;\n                }\n            }\n#endif\n        }\n        hash_size = _private_tls_mac_length(context);\n        sha256_process(&hash->hash32, in, len);\n        sha384_process(&hash->hash48, in, len);\n        if (!hash_size)\n            hash_size = TLS_SHA256_MAC_SIZE;\n    } else {\n#ifdef TLS_LEGACY_SUPPORT\n        if (!hash->created)\n            _private_tls_create_hash(context);\n        md5_process(&hash->hash32, in, len);\n        sha1_process(&hash->hash2, in, len);\n#endif\n    }\n    if ((context->request_client_certificate) && (len)) {\n        /* cache all messages for verification */\n        int new_len = context->cached_handshake_len + len;\n\n        context->cached_handshake = (unsigned char *)TLS_REALLOC(context->cached_handshake, new_len);\n        if (context->cached_handshake) {\n            memcpy(context->cached_handshake + context->cached_handshake_len, in, len);\n            context->cached_handshake_len = new_len;\n        } else\n            context->cached_handshake_len = 0;\n    }\n    return 0;\n}\n\n#ifdef TLS_LEGACY_SUPPORT\nint _private_tls_change_hash_type(struct TLSContext *context) {\n    TLSHash *hash;\n\n    if (!context)\n        return 0;\n    hash = _private_tls_ensure_hash(context);\n    if ((hash) && (hash->created) && (context->cached_handshake) && (context->cached_handshake_len)) {\n        int res;\n\n        _private_tls_destroy_hash(context);\n        res = _private_tls_update_hash(context, context->cached_handshake, context->cached_handshake_len);\n        TLS_FREE(context->cached_handshake);\n        context->cached_handshake = NULL;\n        context->cached_handshake_len = 0;\n        return res;\n    }\n    return 0;\n}\n#endif\n\nint _private_tls_done_hash(struct TLSContext *context, unsigned char *hout) {\n    int hash_size = 0;\n    TLSHash *hash;\n\n    if (!context)\n        return 0;\n    hash = _private_tls_ensure_hash(context);\n    if (!hash->created)\n        return 0;\n    \n    if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        unsigned char temp[TLS_MAX_SHA_SIZE];\n\n        if (!hout)\n            hout = temp;\n        /* TLS_HASH_DONE(&hash->hash, hout); */\n        hash_size = _private_tls_mac_length(context);\n        if (hash_size == TLS_SHA384_MAC_SIZE) {\n            sha256_done(&hash->hash32, temp);\n            sha384_done(&hash->hash48, hout);\n        } else {\n            sha256_done(&hash->hash32, hout);\n            sha384_done(&hash->hash48, temp);\n            hash_size = TLS_SHA256_MAC_SIZE;\n        }\n    } else {\n#ifdef TLS_LEGACY_SUPPORT\n        /* TLS_V11 */\n        unsigned char temp[TLS_V11_HASH_SIZE];\n\n        if (!hout)\n            hout = temp;\n        md5_done(&hash->hash32, hout);\n        sha1_done(&hash->hash2, hout + 16);\n        hash_size = TLS_V11_HASH_SIZE;\n#endif\n    }\n    hash->created = 0;\n    if (context->cached_handshake) {\n        /* not needed anymore? */\n        TLS_FREE(context->cached_handshake);\n        context->cached_handshake = NULL;\n        context->cached_handshake_len = 0;\n    }\n    return hash_size;\n}\n\nint _private_tls_get_hash_idx(struct TLSContext *context) {\n    if (!context)\n        return -1;\n    switch (_private_tls_mac_length(context)) {\n        case TLS_SHA256_MAC_SIZE:\n            return find_hash(\"sha256\");\n        case TLS_SHA384_MAC_SIZE:\n            return find_hash(\"sha384\");\n        case TLS_SHA1_MAC_SIZE:\n            return find_hash(\"sha1\");\n    }\n    return -1;\n}\n\nint _private_tls_get_hash(struct TLSContext *context, unsigned char *hout) {\n    TLSHash *hash;\n    int hash_size = 0;\n\n    if (!context)\n        return 0;\n    hash = _private_tls_ensure_hash(context);\n    if (!hash->created)\n        return 0;\n    \n    if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        hash_state prec;\n\n        hash_size = _private_tls_mac_length(context);\n        if (hash_size == TLS_SHA384_MAC_SIZE) {\n            memcpy(&prec, &hash->hash48, sizeof(hash_state));\n            sha384_done(&hash->hash48, hout);\n            memcpy(&hash->hash48, &prec, sizeof(hash_state));\n        } else {\n            memcpy(&prec, &hash->hash32, sizeof(hash_state));\n            hash_size = TLS_SHA256_MAC_SIZE;\n            sha256_done(&hash->hash32, hout);\n            memcpy(&hash->hash32, &prec, sizeof(hash_state));\n        }\n    } else {\n#ifdef TLS_LEGACY_SUPPORT\n        /* TLS_V11 */\n        hash_state prec;\n        \n        memcpy(&prec, &hash->hash32, sizeof(hash_state));\n        md5_done(&hash->hash32, hout);\n        memcpy(&hash->hash32, &prec, sizeof(hash_state));\n        \n        memcpy(&prec, &hash->hash2, sizeof(hash_state));\n        sha1_done(&hash->hash2, hout + 16);\n        memcpy(&hash->hash2, &prec, sizeof(hash_state));\n        \n        hash_size = TLS_V11_HASH_SIZE;\n#endif\n    }\n    return hash_size;\n}\n\nint _private_tls_write_packet(struct TLSPacket *packet) {\n    struct TLSContext *context;\n    if (!packet)\n        return -1;\n    context = packet->context;\n    if (!context)\n        return -1;\n    \n    if (context->tls_buffer) {\n        int written;\n        int len = context->tls_buffer_len + packet->len;\n\n        context->tls_buffer = (unsigned char *)TLS_REALLOC(context->tls_buffer, len);\n        if (!context->tls_buffer) {\n            context->tls_buffer_len = 0;\n            return -1;\n        }\n        memcpy(context->tls_buffer + context->tls_buffer_len, packet->buf, packet->len);\n        context->tls_buffer_len = len;\n        written = packet->len;\n        tls_destroy_packet(packet);\n        return written;\n    }\n    context->tls_buffer_len = packet->len;\n    context->tls_buffer = packet->buf;\n    packet->buf = NULL;\n    packet->len = 0;\n    packet->size = 0;\n    tls_destroy_packet(packet);\n    return context->tls_buffer_len;\n}\n\nint _private_tls_write_app_data(struct TLSContext *context, const unsigned char *buf, unsigned int buf_len) {\n    int len;\n\n    if (!context)\n        return -1;\n    if ((!buf) || (!buf_len))\n        return 0;\n    \n    len = context->application_buffer_len + buf_len;\n    context->application_buffer = (unsigned char *)TLS_REALLOC(context->application_buffer, len);\n    if (!context->application_buffer) {\n        context->application_buffer_len = 0;\n        return -1;\n    }\n    memcpy(context->application_buffer + context->application_buffer_len, buf, buf_len);\n    context->application_buffer_len = len;\n    return buf_len;\n}\n\nconst unsigned char *tls_get_write_buffer(struct TLSContext *context, unsigned int *outlen) {\n    if (!outlen)\n        return NULL;\n    if (!context) {\n        *outlen = 0;\n        return NULL;\n    }\n    /* check if any error */\n    if (context->sleep_until) {\n        if (context->sleep_until < time(NULL)) {\n            *outlen = 0;\n            return NULL;\n        }\n        context->sleep_until = 0;\n    }\n    *outlen = context->tls_buffer_len;\n    return context->tls_buffer;\n}\n\nconst unsigned char *tls_get_message(struct TLSContext *context, unsigned int *outlen, unsigned int offset) {\n    unsigned char *tls_buffer;\n    unsigned int tls_buffer_len;\n    unsigned int len = 0;\n\n    if (!outlen)\n        return NULL;\n    if ((!context) || (!context->tls_buffer)) {\n        *outlen = 0;\n        return NULL;\n    }\n\n    if (offset >= context->tls_buffer_len) {\n        *outlen = 0;\n        return NULL;\n    }\n    /* check if any error */\n    if (context->sleep_until) {\n        if (context->sleep_until < time(NULL)) {\n            *outlen = 0;\n            return NULL;\n        }\n        context->sleep_until = 0;\n    }\n    tls_buffer = &context->tls_buffer[offset];\n    tls_buffer_len = context->tls_buffer_len - offset;\n    if (context->dtls) {\n        if (tls_buffer_len < 13) {\n            *outlen = 0;\n            return NULL;\n        }\n\n        len = ntohs(*(unsigned short *)&tls_buffer[11]) + 13;\n    } else {\n        if (tls_buffer_len < 5) {\n            *outlen = 0;\n            return NULL;\n        }\n        len = ntohs(*(unsigned short *)&tls_buffer[3]) + 5;\n    }\n    if (len > tls_buffer_len) {\n        *outlen = 0;\n        return NULL;\n    }\n\n    *outlen = len;\n    return tls_buffer;\n}\n\nvoid tls_buffer_clear(struct TLSContext *context) {\n    if ((context) && (context->tls_buffer)) {\n        TLS_FREE(context->tls_buffer);\n        context->tls_buffer = NULL;\n        context->tls_buffer_len = 0;\n    }\n}\n\nint tls_established(struct TLSContext *context) {\n    if (context) {\n        if (context->critical_error)\n            return -1;\n        \n        if (context->connection_status == 0xFF)\n            return 1;\n\n#ifdef TLS_12_FALSE_START\n        /* allow false start */\n        if ((!context->is_server) && (context->version == TLS_V12) && (context->false_start))\n            return 1;\n#endif\n    }\n    return 0;\n}\n\nvoid tls_read_clear(struct TLSContext *context) {\n    if ((context) && (context->application_buffer)) {\n        TLS_FREE(context->application_buffer);\n        context->application_buffer = NULL;\n        context->application_buffer_len = 0;\n    }\n}\n\nint tls_read(struct TLSContext *context, unsigned char *buf, unsigned int size) {\n    if (!context)\n        return -1;\n    if ((context->application_buffer) && (context->application_buffer_len)) {\n        if (context->application_buffer_len < size)\n            size = context->application_buffer_len;\n        \n        memcpy(buf, context->application_buffer, size);\n        if (context->application_buffer_len == size) {\n            TLS_FREE(context->application_buffer);\n            context->application_buffer = NULL;\n            context->application_buffer_len = 0;\n            return size;\n        }\n        context->application_buffer_len -= size;\n        memmove(context->application_buffer, context->application_buffer + size, context->application_buffer_len);\n        return size;\n    }\n    return 0;\n}\n\nstruct TLSContext *tls_create_context(unsigned char is_server, unsigned short version) {\n    struct TLSContext *context = (struct TLSContext *)TLS_MALLOC(sizeof(struct TLSContext));\n    if (context) {\n        memset(context, 0, sizeof(struct TLSContext));\n        context->is_server = is_server;\n        if ((version == DTLS_V13) || (version == DTLS_V12) || (version == DTLS_V10))\n            context->dtls = 1;\n        context->version = version;\n    }\n    return context;\n}\n\n#ifdef TLS_FORWARD_SECRECY\nconst struct ECCCurveParameters *tls_set_curve(struct TLSContext *context, const struct ECCCurveParameters *curve) {\n    const struct ECCCurveParameters *old_curve;\n\n    if (!context->is_server)\n        return NULL;\n    old_curve = context->curve;\n    context->curve = curve;\n    return old_curve;\n}\n#endif\n\nstruct TLSContext *tls_accept(struct TLSContext *context) {\n    struct TLSContext *child;\n\n    if ((!context) || (!context->is_server))\n        return NULL;\n    child = (struct TLSContext *)TLS_MALLOC(sizeof(struct TLSContext));\n    if (child) {\n        memset(child, 0, sizeof(struct TLSContext));\n        child->is_server = 1;\n        child->is_child = 1;\n        child->dtls = context->dtls;\n        child->version = context->version;\n        child->certificates = context->certificates;\n        child->certificates_count = context->certificates_count;\n        child->private_key = context->private_key;\n#ifdef TLS_ECDSA_SUPPORTED\n        child->ec_private_key = context->ec_private_key;\n#endif\n        child->exportable = context->exportable;\n        child->root_certificates = context->root_certificates;\n        child->root_count = context->root_count;\n#ifdef TLS_FORWARD_SECRECY\n        child->default_dhe_p = context->default_dhe_p;\n        child->default_dhe_g = context->default_dhe_g;\n        child->curve = context->curve;\n#endif\n        child->alpn = context->alpn;\n        child->alpn_count = context->alpn_count;\n    }\n    return child;\n}\n\n#ifdef TLS_FORWARD_SECRECY\nvoid _private_tls_dhe_free(struct TLSContext *context) {\n    if (context->dhe) {\n        _private_tls_dh_clear_key(context->dhe);\n        TLS_FREE(context->dhe);\n        context->dhe = NULL;\n    }\n}\n\nvoid _private_tls_dhe_create(struct TLSContext *context) {\n    _private_tls_dhe_free(context);\n    context->dhe = (DHKey *)TLS_MALLOC(sizeof(DHKey));\n    if (context->dhe)\n        memset(context->dhe, 0, sizeof(DHKey));\n}\n\nvoid _private_tls_ecc_dhe_free(struct TLSContext *context) {\n    if (context->ecc_dhe) {\n        ecc_free(context->ecc_dhe);\n        TLS_FREE(context->ecc_dhe);\n        context->ecc_dhe = NULL;\n    }\n}\n\nvoid _private_tls_ecc_dhe_create(struct TLSContext *context) {\n    _private_tls_ecc_dhe_free(context);\n    context->ecc_dhe = (ecc_key *)TLS_MALLOC(sizeof(ecc_key));\n    memset(context->ecc_dhe, 0, sizeof(ecc_key));\n}\n\nint tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, const char *g_hex_str) {\n    size_t p_len, g_len;\n\n    if ((!context) || (context->is_child) || (!context->is_server) || (!p_hex_str) || (!g_hex_str))\n        return 0;\n    \n    TLS_FREE(context->default_dhe_p);\n    TLS_FREE(context->default_dhe_g);\n    \n    context->default_dhe_p = NULL;\n    context->default_dhe_g = NULL;\n    \n    p_len = strlen(p_hex_str);\n    g_len = strlen(g_hex_str);\n    if ((p_len <= 0) || (g_len <= 0))\n        return 0;\n    context->default_dhe_p = (char *)TLS_MALLOC(p_len + 1);\n    if (!context->default_dhe_p)\n        return 0;\n    context->default_dhe_g = (char *)TLS_MALLOC(g_len + 1);\n    if (!context->default_dhe_g)\n        return 0;\n    \n    memcpy(context->default_dhe_p, p_hex_str, p_len);\n    context->default_dhe_p[p_len] = 0;\n    \n    memcpy(context->default_dhe_g, g_hex_str, g_len);\n    context->default_dhe_g[g_len] = 0;\n    return 1;\n}\n#endif\n\nconst char *tls_alpn(struct TLSContext *context) {\n    if (!context)\n        return NULL;\n    return context->negotiated_alpn;\n}\n\nint tls_add_alpn(struct TLSContext *context, const char *alpn) {\n    int len;\n    char *alpn_ref;\n\n    if ((!context) || (!alpn) || (!alpn[0]) || ((context->is_server) && (context->is_child)))\n        return TLS_GENERIC_ERROR;\n    len = strlen(alpn);\n    if (tls_alpn_contains(context, alpn, len))\n        return 0;\n    context->alpn = (char **)TLS_REALLOC(context->alpn, (context->alpn_count + 1) * sizeof(char *));\n    if (!context->alpn) {\n        context->alpn_count = 0;\n        return TLS_NO_MEMORY;\n    }\n    alpn_ref = (char *)TLS_MALLOC(len+1);\n    context->alpn[context->alpn_count] = alpn_ref;\n    if (alpn_ref) {\n        memcpy(alpn_ref, alpn, len);\n        alpn_ref[len] = 0;\n        context->alpn_count++;\n    } else\n        return TLS_NO_MEMORY;\n    return 0;\n}\n\nint tls_alpn_contains(struct TLSContext *context, const char *alpn, unsigned char alpn_size) {\n    if ((!context) || (!alpn) || (!alpn_size))\n        return 0;\n\n    if (context->alpn) {\n        int i;\n\n        for (i = 0; i < context->alpn_count; i++) {\n            const char *alpn_local = context->alpn[i];\n\n            if (alpn_local) {\n                int len = strlen(alpn_local);\n\n                if (alpn_size == len) {\n                    if (!memcmp(alpn_local, alpn, alpn_size))\n                        return 1;\n                }\n            }\n        }\n    }\n    return 0;\n}\n\nvoid tls_destroy_context(struct TLSContext *context) {\n    unsigned int i;\n\n    if (!context)\n        return;\n    if (!context->is_child) {\n        if (context->certificates) {\n            for (i = 0; i < context->certificates_count; i++)\n                tls_destroy_certificate(context->certificates[i]);\n        }\n        if (context->root_certificates) {\n            for (i = 0; i < context->root_count; i++)\n                tls_destroy_certificate(context->root_certificates[i]);\n            TLS_FREE(context->root_certificates);\n            context->root_certificates = NULL;\n        }\n        if (context->private_key)\n            tls_destroy_certificate(context->private_key);\n#ifdef TLS_ECDSA_SUPPORTED\n        if (context->ec_private_key)\n            tls_destroy_certificate(context->ec_private_key);\n#endif\n        TLS_FREE(context->certificates);\n#ifdef TLS_FORWARD_SECRECY\n        TLS_FREE(context->default_dhe_p);\n        TLS_FREE(context->default_dhe_g);\n#endif\n        if (context->alpn) {\n            for (i = 0; i < context->alpn_count; i++)\n                TLS_FREE(context->alpn[i]);\n            TLS_FREE(context->alpn);\n        }\n    }\n    if (context->client_certificates) {\n        for (i = 0; i < context->client_certificates_count; i++)\n            tls_destroy_certificate(context->client_certificates[i]);\n        TLS_FREE(context->client_certificates);\n    }\n    context->client_certificates = NULL;\n    TLS_FREE(context->master_key);\n    TLS_FREE(context->premaster_key);\n    if (context->crypto.created)\n        _private_tls_crypto_done(context);\n    TLS_FREE(context->message_buffer);\n    _private_tls_done_hash(context, NULL);\n    _private_tls_destroy_hash(context);\n    TLS_FREE(context->tls_buffer);\n    TLS_FREE(context->application_buffer);\n    /* zero out the keys before free */\n    if ((context->exportable_keys) && (context->exportable_size))\n        memset(context->exportable_keys, 0, context->exportable_size);\n    TLS_FREE(context->exportable_keys);\n    TLS_FREE(context->sni);\n    TLS_FREE(context->dtls_cookie);\n    TLS_FREE(context->cached_handshake);\n#ifdef TLS_FORWARD_SECRECY\n    _private_tls_dhe_free(context);\n    _private_tls_ecc_dhe_free(context);\n#endif\n#ifdef TLS_ACCEPT_SECURE_RENEGOTIATION\n    TLS_FREE(context->verify_data);\n#endif\n    TLS_FREE(context->negotiated_alpn);\n#ifdef WITH_TLS_13\n    TLS_FREE(context->finished_key);\n    TLS_FREE(context->remote_finished_key);\n    TLS_FREE(context->server_finished_hash);\n#endif\n#ifdef TLS_CURVE25519\n    TLS_FREE(context->client_secret);\n#endif\n    TLS_FREE(context);\n}\n\n#ifdef TLS_ACCEPT_SECURE_RENEGOTIATION\nvoid _private_tls_reset_context(struct TLSContext *context) {\n    unsigned int i;\n\n    if (!context)\n        return;\n    if (!context->is_child) {\n        if (context->certificates) {\n            for (i = 0; i < context->certificates_count; i++)\n                tls_destroy_certificate(context->certificates[i]);\n        }\n        context->certificates = NULL;\n        if (context->private_key) {\n            tls_destroy_certificate(context->private_key);\n            context->private_key = NULL;\n        }\n#ifdef TLS_ECDSA_SUPPORTED\n        if (context->ec_private_key) {\n            tls_destroy_certificate(context->ec_private_key);\n            context->ec_private_key = NULL;\n        }\n#endif\n        TLS_FREE(context->certificates);\n        context->certificates = NULL;\n#ifdef TLS_FORWARD_SECRECY\n        TLS_FREE(context->default_dhe_p);\n        TLS_FREE(context->default_dhe_g);\n        context->default_dhe_p = NULL;\n        context->default_dhe_g = NULL;\n#endif\n    }\n    if (context->client_certificates) {\n        for (i = 0; i < context->client_certificates_count; i++)\n            tls_destroy_certificate(context->client_certificates[i]);\n        TLS_FREE(context->client_certificates);\n    }\n    context->client_certificates = NULL;\n    TLS_FREE(context->master_key);\n    context->master_key = NULL;\n    TLS_FREE(context->premaster_key);\n    context->premaster_key = NULL;\n    if (context->crypto.created)\n        _private_tls_crypto_done(context);\n    _private_tls_done_hash(context, NULL);\n    _private_tls_destroy_hash(context);\n    TLS_FREE(context->application_buffer);\n    context->application_buffer = NULL;\n    /* zero out the keys before free */\n    if ((context->exportable_keys) && (context->exportable_size))\n        memset(context->exportable_keys, 0, context->exportable_size);\n    TLS_FREE(context->exportable_keys);\n    context->exportable_keys =  NULL;\n    TLS_FREE(context->sni);\n    context->sni = NULL;\n    TLS_FREE(context->dtls_cookie);\n    context->dtls_cookie = NULL;\n    TLS_FREE(context->cached_handshake);\n    context->cached_handshake = NULL;\n    context->connection_status = 0;\n#ifdef TLS_FORWARD_SECRECY\n    _private_tls_dhe_free(context);\n    _private_tls_ecc_dhe_free(context);\n#endif\n}\n#endif\n\nint tls_cipher_supported(struct TLSContext *context, unsigned short cipher) {\n    if (!context)\n        return 0;\n\n    switch (cipher) {\n#ifdef WITH_TLS_13\n        case TLS_AES_128_GCM_SHA256:\n        case TLS_AES_256_GCM_SHA384:\n        case TLS_CHACHA20_POLY1305_SHA256:\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n                return 1;\n            return 0;\n#endif\n#ifdef TLS_FORWARD_SECRECY\n#ifdef TLS_ECDSA_SUPPORTED\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:\n#ifdef TLS_CLIENT_ECDSA\n            if ((context) && (((context->certificates) && (context->certificates_count) && (context->ec_private_key)) || (!context->is_server)))\n#else\n            if ((context) && (context->certificates) && (context->certificates_count) && (context->ec_private_key))\n#endif\n                return 1;\n            return 0;\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:\n#endif\n            if ((context->version == TLS_V12) || (context->version == DTLS_V12)) {\n#ifdef TLS_CLIENT_ECDSA\n                if ((context) && (((context->certificates) && (context->certificates_count) && (context->ec_private_key)) || (!context->is_server)))\n#else\n                if ((context) && (context->certificates) && (context->certificates_count) && (context->ec_private_key))\n#endif\n                    return 1;\n            }\n            return 0;\n#endif\n        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:\n        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:\n#endif\n        case TLS_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_RSA_WITH_AES_256_CBC_SHA:\n            return 1;\n#ifdef TLS_FORWARD_SECRECY\n        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:\n        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n#endif\n#endif\n        case TLS_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_RSA_WITH_AES_256_CBC_SHA256:\n        case TLS_RSA_WITH_AES_256_GCM_SHA384:\n            if ((context->version == TLS_V12) || (context->version == DTLS_V12))\n                return 1;\n            return 0;\n    }\n    return 0;\n}\n\nint tls_cipher_is_fs(struct TLSContext *context, unsigned short cipher) {\n    if (!context)\n        return 0;\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        switch (cipher) {\n            case TLS_AES_128_GCM_SHA256:\n            case TLS_AES_256_GCM_SHA384:\n            case TLS_CHACHA20_POLY1305_SHA256:\n                return 1;\n        }\n        return 0;\n    }\n#endif\n    switch (cipher) {\n#ifdef TLS_ECDSA_SUPPORTED\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:\n#endif\n            if ((context) && (context->certificates) && (context->certificates_count) && (context->ec_private_key))\n                return 1;\n            return 0;\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n            if ((context->version == TLS_V12) || (context->version == DTLS_V12)) {\n                if ((context) && (context->certificates) && (context->certificates_count) && (context->ec_private_key))\n                    return 1;\n            }\n            return 0;\n#endif\n        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:\n        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:\n            return 1;\n        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:\n        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:\n        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n        case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n#endif\n            if ((context->version == TLS_V12) || (context->version == DTLS_V12))\n                return 1;\n            break;\n    }\n    return 0;\n}\n\n#ifdef WITH_KTLS\nint _private_tls_prefer_ktls(struct TLSContext *context, unsigned short cipher) {\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13) || ((context->version != TLS_V12) && (context->version != DTLS_V12)))\n        return 0;\n\n    switch (cipher) {\n        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13) || (context->version == TLS_V12) || (context->version == DTLS_V12)) {\n                if ((context->certificates) && (context->certificates_count) && (context->ec_private_key))\n                    return 1;\n            }\n            break;\n        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n            return 1;\n    }\n    return 0;\n}\n#endif\n\nint tls_choose_cipher(struct TLSContext *context, const unsigned char *buf, int buf_len, int *scsv_set) {\n    int i;\n    int selected_cipher = TLS_NO_COMMON_CIPHER;\n\n    if (scsv_set)\n        *scsv_set = 0;\n    if (!context)\n        return 0;\n#ifdef TLS_FORWARD_SECRECY\n#ifdef WITH_KTLS\n    for (i = 0; i < buf_len; i+=2) {\n        unsigned short cipher = ntohs(*(unsigned short *)&buf[i]);\n        if (_private_tls_prefer_ktls(context, cipher)) {\n            selected_cipher = cipher;\n            break;\n        }\n    }\n#endif\n    if (selected_cipher == TLS_NO_COMMON_CIPHER) {\n        for (i = 0; i < buf_len; i+=2) {\n            unsigned short cipher = ntohs(*(unsigned short *)&buf[i]);\n            if (tls_cipher_is_fs(context, cipher)) {\n                selected_cipher = cipher;\n                break;\n            }\n        }\n    }\n#endif\n    for (i = 0; i < buf_len; i+=2) {\n        unsigned short cipher = ntohs(*(unsigned short *)&buf[i]);\n        if (cipher == TLS_FALLBACK_SCSV) {\n            if (scsv_set)\n                *scsv_set = 1;\n            if (selected_cipher != TLS_NO_COMMON_CIPHER)\n                break;\n        }\n#ifndef TLS_ROBOT_MITIGATION\n        else\n        if ((selected_cipher == TLS_NO_COMMON_CIPHER) && (tls_cipher_supported(context, cipher)))\n            selected_cipher = cipher;\n#endif\n    }\n    return selected_cipher;\n}\n\nint tls_cipher_is_ephemeral(struct TLSContext *context) {\n    if (context) {\n        switch (context->cipher) {\n            case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:\n            case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:\n            case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:\n            case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:\n            case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n            case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:\n            case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n                return 1;\n            case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:\n            case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:\n            case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:\n            case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n            case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:\n            case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n            case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:\n            case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:\n            case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:\n            case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:\n            case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n            case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n            case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:\n                return 2;\n#ifdef WITH_TLS_13\n            case TLS_AES_128_GCM_SHA256:\n            case TLS_CHACHA20_POLY1305_SHA256:\n            case TLS_AES_128_CCM_SHA256:\n            case TLS_AES_128_CCM_8_SHA256:\n            case TLS_AES_256_GCM_SHA384:\n                if (context->dhe)\n                    return 1;\n                return 2;\n#endif\n        }\n    }\n    return 0;\n}\n\nconst char *tls_cipher_name(struct TLSContext *context) {\n    if (context) {\n        switch (context->cipher) {\n            case TLS_RSA_WITH_AES_128_CBC_SHA:\n                return \"RSA-AES128CBC-SHA\";\n            case TLS_RSA_WITH_AES_256_CBC_SHA:\n                return \"RSA-AES256CBC-SHA\";\n            case TLS_RSA_WITH_AES_128_CBC_SHA256:\n                return \"RSA-AES128CBC-SHA256\";\n            case TLS_RSA_WITH_AES_256_CBC_SHA256:\n                return \"RSA-AES256CBC-SHA256\";\n            case TLS_RSA_WITH_AES_128_GCM_SHA256:\n                return \"RSA-AES128GCM-SHA256\";\n            case TLS_RSA_WITH_AES_256_GCM_SHA384:\n                return \"RSA-AES256GCM-SHA384\";\n            case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:\n                return \"DHE-RSA-AES128CBC-SHA\";\n            case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:\n                return \"DHE-RSA-AES256CBC-SHA\";\n            case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:\n                return \"DHE-RSA-AES128CBC-SHA256\";\n            case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:\n                return \"DHE-RSA-AES256CBC-SHA256\";\n            case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n                return \"DHE-RSA-AES128GCM-SHA256\";\n            case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:\n                return \"DHE-RSA-AES256GCM-SHA384\";\n            case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:\n                return \"ECDHE-RSA-AES128CBC-SHA\";\n            case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:\n                return \"ECDHE-RSA-AES256CBC-SHA\";\n            case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:\n                return \"ECDHE-RSA-AES128CBC-SHA256\";\n            case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n                return \"ECDHE-RSA-AES128GCM-SHA256\";\n            case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:\n                return \"ECDHE-RSA-AES256GCM-SHA384\";\n            case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:\n                return \"ECDHE-ECDSA-AES128CBC-SHA\";\n            case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:\n                return \"ECDHE-ECDSA-AES256CBC-SHA\";\n            case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:\n                return \"ECDHE-ECDSA-AES128CBC-SHA256\";\n            case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:\n                return \"ECDHE-ECDSA-AES256CBC-SHA384\";\n            case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n                return \"ECDHE-ECDSA-AES128GCM-SHA256\";\n            case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n                return \"ECDHE-ECDSA-AES256GCM-SHA384\";\n            case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n                return \"ECDHE-RSA-CHACHA20-POLY1305-SHA256\";\n            case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:\n                return \"ECDHE-ECDSA-CHACHA20-POLY1305-SHA256\";\n            case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:\n                return \"ECDHE-DHE-CHACHA20-POLY1305-SHA256\";\n            case TLS_AES_128_GCM_SHA256:\n                return \"TLS-AES-128-GCM-SHA256\";\n            case TLS_AES_256_GCM_SHA384:\n                return \"TLS-AES-256-GCM-SHA384\";\n            case TLS_CHACHA20_POLY1305_SHA256:\n                return \"TLS-CHACHA20-POLY1305-SHA256\";\n            case TLS_AES_128_CCM_SHA256:\n                return \"TLS-AES-128-CCM-SHA256\";\n            case TLS_AES_128_CCM_8_SHA256:\n                return \"TLS-AES-128-CCM-8-SHA256\";\n        }\n    }\n    return \"UNKNOWN\";\n}\n\n#ifdef TLS_FORWARD_SECRECY\nint _private_tls_dh_export_Y(unsigned char *Ybuf, unsigned long *Ylen, DHKey *key) {\n    unsigned long len;\n    \n    if ((Ybuf == NULL) || (Ylen == NULL) || (key == NULL))\n        return TLS_GENERIC_ERROR;\n    \n    len = mp_unsigned_bin_size(key->y);\n    if (len > *Ylen)\n        return TLS_GENERIC_ERROR;\n\n    *Ylen = len;\n    return 0;\n }\n\nint _private_tls_dh_export_pqY(unsigned char *pbuf, unsigned long *plen, unsigned char *gbuf, unsigned long *glen, unsigned char *Ybuf, unsigned long *Ylen, DHKey *key) {\n    unsigned long len;\n    int err;\n    \n    if ((pbuf  == NULL) || (plen  == NULL) || (gbuf == NULL) || (glen == NULL) || (Ybuf == NULL) || (Ylen == NULL) || (key == NULL))\n        return TLS_GENERIC_ERROR;\n    \n    len = mp_unsigned_bin_size(key->y);\n    if (len > *Ylen)\n        return TLS_GENERIC_ERROR;\n    \n    if ((err = mp_to_unsigned_bin(key->y, Ybuf)) != CRYPT_OK)\n        return err;\n    \n    *Ylen = len;\n    \n    len = mp_unsigned_bin_size(key->p);\n    if (len > *plen)\n        return TLS_GENERIC_ERROR;\n    \n    if ((err = mp_to_unsigned_bin(key->p, pbuf)) != CRYPT_OK)\n        return err;\n    \n    *plen = len;\n    \n    len = mp_unsigned_bin_size(key->g);\n    if (len > *glen)\n        return TLS_GENERIC_ERROR;\n    \n    if ((err = mp_to_unsigned_bin(key->g, gbuf)) != CRYPT_OK)\n        return err;\n    \n    *glen = len;\n    \n    return 0;\n}\n\nvoid _private_tls_dh_clear_key(DHKey *key) {\n    mp_clear_multi(key->g, key->p, key->x, key->y, NULL);\n    key->g = NULL;\n    key->p = NULL;\n    key->x = NULL;\n    key->y = NULL;\n}\n\nint _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const char *gbuf, int pbuf_len, int gbuf_len) {\n    unsigned char *buf;\n    int err;\n    static prng_state prng;\n    int wprng;\n\n    if (!key)\n        return TLS_GENERIC_ERROR;\n    \n    wprng = find_prng(\"sprng\");\n    if ((err = prng_is_valid(wprng)) != CRYPT_OK)\n        return err;\n    \n    buf = (unsigned char *)TLS_MALLOC(keysize);\n    if (!buf)\n        return TLS_NO_MEMORY;\n    \n    if (rng_make_prng(keysize, wprng, &prng, NULL) != CRYPT_OK) {\n        TLS_FREE(buf);\n        return TLS_GENERIC_ERROR;\n    }\n    \n    if (prng_descriptor[wprng].read(buf, keysize, &prng) != (unsigned long)keysize) {\n        TLS_FREE(buf);\n        return TLS_GENERIC_ERROR;\n    }\n    \n    if ((err = mp_init_multi(&key->g, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) {\n        TLS_FREE(buf);\n        \n        return TLS_GENERIC_ERROR;\n    }\n    \n    if (gbuf_len <= 0) {\n        if ((err = mp_read_radix(key->g, gbuf, 16)) != CRYPT_OK) {\n            TLS_FREE(buf);\n            _private_tls_dh_clear_key(key);\n            return TLS_GENERIC_ERROR;\n        }\n    } else {\n        if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)gbuf, gbuf_len)) != CRYPT_OK) {\n            TLS_FREE(buf);\n            _private_tls_dh_clear_key(key);\n            return TLS_GENERIC_ERROR;\n        }\n    }\n    \n    if (pbuf_len <= 0) {\n        if ((err = mp_read_radix(key->p, pbuf, 16)) != CRYPT_OK) {\n            TLS_FREE(buf);\n            _private_tls_dh_clear_key(key);\n            return TLS_GENERIC_ERROR;\n        }\n    } else {\n        if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)pbuf, pbuf_len)) != CRYPT_OK) {\n            TLS_FREE(buf);\n            _private_tls_dh_clear_key(key);\n            return TLS_GENERIC_ERROR;\n        }\n    }\n    \n    if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) {\n        TLS_FREE(buf);\n        _private_tls_dh_clear_key(key);\n        return TLS_GENERIC_ERROR;\n    }\n    \n    if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) {\n        TLS_FREE(buf);\n        _private_tls_dh_clear_key(key);\n        return TLS_GENERIC_ERROR;\n    }\n    \n    TLS_FREE(buf);\n    return 0;\n}\n#endif\n\nint tls_is_ecdsa(struct TLSContext *context) {\n    if (!context)\n        return 0;\n    switch (context->cipher) {\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:\n#endif\n            return 1;\n    }\n#ifdef WITH_TLS_13\n    if (context->ec_private_key)\n        return 1;\n#endif\n    return 0;\n}\n\nstruct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) {\n    int ephemeral;\n    struct TLSPacket *packet;\n\n    if (context->is_server) {\n        DEBUG_PRINT0(\"CANNOT BUILD CLIENT KEY EXCHANGE MESSAGE FOR SERVERS\\n\");\n        return NULL;\n    }\n    \n    packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0);\n    tls_packet_uint8(packet, 0x10);\n#ifdef TLS_FORWARD_SECRECY\n    ephemeral = tls_cipher_is_ephemeral(context);\n    if ((ephemeral) && (context->premaster_key) && (context->premaster_key_len)) {\n        if (ephemeral == 1) {\n            unsigned char dh_Ys[0xFFF];\n            unsigned char dh_p[0xFFF];\n            unsigned char dh_g[0xFFF];\n            unsigned long dh_p_len = sizeof(dh_p);\n            unsigned long dh_g_len = sizeof(dh_g);\n            unsigned long dh_Ys_len = sizeof(dh_Ys);\n            \n            if (_private_tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, context->dhe)) {\n                DEBUG_PRINT1(\"ERROR EXPORTING DHE KEY %p\\n\", context->dhe);\n                TLS_FREE(packet);\n                _private_tls_dhe_free(context);\n                return NULL;\n            }\n            _private_tls_dhe_free(context);\n            DEBUG_DUMP_HEX_LABEL(\"Yc\", dh_Ys, dh_Ys_len);\n            tls_packet_uint24(packet, dh_Ys_len + 2);\n            if (context->dtls)\n                _private_dtls_handshake_data(context, packet, dh_Ys_len + 2);\n            tls_packet_uint16(packet, dh_Ys_len);\n            tls_packet_append(packet, dh_Ys, dh_Ys_len);\n        } else\n        if (context->ecc_dhe) {\n            unsigned char out[TLS_MAX_RSA_KEY];\n            unsigned long out_len = TLS_MAX_RSA_KEY;\n            \n            if (ecc_ansi_x963_export(context->ecc_dhe, out, &out_len)) {\n                DEBUG_PRINT0(\"Error exporting ECC key\\n\");\n                TLS_FREE(packet);\n                return NULL;\n            }\n            _private_tls_ecc_dhe_free(context);\n            tls_packet_uint24(packet, out_len + 1);\n            if (context->dtls) {\n                _private_dtls_handshake_data(context, packet, out_len + 1);\n                context->dtls_seq++;\n            }\n            tls_packet_uint8(packet, out_len);\n            tls_packet_append(packet, out, out_len);\n        } \n#ifdef TLS_CURVE25519\n        else\n        if ((context->curve == &x25519) && (context->client_secret)) {\n            static const unsigned char basepoint[32] = {9};\n            unsigned char shared_key[32];\n\n            curve25519(shared_key, context->client_secret, basepoint);\n            tls_packet_uint24(packet, 32 + 1);\n            tls_packet_uint8(packet, 32);\n            tls_packet_append(packet, shared_key, 32);\n            TLS_FREE(context->client_secret);\n            context->client_secret = NULL;\n        }\n#endif\n        _private_tls_compute_key(context, 48);\n    } else\n#endif\n    _private_tls_build_random(packet);\n    context->connection_status = 2;\n    tls_packet_update(packet);\n    return packet;\n}\n\nvoid _private_dtls_handshake_data(struct TLSContext *context, struct TLSPacket *packet, unsigned int framelength) {\n    /* message seq */\n    tls_packet_uint16(packet, context->dtls_seq);\n    /* fragment offset */\n    tls_packet_uint24(packet, 0);\n    /* fragment length */\n    tls_packet_uint24(packet, framelength);\n}\n\nvoid _private_dtls_handshake_copyframesize(struct TLSPacket *packet) {\n    packet->buf[22] = packet->buf[14];\n    packet->buf[23] = packet->buf[15];\n    packet->buf[24] = packet->buf[16];\n}\n\nstruct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int method) {\n    unsigned int params_len, message_len;\n    unsigned char *message;\n    struct TLSPacket *packet;\n    unsigned char dummy[3];\n    int start_len;\n\n    if (!context->is_server) {\n        DEBUG_PRINT0(\"CANNOT BUILD SERVER KEY EXCHANGE MESSAGE FOR CLIENTS\\n\");\n        return NULL;\n    }\n    \n    packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0);\n    tls_packet_uint8(packet, 0x0C);\n    tls_packet_append(packet, dummy, 3);\n    if (context->dtls)\n        _private_dtls_handshake_data(context, packet, 0);\n    start_len = packet->len;\n#ifdef TLS_FORWARD_SECRECY\n    if (method == KEA_dhe_rsa) {\n        const char *default_dhe_p;\n        const char *default_dhe_g;\n        int key_size;\n        unsigned char dh_Ys[0xFFF];\n        unsigned char dh_p[0xFFF];\n        unsigned char dh_g[0xFFF];\n        unsigned long dh_p_len = sizeof(dh_p);\n        unsigned long dh_g_len = sizeof(dh_g);\n        unsigned long dh_Ys_len = sizeof(dh_Ys);\n\n        tls_init();\n        _private_tls_dhe_create(context);\n        default_dhe_p = context->default_dhe_p;\n        default_dhe_g = context->default_dhe_g;\n        \n        if ((!default_dhe_p) || (!default_dhe_g)) {\n            default_dhe_p = TLS_DH_DEFAULT_P;\n            default_dhe_g = TLS_DH_DEFAULT_G;\n            key_size = TLS_DHE_KEY_SIZE / 8;\n        } else {\n            key_size = strlen(default_dhe_p);\n        }\n        if (_private_tls_dh_make_key(key_size, context->dhe, default_dhe_p, default_dhe_g, 0, 0)) {\n            DEBUG_PRINT0(\"ERROR CREATING DHE KEY\\n\");\n            TLS_FREE(packet);\n            TLS_FREE(context->dhe);\n            context->dhe = NULL;\n            return NULL;\n        }\n        \n        if (_private_tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, context->dhe)) {\n            DEBUG_PRINT0(\"ERROR EXPORTING DHE KEY\\n\");\n            TLS_FREE(packet);\n            return NULL;\n        }\n        \n        DEBUG_PRINT3(\"LEN: %lu (%lu, %lu)\\n\", dh_Ys_len, dh_p_len, dh_g_len);\n        DEBUG_DUMP_HEX_LABEL(\"DHE PK\", dh_Ys, dh_Ys_len);\n        DEBUG_DUMP_HEX_LABEL(\"DHE P\", dh_p, dh_p_len);\n        DEBUG_DUMP_HEX_LABEL(\"DHE G\", dh_g, dh_g_len);\n        \n        tls_packet_uint16(packet, dh_p_len);\n        tls_packet_append(packet, dh_p, dh_p_len);\n        \n        tls_packet_uint16(packet, dh_g_len);\n        tls_packet_append(packet, dh_g, dh_g_len);\n        \n        tls_packet_uint16(packet, dh_Ys_len);\n        tls_packet_append(packet, dh_Ys, dh_Ys_len);\n        /* dh_p\n        // dh_g\n        // dh_Ys */\n    } else\n    if (method == KEA_ec_diffie_hellman) {\n        ltc_ecc_set_type *dp;\n        unsigned char out[TLS_MAX_RSA_KEY];\n        unsigned long out_len = TLS_MAX_RSA_KEY;\n        \n        /* 3 = named curve */\n        if (!context->curve)\n            context->curve = default_curve;\n        tls_packet_uint8(packet, 3);\n        tls_packet_uint16(packet, context->curve->iana);\n        tls_init();\n        _private_tls_ecc_dhe_create(context);\n        \n        dp = (ltc_ecc_set_type *)&context->curve->dp;\n        \n        if (ecc_make_key_ex(NULL, find_prng(\"sprng\"), context->ecc_dhe, dp)) {\n            TLS_FREE(context->ecc_dhe);\n            context->ecc_dhe = NULL;\n            DEBUG_PRINT0(\"Error generating ECC key\\n\");\n            TLS_FREE(packet);\n            return NULL;\n        }\n        if (ecc_ansi_x963_export(context->ecc_dhe, out, &out_len)) {\n            DEBUG_PRINT0(\"Error exporting ECC key\\n\");\n            TLS_FREE(packet);\n            return NULL;\n        }\n        tls_packet_uint8(packet, out_len);\n        tls_packet_append(packet, out, out_len);\n    } else\n#endif\n    {\n        TLS_FREE(packet);\n        DEBUG_PRINT1(\"Unsupported ephemeral method: %i\\n\", method);\n        return NULL;\n    }\n    \n    /* signature */\n    params_len = packet->len - start_len;\n    message_len = params_len + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE;\n    message = (unsigned char *)TLS_MALLOC(message_len);\n    if (message) {\n        unsigned char out[TLS_MAX_RSA_KEY];\n        unsigned long out_len = TLS_MAX_RSA_KEY;\n        int hash_algorithm;\n\n        if ((context->version != TLS_V13) && (context->version != DTLS_V13) && (context->version != TLS_V12) && (context->version != DTLS_V12)) {\n            hash_algorithm = _md5_sha1;\n        } else {\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13) || (context->version == TLS_V12) || (context->version == DTLS_V12))\n                hash_algorithm = sha256;\n            else\n                hash_algorithm = sha1;\n            \n#ifdef TLS_ECDSA_SUPPORTED\n            if (tls_is_ecdsa(context)) {\n                if ((context->version == TLS_V13) || (context->version == DTLS_V13) || (context->version == TLS_V12) || (context->version == DTLS_V12))\n                    hash_algorithm = sha512;\n                tls_packet_uint8(packet, hash_algorithm);\n                tls_packet_uint8(packet, ecdsa);\n            } else\n#endif\n            {\n                tls_packet_uint8(packet, hash_algorithm);\n                tls_packet_uint8(packet, rsa_sign);\n            }\n        }\n        \n        memcpy(message, context->remote_random, TLS_CLIENT_RANDOM_SIZE);\n        memcpy(message + TLS_CLIENT_RANDOM_SIZE, context->local_random, TLS_SERVER_RANDOM_SIZE);\n        memcpy(message + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE, packet->buf + start_len, params_len);\n#ifdef TLS_ECDSA_SUPPORTED\n        if (tls_is_ecdsa(context)) {\n            if (_private_tls_sign_ecdsa(context, hash_algorithm, message, message_len, out, &out_len) == 1) {\n                DEBUG_PRINT1(\"Signing OK! (ECDSA, length %lu)\\n\", out_len);\n                tls_packet_uint16(packet, out_len);\n                tls_packet_append(packet, out, out_len);\n            }\n        } else\n#endif\n        if (_private_tls_sign_rsa(context, hash_algorithm, message, message_len, out, &out_len) == 1) {\n            DEBUG_PRINT1(\"Signing OK! (length %lu)\\n\", out_len);\n            tls_packet_uint16(packet, out_len);\n            tls_packet_append(packet, out, out_len);\n        }\n        TLS_FREE(message);\n    }\n    if ((!packet->broken) && (packet->buf)) {\n        int remaining = packet->len - start_len;\n        int payload_pos = 6;\n\n        if (context->dtls)\n            payload_pos = 14;\n        packet->buf[payload_pos] = remaining / 0x10000;\n        remaining %= 0x10000;\n        packet->buf[payload_pos + 1] = remaining / 0x100;\n        remaining %= 0x100;\n        packet->buf[payload_pos + 2] = remaining;\n        if (context->dtls) {\n            _private_dtls_handshake_copyframesize(packet);\n            context->dtls_seq++;\n        }\n    }\n    tls_packet_update(packet);\n    return packet;\n}\n\nvoid _private_tls_set_session_id(struct TLSContext *context) {\n    if (((context->version == TLS_V13) || (context->version == DTLS_V13)) && (context->session_size == TLS_MAX_SESSION_ID))\n        return;\n    if (tls_random(context->session, TLS_MAX_SESSION_ID))\n        context->session_size = TLS_MAX_SESSION_ID;\n    else\n        context->session_size = 0;\n}\n\nstruct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrade) {\n    unsigned short packet_version;\n    unsigned short version;\n    struct TLSPacket *packet;\n\n    tls_init();\n#ifdef WITH_TLS_13\n    if (context->connection_status == 4) {\n        static unsigned char sha256_helloretryrequest[] = {0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C};\n        unsigned char header[4] = {0xFE, 0, 0, 0};\n        unsigned char hash[TLS_MAX_SHA_SIZE ];\n        int hash_len;\n\n        memcpy(context->local_random, sha256_helloretryrequest, 32);\n        hash_len = _private_tls_done_hash(context, hash);\n        header[3] = (unsigned char)hash_len;\n        _private_tls_update_hash(context, header, sizeof(header));\n        _private_tls_update_hash(context, hash, hash_len);\n    } else\n    if ((!context->is_server) || ((context->version != TLS_V13) && (context->version != DTLS_V13)))\n#endif\n    if (!tls_random(context->local_random, context->is_server ? TLS_SERVER_RANDOM_SIZE : TLS_CLIENT_RANDOM_SIZE))\n        return NULL;\n    if (!context->is_server)\n        *(unsigned int *)context->local_random = htonl((unsigned int)time(NULL));\n\n    if ((context->is_server) && (tls13_downgrade)) {\n        if ((tls13_downgrade == TLS_V12) || (tls13_downgrade == DTLS_V12))\n            memcpy(context->local_random + TLS_SERVER_RANDOM_SIZE - 8, \"DOWNGRD\\x01\", 8);\n        else\n            memcpy(context->local_random + TLS_SERVER_RANDOM_SIZE - 8, \"DOWNGRD\\x00\", 8);\n    }\n    packet_version = context->version;\n    version = context->version;\n#ifdef WITH_TLS_13\n    if (context->version == TLS_V13)\n        version = TLS_V12;\n    else\n    if (context->version == DTLS_V13)\n        version = DTLS_V12;\n#endif\n    packet = tls_create_packet(context, TLS_HANDSHAKE, version, 0);\n    if (packet) {\n        int extension_len = 0;\n        int alpn_len = 0;\n        int alpn_negotiated_len = 0;\n        int i;\n        unsigned char dummy[3];\n        int start_len;\n#ifdef WITH_TLS_13\n        unsigned char shared_key[TLS_MAX_RSA_KEY];\n        unsigned long shared_key_len = TLS_MAX_RSA_KEY;\n        unsigned short shared_key_short = 0;\n        int selected_group = 0;\n#endif\n\n        /* hello */\n        if (context->is_server)\n            tls_packet_uint8(packet, 0x02);\n        else\n            tls_packet_uint8(packet, 0x01);\n        tls_packet_append(packet, dummy, 3);\n\n        if (context->dtls)\n            _private_dtls_handshake_data(context, packet, 0);\n\n        start_len = packet->len;\n        tls_packet_uint16(packet, version);\n        if (context->is_server)\n            tls_packet_append(packet, context->local_random, TLS_SERVER_RANDOM_SIZE);\n        else\n            tls_packet_append(packet, context->local_random, TLS_CLIENT_RANDOM_SIZE);\n\n#ifdef IGNORE_SESSION_ID\n        /* session size */\n        tls_packet_uint8(packet, 0);\n#else\n        _private_tls_set_session_id(context);\n        /* session size */\n        tls_packet_uint8(packet, context->session_size);\n        if (context->session_size)\n            tls_packet_append(packet, context->session, context->session_size);\n#endif\n\n#ifdef WITH_TLS_13\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n            if (context->connection_status == 4) {\n                /* connection_status == 4 => hello retry request */\n                extension_len += 6;\n            } else\n            if (context->is_server) {\n#ifdef TLS_CURVE25519\n                if (context->curve == &x25519) {\n                    extension_len += 8 + 32;\n                    shared_key_short = (unsigned short)32;\n                    if (context->finished_key) {\n                        memcpy(shared_key, context->finished_key, 32);\n                        TLS_FREE(context->finished_key);\n                        context->finished_key = NULL;\n                    }\n                    selected_group = context->curve->iana;\n                    /* make context->curve NULL (x25519 is a different implementation) */\n                    context->curve = NULL;\n                } else\n#endif\n                if (context->ecc_dhe) {\n                    if (ecc_ansi_x963_export(context->ecc_dhe, shared_key, &shared_key_len)) {\n                        DEBUG_PRINT0(\"Error exporting ECC DHE key\\n\");\n                        tls_destroy_packet(packet);\n                        return tls_build_alert(context, 1, internal_error);\n                    }\n                    _private_tls_ecc_dhe_free(context);\n                    extension_len += 8 + shared_key_len;\n                    shared_key_short = (unsigned short)shared_key_len;\n                    if (context->curve)\n                        selected_group = context->curve->iana;\n                } else\n                if (context->dhe) {\n                    selected_group = context->dhe->iana;\n                    _private_tls_dh_export_Y(shared_key, &shared_key_len, context->dhe);\n                    _private_tls_dhe_free(context);\n                    extension_len += 8 + shared_key_len;\n                    shared_key_short = (unsigned short)shared_key_len;\n                }\n            }\n            /* supported versions */\n            if (context->is_server)\n                extension_len += 6;\n            else\n                extension_len += 11;\n        }\n        if ((context->is_server) && (context->negotiated_alpn) && (context->version != TLS_V13) && (context->version != DTLS_V13)) {\n#else\n        if ((context->is_server) && (context->negotiated_alpn)) {\n#endif\n            alpn_negotiated_len = strlen(context->negotiated_alpn);\n            alpn_len = alpn_negotiated_len + 1;\n            extension_len += alpn_len + 6;\n        } else\n        if ((!context->is_server) && (context->alpn_count)) {\n            for (i = 0; i < context->alpn_count;i++) {\n                if (context->alpn[i]) {\n                    int len = strlen(context->alpn[i]);\n                    if (len)\n                        alpn_len += len + 1;\n                }\n            }\n            if (alpn_len)\n                extension_len += alpn_len + 6;\n        }\n\n        /* ciphers */\n        if (context->is_server) {\n            /* fallback ... this should never happen */\n            if (!context->cipher)\n                context->cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;\n            \n            tls_packet_uint16(packet, context->cipher);\n            /* no compression */\n            tls_packet_uint8(packet, 0);\n#ifndef STRICT_TLS\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13) || (context->version == TLS_V12) || (context->version == DTLS_V12)) {\n                /* extensions size */\n#ifdef WITH_TLS_13\n                if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n                    tls_packet_uint16(packet, extension_len);\n                } else \n#endif\n                {\n                    tls_packet_uint16(packet, 5 + extension_len);\n                    /* secure renegotation: advertise it, but refuse renegotiation */\n                    tls_packet_uint16(packet, 0xff01);\n#ifdef TLS_ACCEPT_SECURE_RENEGOTIATION\n                    /* a little defensive */\n                    if ((context->verify_len) && (!context->verify_data))\n                        context->verify_len = 0;\n                    tls_packet_uint16(packet, context->verify_len + 1);\n                    tls_packet_uint8(packet, context->verify_len);\n                    if (context->verify_len)\n                        tls_packet_append(packet, (unsigned char *)context->verify_data, context->verify_len);\n#else\n                    tls_packet_uint16(packet, 1);\n                    tls_packet_uint8(packet, 0);\n#endif\n                }\n                if (alpn_len) {\n                    tls_packet_uint16(packet, 0x10);\n                    tls_packet_uint16(packet, alpn_len + 2);\n                    tls_packet_uint16(packet, alpn_len);\n\n                    tls_packet_uint8(packet, alpn_negotiated_len);\n                    tls_packet_append(packet, (unsigned char *)context->negotiated_alpn, alpn_negotiated_len);\n                }\n            }\n#endif\n        } else {\n            if (context->dtls) {\n                tls_packet_uint8(packet, context->dtls_cookie_len);\n                if (context->dtls_cookie_len)\n                    tls_packet_append(packet, context->dtls_cookie, context->dtls_cookie_len);\n            }\n\n#ifndef STRICT_TLS\n#ifdef WITH_TLS_13\n#ifdef TLS_FORWARD_SECRECY\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n    #ifdef TLS_WITH_CHACHA20_POLY1305\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(9, 0));\n                tls_packet_uint16(packet, TLS_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_AES_256_GCM_SHA384);\n                tls_packet_uint16(packet, TLS_CHACHA20_POLY1305_SHA256);\n    #else\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(8, 0));\n                tls_packet_uint16(packet, TLS_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_AES_256_GCM_SHA384);\n    #endif\n    #ifdef TLS_PREFER_CHACHA20\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256);\n    #else\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256);\n    #endif\n            } else\n#endif\n#endif\n            if ((context->version == TLS_V12) || (context->version == DTLS_V12)) {\n#endif\n#ifdef TLS_FORWARD_SECRECY\n#ifdef TLS_CLIENT_ECDHE\n#ifdef TLS_WITH_CHACHA20_POLY1305\n    #ifdef TLS_CLIENT_ECDSA\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(17, 5));\n    #ifdef TLS_PREFER_CHACHA20\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);\n    #endif\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);\n    #ifndef TLS_PREFER_CHACHA20\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);\n    #endif\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);\n    #else\n                /* sizeof ciphers (16 ciphers * 2 bytes) */\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(11, 5));\n    #endif\n#else\n    #ifdef TLS_CLIENT_ECDSA\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(13, 5));\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);\n                tls_packet_uint16(packet, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);\n    #else\n                /* sizeof ciphers (14 ciphers * 2 bytes) */\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(9, 5));\n    #endif\n#endif\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                #ifdef TLS_PREFER_CHACHA20\n                    tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);\n                #endif\n#endif\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256);\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                #ifndef TLS_PREFER_CHACHA20\n                    tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);\n                #endif\n#endif\n#else\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                /* sizeof ciphers (11 ciphers * 2 bytes) */\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(6, 5));\n#else\n                /* sizeof ciphers (10 ciphers * 2 bytes) */\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(5, 5));\n#endif\n#endif\n                /* not yet supported, because the first message sent (this one)\n                   is already hashed by the client with sha256 (sha384 not yet supported client-side)\n                   but is fully supported server-side\n                // tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384); */\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_256_CBC_SHA);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_128_CBC_SHA);\n#ifdef TLS_WITH_CHACHA20_POLY1305\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256);\n#endif\n#else\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(0, 5));\n#endif\n                /* tls_packet_uint16(packet, TLS_RSA_WITH_AES_256_GCM_SHA384); */\n\t\t/* acme.com grrrr */\n                tls_packet_uint16(packet, TLS_RSA_WITH_AES_128_GCM_SHA256);\n#ifndef TLS_ROBOT_MITIGATION\n                tls_packet_uint16(packet, TLS_RSA_WITH_AES_256_CBC_SHA256);\n                tls_packet_uint16(packet, TLS_RSA_WITH_AES_128_CBC_SHA256);\n                tls_packet_uint16(packet, TLS_RSA_WITH_AES_256_CBC_SHA);\n                tls_packet_uint16(packet, TLS_RSA_WITH_AES_128_CBC_SHA);\n#endif\n#ifndef STRICT_TLS\n            } else {\n#ifdef TLS_FORWARD_SECRECY\n#ifdef TLS_CLIENT_ECDHE\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(5, 2));\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);\n                tls_packet_uint16(packet, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);\n#else\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(3, 2));\n#endif\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_256_CBC_SHA);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_256_CBC_SHA);\n                tls_packet_uint16(packet, TLS_DHE_RSA_WITH_AES_128_CBC_SHA);\n#else\n                tls_packet_uint16(packet, TLS_CIPHERS_SIZE(0, 2));\n#endif\n#ifndef TLS_ROBOT_MITIGATION\n                tls_packet_uint16(packet, TLS_RSA_WITH_AES_256_CBC_SHA);\n                tls_packet_uint16(packet, TLS_RSA_WITH_AES_128_CBC_SHA);\n#endif\n            }\n#endif\n            /* compression */\n            tls_packet_uint8(packet, 1);\n            /* no compression */\n            tls_packet_uint8(packet, 0);\n            /* CK: disable renegotiation if TLS v1.2 */\n            /* CK: must include signature algorithms, nginx barfs without */\n            if ((context->version == TLS_V12) || (context->version == DTLS_V12)) {\n                extension_len += 27;\n            }\n\n            if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) {\n                int sni_len = 0;\n                if (context->sni)\n                    sni_len = strlen(context->sni);\n                \n#ifdef TLS_CLIENT_ECDHE\n                extension_len += 12;\n                if ((context->version == TLS_V12) || (context->version == DTLS_V12))\n                    extension_len += 6; /* CK: needed for EC with 1.2 only */\n#endif\n                if (sni_len)\n                    extension_len += sni_len + 9;\n#ifdef WITH_TLS_13\n                if ((!context->is_server) && ((context->version == TLS_V13) || (context->version == DTLS_V13))) {\n#ifdef TLS_CURVE25519\n                    extension_len += 70;\n#else\n                    /* secp256r1 produces 65 bytes export */\n                    extension_len += 109;\n#endif\n                }\n#endif\n                tls_packet_uint16(packet, extension_len);\n\n                /* CK: disable renegotiation if TLS v1.2 */\n                if ((context->version == TLS_V12) || (context->version == DTLS_V12)) {\n                    tls_packet_uint16(packet, 0xff01);\n                    tls_packet_uint16(packet, 0x0001);\n                    tls_packet_uint8(packet, 0x00);\n\n                    /* CK: accept any signature algorithm */\n                    tls_packet_uint16(packet, 0x000d);\n                    tls_packet_uint16(packet, 0x0012);\n                    tls_packet_uint16(packet, 0x0010);\n                    tls_packet_uint16(packet, 0x0401);\n                    tls_packet_uint16(packet, 0x0403);\n                    tls_packet_uint16(packet, 0x0501);\n                    tls_packet_uint16(packet, 0x0503);\n                    tls_packet_uint16(packet, 0x0601);\n                    tls_packet_uint16(packet, 0x0603);\n                    tls_packet_uint16(packet, 0x0201);\n                    tls_packet_uint16(packet, 0x0203);\n                }\n\n                if (sni_len) {\n                    /* sni extension */\n                    tls_packet_uint16(packet, 0x00);\n                    /* sni extension len */\n                    tls_packet_uint16(packet, sni_len + 5);\n                    /* sni len */\n                    tls_packet_uint16(packet, sni_len + 3);\n                    /* sni type */\n                    tls_packet_uint8(packet, 0);\n                    /* sni host len */\n                    tls_packet_uint16(packet, sni_len);\n                    tls_packet_append(packet, (unsigned char *)context->sni, sni_len);\n                }\n#ifdef TLS_FORWARD_SECRECY\n#ifdef TLS_CLIENT_ECDHE\n                /* supported groups */\n                tls_packet_uint16(packet, 0x0A);\n                tls_packet_uint16(packet, 8);\n                /* 3 curves x 2 bytes */\n                tls_packet_uint16(packet, 6);\n                tls_packet_uint16(packet, secp256r1.iana);\n                tls_packet_uint16(packet, secp384r1.iana);\n#ifdef TLS_CURVE25519\n                tls_packet_uint16(packet, x25519.iana);\n#else\n                tls_packet_uint16(packet, secp521r1.iana);\n#endif\n\n                /* CK: add EC point formats for TLS 1.2 and 1.3 */\n                if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) {\n                    tls_packet_uint16(packet, 0x000b);\n                    tls_packet_uint16(packet, 0x0002);\n                    tls_packet_uint8 (packet,   0x01);\n                    tls_packet_uint8 (packet,   0x00);\n                }\n#endif\n#endif\n                if (alpn_len) {\n                    tls_packet_uint16(packet, 0x10);\n                    tls_packet_uint16(packet, alpn_len + 2);\n                    tls_packet_uint16(packet, alpn_len);\n\n                    for (i = 0; i < context->alpn_count;i++) {\n                        if (context->alpn[i]) {\n                            int len = strlen(context->alpn[i]);\n                            if (len) {\n                                tls_packet_uint8(packet, len);\n                                tls_packet_append(packet, (unsigned char *)context->alpn[i], len);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n#ifdef WITH_TLS_13\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n            /* supported versions */\n            tls_packet_uint16(packet, 0x2B);\n            if (context->is_server) {\n                tls_packet_uint16(packet, 2);\n                if (context->version == TLS_V13)\n                    tls_packet_uint16(packet, context->tls13_version ? context->tls13_version : TLS_V13);\n                else\n                    tls_packet_uint16(packet, context->version);\n            } else {\n                tls_packet_uint16(packet, 7);\n                tls_packet_uint8(packet, 6);\n                tls_packet_uint16(packet, TLS_V13);\n                tls_packet_uint16(packet, TLS_V12);\n                tls_packet_uint16(packet, 0x7F1C);\n            }\n            if (context->connection_status == 4) {\n                /* fallback to the mandatory secp256r1 */\n                tls_packet_uint16(packet, 0x33);\n                tls_packet_uint16(packet, 2);\n                tls_packet_uint16(packet, (unsigned short)secp256r1.iana);\n            }\n            if (((shared_key_short) && (selected_group)) || (!context->is_server)) {\n                /* key share */\n                tls_packet_uint16(packet, 0x33);\n                if (context->is_server) {\n                    tls_packet_uint16(packet, shared_key_short + 4);\n                    tls_packet_uint16(packet, (unsigned short)selected_group);\n                    tls_packet_uint16(packet, shared_key_short);\n                    tls_packet_append(packet, (unsigned char *)shared_key, shared_key_short);\n                } else {\n#ifdef TLS_CURVE25519\n                    static const unsigned char basepoint[32] = {9};\n\n                    /* make key */\n                    shared_key_short = 32;\n                    tls_packet_uint16(packet, shared_key_short + 6);\n                    tls_packet_uint16(packet, shared_key_short + 4);\n\n                    TLS_FREE(context->client_secret);\n                    context->client_secret = (unsigned char *)TLS_MALLOC(32);\n                    if (!context->client_secret) {\n                        DEBUG_PRINT0(\"ERROR IN TLS_MALLOC\");\n                        TLS_FREE(packet);\n                        return NULL;\n\n                    }\n\n                    tls_random(context->client_secret, 32);\n\n                    context->client_secret[0] &= 248;\n                    context->client_secret[31] &= 127;\n                    context->client_secret[31] |= 64;\n\n                    curve25519(shared_key, context->client_secret, basepoint);\n\n                    tls_packet_uint16(packet, (unsigned short)x25519.iana);\n                    tls_packet_uint16(packet, shared_key_short);\n                    tls_packet_append(packet, (unsigned char *)shared_key, shared_key_short);\n#else\n                    ltc_ecc_set_type *dp;\n                    unsigned char out[TLS_MAX_RSA_KEY];\n                    unsigned long out_len;\n\n                    /* make key */\n                    shared_key_short = 65;\n                    tls_packet_uint16(packet, shared_key_short + 6);\n                    tls_packet_uint16(packet, shared_key_short + 4);\n\n                    _private_tls_ecc_dhe_create(context);      \n                    dp = (ltc_ecc_set_type *)&secp256r1.dp;\n        \n                    if (ecc_make_key_ex(NULL, find_prng(\"sprng\"), context->ecc_dhe, dp)) {\n                        TLS_FREE(context->ecc_dhe);\n                        context->ecc_dhe = NULL;\n                        DEBUG_PRINT0(\"Error generating ECC key\\n\");\n                        TLS_FREE(packet);\n                        return NULL;\n                    }\n                    out_len = shared_key_short;\n                    if (ecc_ansi_x963_export(context->ecc_dhe, out, &out_len)) {\n                        DEBUG_PRINT0(\"Error exporting ECC key\\n\");\n                        TLS_FREE(packet);\n                        return NULL;\n                    }\n\n                    tls_packet_uint16(packet, (unsigned short)secp256r1.iana);\n                    tls_packet_uint16(packet, out_len);\n                    tls_packet_append(packet, (unsigned char *)out, shared_key_short);\n#endif\n                }\n            }\n            if (!context->is_server) {\n                /* signature algorithms */\n                tls_packet_uint16(packet, 0x0D);\n                tls_packet_uint16(packet, 24);\n                tls_packet_uint16(packet, 22);\n                tls_packet_uint16(packet, 0x0403);\n                tls_packet_uint16(packet, 0x0503);\n                tls_packet_uint16(packet, 0x0603);\n                tls_packet_uint16(packet, 0x0804);\n                tls_packet_uint16(packet, 0x0805);\n                tls_packet_uint16(packet, 0x0806);\n                tls_packet_uint16(packet, 0x0401);\n                tls_packet_uint16(packet, 0x0501);\n                tls_packet_uint16(packet, 0x0601);\n                tls_packet_uint16(packet, 0x0203);\n                tls_packet_uint16(packet, 0x0201);\n            }\n        }\n#endif\n        \n        if ((!packet->broken) && (packet->buf)) {\n            int remaining = packet->len - start_len;\n            int payload_pos = 6;\n\n            if (context->dtls)\n                payload_pos = 14;\n            packet->buf[payload_pos] = remaining / 0x10000;\n            remaining %= 0x10000;\n            packet->buf[payload_pos + 1] = remaining / 0x100;\n            remaining %= 0x100;\n            packet->buf[payload_pos + 2] = remaining;\n            if (context->dtls) {\n                _private_dtls_handshake_copyframesize(packet);\n                context->dtls_seq++;\n            }\n        }\n        tls_packet_update(packet);\n    }\n    DEBUG_DUMP_HEX_LABEL(\"complete hello packet\", packet->buf, packet->len);\n    return packet;\n}\n\nstruct TLSPacket *tls_certificate_request(struct TLSContext *context) {\n    unsigned short packet_version;\n    struct TLSPacket *packet;\n\n    if ((!context) || (!context->is_server))\n        return NULL;\n    packet_version = context->version;\n    packet = tls_create_packet(context, TLS_HANDSHAKE, packet_version, 0);\n    if (packet) {\n        unsigned char dummy[3];\n        int start_len;\n\n        /* certificate request */\n        tls_packet_uint8(packet, 0x0D);\n        tls_packet_append(packet, dummy, 3);\n        if (context->dtls)\n            _private_dtls_handshake_data(context, packet, 0);\n        start_len = packet->len;\n#ifdef WITH_TLS_13\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n            /* certificate request context */\n            tls_packet_uint8(packet, 0);\n            /* extensions */\n            tls_packet_uint16(packet, 18);\n            /* signature algorithms */\n            tls_packet_uint16(packet, 0x0D);\n            tls_packet_uint16(packet, 14);\n            tls_packet_uint16(packet, 12);\n            /* rsa_pkcs1_sha256\n            // tls_packet_uint16(packet, 0x0401);\n            // rsa_pkcs1_sha384\n            // tls_packet_uint16(packet, 0x0501);\n            // rsa_pkcs1_sha512\n            // tls_packet_uint16(packet, 0x0601); */\n\n            /* ecdsa_secp256r1_sha256 */\n            tls_packet_uint16(packet, 0x0403);\n            /* ecdsa_secp384r1_sha384 */\n            tls_packet_uint16(packet, 0x0503);\n            /* ecdsa_secp521r1_sha512 */\n            tls_packet_uint16(packet, 0x0604);\n            /* rsa_pss_rsae_sha256 */\n            tls_packet_uint16(packet, 0x0804);\n            /* rsa_pss_rsae_sha384 */\n            tls_packet_uint16(packet, 0x0805);\n            /* rsa_pss_rsae_sha512 */\n            tls_packet_uint16(packet, 0x0806);\n        } else\n#endif\n        {\n            tls_packet_uint8(packet, 1);\n            tls_packet_uint8(packet, rsa_sign);\n            if ((context->version == TLS_V12) || (context->version == DTLS_V12)) {\n                /* 10 pairs or 2 bytes */\n                tls_packet_uint16(packet, 10);\n                tls_packet_uint8(packet, sha256);\n                tls_packet_uint8(packet, rsa);\n                tls_packet_uint8(packet, sha1);\n                tls_packet_uint8(packet, rsa);\n                tls_packet_uint8(packet, sha384);\n                tls_packet_uint8(packet, rsa);\n                tls_packet_uint8(packet, sha512);\n                tls_packet_uint8(packet, rsa);\n                tls_packet_uint8(packet, md5);\n                tls_packet_uint8(packet, rsa);\n            }\n            /* no DistinguishedName yet */\n            tls_packet_uint16(packet, 0);\n        }\n        if (!packet->broken) {\n            int remaining = packet->len - start_len;\n            int payload_pos = 6;\n\n            if (context->dtls)\n                payload_pos = 14;\n            packet->buf[payload_pos] = remaining / 0x10000;\n            remaining %= 0x10000;\n            packet->buf[payload_pos + 1] = remaining / 0x100;\n            remaining %= 0x100;\n            packet->buf[payload_pos + 2] = remaining;\n\n            if (context->dtls) {\n                _private_dtls_handshake_copyframesize(packet);\n                context->dtls_seq++;\n            }\n        }\n        tls_packet_update(packet);\n    }\n    return packet;\n}\n\nint _private_dtls_build_cookie(struct TLSContext *context) {\n    if ((!context->dtls_cookie) || (!context->dtls_cookie_len)) {\n        hmac_state hmac;\n        unsigned long out_size = DTLS_COOKIE_SIZE;\n\n        context->dtls_cookie = (unsigned char *)TLS_MALLOC(DTLS_COOKIE_SIZE);\n        if (!context->dtls_cookie)\n            return 0;\n\n#ifdef WITH_RANDOM_DLTS_COOKIE\n        if (!tls_random(context->dtls_cookie, DTLS_COOKIE_SIZE)) {\n            TLS_FREE(context->dtls_cookie);\n            context->dtls_cookie = NULL;\n            return 0;\n        }\n        context->dtls_cookie_len = DTLS_COOKIE_SIZE;\n#else\n        hmac_init(&hmac, find_hash(\"sha256\"), dtls_secret, sizeof(dtls_secret));\n        hmac_process(&hmac, context->remote_random, TLS_CLIENT_RANDOM_SIZE);\n\n        hmac_done(&hmac, context->dtls_cookie, &out_size);\n#endif\n    }\n    return 1;\n}\n\nstruct TLSPacket *tls_build_verify_request(struct TLSContext *context) {\n    unsigned short packet_version;\n    struct TLSPacket *packet;\n\n    if ((!context->is_server) || (!context->dtls))\n        return NULL;\n    \n    if ((!context->dtls_cookie) || (!context->dtls_cookie_len)) {\n        if (!_private_dtls_build_cookie(context))\n            return NULL;\n    }\n\n    packet_version = context->version;\n    packet = tls_create_packet(context, TLS_HANDSHAKE, packet_version, 0);\n    if (packet) {\n        /* verify request */\n        tls_packet_uint8(packet, 0x03);\n        /* 24-bit length */\n        tls_packet_uint24(packet, context->dtls_cookie_len + 3);\n        /* 16-bit message_sequence */\n        tls_packet_uint16(packet, 0);\n        /* 24-bit fragment_offset */\n        tls_packet_uint24(packet, 0);\n        /* 24-bit fragment_offset */\n        tls_packet_uint24(packet, context->dtls_cookie_len + 3);\n        /* server_version */\n        tls_packet_uint16(packet, context->version);\n        tls_packet_uint8(packet, context->dtls_cookie_len);\n        tls_packet_append(packet, context->dtls_cookie, context->dtls_cookie_len);\n        tls_packet_update(packet);\n    }\n    return packet;\n}\n\nint _private_dtls_check_packet(const unsigned char *buf, int buf_len) {\n    unsigned int bytes_to_follow, fragment_offset, fragment_length;\n    CHECK_SIZE(11, buf_len, TLS_NEED_MORE_DATA)\n\n    bytes_to_follow = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    /* not used: unsigned short message_seq = ntohs(*(unsigned short *)&buf[3]); */\n    fragment_offset = buf[5] * 0x10000 + buf[6] * 0x100 + buf[7];\n    fragment_length = buf[8] * 0x10000 + buf[9] * 0x100 + buf[10];\n\n    if ((fragment_offset) || (fragment_length != bytes_to_follow)) {\n        DEBUG_PRINT0(\"FRAGMENTED PACKETS NOT SUPPORTED\\n\");\n        return TLS_FEATURE_NOT_SUPPORTED;\n    }\n    return bytes_to_follow;\n}\n\nvoid _private_dtls_reset(struct TLSContext *context) {\n    context->dtls_epoch_local = 0;\n    context->dtls_epoch_remote = 0;\n    context->dtls_seq = 0;\n    _private_tls_destroy_hash(context);\n    context->connection_status = 0;\n}\n\nint tls_parse_verify_request(struct TLSContext *context, const unsigned char *buf, int buf_len, unsigned int *write_packets) {\n    int res = 11;\n    int bytes_to_follow;\n    unsigned char len;\n\n    *write_packets = 0;\n    if ((context->connection_status != 0) || (!context->dtls)) {\n        DEBUG_PRINT0(\"UNEXPECTED VERIFY REQUEST MESSAGE\\n\");\n        return TLS_UNEXPECTED_MESSAGE;\n    }\n    bytes_to_follow = _private_dtls_check_packet(buf, buf_len);\n    if (bytes_to_follow < 0)\n        return bytes_to_follow;\n\n    CHECK_SIZE(bytes_to_follow, buf_len - res, TLS_NEED_MORE_DATA)\n    /* not used: unsigned short version = ntohs(*(unsigned short *)&buf[res]); */\n    res += 2;\n    len = buf[res];\n    res++;\n    TLS_FREE(context->dtls_cookie);\n    context->dtls_cookie_len = 0;\n    if (len) {\n        CHECK_SIZE(len, buf_len - res, TLS_NEED_MORE_DATA)\n        context->dtls_cookie = (unsigned char *)TLS_MALLOC(len);\n        if (!context->dtls_cookie)\n            return TLS_NO_MEMORY;\n        context->dtls_cookie_len = len;\n        memcpy(context->dtls_cookie, &buf[res], len);\n        res += len;\n        *write_packets = 4;\n    }\n\n    /* reset context */\n    _private_dtls_reset(context);\n    return res;\n}\n\nvoid _private_dtls_reset_cookie(struct TLSContext *context) {\n    TLS_FREE(context->dtls_cookie);\n    context->dtls_cookie = NULL;\n    context->dtls_cookie_len = 0;\n}\n\n#ifdef WITH_TLS_13\nint _private_tls_parse_key_share(struct TLSContext *context, const unsigned char *buf, int buf_len) {\n    int i = 0;\n    struct ECCCurveParameters *curve = 0;\n    DHKey *dhkey = 0;\n    int dhe_key_size = 0;\n    const unsigned char *buffer = NULL;\n    unsigned char *out2;\n    unsigned long out_size;\n    unsigned short key_size = 0;\n\n    while (buf_len >= 4) {\n#if NO_FUNNY_ALIGNMENT\n        unsigned short named_group = __toshort(buf, i);\n        i += 2;\n        buf_len -= 2;\n\n        key_size = __toshort(buf, i);\n        i += 2;\n        buf_len -= 2;\n#else\n        unsigned short named_group = ntohs(*(unsigned short *)&buf[i]);\n        i += 2;\n        buf_len -= 2;\n\n        key_size = ntohs(*(unsigned short *)&buf[i]);\n        i += 2;\n        buf_len -= 2;\n#endif\n\n        if (key_size > buf_len)\n            return TLS_BROKEN_PACKET;\n\n        switch (named_group) {\n            case 0x0017:\n                curve = &secp256r1;\n                buffer = &buf[i];\n                DEBUG_PRINT0(\"KEY SHARE => secp256r1\\n\");\n                buf_len = 0;\n                continue;\n            case 0x0018:\n                /* secp384r1 */\n                curve = &secp384r1;\n                buffer = &buf[i];\n                DEBUG_PRINT0(\"KEY SHARE => secp384r1\\n\");\n                buf_len = 0;\n                continue;\n            case 0x0019:\n                /* secp521r1 */\n                break;\n            case 0x001D:\n                /* x25519 */\n#ifdef TLS_CURVE25519\n                if (key_size != 32) {\n                    DEBUG_PRINT1(\"INVALID x25519 KEY SIZE (%i)\\n\", key_size);\n                    continue;\n                }\n                curve = &x25519;\n                buffer = &buf[i];\n                DEBUG_PRINT0(\"KEY SHARE => x25519\\n\");\n                buf_len = 0;\n                continue;\n#endif\n                break;\n\n            case 0x001E:\n                /* x448 */\n                break;\n            case 0x0100:\n                dhkey = &ffdhe2048;\n                dhe_key_size = 2048;\n                break;\n            case 0x0101:\n                dhkey = &ffdhe3072;\n                dhe_key_size = 3072;\n                break;\n            case 0x0102:\n                dhkey = &ffdhe4096;\n                dhe_key_size = 4096;\n                break;\n            case 0x0103:\n                dhkey = &ffdhe6144;\n                dhe_key_size = 6144;\n                break;\n            case 0x0104:\n                dhkey = &ffdhe8192;\n                dhe_key_size = 8192;\n                break;\n        }\n        i += key_size;\n        buf_len -= key_size;\n\n        if (!context->is_server)\n            break;\n    }\n    tls_init();\n    if (curve) {\n        ecc_key client_key;\n        ltc_ecc_set_type *dp;\n        int err;\n\n        context->curve = curve;\n#ifdef TLS_CURVE25519\n        if (curve == &x25519) {\n            unsigned char secret[32];\n            static const unsigned char basepoint[32] = {9};\n\n            if ((context->is_server) && (!tls_random(context->local_random, TLS_SERVER_RANDOM_SIZE)))\n                return TLS_GENERIC_ERROR;\n\n            if ((context->is_server) || (!context->client_secret)) {\n                tls_random(secret, 32);\n\n                secret[0] &= 248;\n                secret[31] &= 127;\n                secret[31] |= 64;\n\n                /* use finished key to store public key */\n                TLS_FREE(context->finished_key);\n                context->finished_key = (unsigned char *)TLS_MALLOC(32);\n                if (!context->finished_key)\n                    return TLS_GENERIC_ERROR;\n\n                curve25519(context->finished_key, secret, basepoint);\n\n                TLS_FREE(context->premaster_key);\n                context->premaster_key = (unsigned char *)TLS_MALLOC(32);\n                if (!context->premaster_key)\n                    return TLS_GENERIC_ERROR;\n\n                curve25519(context->premaster_key, secret, buffer);\n                context->premaster_key_len = 32;\n            } else {\n                TLS_FREE(context->premaster_key);\n                context->premaster_key = (unsigned char *)TLS_MALLOC(32);\n                if (!context->premaster_key)\n                    return TLS_GENERIC_ERROR;\n\n                curve25519(context->premaster_key, context->client_secret, buffer);\n                context->premaster_key_len = 32;\n\n                TLS_FREE(context->client_secret);\n                context->client_secret = NULL;\n            }\n            DEBUG_DUMP_HEX_LABEL(\"x25519 KEY\", context->premaster_key, context->premaster_key_len);\n\n            return 0;\n        }\n#endif\n        if (context->is_server) {\n            _private_tls_ecc_dhe_create(context);\n            if (ecc_make_key_ex(NULL, find_prng(\"sprng\"), context->ecc_dhe, (ltc_ecc_set_type *)&context->curve->dp)) {\n                TLS_FREE(context->ecc_dhe);\n                context->ecc_dhe = NULL;\n                DEBUG_PRINT0(\"Error generating ECC DHE key\\n\");\n                return TLS_GENERIC_ERROR;\n            }\n        }\n\n        dp = (ltc_ecc_set_type *)&context->curve->dp;\n\n        if ((context->is_server) && (!tls_random(context->local_random, TLS_SERVER_RANDOM_SIZE)))\n            return TLS_GENERIC_ERROR;\n\n        memset(&client_key, 0, sizeof(client_key));\n        if (ecc_ansi_x963_import_ex(buffer, key_size, &client_key, dp)) {\n            DEBUG_PRINT0(\"Error importing ECC DHE key\\n\");\n            return TLS_GENERIC_ERROR;\n        }\n        out2 = (unsigned char *)TLS_MALLOC(key_size);\n        out_size = key_size;\n    \n        err = ecc_shared_secret(context->ecc_dhe, &client_key, out2, &out_size);\n        ecc_free(&client_key);\n\n        if (err) {\n            DEBUG_PRINT1(\"ECC DHE DECRYPT ERROR %i\\n\", err);\n            TLS_FREE(out2);\n            return TLS_GENERIC_ERROR;\n        }\n        DEBUG_PRINT1(\"OUT_SIZE: %lu\\n\", out_size);\n        DEBUG_DUMP_HEX_LABEL(\"ECC DHE\", out2, out_size);\n\n        TLS_FREE(context->premaster_key);\n        context->premaster_key = out2;\n        context->premaster_key_len = out_size;\n        return 0;\n    } else\n    if ((dhkey) && (buffer)) {\n        unsigned int dhe_out_size;\n\n        _private_tls_dhe_create(context);\n        if (!tls_random(context->local_random, TLS_SERVER_RANDOM_SIZE))\n            return TLS_GENERIC_ERROR;\n        if (_private_tls_dh_make_key(dhe_key_size / 8, context->dhe, (const char *)dhkey->p, (const char *)dhkey->g, 0, 0)) {\n            TLS_FREE(context->dhe);\n            context->dhe = NULL;\n            DEBUG_PRINT0(\"Error generating DHE key\\n\");\n            return TLS_GENERIC_ERROR;\n        }\n\n        out2 = _private_tls_decrypt_dhe(context, buffer, key_size, &dhe_out_size, 0);\n        if (!out2) {\n            DEBUG_PRINT0(\"Error generating DHE shared key\\n\");\n            return TLS_GENERIC_ERROR;\n        }\n\n        TLS_FREE(context->premaster_key);\n        context->premaster_key = out2;\n        context->premaster_key_len = dhe_out_size;\n        if (context->dhe)\n            context->dhe->iana = dhkey->iana;\n        return 0;\n    }\n    DEBUG_PRINT0(\"NO COMMON KEY SHARE SUPPORTED\\n\");\n    return TLS_NO_COMMON_CIPHER;\n}\n#endif\n\nint tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int buf_len, unsigned int *write_packets, unsigned int *dtls_verified) {\n    int res = 0;\n    int downgraded = 0;\n    int hello_min_size;\n    unsigned int bytes_to_follow;\n    unsigned short version;\n    unsigned short cipher = 0;\n    unsigned char session_len;\n    const unsigned char *cipher_buffer = NULL;\n    unsigned short cipher_len = 0;\n    int scsv_set = 0;\n#ifdef WITH_TLS_13\n    const unsigned char *key_share = NULL;\n    unsigned short key_size = 0;\n#endif\n\n    *write_packets = 0;\n    *dtls_verified = 0;\n    if ((context->connection_status != 0) && (context->connection_status != 4)) {\n        /* ignore multiple hello on dtls */\n        if (context->dtls) {\n            DEBUG_PRINT0(\"RETRANSMITTED HELLO MESSAGE RECEIVED\\n\");\n            return 1;\n        }\n        DEBUG_PRINT0(\"UNEXPECTED HELLO MESSAGE\\n\");\n        return TLS_UNEXPECTED_MESSAGE;\n    }\n    \n    hello_min_size = context->dtls ? TLS_CLIENT_HELLO_MINSIZE + 8 : TLS_CLIENT_HELLO_MINSIZE;\n    CHECK_SIZE(hello_min_size, buf_len, TLS_NEED_MORE_DATA)\n    /* big endian */\n    bytes_to_follow = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    res += 3;\n    if (context->dtls) {\n        int dtls_check = _private_dtls_check_packet(buf, buf_len);\n        if (dtls_check < 0)\n            return dtls_check;\n        /* 16 bit message seq + 24 bit fragment offset + 24 bit fragment length */\n        res += 8;\n    }\n    CHECK_SIZE(bytes_to_follow, buf_len - res, TLS_NEED_MORE_DATA)\n    \n    CHECK_SIZE(2, buf_len - res, TLS_NEED_MORE_DATA)\n#if NO_FUNNY_ALIGNMENT\n    version = __toshort(buf, res);\n#else\n    version = ntohs(*(unsigned short *)&buf[res]);\n#endif\n    \n    res += 2;\n    VERSION_SUPPORTED(version, TLS_NOT_SAFE)\n    DEBUG_PRINT2(\"VERSION REQUIRED BY REMOTE %x, VERSION NOW %x\\n\", (int)version, (int)context->version);\n#ifdef TLS_LEGACY_SUPPORT\n#ifndef TLS_FORCE_LOCAL_VERSION\n    /* downgrade? */\n    if (context->dtls) {\n        /* for dlts, newer version has lower id (1.0 = FEFF, 1.2 = FEFD) */\n        if (context->version < version)\n            downgraded = 1;\n    } else {\n        if (context->version > version)\n            downgraded = 1;\n    }\n    if (downgraded) {\n        context->version = version;\n        if (!context->is_server)\n            _private_tls_change_hash_type(context);\n        DEBUG_PRINT1(\"DOWNGRADED TO %x\\n\", (int)context->version);\n    }\n#endif\n#else\n    /* allow downgrade from TLS 1.3 to TLS 1.2 if remote negotiates that,\n       but not any further */\n    if (context->version == TLS_V13 && version == TLS_V12) {\n        downgraded = 1;\n        context->version = version;\n        if (!context->is_server)\n            _private_tls_change_hash_type(context);\n        DEBUG_PRINT1(\"DOWNGRADED TO %x\\n\", (int)context->version);\n    }\n#endif\n\n    memcpy(context->remote_random, &buf[res], TLS_CLIENT_RANDOM_SIZE);\n    res += TLS_CLIENT_RANDOM_SIZE;\n    \n    session_len = buf[res++];\n    CHECK_SIZE(session_len, buf_len - res, TLS_NEED_MORE_DATA)\n    if ((session_len) && (session_len <= TLS_MAX_SESSION_ID)) {\n        memcpy(context->session, &buf[res], session_len);\n        context->session_size = session_len;\n        DEBUG_DUMP_HEX_LABEL(\"REMOTE SESSION ID: \", context->session, context->session_size);\n    } else\n        context->session_size = 0;\n    res += session_len;\n\n    if (context->is_server) {\n        unsigned char compression_list_size;\n\n        if (context->dtls) {\n            unsigned char tls_cookie_len;\n\n            CHECK_SIZE(1, buf_len - res, TLS_NEED_MORE_DATA)\n            tls_cookie_len = buf[res++];\n            if (tls_cookie_len) {\n                CHECK_SIZE(tls_cookie_len, buf_len - res, TLS_NEED_MORE_DATA)\n                if ((!context->dtls_cookie_len) || (!context->dtls_cookie))\n                    _private_dtls_build_cookie(context);\n\n                if ((context->dtls_cookie_len != tls_cookie_len) || (!context->dtls_cookie)) {\n                    *dtls_verified = 2;\n                    _private_dtls_reset_cookie(context);\n                    DEBUG_PRINT0(\"INVALID DTLS COOKIE\\n\");\n                    return TLS_BROKEN_PACKET;\n                }\n                if (memcmp(context->dtls_cookie, &buf[res], tls_cookie_len)) {\n                    *dtls_verified = 3;\n                    _private_dtls_reset_cookie(context);\n                    DEBUG_PRINT0(\"MISMATCH DTLS COOKIE\\n\");\n                    return TLS_BROKEN_PACKET;\n                }\n                _private_dtls_reset_cookie(context);\n                context->dtls_seq++;\n                *dtls_verified = 1;\n                res += tls_cookie_len;\n            } else {\n                *write_packets = 2;\n                return buf_len;\n            }\n        }\n        CHECK_SIZE(2, buf_len - res, TLS_NEED_MORE_DATA)\n#if NO_FUNNY_ALIGNMENT\n        cipher_len = __toshort(buf, res);\n#else\n        cipher_len = ntohs(*(unsigned short *)&buf[res]);\n#endif\n        res += 2;\n        CHECK_SIZE(cipher_len, buf_len - res, TLS_NEED_MORE_DATA)\n        /* faster than cipher_len % 2 */\n        if (cipher_len & 1)\n            return TLS_BROKEN_PACKET;\n\n        cipher_buffer = &buf[res];\n        res += cipher_len;\n        \n        CHECK_SIZE(1, buf_len - res, TLS_NEED_MORE_DATA)\n        compression_list_size = buf[res++];\n        CHECK_SIZE(compression_list_size, buf_len - res, TLS_NEED_MORE_DATA)\n        \n        /* no compression support */\n        res += compression_list_size;\n    } else {\n        unsigned char compression;\n\n        CHECK_SIZE(2, buf_len - res, TLS_NEED_MORE_DATA)\n        cipher = ntohs(*(unsigned short *)&buf[res]);\n        res += 2;\n        context->cipher = cipher;\n#ifndef WITH_TLS_13\n        if (!tls_cipher_supported(context, cipher)) {\n            context->cipher = 0;\n            DEBUG_PRINT0(\"NO CIPHER SUPPORTED\\n\");\n            return TLS_NO_COMMON_CIPHER;\n        }\n        DEBUG_PRINT1(\"CIPHER: %s\\n\", tls_cipher_name(context));\n#endif\n        CHECK_SIZE(1, buf_len - res, TLS_NEED_MORE_DATA)\n        compression = buf[res++];\n        if (compression != 0) {\n            DEBUG_PRINT0(\"COMPRESSION NOT SUPPORTED\\n\");\n            return TLS_COMPRESSION_NOT_SUPPORTED;\n        }\n    }\n    \n    if (res > 0) {\n        if (context->is_server)\n            *write_packets = 2;\n        if (context->connection_status != 4)\n            context->connection_status = 1;\n    }\n    \n    \n    if (res > 2)\n        res += 2;\n    while (buf_len - res >= 4) {\n        unsigned short extension_type, extension_len;\n\n        /* have extensions */\n#if NO_FUNNY_ALIGNMENT\n        extension_type = __toshort(buf, res);\n        res += 2;\n        extension_len = __toshort(buf, res);\n#else\n        extension_type = ntohs(*(unsigned short *)&buf[res]);\n        res += 2;\n        extension_len = ntohs(*(unsigned short *)&buf[res]);\n#endif\n        res += 2;\n        DEBUG_PRINT3(\"Extension: 0x0%x (%i), len: %i\\n\", (int)extension_type, (int)extension_type, (int)extension_len);\n        if (extension_len) {\n            /* SNI extension */\n            CHECK_SIZE(extension_len, buf_len - res, TLS_NEED_MORE_DATA)\n            if (extension_type == 0x00) {\n/* commented out originally\n                unsigned short sni_len = ntohs(*(unsigned short *)&buf[res]);\n                unsigned char sni_type = buf[res + 2];\n*/\n#if NO_FUNNY_ALIGNMENT\n                unsigned short sni_host_len = __toshort(buf, (res + 3));\n#else\n                unsigned short sni_host_len = ntohs(*(unsigned short *)&buf[res + 3]);\n#endif\n                CHECK_SIZE(sni_host_len, buf_len - res - 5, TLS_NEED_MORE_DATA)\n                if (sni_host_len) {\n                    TLS_FREE(context->sni);\n                    context->sni = (char *)TLS_MALLOC(sni_host_len + 1);\n                    if (context->sni) {\n                        memcpy(context->sni, &buf[res + 5], sni_host_len);\n                        context->sni[sni_host_len] = 0;\n                        DEBUG_PRINT1(\"SNI HOST INDICATOR: [%s]\\n\", context->sni);\n                    }\n                }\n            } else\n#ifdef TLS_FORWARD_SECRECY\n            if (extension_type == 0x0A) {\n                /* supported groups */\n                if (buf_len - res > 2) {\n                    unsigned short group_len = ntohs(*(unsigned short *)&buf[res]);\n                    if (buf_len - res >= group_len + 2) {\n                        int i;\n                        int selected = 0;\n\n                        DEBUG_DUMP_HEX_LABEL(\"SUPPORTED GROUPS\", &buf[res + 2], group_len);\n                        for (i = 0; i < group_len; i += 2) {\n                            unsigned short iana_n = ntohs(*(unsigned short *)&buf[res + 2 + i]);\n                            switch (iana_n) {\n                                case 23:\n                                    context->curve = &secp256r1;\n                                    selected = 1;\n                                    break;\n                                case 24:\n                                    context->curve = &secp384r1;\n                                    selected = 1;\n                                    break;\n#ifdef WITH_TLS_13\n#if(0)\n                                /* needs different implementation */\n                                case 29:\n                                    context->curve = &x25519;\n                                    selected = 1;\n                                    break;\n#endif\n#endif\n                                case 25:\n                                    context->curve = &secp521r1;\n                                    selected = 1;\n                                    break;\n                            }\n                            if (selected) {\n                                DEBUG_PRINT1(\"SELECTED CURVE %s\\n\", context->curve->name);\n                                break;\n                            }\n                        }\n                    }\n                }\n            } else\n#endif\n            if ((extension_type == 0x10) && (context->alpn) && (context->alpn_count)) {\n                if (buf_len - res > 2) {\n                    unsigned short alpn_len = ntohs(*(unsigned short *)&buf[res]);\n                    if ((alpn_len) && (alpn_len <= extension_len - 2)) {\n                        unsigned char *alpn = (unsigned char *)&buf[res + 2];\n                        int alpn_pos = 0;\n\n                        while (alpn_pos < alpn_len) {\n                            unsigned char alpn_size = alpn[alpn_pos++];\n\n                            if (alpn_size + alpn_pos >= extension_len)\n                                break;\n                            if ((alpn_size) && (tls_alpn_contains(context, (char *)&alpn[alpn_pos], alpn_size))) {\n                                TLS_FREE(context->negotiated_alpn);\n                                context->negotiated_alpn = (char *)TLS_MALLOC(alpn_size + 1);\n                                if (context->negotiated_alpn) {\n                                    memcpy(context->negotiated_alpn, &alpn[alpn_pos], alpn_size);\n                                    context->negotiated_alpn[alpn_size] = 0;\n                                    DEBUG_PRINT1(\"NEGOTIATED ALPN: %s\\n\", context->negotiated_alpn);\n                                }\n                                break;\n                            }\n                            alpn_pos += alpn_size;\n                            /* ServerHello contains just one ALPN */\n                            if (!context->is_server)\n                                break;\n                        }\n                    }\n                }\n            } else\n            if (extension_type == 0x0D) {\n                /* supported signatures */\n                DEBUG_DUMP_HEX_LABEL(\"SUPPORTED SIGNATURES\", &buf[res], extension_len);\n            } else\n            if (extension_type == 0x0B) {\n                /* supported point formats */\n                DEBUG_DUMP_HEX_LABEL(\"SUPPORTED POINT FORMATS\", &buf[res], extension_len);\n            }\n#ifdef WITH_TLS_13\n            else\n            if (extension_type == 0x2B) {\n                /* supported versions */\n                if ((context->is_server) && (buf[res] == extension_len - 1)) {\n                    if (extension_len > 2) {\n                        int i;\n                        int limit = (int)buf[res];\n\n                        DEBUG_DUMP_HEX_LABEL(\"SUPPORTED VERSIONS\", &buf[res], extension_len);\n                        if (limit == extension_len - 1) {\n                            for (i = 1; i < limit; i += 2) {\n                                if ((ntohs(*(unsigned short *)&buf[res + i]) == TLS_V13) || (ntohs(*(unsigned short *)&buf[res + i]) == 0x7F1C)) {\n                                    context->version = TLS_V13;\n                                    context->tls13_version = ntohs(*(unsigned short *)&buf[res + i]);\n                                    DEBUG_PRINT0(\"TLS 1.3 SUPPORTED\\n\");\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                } else\n                if ((!context->is_server) && (extension_len == 2)) {\n#if NO_FUNNY_ALIGNMENT\n                    if ((__toshort(buf, res) == TLS_V13) || (__toshort(buf, res) == 0x7F1C))\n#else\n                    if ((ntohs(*(unsigned short *)&buf[res]) == TLS_V13) || (ntohs(*(unsigned short *)&buf[res]) == 0x7F1C))\n#endif\n                    {\n                        context->version = TLS_V13;\n#if NO_FUNNY_ALIGNMENT\n                        context->tls13_version = __toshort(buf, res);\n#else\n                        context->tls13_version = ntohs(*(unsigned short *)&buf[res]);\n#endif\n\n                        DEBUG_PRINT0(\"TLS 1.3 SUPPORTED\\n\");\n                    }\n                }\n            } else\n            if (extension_type == 0x2A) {\n                /* early data */\n                DEBUG_DUMP_HEX_LABEL(\"EXTENSION, EARLY DATA\", &buf[res], extension_len);\n            } else\n            if (extension_type == 0x29) {\n                /* pre-shared key */\n                DEBUG_DUMP_HEX_LABEL(\"EXTENSION, PRE SHARED KEY\", &buf[res], extension_len);\n            } else\n            if (extension_type == 0x33) {\n                /* key share */\n                if (context->is_server) {\n                    key_size = ntohs(*(unsigned short *)&buf[res]);\n                    if ((context->is_server) && (key_size > extension_len - 2)) {\n                        DEBUG_PRINT0(\"BROKEN KEY SHARE\\n\");\n                        return TLS_BROKEN_PACKET;\n                    }\n                } else {\n                    key_size = extension_len;\n                }\n                DEBUG_DUMP_HEX_LABEL(\"EXTENSION, KEY SHARE\", &buf[res], extension_len);\n                if (context->is_server)\n                    key_share = &buf[res + 2];\n                else\n                    key_share = &buf[res];\n            } else\n            if (extension_type == 0x0D) {\n                /* signature algorithms */\n                DEBUG_DUMP_HEX_LABEL(\"EXTENSION, SIGNATURE ALGORITHMS\", &buf[res], extension_len);\n            } else\n            if (extension_type == 0x2D) {\n                /* psk key exchange modes */\n                DEBUG_DUMP_HEX_LABEL(\"EXTENSION, PSK KEY EXCHANGE MODES\", &buf[res], extension_len);\n            }\n#endif\n            res += extension_len;\n        }\n    }\n    if (buf_len != res)\n        return TLS_NEED_MORE_DATA;\n    if ((context->is_server) && (cipher_buffer) && (cipher_len)) {\n        int cipher = tls_choose_cipher(context, cipher_buffer, cipher_len, &scsv_set);\n        if (cipher < 0) {\n            DEBUG_PRINT0(\"NO COMMON CIPHERS\\n\");\n            return cipher;\n        }\n        if ((downgraded) && (scsv_set)) {\n            DEBUG_PRINT0(\"NO DOWNGRADE (SCSV SET)\\n\");\n            _private_tls_write_packet(tls_build_alert(context, 1, inappropriate_fallback));\n            context->critical_error = 1;\n            return TLS_NOT_SAFE;\n        }\n        context->cipher = cipher;\n    }\n#ifdef WITH_TLS_13\n    if (!context->is_server) {\n        if (!tls_cipher_supported(context, cipher)) {\n            context->cipher = 0;\n            DEBUG_PRINT0(\"NO CIPHER SUPPORTED\\n\");\n            return TLS_NO_COMMON_CIPHER;\n        }\n        DEBUG_PRINT1(\"CIPHER: %s\\n\", tls_cipher_name(context));\n    }\n\n    if ((key_share) && (key_size) && ((context->version == TLS_V13) || (context->version == DTLS_V13))) {\n        int key_share_err = _private_tls_parse_key_share(context, key_share, key_size);\n        if (key_share_err) {\n            /* request hello retry */\n            if (context->connection_status != 4) {\n                *write_packets = 5;\n                context->hs_messages[1] = 0;\n                context->connection_status = 4;\n                return res;\n            } else\n                return key_share_err;\n        }\n        /* we have key share */\n        if (context->is_server)\n            context->connection_status = 3;\n        else\n            context->connection_status = 2;\n    }\n#endif\n    return res;\n}\n\nint tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, int buf_len, int is_client) {\n    int res = 0;\n    int size;\n    unsigned int size_of_all_certificates;\n    int idx = 0;\n    int valid_certificate = 0;\n\n    CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA)\n    size_of_all_certificates = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    \n    if (size_of_all_certificates <= 4)\n        return 3 + size_of_all_certificates;\n    res += 3;\n    if (context->dtls) {\n        int dtls_check = _private_dtls_check_packet(buf, buf_len);\n        if (dtls_check < 0)\n            return dtls_check;\n        res += 8;\n    }\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        int context_size = buf[res];\n        res++;\n        /* must be 0 */\n        if (context_size)\n            res += context_size;\n    }\n#endif\n\n    CHECK_SIZE(size_of_all_certificates, buf_len - res, TLS_NEED_MORE_DATA);\n    size = size_of_all_certificates;\n    while (size > 0) {\n        unsigned int certificate_size, certificate_size2, remaining;\n        int certificates_in_chain = 0;\n        int res2;\n\n        idx++;\n        CHECK_SIZE(3, buf_len - res, TLS_NEED_MORE_DATA);\n        certificate_size = buf[res] * 0x10000 + buf[res + 1] * 0x100 + buf[res + 2];\n        res += 3;\n        CHECK_SIZE(certificate_size, buf_len - res, TLS_NEED_MORE_DATA)\n        /* load chain */\n        res2 = res;\n        remaining = certificate_size;\n        do {\n            struct TLSCertificate *cert;\n\n            if (remaining <= 3)\n                break;\n            certificates_in_chain++;\n            certificate_size2 = buf[res2] * 0x10000 + buf[res2 + 1] * 0x100 + buf[res2 + 2];\n            res2 += 3;\n            remaining -= 3;\n            if (certificate_size2 > remaining) {\n                DEBUG_PRINT2(\"Invalid certificate size (%i from %i bytes remaining)\\n\", certificate_size2, remaining);\n                break;\n            }\n            remaining -= certificate_size2;\n            \n            cert = asn1_parse(context, &buf[res2], certificate_size2, is_client);\n            if (cert) {\n                if (certificate_size2) {\n                    cert->bytes = (unsigned char *)TLS_MALLOC(certificate_size2);\n                    if (cert->bytes) {\n                        cert->len = certificate_size2;\n                        memcpy(cert->bytes, &buf[res2], certificate_size2);\n                    }\n                }\n                /* valid certificate */\n                if (is_client) {\n                    valid_certificate = 1;\n                    context->client_certificates = (struct TLSCertificate **)TLS_REALLOC(context->client_certificates, (context->client_certificates_count + 1) * sizeof(struct TLSCertificate *));\n                    context->client_certificates[context->client_certificates_count] = cert;\n                    context->client_certificates_count++;\n                } else {\n                    context->certificates = (struct TLSCertificate **)TLS_REALLOC(context->certificates, (context->certificates_count + 1) * sizeof(struct TLSCertificate *));\n                    context->certificates[context->certificates_count] = cert;\n                    context->certificates_count++;\n                    if ((cert->pk) || (cert->priv))\n                        valid_certificate = 1;\n                    else\n                    if (!context->is_server)\n                        valid_certificate = 1;\n                }\n            }\n            res2 += certificate_size2;\n#ifdef WITH_TLS_13\n            /* extension */\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n                if (remaining >= 2) {\n                    unsigned short size = ntohs(*(unsigned short *)&buf[res2]);\n\n                    /* ignore extensions */\n                    remaining -= 2;\n                    if ((size) && (size >= remaining)) {\n                        res2 += size;\n                        remaining -= size;\n                    }\n                }\n            }\n#endif\n        } while (remaining > 0);\n        if (remaining) {\n            DEBUG_PRINT1(\"Extra %i bytes after certificate\\n\", remaining);\n        }\n        size -= certificate_size + 3;\n        res += certificate_size;\n    }\n    if (!valid_certificate)\n        return TLS_UNSUPPORTED_CERTIFICATE;\n    if (res != buf_len) {\n        DEBUG_PRINT2(\"Warning: %i bytes read from %i byte buffer\\n\", (int)res, (int)buf_len);\n    }\n    return res;\n}\n\nint _private_tls_parse_dh(const unsigned char *buf, int buf_len, const unsigned char **out, int *out_size) {\n    int res = 0;\n    unsigned short size;\n\n    *out = NULL;\n    *out_size = 0;\n    CHECK_SIZE(2, buf_len, TLS_NEED_MORE_DATA)\n    size = ntohs(*(unsigned short *)buf);\n    res += 2;\n    CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA)\n    DEBUG_DUMP_HEX(&buf[res], size);\n    *out = &buf[res];\n    *out_size = size;\n    res += size;\n    return res;\n}\n\nint _private_tls_parse_random(struct TLSContext *context, const unsigned char *buf, int buf_len) {\n    int res = 0;\n    unsigned int out_len = 0;\n    unsigned char *random = NULL;\n    int ephemeral = tls_cipher_is_ephemeral(context);\n    unsigned short size;\n\n    if (ephemeral == 2) {\n        CHECK_SIZE(1, buf_len, TLS_NEED_MORE_DATA)\n        size = buf[0];\n        res += 1;\n    } else {\n        CHECK_SIZE(2, buf_len, TLS_NEED_MORE_DATA)\n        size = ntohs(*(unsigned short *)buf);\n        res += 2;\n    }\n    \n    CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA)\n    switch (ephemeral) {\n#ifdef TLS_FORWARD_SECRECY\n        case 1:\n            random = _private_tls_decrypt_dhe(context, &buf[res], size, &out_len, 1);\n            break;\n        case 2:\n            random = _private_tls_decrypt_ecc_dhe(context, &buf[res], size, &out_len, 1);\n            break;\n#endif\n        default:\n            random = _private_tls_decrypt_rsa(context, &buf[res], size, &out_len);\n    }\n    \n    if ((random) && (out_len > 2)) {\n        DEBUG_DUMP_HEX_LABEL(\"PRE MASTER KEY\", random, out_len);\n        TLS_FREE(context->premaster_key);\n        context->premaster_key = random;\n        context->premaster_key_len = out_len;\n        _private_tls_compute_key(context, 48);\n    } else {\n        TLS_FREE(random);\n        return 0;\n    }\n    res += size;\n    return res;\n}\n\nint _private_tls_build_random(struct TLSPacket *packet) {\n    int res = 0;\n    unsigned char rand_bytes[48];\n    int bytes = 48;\n    unsigned int out_len;\n    unsigned char *random;\n\n    if (!tls_random(rand_bytes, bytes))\n        return TLS_GENERIC_ERROR;\n    \n    /* max supported version */\n    if (packet->context->is_server)\n        *(unsigned short *)rand_bytes = htons(packet->context->version);\n    else\n    if (packet->context->dtls)\n        *(unsigned short *)rand_bytes = htons(DTLS_V12);\n    else\n        *(unsigned short *)rand_bytes = htons(TLS_V12);\n    /* DEBUG_DUMP_HEX_LABEL(\"PREMASTER KEY\", rand_bytes, bytes); */\n    \n    TLS_FREE(packet->context->premaster_key);\n    packet->context->premaster_key = (unsigned char *)TLS_MALLOC(bytes);\n    if (!packet->context->premaster_key)\n        return TLS_NO_MEMORY;\n    \n    packet->context->premaster_key_len = bytes;\n    memcpy(packet->context->premaster_key, rand_bytes, packet->context->premaster_key_len);\n    \n    random = _private_tls_encrypt_rsa(packet->context, packet->context->premaster_key, packet->context->premaster_key_len, &out_len);\n    \n    _private_tls_compute_key(packet->context, bytes);\n    if ((random) && (out_len > 2)) {\n        tls_packet_uint24(packet, out_len + 2);\n        if (packet->context->dtls)\n            _private_dtls_handshake_data(packet->context, packet, out_len + 2);\n        tls_packet_uint16(packet, out_len);\n        tls_packet_append(packet, random, out_len);\n    } else\n        res = TLS_GENERIC_ERROR;\n    TLS_FREE(random);\n    if (res)\n        return res;\n    \n    return out_len + 2;\n}\n\nconst unsigned char *_private_tls_parse_signature(struct TLSContext *context, const unsigned char *buf, int buf_len, int *hash_algorithm, int *sign_algorithm, int *sig_size, int *offset) {\n    int res = 0;\n    unsigned short size;\n\n    CHECK_SIZE(2, buf_len, NULL)\n    *hash_algorithm = _md5_sha1;\n    *sign_algorithm = rsa_sign;\n    *sig_size = 0;\n    if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        *hash_algorithm = buf[res];\n        res++;\n        *sign_algorithm = buf[res];\n        res++;\n    }\n\n    /* convert PSS signatures, which \"swap\" the hash and signing bytes */\n    if (*hash_algorithm == pss_rsae) {\n        /* we support 08 04,05,06 which are SHA256, 384, 512. */\n        *hash_algorithm = *sign_algorithm;\n        *sign_algorithm = pss_rsae;\n    }\n#if NO_FUNNY_ALIGNMENT\n    size = __toshort(buf, res);\n#else\n    size = ntohs(*(unsigned short *)&buf[res]);\n#endif\n    res += 2;\n    CHECK_SIZE(size, buf_len - res, NULL)\n    DEBUG_DUMP_HEX(&buf[res - 4], size);\n    *sig_size = size;\n    *offset = res + size;\n    return &buf[res];\n}\n\nint tls_parse_server_key_exchange(struct TLSContext *context, const unsigned char *buf, int buf_len) {\n    int res = 0;\n    int dh_res = 0;\n    unsigned int size;\n    const unsigned char *packet_ref;\n    unsigned char has_ds_params = 0;\n    unsigned int key_size = 0;\n    const unsigned char *dh_p = NULL;\n    int dh_p_len = 0;\n    const unsigned char *dh_g = NULL;\n    int dh_g_len = 0;\n    const unsigned char *dh_Ys = NULL;\n    int dh_Ys_len = 0;\n    int sign_size;\n    int hash_algorithm;\n    int sign_algorithm;\n    int packet_size;\n    int offset = 0;\n    const unsigned char *signature;\n    unsigned int message_len;\n    unsigned char *message;\n#ifdef TLS_FORWARD_SECRECY\n    const struct ECCCurveParameters *curve = NULL;\n    const unsigned char *pk_key = NULL;\n    int ephemeral;\n#endif\n\n    CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA)\n    size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    res += 3;\n    if (context->dtls) {\n        int dtls_check = _private_dtls_check_packet(buf, buf_len);\n        if (dtls_check < 0)\n            return dtls_check;\n        res += 8;\n    }\n    packet_ref = buf + res;\n    CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA);\n    \n    if (!size)\n        return res;\n    \n#ifdef TLS_FORWARD_SECRECY\n    ephemeral = tls_cipher_is_ephemeral(context);\n    if (ephemeral) {\n        if (ephemeral == 1) {\n            has_ds_params = 1;\n        } else {\n            int iana_n;\n\n            if (buf[res++] != 3) {\n                /* named curve; any other method is not supported */\n                return 0;\n            }\n            CHECK_SIZE(3, buf_len - res, TLS_NEED_MORE_DATA);\n#if NO_FUNNY_ALIGNMENT\n            iana_n = __toshort(buf, res);\n#else\n            iana_n = ntohs(*(unsigned short *)&buf[res]);\n#endif\n            res += 2;\n            key_size = buf[res];\n            res++;\n            CHECK_SIZE(key_size, buf_len - res, TLS_NEED_MORE_DATA);\n            DEBUG_PRINT1(\"IANA CURVE NUMBER: %i\\n\", iana_n);\n            switch (iana_n) {\n                case 19:\n                    curve = &secp192r1;\n                    break;\n                case 20:\n                    curve = &secp224k1;\n                    break;\n                case 21:\n                    curve = &secp224r1;\n                    break;\n                case 22:\n                    curve = &secp256k1;\n                    break;\n                case 23:\n                    curve = &secp256r1;\n                    break;\n                case 24:\n                    curve = &secp384r1;\n                    break;\n                case 25:\n                    curve = &secp521r1;\n                    break;\n#ifdef TLS_CURVE25519\n                case 29:\n                    curve = &x25519;\n                    break;\n#endif\n                default:\n                    DEBUG_PRINT0(\"UNSUPPORTED CURVE\\n\");\n                    return TLS_GENERIC_ERROR;\n            }\n            pk_key = &buf[res];\n            res += key_size;\n            context->curve = curve;\n        }\n    }\n#endif\n    if (has_ds_params) {\n        DEBUG_PRINT0(\"          dh_p: \");\n        dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_p, &dh_p_len);\n        if (dh_res <= 0)\n            return TLS_BROKEN_PACKET;\n        res += dh_res;\n        DEBUG_PRINT0(\"\\n\");\n        \n        DEBUG_PRINT0(\"          dh_q: \");\n        dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_g, &dh_g_len);\n        if (dh_res <= 0)\n            return TLS_BROKEN_PACKET;\n        res += dh_res;\n        DEBUG_PRINT0(\"\\n\");\n        \n        DEBUG_PRINT0(\"          dh_Ys: \");\n        dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_Ys, &dh_Ys_len);\n        if (dh_res <= 0)\n            return TLS_BROKEN_PACKET;\n        res += dh_res;\n        DEBUG_PRINT0(\"\\n\");\n    }\n\n    packet_size = res - 3;\n    if (context->dtls)\n        packet_size -= 8;\n    DEBUG_PRINT3(\"          SIGNATURE (%i/%i/%i): \", packet_size, dh_res, key_size);\n    signature = _private_tls_parse_signature(context, &buf[res], buf_len - res, &hash_algorithm, &sign_algorithm, &sign_size, &offset);\n    DEBUG_PRINT0(\"\\n\");\n    if ((sign_size <= 0) || (!signature))\n        return TLS_BROKEN_PACKET;\n    res += offset;\n    /* check signature */\n    message_len = packet_size + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE;\n    message = (unsigned char *)TLS_MALLOC(message_len);\n    if (message) {        \n        memcpy(message, context->local_random, TLS_CLIENT_RANDOM_SIZE);\n        memcpy(message + TLS_CLIENT_RANDOM_SIZE, context->remote_random, TLS_SERVER_RANDOM_SIZE);\n        memcpy(message + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE, packet_ref, packet_size);\n#ifdef TLS_CLIENT_ECDSA\n        if (tls_is_ecdsa(context)) {\n            if (_private_tls_verify_ecdsa(context, hash_algorithm, signature, sign_size, message, message_len, NULL) != 1) {\n                DEBUG_PRINT0(\"ECC Server signature FAILED!\\n\");\n                TLS_FREE(message);\n                return TLS_BROKEN_PACKET;\n            }\n        } else \n#endif\n        if (sign_algorithm == pss_rsae) {\n            if (_private_tls_verify_rsa(context, hash_algorithm, signature, sign_size, message, message_len, pss_rsae) != 1) {\n                DEBUG_PRINT0(\"PSS Server signature FAILED!\\n\");\n                TLS_FREE(message);\n                return TLS_BROKEN_PACKET;\n            }\n        } else\n        {\n            if (_private_tls_verify_rsa(context, hash_algorithm, signature, sign_size, message, message_len, 0) != 1) {\n                DEBUG_PRINT0(\"Server signature FAILED!\\n\");\n                TLS_FREE(message);\n                return TLS_BROKEN_PACKET;\n            }\n        }\n        TLS_FREE(message);\n    }\n    \n    if (buf_len - res) {\n        DEBUG_PRINT1(\"EXTRA %i BYTES AT THE END OF MESSAGE\\n\", buf_len - res);\n        DEBUG_DUMP_HEX(&buf[res], buf_len - res);\n        DEBUG_PRINT0(\"\\n\");\n    }\n#ifdef TLS_FORWARD_SECRECY\n    if (ephemeral == 1) {\n        unsigned int dh_key_size = 0;\n        unsigned char *key;\n        int dhe_key_size = dh_p_len;\n\n        _private_tls_dhe_create(context);\n        DEBUG_DUMP_HEX_LABEL(\"DHP\", dh_p, dh_p_len);\n        DEBUG_DUMP_HEX_LABEL(\"DHG\", dh_g, dh_g_len);\n        if (dh_g_len > dh_p_len)\n            dhe_key_size = dh_g_len;\n        if (_private_tls_dh_make_key(dhe_key_size, context->dhe, (const char *)dh_p, (const char *)dh_g, dh_p_len, dh_g_len)) {\n            DEBUG_PRINT0(\"ERROR CREATING DHE KEY\\n\");\n            TLS_FREE(context->dhe);\n            context->dhe = NULL;\n            return TLS_GENERIC_ERROR;\n        }\n        \n        key = _private_tls_decrypt_dhe(context, dh_Ys, dh_Ys_len, &dh_key_size, 0);\n        DEBUG_DUMP_HEX_LABEL(\"DH COMMON SECRET\", key, dh_key_size);\n        if ((key) && (dh_key_size)) {\n            TLS_FREE(context->premaster_key);\n            context->premaster_key = key;\n            context->premaster_key_len = dh_key_size;\n        }\n    } else\n    if ((ephemeral == 2) && (curve) && (pk_key) && (key_size)) {\n#ifdef TLS_CURVE25519\n        if (curve == &x25519) {\n            if (key_size != 32) {\n                DEBUG_PRINT0(\"INVALID X25519 PUBLIC SIZE\");\n                return TLS_GENERIC_ERROR;\n            }\n\n            TLS_FREE(context->client_secret);\n            context->client_secret = (unsigned char *)TLS_MALLOC(32);\n            if (!context->client_secret) {\n                DEBUG_PRINT0(\"ERROR IN TLS_MALLOC\");\n                return TLS_GENERIC_ERROR;\n            }\n            \n            tls_random(context->client_secret, 32);\n\n            context->client_secret[0] &= 248;\n            context->client_secret[31] &= 127;\n            context->client_secret[31] |= 64;\n\n            TLS_FREE(context->premaster_key);\n            context->premaster_key = (unsigned char *)TLS_MALLOC(32);\n            if (!context->premaster_key)\n                return TLS_GENERIC_ERROR;\n\n            curve25519(context->premaster_key, context->client_secret, pk_key);\n            context->premaster_key_len = 32;\n        } else\n#endif\n        {\n            ltc_ecc_set_type *dp;\n            unsigned int out_len = 0;\n\n            tls_init();\n            _private_tls_ecc_dhe_create(context);\n        \n            dp = (ltc_ecc_set_type *)&curve->dp;\n            if (ecc_make_key_ex(NULL, find_prng(\"sprng\"), context->ecc_dhe, dp)) {\n                TLS_FREE(context->ecc_dhe);\n                context->ecc_dhe = NULL;\n                DEBUG_PRINT0(\"Error generating ECC key\\n\");\n                return TLS_GENERIC_ERROR;\n            }\n        \n            TLS_FREE(context->premaster_key);\n            context->premaster_key_len = 0;\n        \n            context->premaster_key = _private_tls_decrypt_ecc_dhe(context, pk_key, key_size, &out_len, 0);\n            if (context->premaster_key)\n                context->premaster_key_len = out_len;\n        }\n    }\n#endif\n    return res;\n}\n\nint tls_parse_client_key_exchange(struct TLSContext *context, const unsigned char *buf, int buf_len) {\n    int res = 0;\n    int dh_res = 0;\n    unsigned int size;\n\n    if (context->connection_status != 1) {\n        DEBUG_PRINT1(\"UNEXPECTED CLIENT KEY EXCHANGE MESSAGE (connections status: %i)\\n\", (int)context->connection_status);\n        return TLS_UNEXPECTED_MESSAGE;\n    }\n\n    CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA)\n    \n    size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    res += 3;\n    if (context->dtls) {\n        int dtls_check = _private_dtls_check_packet(buf, buf_len);\n        if (dtls_check < 0)\n            return dtls_check;\n        res += 8;\n    }\n\n    CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA);\n\n    if (!size)\n        return res;\n    \n    dh_res = _private_tls_parse_random(context, &buf[res], size);\n    if (dh_res <= 0) {\n        DEBUG_PRINT0(\"broken key\\n\");\n        return TLS_BROKEN_PACKET;\n    }\n    DEBUG_PRINT0(\"\\n\");\n    \n    res += size;\n    context->connection_status = 2;\n    return res;\n}\n\nint tls_parse_server_hello_done(struct TLSContext *context, const unsigned char *buf, int buf_len) {\n    int res = 0;\n    unsigned int size;\n\n    CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA)\n    size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    res += 3;\n    if (context->dtls) {\n        int dtls_check = _private_dtls_check_packet(buf, buf_len);\n        if (dtls_check < 0)\n            return dtls_check;\n        res += 8;\n    }\n    \n    CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA);\n    \n    res += size;\n    return res;\n}\n\nint tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int buf_len, unsigned int *write_packets) {\n    int res = 0;\n    unsigned int size, hash_len;\n    unsigned char hash[TLS_MAX_SHA_SIZE];\n\n    if ((context->connection_status < 2) || (context->connection_status == 0xFF))  {\n        DEBUG_PRINT0(\"UNEXPECTED FINISHED MESSAGE\\n\");\n        return TLS_UNEXPECTED_MESSAGE;\n    }\n    \n    *write_packets = 0;\n    CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA)\n    \n    size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    res += 3;\n    if (context->dtls) {\n        int dtls_check = _private_dtls_check_packet(buf, buf_len);\n        if (dtls_check < 0)\n            return dtls_check;\n        res += 8;\n    }\n    \n    if (size < TLS_MIN_FINISHED_OPAQUE_LEN) {\n        DEBUG_PRINT1(\"Invalid finished pachet size: %i\\n\", size);\n        return TLS_BROKEN_PACKET;\n    }\n    \n    CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA);\n    \n    hash_len = _private_tls_get_hash(context, hash);\n\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        unsigned char hash_out[TLS_MAX_SHA_SIZE];\n        unsigned long out_size = TLS_MAX_SHA_SIZE;\n        hmac_state hmac;\n\n        if ((!context->remote_finished_key) || (!hash_len)) {\n            DEBUG_PRINT0(\"NO FINISHED KEY COMPUTED OR NO HANDSHAKE HASH\\n\");\n            return TLS_NOT_VERIFIED;\n        }\n\n        DEBUG_DUMP_HEX_LABEL(\"HS HASH\", hash, hash_len);\n        DEBUG_DUMP_HEX_LABEL(\"HS FINISH\", context->finished_key, hash_len);\n        DEBUG_DUMP_HEX_LABEL(\"HS REMOTE FINISH\", context->remote_finished_key, hash_len);\n\n        out_size = hash_len;\n        hmac_init(&hmac, _private_tls_get_hash_idx(context), context->remote_finished_key, hash_len);\n        hmac_process(&hmac, hash, hash_len);\n        hmac_done(&hmac, hash_out, &out_size);\n\n        if ((size != out_size) || (memcmp(hash_out, &buf[res], size))) {\n            DEBUG_PRINT2(\"Finished validation error (sequence number, local: %i, remote: %i)\\n\", (int)context->local_sequence_number, (int)context->remote_sequence_number);\n            DEBUG_DUMP_HEX_LABEL(\"FINISHED OPAQUE\", &buf[res], size);\n            DEBUG_DUMP_HEX_LABEL(\"VERIFY\", hash_out, out_size);\n            return TLS_NOT_VERIFIED;\n        }\n        if (context->is_server) {\n            context->connection_status = 0xFF;\n            res += size;\n            _private_tls13_key(context, 0);\n            context->local_sequence_number = 0;\n            context->remote_sequence_number = 0;\n            return res;\n        }\n    } else\n#endif\n    {\n        /* verify */\n        unsigned char *out = (unsigned char *)TLS_MALLOC(size);\n        if (!out) {\n            DEBUG_PRINT1(\"Error in TLS_MALLOC (%i bytes)\\n\", (int)size);\n            return TLS_NO_MEMORY;\n        }\n    \n        /* server verifies client's message */\n        if (context->is_server)\n            _private_tls_prf(context, out, size, context->master_key, context->master_key_len, (unsigned char *)\"client finished\", 15, hash, hash_len, NULL, 0);\n        else\n            _private_tls_prf(context, out, size, context->master_key, context->master_key_len, (unsigned char *)\"server finished\", 15, hash, hash_len, NULL, 0);\n    \n        if (memcmp(out, &buf[res], size)) {\n            TLS_FREE(out);\n            DEBUG_PRINT2(\"Finished validation error (sequence number, local: %i, remote: %i)\\n\", (int)context->local_sequence_number, (int)context->remote_sequence_number);\n            DEBUG_DUMP_HEX_LABEL(\"FINISHED OPAQUE\", &buf[res], size);\n            DEBUG_DUMP_HEX_LABEL(\"VERIFY\", out, size);\n            return TLS_NOT_VERIFIED;\n        }\n        TLS_FREE(out);\n    }\n    if (context->is_server)\n        *write_packets = 3;\n    else\n        context->connection_status = 0xFF;\n#ifdef TLS_ACCEPT_SECURE_RENEGOTIATION\n    if (size) {\n        if (context->is_server) {\n            TLS_FREE(context->verify_data);\n            context->verify_data = (unsigned char *)TLS_MALLOC(size);\n            if (context->verify_data) {\n                memcpy(context->verify_data, out, size);\n                context->verify_len = size;\n            }\n        } else {\n            /* concatenate client verify and server verify */\n            context->verify_data = (unsigned char *)TLS_REALLOC(context->verify_data, size);\n            if (context->verify_data) {\n                memcpy(context->verify_data + context->verify_len, out, size);\n                context->verify_len += size;\n            } else\n                context->verify_len = 0;\n        }\n    }\n#endif\n    res += size;\n    return res;\n}\n\n#ifdef WITH_TLS_13\nint tls_parse_verify_tls13(struct TLSContext *context, const unsigned char *buf, int buf_len) {\n    unsigned char signing_data[TLS_MAX_HASH_SIZE + 98];\n    int signing_data_len;\n    unsigned int size;\n    int valid = 0;\n    unsigned short signature, signature_size;\n\n    CHECK_SIZE(7, buf_len, TLS_NEED_MORE_DATA)\n    size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    \n    if (size < 2)\n        return buf_len;\n\n    /* first 64 bytes to 0x20 (32) */\n    memset(signing_data, 0x20, 64);\n    /* context string 33 bytes */\n    if (context->is_server)\n        memcpy(signing_data + 64, \"TLS 1.3, server CertificateVerify\", 33);\n    else\n        memcpy(signing_data + 64, \"TLS 1.3, client CertificateVerify\", 33);\n    /* a single 0 byte separator */\n    signing_data[97] = 0;\n    signing_data_len = 98;\n\n    signing_data_len += _private_tls_get_hash(context, signing_data + 98);\n    DEBUG_DUMP_HEX_LABEL(\"signature data\", signing_data, signing_data_len);\n#if NO_FUNNY_ALIGNMENT\n    signature = __toshort(buf, 3);\n    signature_size = __toshort(buf, 5);\n#else\n    signature = ntohs(*(unsigned short *)&buf[3]);\n    signature_size = ntohs(*(unsigned short *)&buf[5]);\n#endif\n    CHECK_SIZE(7 + size, buf_len, TLS_NEED_MORE_DATA)\n    switch (signature) {\n#ifdef TLS_ECDSA_SUPPORTED\n        case 0x0403:\n            /* secp256r1 + sha256 */\n            valid = _private_tls_verify_ecdsa(context, sha256, buf + 7, signature_size, signing_data, signing_data_len, &secp256r1);\n            break;\n        case 0x0503:\n            /* secp384r1 + sha384 */\n            valid = _private_tls_verify_ecdsa(context, sha384, buf + 7, signature_size, signing_data, signing_data_len, &secp384r1);\n            break;\n        case 0x0603:\n            /* secp521r1 + sha512 */\n            valid = _private_tls_verify_ecdsa(context, sha512, buf + 7, signature_size, signing_data, signing_data_len, &secp521r1);\n            break;\n#endif\n        case 0x0804:\n            valid = _private_tls_verify_rsa(context, sha256, buf + 7, signature_size, signing_data, signing_data_len, 0); /* ??? */\n            break;\n        default:\n            DEBUG_PRINT1(\"Unsupported signature: %x\\n\", (int)signature);\n            return TLS_UNSUPPORTED_CERTIFICATE;\n    }\n    if (valid != 1) {\n        DEBUG_PRINT0(\"Signature FAILED!\\n\");\n        return TLS_DECRYPTION_FAILED;\n    }\n    return buf_len;\n}\n#endif\n\nint tls_parse_verify(struct TLSContext *context, const unsigned char *buf, int buf_len) {\n    unsigned int bytes_to_follow;\n    int res = -1;\n\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n        return tls_parse_verify_tls13(context, buf, buf_len);\n#endif\n    CHECK_SIZE(7, buf_len, TLS_BAD_CERTIFICATE)\n    bytes_to_follow = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2];\n    CHECK_SIZE(bytes_to_follow, buf_len - 3, TLS_BAD_CERTIFICATE)\n\n    if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        unsigned int hash = buf[3];\n        unsigned int algorithm = buf[4];\n        unsigned short size;\n\n        if (algorithm != rsa)\n            return TLS_UNSUPPORTED_CERTIFICATE;\n        size = ntohs(*(unsigned short *)&buf[5]);\n        CHECK_SIZE(size, bytes_to_follow - 4, TLS_BAD_CERTIFICATE)\n        DEBUG_PRINT3(\"ALGORITHM %i/%i (%i)\\n\", hash, algorithm, (int)size);\n        DEBUG_DUMP_HEX_LABEL(\"VERIFY\", &buf[7], bytes_to_follow - 7);\n        \n        res = _private_tls_verify_rsa(context, hash, &buf[7], size, context->cached_handshake, context->cached_handshake_len, 0);\n    } else {\n#ifdef TLS_LEGACY_SUPPORT\n        unsigned short size = ntohs(*(unsigned short *)&buf[3]);\n        CHECK_SIZE(size, bytes_to_follow - 2, TLS_BAD_CERTIFICATE)\n        res = _private_tls_verify_rsa(context, md5, &buf[5], size, context->cached_handshake, context->cached_handshake_len, 0);\n#endif\n    }\n    if (context->cached_handshake) {\n        /* not needed anymore? */\n        TLS_FREE(context->cached_handshake);\n        context->cached_handshake = NULL;\n        context->cached_handshake_len = 0;\n    }\n    if (res == 1) {\n        DEBUG_PRINT0(\"Signature OK\\n\");\n        context->client_verified = 1;\n    } else {\n        DEBUG_PRINT0(\"Signature FAILED\\n\");\n        context->client_verified = 0;\n    }\n    return 1;\n}\n\nint tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int buf_len, tls_validation_function certificate_verify) {\n    int orig_len = buf_len;\n    if (context->connection_status == 0xFF) {\n#ifndef TLS_ACCEPT_SECURE_RENEGOTIATION\n        /* renegotiation disabled (emit warning alert) */\n        _private_tls_write_packet(tls_build_alert(context, 0, no_renegotiation));\n        return 1;\n#endif\n    }\n\n    while ((buf_len >= 4) && (!context->critical_error)) {\n        unsigned char type;\n        unsigned int payload_size;\n        int payload_res = 0;\n        unsigned char update_hash = 1;\n        unsigned int write_packets = 0;\n        unsigned int dtls_cookie_verified = 0;\n        int certificate_verify_alert = no_error;\n\n        CHECK_SIZE(1, buf_len, TLS_NEED_MORE_DATA)\n        type = buf[0];\n        payload_size = buf[1] * 0x10000 + buf[2] * 0x100 + buf[3] + 3;\n        if (context->dtls)\n            payload_size += 8;\n        CHECK_SIZE(payload_size + 1, buf_len, TLS_NEED_MORE_DATA)\n        switch (type) {\n                /* hello request */\n            case 0x00:\n                CHECK_HANDSHAKE_STATE(context, 0, 1);\n                DEBUG_PRINT0(\" => HELLO REQUEST (RENEGOTIATION?)\\n\");\n                if (context->dtls)\n                    context->dtls_seq = 0;\n                if (context->is_server)\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                else {\n                    if (context->connection_status == 0xFF) {\n                        /* renegotiation */\n#ifdef TLS_ACCEPT_SECURE_RENEGOTIATION\n                        if (context->critical_error)\n                            payload_res = TLS_UNEXPECTED_MESSAGE;\n                        else {\n                            _private_tls_reset_context(context);\n                            _private_tls_write_packet(tls_build_hello(context, 0));\n                            return 1;\n                        }\n#else\n                        payload_res = TLS_NO_RENEGOTIATION;\n#endif\n                    } else\n                        payload_res = TLS_UNEXPECTED_MESSAGE;\n                }\n                /* no payload */\n                break;\n                /* client hello */\n            case 0x01:\n                CHECK_HANDSHAKE_STATE(context, 1, (context->dtls ? 2 : 1));\n                DEBUG_PRINT0(\" => CLIENT HELLO\\n\");\n                if (context->is_server) {\n                    payload_res = tls_parse_hello(context, buf + 1, payload_size, &write_packets, &dtls_cookie_verified);\n                    DEBUG_PRINT2(\" => DTLS COOKIE VERIFIED: %i (%i)\\n\", dtls_cookie_verified, payload_res);\n                    if ((context->dtls) && (payload_res > 0) && (!dtls_cookie_verified) && (context->connection_status == 1)) {\n                        /* wait client hello */\n                        context->connection_status = 3;\n                        update_hash = 0;\n                    }\n                } else\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                break;\n                /* server hello */\n            case 0x02:\n                CHECK_HANDSHAKE_STATE(context, 2, 1);\n                DEBUG_PRINT0(\" => SERVER HELLO\\n\");\n                if (context->is_server)\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                else\n                    payload_res = tls_parse_hello(context, buf + 1, payload_size, &write_packets, &dtls_cookie_verified);\n                break;\n                /* hello verify request */\n            case 0x03:\n                DEBUG_PRINT0(\" => VERIFY REQUEST\\n\");\n                CHECK_HANDSHAKE_STATE(context, 3, 1);\n                if ((context->dtls) && (!context->is_server)) {\n                    payload_res = tls_parse_verify_request(context, buf + 1, payload_size, &write_packets);\n                    update_hash = 0;\n                } else\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                break;\n                /* certificate */\n            case 0x0B:\n                CHECK_HANDSHAKE_STATE(context, 4, 1);\n                DEBUG_PRINT0(\" => CERTIFICATE\\n\");\n#ifdef WITH_TLS_13\n                if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n                    if (context->connection_status == 2) {\n                        payload_res = tls_parse_certificate(context, buf + 1, payload_size, context->is_server);\n                        if (context->is_server) {\n                            if ((certificate_verify) && (context->client_certificates_count))\n                                certificate_verify_alert = certificate_verify(context, context->client_certificates, context->client_certificates_count);\n                            /* empty certificates are permitted for client */\n                            if (payload_res <= 0)\n                                payload_res = 1;\n                        } else {\n                            if ((certificate_verify) && (context->certificates_count))\n                                certificate_verify_alert = certificate_verify(context, context->certificates, context->certificates_count);\n                        }\n                    } else\n                        payload_res = TLS_UNEXPECTED_MESSAGE;\n                } else\n#endif\n                if (context->connection_status == 1) {\n                    if (context->is_server) {\n                        /* client certificate */\n                        payload_res = tls_parse_certificate(context, buf + 1, payload_size, 1);\n                        if ((certificate_verify) && (context->client_certificates_count))\n                            certificate_verify_alert = certificate_verify(context, context->client_certificates, context->client_certificates_count);\n                        /* empty certificates are permitted for client */\n                        if (payload_res <= 0)\n                            payload_res = 1;\n                    } else {\n                        payload_res = tls_parse_certificate(context, buf + 1, payload_size, 0);\n                        if ((certificate_verify) && (context->certificates_count))\n                            certificate_verify_alert = certificate_verify(context, context->certificates, context->certificates_count);\n                    }\n                } else\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                break;\n                /* server key exchange */\n            case 0x0C:\n                CHECK_HANDSHAKE_STATE(context, 5, 1);\n                DEBUG_PRINT0(\" => SERVER KEY EXCHANGE\\n\");\n                if (context->is_server)\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                else\n                    payload_res = tls_parse_server_key_exchange(context, buf + 1, payload_size);\n                break;\n                /* certificate request */\n            case 0x0D:\n                CHECK_HANDSHAKE_STATE(context, 6, 1);\n                /* server to client */\n                if (context->is_server)\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                else\n                    context->client_verified = 2;\n                DEBUG_PRINT0(\" => CERTIFICATE REQUEST\\n\");\n                break;\n                /* server hello done */\n            case 0x0E:\n                CHECK_HANDSHAKE_STATE(context, 7, 1);\n                DEBUG_PRINT0(\" => SERVER HELLO DONE\\n\");\n                if (context->is_server) {\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                } else {\n                    payload_res = tls_parse_server_hello_done(context, buf + 1, payload_size);\n                    if (payload_res > 0)\n                        write_packets = 1;\n                }\n                break;\n                /* certificate verify */\n            case 0x0F:\n                CHECK_HANDSHAKE_STATE(context, 8, 1);\n                DEBUG_PRINT0(\" => CERTIFICATE VERIFY\\n\");\n                if (context->connection_status == 2)\n                    payload_res = tls_parse_verify(context, buf + 1, payload_size);\n                else\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                break;\n                /* client key exchange */\n            case 0x10:\n                CHECK_HANDSHAKE_STATE(context, 9, 1);\n                DEBUG_PRINT0(\" => CLIENT KEY EXCHANGE\\n\");\n                if (context->is_server)\n                    payload_res = tls_parse_client_key_exchange(context, buf + 1, payload_size);\n                else\n                    payload_res = TLS_UNEXPECTED_MESSAGE;\n                break;\n                /* finished */\n            case 0x14:\n                if (context->cached_handshake) {\n                    TLS_FREE(context->cached_handshake);\n                    context->cached_handshake = NULL;\n                    context->cached_handshake_len = 0;\n                }\n                CHECK_HANDSHAKE_STATE(context, 10, 1);\n                DEBUG_PRINT0(\" => FINISHED\\n\");\n                payload_res = tls_parse_finished(context, buf + 1, payload_size, &write_packets);\n                if (payload_res > 0)\n                    memset(context->hs_messages, 0, sizeof(context->hs_messages));\n #ifdef WITH_TLS_13\n                if ((!context->is_server) && ((context->version == TLS_V13) || (context->version == DTLS_V13))) {\n                    update_hash = 0;\n                    DEBUG_PRINT0(\"<= SENDING FINISHED\\n\");\n                    _private_tls_update_hash(context, buf, payload_size + 1);\n                    _private_tls_write_packet(tls_build_finished(context));\n                    _private_tls13_key(context, 0);\n                    context->connection_status = 0xFF;\n                    context->local_sequence_number = 0;\n                    context->remote_sequence_number = 0;\n                }\n#endif\n                break;\n#ifdef WITH_TLS_13\n            case 0x08:\n                /* encrypted extensions ... ignore it for now */\n                break;\n#endif\n            default:\n                DEBUG_PRINT1(\" => NOT UNDERSTOOD PAYLOAD TYPE: %x\\n\", (int)type);\n                return TLS_NOT_UNDERSTOOD;\n        }\n        if ((type != 0x00) && (update_hash))\n            _private_tls_update_hash(context, buf, payload_size + 1);\n        \n        if (certificate_verify_alert != no_error) {\n            _private_tls_write_packet(tls_build_alert(context, 1, certificate_verify_alert));\n            context->critical_error = 1;\n        }\n        \n        if (payload_res < 0) {\n            switch (payload_res) {\n                case TLS_UNEXPECTED_MESSAGE:\n                    _private_tls_write_packet(tls_build_alert(context, 1, unexpected_message));\n                    break;\n                case TLS_COMPRESSION_NOT_SUPPORTED:\n                    _private_tls_write_packet(tls_build_alert(context, 1, decompression_failure));\n                    break;\n                case TLS_BROKEN_PACKET:\n                    _private_tls_write_packet(tls_build_alert(context, 1, decode_error));\n                    break;\n                case TLS_NO_MEMORY:\n                    _private_tls_write_packet(tls_build_alert(context, 1, internal_error));\n                    break;\n                case TLS_NOT_VERIFIED:\n                    _private_tls_write_packet(tls_build_alert(context, 1, bad_record_mac));\n                    break;\n                case TLS_BAD_CERTIFICATE:\n                    if (context->is_server) {\n                        /* bad client certificate, continue */\n                        _private_tls_write_packet(tls_build_alert(context, 0, bad_certificate));\n                        payload_res = 0;\n                    } else\n                        _private_tls_write_packet(tls_build_alert(context, 1, bad_certificate));\n                    break;\n                case TLS_UNSUPPORTED_CERTIFICATE:\n                    _private_tls_write_packet(tls_build_alert(context, 1, unsupported_certificate));\n                    break;\n                case TLS_NO_COMMON_CIPHER:\n                    _private_tls_write_packet(tls_build_alert(context, 1, insufficient_security));\n                    break;\n                case TLS_NOT_UNDERSTOOD:\n                    _private_tls_write_packet(tls_build_alert(context, 1, internal_error));\n                    break;\n                case TLS_NO_RENEGOTIATION:\n                    _private_tls_write_packet(tls_build_alert(context, 0, no_renegotiation));\n                    payload_res = 0;\n                    break;\n                case TLS_DECRYPTION_FAILED:\n                    _private_tls_write_packet(tls_build_alert(context, 1, decryption_failed_RESERVED));\n                    break;\n            }\n            if (payload_res < 0)\n                return payload_res;\n        }\n        if (certificate_verify_alert != no_error)\n            payload_res = TLS_BAD_CERTIFICATE;\n        \n        /* except renegotiation */\n        switch (write_packets) {\n            case 1:\n                if (context->client_verified == 2) {\n                    DEBUG_PRINT0(\"<= Building CERTIFICATE \\n\");\n                    _private_tls_write_packet(tls_build_certificate(context));\n                    context->client_verified = 0;\n                }\n                /* client handshake */\n                DEBUG_PRINT0(\"<= Building KEY EXCHANGE\\n\");\n                _private_tls_write_packet(tls_build_client_key_exchange(context));\n                DEBUG_PRINT0(\"<= Building CHANGE CIPHER SPEC\\n\");\n                _private_tls_write_packet(tls_build_change_cipher_spec(context));\n                context->cipher_spec_set = 1;\n                context->local_sequence_number = 0;\n                DEBUG_PRINT0(\"<= Building CLIENT FINISHED\\n\");\n                _private_tls_write_packet(tls_build_finished(context));\n                context->cipher_spec_set = 0;\n#ifdef TLS_12_FALSE_START\n                if ((!context->is_server) && (context->version == TLS_V12)) {\n                    /* https://tools.ietf.org/html/rfc7918\n                       5.1.  Symmetric Cipher\n                       Clients MUST NOT use the False Start protocol modification in a\n                       handshake unless the cipher suite uses a symmetric cipher that is\n                       considered cryptographically strong. */\n                    switch (context->cipher) {\n                        case TLS_RSA_WITH_AES_128_GCM_SHA256:\n                        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n                        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n                        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n                        case TLS_RSA_WITH_AES_256_GCM_SHA384:\n                        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:\n                        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:\n                        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:\n                            context->false_start = 1;\n                            break;\n                    }\n                }\n#endif\n                break;\n            case 2:\n                /* server handshake */\n                if ((context->dtls) && (dtls_cookie_verified == 0)) {\n                    _private_tls_write_packet(tls_build_verify_request(context));\n                    _private_dtls_reset(context);\n                } else {\n                    int ephemeral_cipher;\n                    DEBUG_PRINT0(\"<= SENDING SERVER HELLO\\n\");\n#ifdef WITH_TLS_13\n                    if (context->connection_status == 3) {\n                        context->connection_status = 2;\n                        _private_tls_write_packet(tls_build_hello(context, 0));\n                        _private_tls_write_packet(tls_build_change_cipher_spec(context));\n                        _private_tls13_key(context, 1);\n                        context->cipher_spec_set = 1;\n                        DEBUG_PRINT0(\"<= SENDING ENCRYPTED EXTENSIONS\\n\");\n                        _private_tls_write_packet(tls_build_encrypted_extensions(context));\n                        if (context->request_client_certificate) {\n                            DEBUG_PRINT0(\"<= SENDING CERTIFICATE REQUEST\\n\");\n                            _private_tls_write_packet(tls_certificate_request(context));\n                        }\n                        DEBUG_PRINT0(\"<= SENDING CERTIFICATE\\n\");\n                        _private_tls_write_packet(tls_build_certificate(context));\n                        DEBUG_PRINT0(\"<= SENDING CERTIFICATE VERIFY\\n\");\n                        _private_tls_write_packet(tls_build_certificate_verify(context));\n                        DEBUG_PRINT0(\"<= SENDING FINISHED\\n\");\n                        _private_tls_write_packet(tls_build_finished(context));\n                        /* new key */\n                        TLS_FREE(context->server_finished_hash);\n                        context->server_finished_hash = (unsigned char *)TLS_MALLOC(_private_tls_mac_length(context));\n                        if (context->server_finished_hash)\n                            _private_tls_get_hash(context, context->server_finished_hash);\n                        break;\n                    }\n#endif\n                    _private_tls_write_packet(tls_build_hello(context, 0));\n                    DEBUG_PRINT0(\"<= SENDING CERTIFICATE\\n\");\n                    _private_tls_write_packet(tls_build_certificate(context));\n                    ephemeral_cipher = tls_cipher_is_ephemeral(context);\n                    if (ephemeral_cipher) {\n                        DEBUG_PRINT0(\"<= SENDING EPHEMERAL DH KEY\\n\");\n                        _private_tls_write_packet(tls_build_server_key_exchange(context, ephemeral_cipher == 1 ? KEA_dhe_rsa : KEA_ec_diffie_hellman));\n                    }\n                    if (context->request_client_certificate) {\n                        DEBUG_PRINT0(\"<= SENDING CERTIFICATE REQUEST\\n\");\n                        _private_tls_write_packet(tls_certificate_request(context));\n                    }\n                    DEBUG_PRINT0(\"<= SENDING DONE\\n\");\n                    _private_tls_write_packet(tls_build_done(context));\n                }\n                break;\n            case 3:\n                /* finished */\n                _private_tls_write_packet(tls_build_change_cipher_spec(context));\n                _private_tls_write_packet(tls_build_finished(context));\n                context->connection_status = 0xFF;\n                break;\n            case 4:\n                /* dtls only */\n                context->dtls_seq = 1;\n                _private_tls_write_packet(tls_build_hello(context, 0));\n                break;\n#ifdef WITH_TLS_13\n            case 5:\n                /* hello retry request */\n                DEBUG_PRINT0(\"<= SENDING HELLO RETRY REQUEST\\n\");\n                _private_tls_write_packet(tls_build_hello(context, 0));\n                break;\n#endif\n        }\n        payload_size++;\n        buf += payload_size;\n        buf_len -= payload_size;\n    }\n    return orig_len;\n}\n\nunsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *context, const unsigned char *buf, int buf_len, const unsigned char *buf2, int buf_len2, unsigned char *out, unsigned int outlen, uint64_t remote_sequence_number) {\n    hmac_state hash;\n    int mac_size = outlen;\n    int hash_idx;\n    uint64_t squence_number;\n    unsigned long ref_outlen;\n\n    if (mac_size == TLS_SHA1_MAC_SIZE)\n        hash_idx = find_hash(\"sha1\");\n    else\n    if (mac_size == TLS_SHA384_MAC_SIZE)\n        hash_idx = find_hash(\"sha384\");\n    else\n        hash_idx = find_hash(\"sha256\");\n    \n    if (hmac_init(&hash, hash_idx, local ? context->crypto.ctx_local_mac.local_mac : context->crypto.ctx_remote_mac.remote_mac, mac_size))\n        return 0;\n\n    if (context->dtls)\n        squence_number = htonll(remote_sequence_number);\n    else\n    if (local)\n        squence_number = htonll(context->local_sequence_number);\n    else\n        squence_number = htonll(context->remote_sequence_number);\n\n    if (hmac_process(&hash, (unsigned char *)&squence_number, sizeof(uint64_t)))\n        return 0;\n    \n    if (hmac_process(&hash, buf, buf_len))\n        return 0;\n    if ((buf2) && (buf_len2)) {\n        if (hmac_process(&hash, buf2, buf_len2))\n            return 0;\n    }\n    ref_outlen = outlen;\n    if (hmac_done(&hash, out, &ref_outlen))\n        return 0;\n    \n    return (unsigned int)ref_outlen;\n}\n\nint tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_len, tls_validation_function certificate_verify) {\n    int res = 5;\n    int header_size;\n    int payload_res = 0;\n    unsigned char type;\n    int buf_pos = 1;\n    unsigned short length, version;\n    unsigned char *pt = NULL;\n    const unsigned char *ptr; \n    int err;\n    uint64_t dtls_sequence_number = 0;\n\n    if (context->dtls)\n        res = 13;\n    header_size = res;\n    \n    CHECK_SIZE(res, buf_len, TLS_NEED_MORE_DATA)\n    \n    type = *buf;\n\n#if NO_FUNNY_ALIGNMENT\n    version = __toshort(buf, buf_pos);\n#else\n    version = ntohs(*(unsigned short *)&buf[buf_pos]);\n#endif\n    buf_pos += 2;\n\n    if (context->dtls) {\n        CHECK_SIZE(buf_pos + 8, buf_len, TLS_NEED_MORE_DATA)\n        dtls_sequence_number = ntohll(*(uint64_t *)&buf[buf_pos]);\n        buf_pos += 8;\n    }\n\n    VERSION_SUPPORTED(version, TLS_NOT_SAFE)\n#if NO_FUNNY_ALIGNMENT\n    length = __toshort(buf, buf_pos);\n#else\n    length = ntohs(*(unsigned short *)&buf[buf_pos]);\n#endif\n    buf_pos += 2;\n\n    ptr = buf + buf_pos;\n\n    CHECK_SIZE(buf_pos + length, buf_len, TLS_NEED_MORE_DATA)\n    DEBUG_PRINT2(\"Message type: 0x%0x, length: %i\\n\", (int)type, (int)length);\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        if (type == TLS_APPLICATION_DATA && !(context->crypto.created) && !(context->is_server)) {\n            /* CK: possible to send wrapped records without a cipher change */\n            DEBUG_PRINT0(\"WRAPPED RECORD WITHOUT CIPHER CHANGE, FORCING KEY\\n\");\n            _private_tls13_key(context, 1);\n            context->cipher_spec_set = 1;\n        }\n    }\n#endif\n    if ((context->cipher_spec_set) && (type != TLS_CHANGE_CIPHER)) {\n        unsigned char aad[16];\n        int aad_size, res0, res1, res2, res3;\n        unsigned char *sequence;\n\n        DEBUG_DUMP_HEX_LABEL(\"encrypted\", &buf[header_size], length);\n        if (!context->crypto.created) {\n            DEBUG_PRINT0(\"Encryption context not created\\n\");\n            _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n            return TLS_BROKEN_PACKET;\n        }\n        pt = (unsigned char *)TLS_MALLOC(length);\n        if (!pt) {\n            DEBUG_PRINT1(\"Error in TLS_MALLOC (%i bytes)\\n\", (int)length);\n            _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n            return TLS_NO_MEMORY;\n        }\n\n        aad_size = sizeof(aad);\n        sequence = aad;\n\n        if (context->crypto.created == 2) {\n            int delta = 8;\n            int pt_length;\n            unsigned char tag[32];\n            unsigned long taglen = 32;\n            unsigned char iv[TLS_13_AES_GCM_IV_LENGTH];\n\n            gcm_reset(&context->crypto.ctx_remote.aes_gcm_remote);\n\n#ifdef WITH_TLS_13\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n                int i;\n                int offset = TLS_13_AES_GCM_IV_LENGTH - 8;\n\n                aad[0] = TLS_APPLICATION_DATA;\n                aad[1] = 0x03;\n                aad[2] = 0x03;\n#if NO_FUNNY_ALIGNMENT\n                __short(aad, 3, buf_len - header_size);\n#else\n                *((unsigned short *)(aad + 3)) = htons(buf_len - header_size);\n#endif\n                aad_size = 5;\n                sequence = aad + 5;\n                if (context->dtls)\n                    *((uint64_t *)sequence) = *(uint64_t *)(buf + 3);\n                else\n#if NO_FUNNY_ALIGNMENT\n#if __BIG_ENDIAN__\n                    memcpy((void *)sequence, (void *)&context->remote_sequence_number, sizeof(uint64_t));\n#else\n                    __llong((void *)sequence, context->remote_sequence_number);\n#endif\n#else\n                    *((uint64_t *)sequence) = htonll(context->remote_sequence_number);\n#endif\n                memcpy(iv, context->crypto.ctx_remote_mac.remote_iv, TLS_13_AES_GCM_IV_LENGTH);\n                for (i = 0; i < 8; i++)\n                    iv[offset + i] = context->crypto.ctx_remote_mac.remote_iv[offset + i] ^ sequence[i];\n                pt_length = buf_len - header_size - TLS_GCM_TAG_LEN;\n                delta = 0;\n            } else {\n#endif\n                aad_size = 13;\n                pt_length = length - 8 - TLS_GCM_TAG_LEN;\n                /* build aad and iv */\n                if (context->dtls)\n                    *((uint64_t *)aad) = htonll(dtls_sequence_number);\n                else\n#if NO_FUNNY_ALIGNMENT\n#if __BIG_ENDIAN__\n                    memcpy((void *)aad, (void *)&context->remote_sequence_number, sizeof(uint64_t));\n#else\n                    __llong((void *)aad, context->remote_sequence_number);\n#endif\n#else\n                    *((uint64_t *)aad) = htonll(context->remote_sequence_number);\n#endif\n                aad[8] = buf[0];\n                aad[9] = buf[1];\n                aad[10] = buf[2];\n\n                memcpy(iv, context->crypto.ctx_remote_mac.remote_aead_iv, 4);\n                memcpy(iv + 4, buf + header_size, 8);\n#if NO_FUNNY_ALIGNMENT\n                __short(aad, 11, pt_length);\n#else\n                *((unsigned short *)(aad + 11)) = htons((unsigned short)pt_length);\n#endif\n#ifdef WITH_TLS_13\n            }\n#endif\n            if (pt_length < 0) {\n                DEBUG_PRINT0(\"Invalid packet length\");\n                TLS_FREE(pt);\n                _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                return TLS_BROKEN_PACKET;\n            }\n            DEBUG_DUMP_HEX_LABEL(\"aad\", aad, aad_size);\n            DEBUG_DUMP_HEX_LABEL(\"aad iv\", iv, 12);\n            \n            res0 = gcm_add_iv(&context->crypto.ctx_remote.aes_gcm_remote, iv, 12);\n            res1 = gcm_add_aad(&context->crypto.ctx_remote.aes_gcm_remote, aad, aad_size);\n            memset(pt, 0, length);\n            DEBUG_PRINT1(\"PT SIZE: %i\\n\", pt_length);\n            res2 = gcm_process(&context->crypto.ctx_remote.aes_gcm_remote, pt, pt_length, buf + header_size + delta, GCM_DECRYPT);\n            res3 = gcm_done(&context->crypto.ctx_remote.aes_gcm_remote, tag, &taglen);\n            if ((res0) || (res1) || (res2) || (res3) || (taglen != TLS_GCM_TAG_LEN)) {\n                DEBUG_PRINT4(\"ERROR: gcm_add_iv: %i, gcm_add_aad: %i, gcm_process: %i, gcm_done: %i\\n\", res0, res1, res2, res3);\n                _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                return TLS_BROKEN_PACKET;\n            }\n            DEBUG_DUMP_HEX_LABEL(\"decrypted\", pt, pt_length);\n            DEBUG_DUMP_HEX_LABEL(\"tag\", tag, taglen);\n            /* check tag */\n            if (memcmp(buf + header_size + delta + pt_length, tag, taglen)) {\n                DEBUG_PRINT1(\"INTEGRITY CHECK FAILED (msg length %i)\\n\", pt_length);\n                DEBUG_DUMP_HEX_LABEL(\"TAG RECEIVED\", buf + header_size + delta + pt_length, taglen);\n                DEBUG_DUMP_HEX_LABEL(\"TAG COMPUTED\", tag, taglen);\n                TLS_FREE(pt);\n                _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                _private_tls_write_packet(tls_build_alert(context, 1, bad_record_mac));\n                return TLS_INTEGRITY_FAILED;\n            }\n            ptr = pt;\n            length = (unsigned short)pt_length;\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        } else\n        if (context->crypto.created == 3) {\n            int pt_length = length - POLY1305_TAGLEN;\n            int rem;\n            unsigned int counter = 1;\n            unsigned char poly1305_key[POLY1305_KEYLEN];\n            unsigned char trail[16];\n            unsigned char mac_tag[POLY1305_TAGLEN];\n            poly1305_context ctx;\n            static unsigned char zeropad[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n\n            aad_size = 16;\n            if (pt_length < 0) {\n                DEBUG_PRINT0(\"Invalid packet length\");\n                TLS_FREE(pt);\n                _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                return TLS_BROKEN_PACKET;\n            }\n#ifdef WITH_TLS_13\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n                aad[0] = TLS_APPLICATION_DATA;\n                aad[1] = 0x03;\n                aad[2] = 0x03;\n#if NO_FUNNY_ALIGNMENT\n                __short(aad, 3, buf_len - header_size);\n#else\n                *((unsigned short *)(aad + 3)) = htons(buf_len - header_size);\n#endif\n                aad_size = 5;\n                sequence = aad + 5;\n                if (context->dtls)\n                    *((uint64_t *)sequence) = *(uint64_t *)(buf + 3);\n                else\n#if NO_FUNNY_ALIGNMENT\n#if __BIG_ENDIAN__\n                    memcpy((void *)sequence, (void *)&context->remote_sequence_number, sizeof(uint64_t));\n#else\n                    __llong((void *)sequence, context->remote_sequence_number);\n#endif\n#else\n                    *((uint64_t *)sequence) = htonll(context->remote_sequence_number);\n#endif\n            } else {\n#endif\n                if (context->dtls)\n                    *((uint64_t *)aad) = htonll(dtls_sequence_number);\n                else\n#if NO_FUNNY_ALIGNMENT\n#if __BIG_ENDIAN__\n                    memcpy((void *)aad, (void *)&context->remote_sequence_number, sizeof(uint64_t));\n#else\n                    __llong((void *)aad, context->remote_sequence_number);\n#endif\n#else\n                    *((uint64_t *)aad) = htonll(context->remote_sequence_number);\n#endif\n                aad[8] = buf[0];\n                aad[9] = buf[1];\n                aad[10] = buf[2];\n#if NO_FUNNY_ALIGNMENT\n                __short(aad, 11, pt_length);\n#else\n                *((unsigned short *)(aad + 11)) = htons((unsigned short)pt_length);\n#endif\n                aad[13] = 0;\n                aad[14] = 0;\n                aad[15] = 0;\n#ifdef WITH_TLS_13\n            }\n#endif\n\n            chacha_ivupdate(&context->crypto.ctx_remote.chacha_remote, context->crypto.ctx_remote_mac.remote_aead_iv, sequence, (unsigned char *)&counter);\n\n            chacha_encrypt_bytes(&context->crypto.ctx_remote.chacha_remote, buf + header_size, pt, pt_length);\n            DEBUG_DUMP_HEX_LABEL(\"decrypted\", pt, pt_length);\n            ptr = pt;\n            length = (unsigned short)pt_length;\n\n            chacha20_poly1305_key(&context->crypto.ctx_remote.chacha_remote, poly1305_key);\n            _private_tls_poly1305_init(&ctx, poly1305_key);\n            _private_tls_poly1305_update(&ctx, aad, aad_size);\n            rem = aad_size % 16;\n            if (rem)\n                _private_tls_poly1305_update(&ctx, zeropad, 16 - rem);\n            _private_tls_poly1305_update(&ctx, buf + header_size, pt_length);\n            rem = pt_length % 16;\n            if (rem)\n                _private_tls_poly1305_update(&ctx, zeropad, 16 - rem);\n            \n            _private_tls_U32TO8(&trail[0], aad_size == 5 ? 5 : 13);\n            _private_tls_U32TO8(&trail[8], pt_length);\n#if NO_FUNNY_ALIGNMENT\n            trail[4] = 0;\n            trail[5] = 0;\n            trail[6] = 0;\n            trail[7] = 0;\n            trail[12] = 0;\n            trail[13] = 0;\n            trail[14] = 0;\n            trail[15] = 0;\n#else\n            *(int *)&trail[4] = 0;\n            *(int *)&trail[12] = 0;\n#endif\n\n            _private_tls_poly1305_update(&ctx, trail, 16);\n            _private_tls_poly1305_finish(&ctx, mac_tag);\n            if (memcmp(mac_tag, buf + header_size + pt_length, POLY1305_TAGLEN)) {\n                DEBUG_PRINT1(\"INTEGRITY CHECK FAILED (msg length %i)\\n\", length);\n                DEBUG_DUMP_HEX_LABEL(\"POLY1305 TAG RECEIVED\", buf + header_size + pt_length, POLY1305_TAGLEN);\n                DEBUG_DUMP_HEX_LABEL(\"POLY1305 TAG COMPUTED\", mac_tag, POLY1305_TAGLEN);\n                TLS_FREE(pt);\n\n                /* silently ignore packet for DTLS */\n                if (context->dtls)\n                    return header_size + length;\n\n                _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                _private_tls_write_packet(tls_build_alert(context, 1, bad_record_mac));\n                return TLS_INTEGRITY_FAILED;\n            }\n#endif\n        } else {\n            unsigned char padding_byte;\n            unsigned char padding;\n            unsigned int decrypted_length;\n            int padding_index;\n            unsigned int mac_size;\n            const unsigned char *message_hmac;\n            unsigned char hmac_out[TLS_MAX_MAC_SIZE];\n            unsigned char temp_buf[5];\n            unsigned int hmac_out_len;\n\n            err = _private_tls_crypto_decrypt(context, buf + header_size, pt, length);\n            if (err) {\n                TLS_FREE(pt);\n                DEBUG_PRINT1(\"Decryption error %i\\n\", (int)err);\n                _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                return TLS_BROKEN_PACKET;\n            }\n            padding_byte = pt[length - 1];\n            padding = padding_byte + 1;\n            \n            /* poodle check */\n            padding_index = length - padding;\n            if (padding_index > 0) {\n                int i;\n                int limit = length - 1;\n                for (i = length - padding; i < limit; i++) {\n                    if (pt[i] != padding_byte) {\n                        TLS_FREE(pt);\n                        DEBUG_PRINT0(\"BROKEN PACKET (POODLE ?)\\n\");\n                        _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                        _private_tls_write_packet(tls_build_alert(context, 1, decrypt_error));\n                        return TLS_BROKEN_PACKET;\n                    }\n                }\n            }\n            \n            decrypted_length = length;\n            if (padding < decrypted_length)\n                decrypted_length -= padding;\n            \n            DEBUG_DUMP_HEX_LABEL(\"decrypted\", pt, decrypted_length);\n            ptr = pt;\n#ifdef TLS_LEGACY_SUPPORT\n            if ((context->version != TLS_V10) && (decrypted_length > TLS_AES_IV_LENGTH)) {\n                decrypted_length -= TLS_AES_IV_LENGTH;\n                ptr += TLS_AES_IV_LENGTH;\n            }\n#else\n            if (decrypted_length > TLS_AES_IV_LENGTH) {\n                decrypted_length -= TLS_AES_IV_LENGTH;\n                ptr += TLS_AES_IV_LENGTH;\n            }\n#endif\n            length = decrypted_length;\n            \n            mac_size = _private_tls_mac_length(context);\n            if ((length < mac_size) || (!mac_size)) {\n                TLS_FREE(pt);\n                DEBUG_PRINT0(\"BROKEN PACKET\\n\");\n                _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                _private_tls_write_packet(tls_build_alert(context, 1, decrypt_error));\n                return TLS_BROKEN_PACKET;\n            }\n            \n            length -= mac_size;\n            \n            message_hmac = &ptr[length];\n            memcpy(temp_buf, buf, 3);\n            *(unsigned short *)(temp_buf + 3) = htons(length);\n            hmac_out_len = _private_tls_hmac_message(0, context, temp_buf, 5, ptr, length, hmac_out, mac_size, dtls_sequence_number);\n            if ((hmac_out_len != mac_size) || (memcmp(message_hmac, hmac_out, mac_size))) {\n                DEBUG_PRINT1(\"INTEGRITY CHECK FAILED (msg length %i)\\n\", length);\n                DEBUG_DUMP_HEX_LABEL(\"HMAC RECEIVED\", message_hmac, mac_size);\n                DEBUG_DUMP_HEX_LABEL(\"HMAC COMPUTED\", hmac_out, hmac_out_len);\n                TLS_FREE(pt);\n\n                /* silently ignore packet for DTLS */\n                if (context->dtls)\n                    return header_size + length;\n\n                _private_random_sleep(context, TLS_MAX_ERROR_SLEEP_uS);\n                _private_tls_write_packet(tls_build_alert(context, 1, bad_record_mac));\n\n                return TLS_INTEGRITY_FAILED;\n            }\n        }\n    }\n    context->remote_sequence_number++;\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        if (/*(context->connection_status == 2) && */(type == TLS_APPLICATION_DATA) && (context->crypto.created)) {\n            do {\n                length--;\n                type = ptr[length];\n            } while (!type);\n        }\n    }\n#endif\n    switch (type) {\n            /* application data */\n        case TLS_APPLICATION_DATA:\n            if (context->connection_status != 0xFF) {\n                DEBUG_PRINT0(\"UNEXPECTED APPLICATION DATA MESSAGE\\n\");\n                DEBUG_DUMP_HEX(ptr, length);\n                DEBUG_PRINT0(\"\\n\");\n                payload_res = TLS_UNEXPECTED_MESSAGE;\n                _private_tls_write_packet(tls_build_alert(context, 1, unexpected_message));\n            } else {\n                DEBUG_PRINT1(\"APPLICATION DATA MESSAGE (TLS VERSION: %x):\\n\", (int)context->version);\n                DEBUG_DUMP(ptr, length);\n                DEBUG_PRINT0(\"\\n\");\n                _private_tls_write_app_data(context, ptr, length);\n            }\n            break;\n            /* handshake */\n        case TLS_HANDSHAKE:\n            DEBUG_PRINT0(\"HANDSHAKE MESSAGE\\n\");\n            payload_res = tls_parse_payload(context, ptr, length, certificate_verify);\n            break;\n            /* change cipher spec */\n        case TLS_CHANGE_CIPHER:\n            context->dtls_epoch_remote++;\n            if (context->connection_status != 2) {\n#ifdef WITH_TLS_13\n                if (context->connection_status == 4) {\n                    DEBUG_PRINT0(\"IGNORING CHANGE CIPHER SPEC MESSAGE (HELLO RETRY REQUEST)\\n\");\n                    break;\n                }\n#endif\n                DEBUG_PRINT1(\"UNEXPECTED CHANGE CIPHER SPEC MESSAGE (%i)\\n\", context->connection_status);\n                _private_tls_write_packet(tls_build_alert(context, 1, unexpected_message));\n                payload_res = TLS_UNEXPECTED_MESSAGE;\n            } else {\n                DEBUG_PRINT0(\"CHANGE CIPHER SPEC MESSAGE\\n\");\n                context->cipher_spec_set = 1;\n                /* reset sequence numbers */\n                context->remote_sequence_number = 0;\n            }\n#ifdef WITH_TLS_13\n            if (!context->is_server)\n                _private_tls13_key(context, 1);\n#endif\n            break;\n            /* alert */\n        case TLS_ALERT:\n            DEBUG_PRINT0(\"ALERT MESSAGE\\n\");\n            if (length >= 2) {\n                int level, code;\n\n                DEBUG_DUMP_HEX(ptr, length);\n                level = ptr[0];\n                code = ptr[1];\n                if (level == TLS_ALERT_CRITICAL) {\n                    context->critical_error = 1;\n                    res = TLS_ERROR_ALERT;\n                }\n                context->error_code = code;\n            }\n            break;\n        default:\n            DEBUG_PRINT1(\"NOT UNDERSTOOD MESSAGE TYPE: %x\\n\", (int)type);\n            TLS_FREE(pt);\n            return TLS_NOT_UNDERSTOOD;\n    }\n    TLS_FREE(pt);\n    \n    if (payload_res < 0)\n        return payload_res;\n    \n    if (res > 0)\n        return header_size + length;\n    \n    return res;\n}\n\nunsigned int asn1_get_len(const unsigned char *buffer, int buf_len, unsigned int *octets) {\n    int i;\n    unsigned char size;\n\n    *octets = 0;\n    if (buf_len < 1)\n        return 0;\n\n    size = buffer[0];\n    if (size & 0x80) {\n        unsigned int ref_octets;\n        unsigned int long_size = 0;\n        unsigned int coef = 1;\n        \n        *octets = size & 0x7F;\n        if ((int)*octets > buf_len - 1)\n            return 0;\n        ref_octets = *octets;\n        /* max 32 bits */\n        if (*octets > 4)\n            ref_octets = 4;\n        if ((int)*octets > buf_len -1)\n            return 0;\n        for (i = ref_octets; i > 0; i--) {\n            long_size += buffer[i] * coef;\n            coef *= 0x100;\n        }\n        ++*octets;\n        return long_size;\n    }\n    ++*octets;\n    return size;\n}\n\nvoid print_index(const unsigned int *fields) {\n    int i = 0;\n    while (fields[i]) {\n        if (i)\n            DEBUG_PRINT0(\".\");\n        DEBUG_PRINT1(\"%i\", fields[i]);\n        i++;\n    }\n    while (i < 6) {\n        DEBUG_PRINT0(\"  \");\n        i++;\n    }\n}\n\nint _is_field(const unsigned int *fields, const unsigned int *prefix) {\n    int i = 0;\n    while (prefix[i]) {\n        if (fields[i] != prefix[i])\n            return 0;\n        i++;\n    }\n    return 1;\n}\n\nint _private_tls_hash_len(int algorithm) {\n    switch (algorithm) {\n        case TLS_RSA_SIGN_MD5:\n            return 16;\n        case TLS_RSA_SIGN_SHA1:\n            return 20;\n        case TLS_RSA_SIGN_SHA256:\n        case TLS_ECDSA_SIGN_SHA256:\n            return 32;\n        case TLS_RSA_SIGN_SHA384:\n            return 48;\n        case TLS_RSA_SIGN_SHA512:\n            return 64;\n    }\n    return 0;\n}\n\nunsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *message, unsigned int message_len) {\n    unsigned char *hash = NULL;\n    int err;\n    hash_state state;\n\n    if ((!message) || (!message_len))\n        return hash;\n    switch (algorithm) {\n        case TLS_RSA_SIGN_MD5:\n            DEBUG_PRINT0(\"SIGN MD5\\n\");\n            hash = (unsigned char *)TLS_MALLOC(16);\n            if (!hash)\n                return NULL;\n            \n            err = md5_init(&state);\n            if (!err) {\n                err = md5_process(&state, message, message_len);\n                if (!err)\n                    err = md5_done(&state, hash);\n            }\n            break;\n        case TLS_RSA_SIGN_SHA1:\n            DEBUG_PRINT0(\"SIGN SHA1\\n\");\n            hash = (unsigned char *)TLS_MALLOC(20);\n            if (!hash)\n                return NULL;\n            \n            err = sha1_init(&state);\n            if (!err) {\n                err = sha1_process(&state, message, message_len);\n                if (!err)\n                    err = sha1_done(&state, hash);\n            }\n            break;\n        case TLS_RSA_SIGN_SHA256:\n        case TLS_ECDSA_SIGN_SHA256:\n            DEBUG_PRINT0(\"SIGN SHA256\\n\");\n            hash = (unsigned char *)TLS_MALLOC(32);\n            if (!hash)\n                return NULL;\n            \n            err = sha256_init(&state);\n            if (!err) {\n                err = sha256_process(&state, message, message_len);\n                if (!err)\n                    err = sha256_done(&state, hash);\n            }\n            break;\n        case TLS_RSA_SIGN_SHA384:\n            DEBUG_PRINT0(\"SIGN SHA384\\n\");\n            hash = (unsigned char *)TLS_MALLOC(48);\n            if (!hash)\n                return NULL;\n            \n            err = sha384_init(&state);\n            if (!err) {\n                err = sha384_process(&state, message, message_len);\n                if (!err)\n                    err = sha384_done(&state, hash);\n            }\n            break;\n        case TLS_RSA_SIGN_SHA512:\n            DEBUG_PRINT0(\"SIGN SHA512\\n\");\n            hash = (unsigned char *)TLS_MALLOC(64);\n            if (!hash)\n                return NULL;\n            \n            err = sha512_init(&state);\n            if (!err) {\n                err = sha512_process(&state, message, message_len);\n                if (!err)\n                    err = sha512_done(&state, hash);\n            }\n            break;\n        default:\n            DEBUG_PRINT0(\"UNKNOWN SIGNATURE ALGORITHM\\n\");\n    }\n    return hash;\n}\n\nint tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCertificate *parent) {\n    int hash_len;\n    int hash_index = -1;\n    rsa_key key;\n    int err;\n    int rsa_stat = 0;\n    unsigned char *signature;\n    int signature_len;\n\n    if ((!cert) || (!parent) || (!cert->sign_key) || (!cert->fingerprint) || (!cert->sign_len) || (!parent->der_bytes) || (!parent->der_len)) {\n        DEBUG_PRINT0(\"CANNOT VERIFY SIGNATURE\");\n        return 0;\n    }\n    tls_init();\n    hash_len = _private_tls_hash_len(cert->algorithm);\n    if (hash_len <= 0)\n        return 0;\n    \n    switch (cert->algorithm) {\n        case TLS_RSA_SIGN_MD5:\n            hash_index = find_hash(\"md5\");\n            break;\n        case TLS_RSA_SIGN_SHA1:\n            hash_index = find_hash(\"sha1\");\n            break;\n        case TLS_RSA_SIGN_SHA256:\n        case TLS_ECDSA_SIGN_SHA256:\n            hash_index = find_hash(\"sha256\");\n            break;\n        case TLS_RSA_SIGN_SHA384:\n            hash_index = find_hash(\"sha384\");\n            break;\n        case TLS_RSA_SIGN_SHA512:\n            hash_index = find_hash(\"sha512\");\n            break;\n        default:\n            DEBUG_PRINT0(\"UNKNOWN SIGNATURE ALGORITHM\\n\");\n            return 0;\n    }\n#ifdef TLS_ECDSA_SUPPORTED\n    if (cert->algorithm == TLS_ECDSA_SIGN_SHA256) {\n        ecc_key key;\n        int ecc_stat = 0;\n        unsigned char *signature = cert->sign_key;\n        int signature_len = cert->sign_len;\n\n        int err = ecc_import(parent->der_bytes, parent->der_len, &key);\n        if (err) {\n            DEBUG_PRINT1(\"Error importing ECC certificate (code: %i)\\n\", err);\n            DEBUG_DUMP_HEX_LABEL(\"CERTIFICATE\", parent->der_bytes, parent->der_len);\n            return 0;\n        }\n        if (!signature[0]) {\n            signature++;\n            signature_len--;\n        }\n        err = ecc_verify_hash(signature, signature_len, cert->fingerprint, hash_len, &ecc_stat, &key);\n        ecc_free(&key);\n        if (err) {\n            DEBUG_PRINT1(\"ECC HASH VERIFY ERROR %i\\n\", err);\n            return 0;\n        }\n        DEBUG_PRINT1(\"ECC CERTIFICATE VALIDATION: %i\\n\", ecc_stat);\n        return ecc_stat;\n    }\n#endif\n    \n    err = rsa_import(parent->der_bytes, parent->der_len, &key);\n    if (err) {\n        DEBUG_PRINT1(\"Error importing RSA certificate (code: %i)\\n\", err);\n        DEBUG_DUMP_HEX_LABEL(\"CERTIFICATE\", parent->der_bytes, parent->der_len);\n        return 0;\n    }\n    signature = cert->sign_key;\n    signature_len = cert->sign_len;\n    if (!signature[0]) {\n        signature++;\n        signature_len--;\n    }\n    err = rsa_verify_hash_ex(signature, signature_len, cert->fingerprint, hash_len, LTC_PKCS_1_V1_5, hash_index, 0, &rsa_stat, &key);\n    rsa_free(&key);\n    if (err) {\n        DEBUG_PRINT1(\"HASH VERIFY ERROR %i\\n\", err);\n        return 0;\n    }\n    DEBUG_PRINT1(\"CERTIFICATE VALIDATION: %i\\n\", rsa_stat);\n    return rsa_stat;\n}\n\nint tls_certificate_chain_is_valid(struct TLSCertificate **certificates, int len) {\n    int i;\n\n    if ((!certificates) || (!len))\n        return bad_certificate;\n    len--;\n\n    /* expired certificate or not yet valid? */\n    if (tls_certificate_is_valid(certificates[0]))\n        return bad_certificate;\n    \n    /* check */\n    for (i = 0; i < len; i++) {\n        /* certificate in chain is expired? */\n        if (tls_certificate_is_valid(certificates[i+1]))\n            return bad_certificate;\n        if (!tls_certificate_verify_signature(certificates[i], certificates[i+1]))\n            return bad_certificate;\n    }\n    return 0;\n}\n\nint tls_certificate_chain_is_valid_root(struct TLSContext *context, struct TLSCertificate **certificates, int len) {\n    int i;\n    unsigned int j;\n\n    if ((!certificates) || (!len) || (!context->root_certificates) || (!context->root_count))\n        return bad_certificate;\n    for (i = 0; i < len; i++) {\n        for (j = 0; j < context->root_count; j++) {\n            /* check if root certificate expired */\n            if (tls_certificate_is_valid(context->root_certificates[j]))\n                continue;\n            /* if any root validates any certificate in the chain, then is root validated */\n            if (tls_certificate_verify_signature(certificates[i], context->root_certificates[j]))\n                return 0;\n        }\n    }\n    return bad_certificate;\n}\n\nint _private_is_oid(struct _private_OID_chain *ref_chain, const unsigned char *looked_oid, int looked_oid_len) {\n    while (ref_chain) {\n        if (ref_chain->oid) {\n            if (_is_oid2(ref_chain->oid, looked_oid, 16, looked_oid_len))\n                return 1;\n        }\n        ref_chain = (struct _private_OID_chain *)ref_chain->top;\n    }\n    return 0;\n}\n\nint _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, const unsigned char *buffer, unsigned int size, int level, unsigned int *fields, unsigned char *has_key, int client_cert, unsigned char *top_oid, struct _private_OID_chain *chain) {\n    struct _private_OID_chain local_chain;\n    unsigned char local_has_key = 0;\n    const unsigned char *cert_data = NULL;\n    unsigned int cert_len = 0;\n    unsigned int pos = 0;\n    int idx = 0;\n    unsigned char oid[16];\n\n    local_chain.top = chain;\n    /* X.690 */\n    memset(oid, 0, 16);\n    local_chain.oid = oid;\n    if (has_key)\n        *has_key = 0;\n    while (pos < size) {\n        unsigned int start_pos = pos;\n        unsigned int octets = 0;\n        unsigned int temp, length;\n        int i1;\n        unsigned char first, type, constructed, element_class;\n\n        CHECK_SIZE(2, size - pos, TLS_NEED_MORE_DATA)\n        first = buffer[pos++];\n        type = first & 0x1F;\n        constructed = first & 0x20;\n        element_class = first >> 6;\n        idx++;\n        if (level <= TLS_ASN1_MAXLEVEL)\n            fields[level - 1] = idx;\n        length = asn1_get_len((unsigned char *)&buffer[pos], size - pos, &octets);\n        if ((octets > 4) || (octets > size - pos))  {\n            DEBUG_PRINT0(\"CANNOT READ CERTIFICATE\\n\");\n            return pos;\n        }\n        pos += octets;\n        CHECK_SIZE(length, size - pos, TLS_NEED_MORE_DATA)\n#if (0)\n        DEBUG_PRINT3(\"FIRST: %x => %x (%i)\\n\", (int)first, (int)type, length);\n        /* sequence */\n        DEBUG_PRINT1(\"%2i: \", level);\n#endif\n#ifdef DEBUG\n        DEBUG_INDEX(fields);\n        for (i1 = 1; i1 < level; i1++)\n            DEBUG_PRINT0(\"  \");\n#endif\n        \n        if ((length) && (constructed)) {\n            switch (type) {\n                case 0x03:\n                    DEBUG_PRINT0(\"CONSTRUCTED BITSTREAM\\n\");\n                    break;\n                case 0x10:\n                    DEBUG_PRINT0(\"SEQUENCE\\n\");\n                    if ((level == 2) && (idx == 1)) {\n                        cert_len = length + (pos - start_pos);\n                        cert_data = &buffer[start_pos];\n                    }\n                    /* private key on server or public key on client */\n                    if ((!cert->version) && (_is_field(fields, priv_der_id))) {\n                        TLS_FREE(cert->der_bytes);\n                        temp = length + (pos - start_pos);\n                        cert->der_bytes = (unsigned char *)TLS_MALLOC(temp);\n                        if (cert->der_bytes) {\n                            memcpy(cert->der_bytes, &buffer[start_pos], temp);\n                            cert->der_len = temp;\n                        } else\n                            cert->der_len = 0;\n                    }\n                    break;\n                case 0x11:\n                    DEBUG_PRINT0(\"EMBEDDED PDV\\n\");\n                    break;\n                case 0x00:\n                    if (element_class == 0x02) {\n                        DEBUG_PRINT0(\"CONTEXT-SPECIFIC\\n\");\n                        break;\n                    }\n                default:\n                    DEBUG_PRINT1(\"CONSTRUCT TYPE %02X\\n\", (int)type);\n            }\n            local_has_key = 0;\n            _private_asn1_parse(context, cert, &buffer[pos], length, level + 1, fields, &local_has_key, client_cert, top_oid, &local_chain);\n            if ((((local_has_key) && (context) && ((!context->is_server) || (client_cert))) || (!context)) && (_is_field(fields, pk_id))) {\n                TLS_FREE(cert->der_bytes);\n                temp = length + (pos - start_pos);\n                cert->der_bytes = (unsigned char *)TLS_MALLOC(temp);\n                if (cert->der_bytes) {\n                    memcpy(cert->der_bytes, &buffer[start_pos], temp);\n                    cert->der_len = temp;\n                } else\n                    cert->der_len = 0;\n            }\n        } else {\n            switch (type) {\n                case 0x00:\n                    /* end of content */\n                    DEBUG_PRINT0(\"END OF CONTENT\\n\");\n                    return pos;\n                    break;\n                case 0x01:\n                    /* boolean */\n                    temp = buffer[pos];\n                    DEBUG_PRINT1(\"BOOLEAN: %i\\n\", temp);\n                    break;\n                case 0x02:\n                    /* integer */\n                    if (_is_field(fields, pk_id)) {\n                        if (has_key)\n                            *has_key = 1;\n                        \n                        if (idx == 1)\n                            tls_certificate_set_key(cert, &buffer[pos], length);\n                        else\n                        if (idx == 2)\n                            tls_certificate_set_exponent(cert, &buffer[pos], length);\n                    } else\n                    if (_is_field(fields, serial_id))\n                        tls_certificate_set_serial(cert, &buffer[pos], length);\n                    if (_is_field(fields, version_id)) {\n                        if (length == 1)\n                            cert->version = buffer[pos];\n#ifdef TLS_X509_V1_SUPPORT\n                        else\n                            cert->version = 0;\n                        idx++;\n#endif\n                    }\n                    if (level >= 2) {\n                        unsigned int fields_temp[3];\n                        fields_temp[0] = fields[level - 2];\n                        fields_temp[1] = fields[level - 1];\n                        fields_temp[2] = 0;\n                        if (_is_field(fields_temp, priv_id))\n                            tls_certificate_set_priv(cert, &buffer[pos], length);\n                    }\n                    DEBUG_PRINT1(\"INTEGER(%i): \", length);\n                    DEBUG_DUMP_HEX(&buffer[pos], length);\n                    if ((chain) && (length > 2)) {\n                        if (_private_is_oid(chain, san_oid, sizeof(san_oid) - 1)) {\n                            cert->san = (unsigned char **)TLS_REALLOC(cert->san, sizeof(unsigned char *) * (cert->san_length + 1));\n                            if (cert->san) {\n                                cert->san[cert->san_length] = NULL;\n                                tls_certificate_set_copy(&cert->san[cert->san_length], &buffer[pos], length);\n                                DEBUG_PRINT1(\" => SUBJECT ALTERNATIVE NAME: %s\", cert->san[cert->san_length ]);\n                                cert->san_length++;\n                            } else\n                                cert->san_length = 0;\n                        }\n                    }\n                    DEBUG_PRINT0(\"\\n\");\n                    break;\n                case 0x03:\n                    if (_is_field(fields, pk_id)) {\n                        if (has_key)\n                            *has_key = 1;                        \n                    }\n                    /* bitstream */\n                    DEBUG_PRINT1(\"BITSTREAM(%i): \", length);\n                    DEBUG_DUMP_HEX(&buffer[pos], length);\n                    DEBUG_PRINT0(\"\\n\");\n                    if (_is_field(fields, sign_id)) {\n                        tls_certificate_set_sign_key(cert, &buffer[pos], length);\n                    } else\n                    if ((cert->ec_algorithm) && (_is_field(fields, pk_id))) {\n                        tls_certificate_set_key(cert, &buffer[pos], length);\n                    } else {\n                        if ((buffer[pos] == 0x00) && (length > 256))\n                            _private_asn1_parse(context, cert, &buffer[pos]+1, length - 1, level + 1, fields, &local_has_key, client_cert, top_oid, &local_chain);\n                        else\n                            _private_asn1_parse(context, cert, &buffer[pos], length, level + 1, fields, &local_has_key, client_cert, top_oid, &local_chain);\n#ifdef TLS_FORWARD_SECRECY\n    #ifdef TLS_ECDSA_SUPPORTED\n                        if (top_oid) {\n                            if (_is_oid2(top_oid, TLS_EC_prime256v1_OID, sizeof(oid), sizeof(TLS_EC_prime256v1) - 1)) {\n                                cert->ec_algorithm = secp256r1.iana;\n                            } else\n                            if (_is_oid2(top_oid, TLS_EC_secp224r1_OID, sizeof(oid), sizeof(TLS_EC_secp224r1_OID) - 1)) {\n                                cert->ec_algorithm = secp224r1.iana;\n                            } else\n                            if (_is_oid2(top_oid, TLS_EC_secp384r1_OID, sizeof(oid), sizeof(TLS_EC_secp384r1_OID) - 1)) {\n                                cert->ec_algorithm = secp384r1.iana;\n                            } else\n                            if (_is_oid2(top_oid, TLS_EC_secp521r1_OID, sizeof(oid), sizeof(TLS_EC_secp521r1_OID) - 1)) {\n                                cert->ec_algorithm = secp521r1.iana;\n                            }\n                            if ((cert->ec_algorithm) && (!cert->pk))\n                                tls_certificate_set_key(cert, &buffer[pos], length);\n                        }\n    #endif\n#endif\n                    }\n                    break;\n                case 0x04:\n                    if ((top_oid) && (_is_field(fields, ecc_priv_id)) && (!cert->priv)) {\n                        DEBUG_PRINT1(\"BINARY STRING(%i): \", length);\n                        DEBUG_DUMP_HEX(&buffer[pos], length);\n                        DEBUG_PRINT0(\"\\n\");\n                        tls_certificate_set_priv(cert, &buffer[pos], length);\n                    } else\n                        _private_asn1_parse(context, cert, &buffer[pos], length, level + 1, fields, &local_has_key, client_cert, top_oid, &local_chain);\n                    break;\n                case 0x05:\n                    DEBUG_PRINT0(\"NULL\\n\");\n                    break;\n                case 0x06:\n                    /* object identifier */\n                    if (_is_field(fields, pk_id)) {\n#ifdef TLS_ECDSA_SUPPORTED\n                        if ((length == 8) || (length == 5))\n                            tls_certificate_set_algorithm(context, &cert->ec_algorithm, &buffer[pos], length);\n                        else\n#endif\n                            tls_certificate_set_algorithm(context, &cert->key_algorithm, &buffer[pos], length);\n                    }\n                    if (_is_field(fields, algorithm_id))\n                        tls_certificate_set_algorithm(context, &cert->algorithm, &buffer[pos], length);\n                    \n                    DEBUG_PRINT1(\"OBJECT IDENTIFIER(%i): \", length);\n                    DEBUG_DUMP_HEX(&buffer[pos], length);\n                    DEBUG_PRINT0(\"\\n\");\n                    /* check previous oid */\n                    if (_is_oid2(oid, ocsp_oid, 16, sizeof(ocsp_oid) - 1))\n                        tls_certificate_set_copy(&cert->ocsp, &buffer[pos], length);\n\n                    if (length < 16)\n                        memcpy(oid, &buffer[pos], length);\n                    else\n                        memcpy(oid, &buffer[pos], 16);\n                    if (top_oid)\n                        memcpy(top_oid, oid, 16);\n                    break;\n                case 0x09:\n                    DEBUG_PRINT1(\"REAL NUMBER(%i): \", length);\n                    DEBUG_DUMP_HEX(&buffer[pos], length);\n                    DEBUG_PRINT0(\"\\n\");\n                    break;\n                case 0x17:\n                    /* utc time */\n                    DEBUG_PRINT0(\"UTC TIME: [\");\n                    DEBUG_DUMP(&buffer[pos], length);\n                    DEBUG_PRINT0(\"]\\n\");\n                    \n                    if (_is_field(fields, validity_id)) {\n                        if (idx == 1)\n                            tls_certificate_set_copy_date(&cert->not_before, &buffer[pos], length);\n                        else\n                            tls_certificate_set_copy_date(&cert->not_after, &buffer[pos], length);\n                    }\n                    break;\n                case 0x18:\n                    /* generalized time */\n                    DEBUG_PRINT0(\"GENERALIZED TIME: [\");\n                    DEBUG_DUMP(&buffer[pos], length);\n                    DEBUG_PRINT0(\"]\\n\");\n                    break;\n                case 0x13:\n                    /* printable string */\n                case 0x0C:\n                case 0x14:\n                case 0x15:\n                case 0x16:\n                case 0x19:\n                case 0x1A:\n                case 0x1B:\n                case 0x1C:\n                case 0x1D:\n                case 0x1E:\n                    if (_is_field(fields, issurer_id)) {\n                        if (_is_oid(oid, country_oid, 3))\n                            tls_certificate_set_copy(&cert->issuer_country, &buffer[pos], length);\n                        else\n                        if (_is_oid(oid, state_oid, 3))\n                            tls_certificate_set_copy(&cert->issuer_state, &buffer[pos], length);\n                        else\n                        if (_is_oid(oid, location_oid, 3))\n                            tls_certificate_set_copy(&cert->issuer_location, &buffer[pos], length);\n                        else\n                        if (_is_oid(oid, entity_oid, 3))\n                            tls_certificate_set_copy(&cert->issuer_entity, &buffer[pos], length);\n                        else\n                        if (_is_oid(oid, subject_oid, 3))\n                            tls_certificate_set_copy(&cert->issuer_subject, &buffer[pos], length);\n                    } else\n                    if (_is_field(fields, owner_id)) {\n                        if (_is_oid(oid, country_oid, 3))\n                            tls_certificate_set_copy(&cert->country, &buffer[pos], length);\n                        else\n                        if (_is_oid(oid, state_oid, 3))\n                            tls_certificate_set_copy(&cert->state, &buffer[pos], length);\n                        else\n                        if (_is_oid(oid, location_oid, 3))\n                            tls_certificate_set_copy(&cert->location, &buffer[pos], length);\n                        else\n                        if (_is_oid(oid, entity_oid, 3))\n                            tls_certificate_set_copy(&cert->entity, &buffer[pos], length);\n                        else\n                        if (_is_oid(oid, subject_oid, 3))\n                            tls_certificate_set_copy(&cert->subject, &buffer[pos], length);\n                    }\n                    DEBUG_PRINT0(\"STR: [\");\n                    DEBUG_DUMP(&buffer[pos], length);\n                    DEBUG_PRINT0(\"]\\n\");\n                    break;\n                case 0x10:\n                    DEBUG_PRINT0(\"EMPTY SEQUENCE\\n\");\n                    break;\n                case 0xA:\n                    DEBUG_PRINT1(\"ENUMERATED(%i): \", length);\n                    DEBUG_DUMP_HEX(&buffer[pos], length);\n                    DEBUG_PRINT0(\"\\n\");\n                    break;\n                default:\n                    DEBUG_PRINT1(\"========> NOT SUPPORTED %x\\n\", (int)type);\n                    /* not supported / needed */\n                    break;\n            }\n        }\n        pos += length;\n    }\n    if ((level == 2) && (cert->sign_key) && (cert->sign_len) && (cert_len) && (cert_data)) {\n        TLS_FREE(cert->fingerprint);\n        cert->fingerprint = _private_tls_compute_hash(cert->algorithm, cert_data, cert_len);\n#ifdef DEBUG\n        if (cert->fingerprint) {\n            DEBUG_DUMP_HEX_LABEL(\"FINGERPRINT\", cert->fingerprint, _private_tls_hash_len(cert->algorithm));\n        }\n#endif\n    }\n    return pos;\n}\n\nstruct TLSCertificate *asn1_parse(struct TLSContext *context, const unsigned char *buffer, unsigned int size, int client_cert) {\n    unsigned int fields[TLS_ASN1_MAXLEVEL];\n    struct TLSCertificate *cert = tls_create_certificate();\n\n    memset(fields, 0, sizeof(int) * TLS_ASN1_MAXLEVEL);\n    if (cert) {\n        if (client_cert < 0) {\n            unsigned char top_oid[16];\n\n            client_cert = 0;\n            /* private key */\n            memset(top_oid, 0, sizeof(top_oid));\n            _private_asn1_parse(context, cert, buffer, size, 1, fields, NULL, client_cert, top_oid, NULL);\n        } else\n            _private_asn1_parse(context, cert, buffer, size, 1, fields, NULL, client_cert, NULL, NULL);\n    }\n    return cert;\n}\n\nint tls_load_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) {\n    unsigned int len;\n    int idx = 0;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    \n    do {\n        struct TLSCertificate *cert;\n        unsigned char *data = tls_pem_decode(pem_buffer, pem_size, idx++, &len);\n        if ((!data) || (!len))\n            break;\n        cert = asn1_parse(context, data, len, 0);\n        if (cert) {\n            if ((cert->version == 2) \n#ifdef TLS_X509_V1_SUPPORT\n                || (cert->version == 0)\n#endif\n            ) {\n                TLS_FREE(cert->der_bytes);\n                cert->der_bytes = data;\n                cert->der_len = len;\n                data = NULL;\n                if (cert->priv) {\n                    DEBUG_PRINT0(\"WARNING - parse error (private key encountered in certificate)\\n\");\n                    TLS_FREE(cert->priv);\n                    cert->priv = NULL;\n                    cert->priv_len = 0;\n                }\n                if (context->is_server) {\n                    context->certificates = (struct TLSCertificate **)TLS_REALLOC(context->certificates, (context->certificates_count + 1) * sizeof(struct TLSCertificate *));\n                    context->certificates[context->certificates_count] = cert;\n                    context->certificates_count++;\n                    DEBUG_PRINT1(\"Loaded certificate: %i\\n\", (int)context->certificates_count);\n                } else {\n                    context->client_certificates = (struct TLSCertificate **)TLS_REALLOC(context->client_certificates, (context->client_certificates_count + 1) * sizeof(struct TLSCertificate *));\n                    context->client_certificates[context->client_certificates_count] = cert;\n                    context->client_certificates_count++;\n                    DEBUG_PRINT1(\"Loaded client certificate: %i\\n\", (int)context->client_certificates_count);\n                }\n            } else {\n                DEBUG_PRINT1(\"WARNING - certificate version error (v%i)\\n\", (int)cert->version);\n                tls_destroy_certificate(cert);\n            }\n        }\n        TLS_FREE(data);\n    } while (1);\n    return context->certificates_count;\n}\n\nint tls_load_private_key(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) {\n    unsigned int len;\n    int idx = 0;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    \n    do {\n        struct TLSCertificate *cert;\n        unsigned char *data = tls_pem_decode(pem_buffer, pem_size, idx++, &len);\n        if ((!data) || (!len))\n            break;\n        cert = asn1_parse(context, data, len, -1);\n        if (cert) {\n            if (!cert->der_len) {\n                TLS_FREE(cert->der_bytes);\n                cert->der_bytes = data;\n                cert->der_len = len;\n            } else\n                TLS_FREE(data);\n            if ((cert) && (cert->priv) && (cert->priv_len)) {\n#ifdef TLS_ECDSA_SUPPORTED\n                if (cert->ec_algorithm) {\n                    DEBUG_PRINT0(\"Loaded ECC private key\\n\");\n                    if (context->ec_private_key)\n                        tls_destroy_certificate(context->ec_private_key);\n                    context->ec_private_key = cert;\n                    return 1;\n                } else\n#endif\n                {\n                    DEBUG_PRINT0(\"Loaded private key\\n\");\n                    if (context->private_key)\n                        tls_destroy_certificate(context->private_key);\n                    context->private_key = cert;\n                    return 1;\n                }\n            }\n            tls_destroy_certificate(cert);\n        } else\n            TLS_FREE(data);\n    } while (1);\n    return 0;\n}\n\nint tls_clear_certificates(struct TLSContext *context) {\n    unsigned int i;\n    if ((!context) || (!context->is_server) || (context->is_child))\n        return TLS_GENERIC_ERROR;\n\n    if (context->root_certificates) {\n        for (i = 0; i < context->root_count; i++)\n            tls_destroy_certificate(context->root_certificates[i]);\n    }\n    context->root_certificates = NULL;\n    context->root_count = 0;\n    if (context->private_key)\n        tls_destroy_certificate(context->private_key);\n    context->private_key = NULL;\n#ifdef TLS_ECDSA_SUPPORTED\n    if (context->ec_private_key)\n        tls_destroy_certificate(context->ec_private_key);\n    context->ec_private_key = NULL;\n#endif\n    TLS_FREE(context->certificates);\n    context->certificates = NULL;\n    context->certificates_count = 0;\n    return 0;\n}\n\n#ifdef WITH_TLS_13\nstruct TLSPacket *tls_build_certificate_verify(struct TLSContext *context) {\n    int packet_size = 2;\n    unsigned char out[TLS_MAX_RSA_KEY];\n#ifdef TLS_ECDSA_SUPPORTED\n    unsigned long out_len = TLS_MAX_RSA_KEY;\n#endif\n    int hash_algorithm = sha256;\n    unsigned char signing_data[TLS_MAX_HASH_SIZE + 98];\n    int signing_data_len;\n    unsigned int size_offset;\n    struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0);\n\n    /* certificate verify */\n    tls_packet_uint8(packet, 0x0F);\n    size_offset = packet->len;\n    tls_packet_uint24(packet, 0);\n\n    /* first 64 bytes to 0x20 (32) */\n    memset(signing_data, 0x20, 64);\n    /* context string 33 bytes */\n    if (context->is_server)\n        memcpy(signing_data + 64, \"TLS 1.3, server CertificateVerify\", 33);\n    else\n        memcpy(signing_data + 64, \"TLS 1.3, client CertificateVerify\", 33);\n    /* a single 0 byte separator */\n    signing_data[97] = 0;\n    signing_data_len = 98;\n\n    signing_data_len += _private_tls_get_hash(context, signing_data + 98);\n    DEBUG_DUMP_HEX_LABEL(\"verify data\", signing_data, signing_data_len);\n#ifdef TLS_ECDSA_SUPPORTED\n    if (tls_is_ecdsa(context)) {\n        switch (context->ec_private_key->ec_algorithm) {\n            case 23:\n                /* secp256r1 + sha256 */\n                tls_packet_uint16(packet, 0x0403);\n                break;\n            case 24:\n                /* secp384r1 + sha384 */\n                tls_packet_uint16(packet, 0x0503);\n                hash_algorithm = sha384;\n                break;\n            case 25:\n                /* secp521r1 + sha512 */\n                tls_packet_uint16(packet, 0x0603);\n                hash_algorithm = sha512;\n                break;\n            default:\n                DEBUG_PRINT0(\"UNSUPPORTED CURVE (SIGNING)\\n\");\n                packet->broken = 1;\n                return packet;\n        }\n    } else\n#endif\n    {\n        tls_packet_uint16(packet, 0x0804);\n    }\n\n#ifdef TLS_ECDSA_SUPPORTED\n    if (tls_is_ecdsa(context)) {\n        if (_private_tls_sign_ecdsa(context, hash_algorithm, signing_data, signing_data_len, out, &out_len) == 1) {\n            DEBUG_PRINT1(\"ECDSA signing OK! (ECDSA, length %lu)\\n\", out_len);\n            tls_packet_uint16(packet, out_len);\n            tls_packet_append(packet, out, out_len);\n            packet_size += out_len + 2;\n        }\n    } else\n#endif\n    if (_private_tls_sign_rsa(context, hash_algorithm, signing_data, signing_data_len, out, &out_len) == 1) {\n        DEBUG_PRINT1(\"RSA signing OK! (length %lu)\\n\", out_len);\n        tls_packet_uint16(packet, out_len);\n        tls_packet_append(packet, out, out_len);\n        packet_size += out_len + 2;\n    }\n    packet->buf[size_offset] = packet_size / 0x10000;\n    packet_size %= 0x10000;\n    packet->buf[size_offset + 1] = packet_size / 0x100;\n    packet_size %= 0x100;\n    packet->buf[size_offset + 2] = packet_size;\n\n    tls_packet_update(packet);\n    return packet;\n}\n#endif\n\nstruct TLSPacket *tls_build_certificate(struct TLSContext *context) {\n    int delta = 3;\n    int i;\n    unsigned int all_certificate_size = 0;\n    int certificates_count;\n    struct TLSCertificate **certificates;\n    struct TLSPacket *packet;\n    int is_ecdsa;\n\n    if (context->is_server) {\n        certificates_count = context->certificates_count;\n        certificates = context->certificates;\n    } else {\n        certificates_count = context->client_certificates_count;\n        certificates = context->client_certificates;\n    }\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n        delta = 5;\n#endif\n#ifdef TLS_ECDSA_SUPPORTED\n    is_ecdsa = tls_is_ecdsa(context);\n    if (is_ecdsa) {\n        for (i = 0; i < certificates_count; i++) {\n            struct TLSCertificate *cert = certificates[i];\n            if ((cert) && (cert->der_len) && (cert->ec_algorithm))\n                all_certificate_size += cert->der_len + delta;\n        }\n    } else {\n        for (i = 0; i < certificates_count; i++) {\n            struct TLSCertificate *cert = certificates[i];\n            if ((cert) && (cert->der_len) && (!cert->ec_algorithm))\n                all_certificate_size += cert->der_len + delta;\n        }\n    }\n#else\n    for (i = 0; i < certificates_count; i++) {\n        struct TLSCertificate *cert = certificates[i];\n        if ((cert) && (cert->der_len))\n            all_certificate_size += cert->der_len + delta;\n    }\n#endif\n    if (!all_certificate_size) {\n        DEBUG_PRINT0(\"NO CERTIFICATE SET\\n\");\n    }\n    packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0);\n    tls_packet_uint8(packet, 0x0B);\n    if (all_certificate_size) {\n#ifdef WITH_TLS_13\n        /* context */\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n            tls_packet_uint24(packet, all_certificate_size + 4);\n            tls_packet_uint8(packet, 0);\n        } else\n#endif\n            tls_packet_uint24(packet, all_certificate_size + 3);\n\n        if (context->dtls)\n            _private_dtls_handshake_data(context, packet, all_certificate_size + 3);\n\n        tls_packet_uint24(packet, all_certificate_size);\n        for (i = 0; i < certificates_count; i++) {\n            struct TLSCertificate *cert = certificates[i];\n            if ((cert) && (cert->der_len)) {\n#ifdef TLS_ECDSA_SUPPORTED\n                /* is RSA certificate? */\n                if ((is_ecdsa) && (!cert->ec_algorithm))\n                    continue;\n                /* is ECC certificate? */\n                if ((!is_ecdsa) && (cert->ec_algorithm))\n                    continue;\n#endif\n                /* 2 times -> one certificate */\n                tls_packet_uint24(packet, cert->der_len);\n                tls_packet_append(packet, cert->der_bytes, cert->der_len);\n#ifdef WITH_TLS_13\n                /* extension */\n                if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n                    tls_packet_uint16(packet, 0);\n#endif\n            }\n        }\n    } else {\n        tls_packet_uint24(packet, all_certificate_size);\n#ifdef WITH_TLS_13\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n            tls_packet_uint8(packet, 0);\n#endif\n\n        if (context->dtls)\n            _private_dtls_handshake_data(context, packet, all_certificate_size);\n    }\n    tls_packet_update(packet);\n    if (context->dtls)\n        context->dtls_seq++;\n    return packet;\n}\n\n#ifdef WITH_TLS_13\nstruct TLSPacket *tls_build_encrypted_extensions(struct TLSContext *context) {\n    struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 3);\n    tls_packet_uint8(packet, 0x08);\n    if (context->negotiated_alpn) {\n        int alpn_negotiated_len = strlen(context->negotiated_alpn);\n        int alpn_len = alpn_negotiated_len + 1;\n\n        tls_packet_uint24(packet, alpn_len + 8);\n        tls_packet_uint16(packet, alpn_len + 6);\n        tls_packet_uint16(packet, 0x10);\n        tls_packet_uint16(packet, alpn_len + 2);\n        tls_packet_uint16(packet, alpn_len);\n\n        tls_packet_uint8(packet, alpn_negotiated_len);\n        tls_packet_append(packet, (unsigned char *)context->negotiated_alpn, alpn_negotiated_len);\n    } else {\n        tls_packet_uint24(packet, 2);\n        tls_packet_uint16(packet, 0);\n    }\n    tls_packet_update(packet);\n    return packet;\n}\n#endif\n\nstruct TLSPacket *tls_build_finished(struct TLSContext *context) {\n    unsigned char hash[TLS_MAX_HASH_SIZE];\n    unsigned long out_size = TLS_MIN_FINISHED_OPAQUE_LEN;\n#ifdef WITH_TLS_13\n    unsigned char out[TLS_MAX_HASH_SIZE];\n#else\n    unsigned char out[TLS_MIN_FINISHED_OPAQUE_LEN];\n#endif\n    unsigned int hash_len;\n    struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, TLS_MIN_FINISHED_OPAQUE_LEN + 64);\n\n    tls_packet_uint8(packet, 0x14);\n#ifdef WITH_TLS_13\n    if ((context->version == TLS_V13) || (context->version == DTLS_V13))\n        tls_packet_uint24(packet, _private_tls_mac_length(context));\n    else\n#endif\n        tls_packet_uint24(packet, TLS_MIN_FINISHED_OPAQUE_LEN);\n    if (context->dtls)\n        _private_dtls_handshake_data(context, packet, TLS_MIN_FINISHED_OPAQUE_LEN);\n    /* verify, server verifies client's message */\n    if (context->is_server) {\n#ifdef WITH_TLS_13\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n            hmac_state hmac;\n\n            hash_len = _private_tls_get_hash(context, hash);\n            if ((!context->finished_key) || (!hash_len)) {\n                DEBUG_PRINT0(\"NO FINISHED KEY COMPUTED OR NO HANDSHAKE HASH\\n\");\n                packet->broken = 1;\n                return packet;\n            }\n\n            DEBUG_DUMP_HEX_LABEL(\"HS HASH\", hash, hash_len);\n            DEBUG_DUMP_HEX_LABEL(\"HS FINISH\", context->finished_key, hash_len);\n            DEBUG_DUMP_HEX_LABEL(\"HS REMOTE FINISH\", context->remote_finished_key, hash_len);\n\n            out_size = hash_len;\n            hmac_init(&hmac, _private_tls_get_hash_idx(context), context->finished_key, hash_len);\n            hmac_process(&hmac, hash, hash_len);\n            hmac_done(&hmac, out, &out_size);\n        } else\n#endif\n        {\n            hash_len = _private_tls_done_hash(context, hash);\n            _private_tls_prf(context, out, TLS_MIN_FINISHED_OPAQUE_LEN, context->master_key, context->master_key_len, (unsigned char *)\"server finished\", 15, hash, hash_len, NULL, 0);\n            _private_tls_destroy_hash(context);\n        }\n    } else {\n#ifdef WITH_TLS_13\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n            hmac_state hmac;\n\n            hash_len = _private_tls_get_hash(context, hash);\n            if ((!context->finished_key) || (!hash_len)) {\n                DEBUG_PRINT0(\"NO FINISHED KEY COMPUTED OR NO HANDSHAKE HASH\\n\");\n                packet->broken = 1;\n                return packet;\n            }\n            DEBUG_DUMP_HEX_LABEL(\"HS HASH\", hash, hash_len);\n            DEBUG_DUMP_HEX_LABEL(\"HS FINISH\", context->finished_key, hash_len);\n            DEBUG_DUMP_HEX_LABEL(\"HS REMOTE FINISH\", context->remote_finished_key, hash_len);\n\n            TLS_FREE(context->server_finished_hash);\n            context->server_finished_hash = (unsigned char *)TLS_MALLOC(hash_len);\n            if (context->server_finished_hash)\n                memcpy(context->server_finished_hash, hash, hash_len);\n\n            out_size = hash_len;\n            hmac_init(&hmac, _private_tls_get_hash_idx(context), context->finished_key, hash_len);\n            hmac_process(&hmac, hash, hash_len);\n            hmac_done(&hmac, out, &out_size);\n        } else {\n#endif\n            hash_len = _private_tls_get_hash(context, hash);\n            _private_tls_prf(context, out, TLS_MIN_FINISHED_OPAQUE_LEN, context->master_key, context->master_key_len, (unsigned char *)\"client finished\", 15, hash, hash_len, NULL, 0);\n#ifdef WITH_TLS_13\n        }\n#endif\n    }\n    tls_packet_append(packet, out, out_size);\n    tls_packet_update(packet);\n    DEBUG_DUMP_HEX_LABEL(\"VERIFY DATA\", out, out_size);\n#ifdef TLS_ACCEPT_SECURE_RENEGOTIATION\n    if (context->is_server) {\n        /* concatenate client verify and server verify */\n        context->verify_data = (unsigned char *)TLS_REALLOC(context->verify_data, out_size);\n        if (context->verify_data) {\n            memcpy(context->verify_data + context->verify_len, out, out_size);\n            context->verify_len += out_size;\n        } else\n            context->verify_len = 0;\n    } else {\n        TLS_FREE(context->verify_data);\n        context->verify_data = (unsigned char *)TLS_MALLOC(out_size);\n        if (context->verify_data) {\n            memcpy(context->verify_data, out, out_size);\n            context->verify_len = out_size;\n        }\n    }\n#endif\n    return packet;\n}\n\nstruct TLSPacket *tls_build_change_cipher_spec(struct TLSContext *context) {\n    struct TLSPacket *packet = tls_create_packet(context, TLS_CHANGE_CIPHER, context->version, 64);\n    tls_packet_uint8(packet, 1);\n    tls_packet_update(packet);\n    context->local_sequence_number = 0;\n    return packet;\n}\n\nstruct TLSPacket *tls_build_done(struct TLSContext *context) {\n    struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0);\n    tls_packet_uint8(packet, 0x0E);\n    tls_packet_uint24(packet, 0);\n    if (context->dtls) {\n        _private_dtls_handshake_data(context, packet, 0);\n        context->dtls_seq++;\n    }\n    tls_packet_update(packet);\n    return packet;\n}\n\nstruct TLSPacket *tls_build_message(struct TLSContext *context, const unsigned char *data, unsigned int len) {\n    struct TLSPacket *packet;\n\n    if ((!data) || (!len))\n        return 0;\n    packet = tls_create_packet(context, TLS_APPLICATION_DATA, context->version, len);\n    tls_packet_append(packet, data, len);\n    tls_packet_update(packet);\n    return packet;\n}\n\nint tls_client_connect(struct TLSContext *context) {\n    if ((context->is_server) || (context->critical_error))\n        return TLS_UNEXPECTED_MESSAGE;\n    \n    return _private_tls_write_packet(tls_build_hello(context, 0));\n}\n\nint tls_write(struct TLSContext *context, const unsigned char *data, unsigned int len) {\n    int actually_written;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n#ifdef TLS_12_FALSE_START\n    if ((context->connection_status != 0xFF) && ((context->is_server) || (context->version != TLS_V12) || (context->critical_error) || (!context->false_start)))\n        return TLS_UNEXPECTED_MESSAGE;\n#else\n    if (context->connection_status != 0xFF)\n        return TLS_UNEXPECTED_MESSAGE;\n#endif\n    if (len > TLS_MAXTLS_APP_SIZE)\n        len = TLS_MAXTLS_APP_SIZE;\n    actually_written = _private_tls_write_packet(tls_build_message(context, data, len));\n    if (actually_written <= 0)\n        return actually_written;\n    return len;\n}\n\nstruct TLSPacket *tls_build_alert(struct TLSContext *context, char critical, unsigned char code) {\n    struct TLSPacket *packet = tls_create_packet(context, TLS_ALERT, context->version, 0);\n    tls_packet_uint8(packet, critical ? TLS_ALERT_CRITICAL : TLS_ALERT_WARNING);\n    if (critical)\n        context->critical_error = 1;\n    tls_packet_uint8(packet, code);\n    tls_packet_update(packet);\n    return packet;\n}\n\nint _private_tls_read_from_file(const char *fname, void *buf, int max_len) {\n    FILE *f = fopen(fname, \"rb\");\n    if (f) {\n        int size = (int)fread(buf, 1, max_len, f);\n        fclose(f);\n        return size;\n    }\n    return 0;\n}\n\nint tls_consume_stream(struct TLSContext *context, const unsigned char *buf, int buf_len, tls_validation_function certificate_verify) {\n    unsigned int orig_len, tls_buffer_len, index = 0;\n    int err_flag = 0;\n    int tls_header_size;\n    int tls_size_offset;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n\n    if (context->critical_error)\n        return TLS_BROKEN_CONNECTION;\n\n    if (buf_len <= 0) {\n        DEBUG_PRINT1(\"tls_consume_stream called with buf_len %i\\n\", buf_len);\n        return 0;\n    }\n\n    if (!buf) {\n        DEBUG_PRINT0(\"tls_consume_stream called NULL buffer\\n\");\n        context->critical_error = 1;\n        return TLS_NO_MEMORY;\n    }\n\n    orig_len = context->message_buffer_len;\n    context->message_buffer_len += buf_len;\n    context->message_buffer = (unsigned char *)TLS_REALLOC(context->message_buffer, context->message_buffer_len);\n    if (!context->message_buffer) {\n        context->message_buffer_len = 0;\n        return TLS_NO_MEMORY;\n    }\n    memcpy(context->message_buffer + orig_len, buf, buf_len);\n    tls_buffer_len = context->message_buffer_len;\n    \n    if (context->dtls) {\n        tls_size_offset = 11;\n        tls_header_size = 13;\n    } else {\n        tls_size_offset = 3;\n        tls_header_size = 5;\n    }\n    while (tls_buffer_len >= 5) {\n        int consumed;\n#if NO_FUNNY_ALIGNMENT\n        unsigned int length = tls_header_size +\n            __toshort(context->message_buffer, (index + tls_size_offset));\n#else\n        unsigned int length = ntohs(*(unsigned short *)&context->message_buffer[index + tls_size_offset]) + tls_header_size;\n#endif\n\n        if (length > tls_buffer_len) {\n            DEBUG_PRINT2(\"NEED DATA: %i/%i\\n\", length, tls_buffer_len);\n            break;\n        }\n        consumed = tls_parse_message(context, &context->message_buffer[index], length, certificate_verify);\n        DEBUG_PRINT1(\"Consumed %i bytes\\n\", consumed);\n        if (consumed < 0) {\n            if (!context->critical_error)\n                context->critical_error = 1;\n            err_flag = consumed;\n            break;\n        }\n        index += length;\n        tls_buffer_len -= length;\n        if (context->critical_error) {\n            err_flag = TLS_BROKEN_CONNECTION;\n            break;\n        }\n    }\n    if (err_flag) {\n        DEBUG_PRINT1(\"ERROR IN CONSUME: %i\\n\", err_flag);\n        context->message_buffer_len = 0;\n        TLS_FREE(context->message_buffer);\n        context->message_buffer = NULL;\n        return err_flag;\n    }\n    if (index) {\n        context->message_buffer_len -= index;\n        if (context->message_buffer_len) {\n            /* no realloc here */\n            memmove(context->message_buffer, context->message_buffer + index, context->message_buffer_len);\n        } else {\n            TLS_FREE(context->message_buffer);\n            context->message_buffer = NULL;\n        }\n    }\n    return index;\n}\n\nvoid tls_close_notify(struct TLSContext *context) {\n    if ((!context) || (context->critical_error))\n        return;\n    context->critical_error = 1;\n    DEBUG_PRINT0(\"CLOSE\\n\");\n    _private_tls_write_packet(tls_build_alert(context, 0, close_notify));\n}\n\nvoid tls_alert(struct TLSContext *context, unsigned char critical, int code) {\n    if (!context)\n        return;\n    if ((!context->critical_error) && (critical))\n        context->critical_error = 1;\n    DEBUG_PRINT0(\"ALERT\\n\");\n    _private_tls_write_packet(tls_build_alert(context, critical, code));\n}\n\nint tls_pending(struct TLSContext *context) {\n    if (!context->message_buffer)\n        return 0;\n    return context->message_buffer_len;\n}\n\nvoid tls_make_exportable(struct TLSContext *context, unsigned char exportable_flag) {\n    context->exportable = exportable_flag;\n    if (!exportable_flag) {\n        /* zero the memory */\n        if ((context->exportable_keys) && (context->exportable_size))\n            memset(context->exportable_keys, 0, context->exportable_size);\n        /* free the memory, if allocated */\n        TLS_FREE(context->exportable_keys);\n        context->exportable_size = 0;\n    }\n}\n\nint tls_export_context(struct TLSContext *context, unsigned char *buffer, unsigned int buf_len, unsigned char small_version) {\n    struct TLSPacket *packet;\n    unsigned int size;\n    uint64_t sequence_number;\n\n    /* only negotiated AND exportable connections may be exported */\n    if ((!context) || (context->critical_error) || (context->connection_status != 0xFF) || (!context->exportable) || (!context->exportable_keys) || (!context->exportable_size) || (!context->crypto.created)) {\n        DEBUG_PRINT1(\"CANNOT EXPORT CONTEXT %i\\n\", (int)context->connection_status);\n        return 0;\n    }\n    \n    packet = tls_create_packet(NULL, TLS_SERIALIZED_OBJECT, context->version, 0);\n    /* export buffer version */\n    tls_packet_uint8(packet, 0x01);\n    tls_packet_uint8(packet, context->connection_status);\n    tls_packet_uint16(packet, context->cipher);\n    if (context->is_child)\n        tls_packet_uint8(packet, 2);\n    else\n        tls_packet_uint8(packet, context->is_server);\n    \n    if (context->crypto.created == 2) {\n        /* aead */\n#ifdef WITH_TLS_13\n        if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n            tls_packet_uint8(packet, TLS_13_AES_GCM_IV_LENGTH);\n            tls_packet_append(packet, context->crypto.ctx_local_mac.local_iv, TLS_13_AES_GCM_IV_LENGTH);\n            tls_packet_append(packet, context->crypto.ctx_remote_mac.remote_iv, TLS_13_AES_GCM_IV_LENGTH);\n        } else {\n#endif\n            tls_packet_uint8(packet, TLS_AES_GCM_IV_LENGTH);\n            tls_packet_append(packet, context->crypto.ctx_local_mac.local_aead_iv, TLS_AES_GCM_IV_LENGTH);\n            tls_packet_append(packet, context->crypto.ctx_remote_mac.remote_aead_iv, TLS_AES_GCM_IV_LENGTH);\n#ifdef WITH_TLS_13\n        }\n#endif\n#ifdef TLS_WITH_CHACHA20_POLY1305\n    } else\n    if (context->crypto.created == 3) {\n        /* ChaCha20 */\n        tls_packet_uint8(packet, TLS_CHACHA20_IV_LENGTH);\n        tls_packet_append(packet, context->crypto.ctx_local_mac.local_nonce, TLS_CHACHA20_IV_LENGTH);\n        tls_packet_append(packet, context->crypto.ctx_remote_mac.remote_nonce, TLS_CHACHA20_IV_LENGTH);\n#endif\n    } else {\n        unsigned char iv[TLS_AES_IV_LENGTH];\n        unsigned long len = TLS_AES_IV_LENGTH;\n        \n        memset(iv, 0, TLS_AES_IV_LENGTH);\n        cbc_getiv(iv, &len, &context->crypto.ctx_local.aes_local);\n        tls_packet_uint8(packet, TLS_AES_IV_LENGTH);\n        tls_packet_append(packet, iv, len);\n        \n        memset(iv, 0, TLS_AES_IV_LENGTH);\n        cbc_getiv(iv, &len, &context->crypto.ctx_remote.aes_remote);\n        tls_packet_append(packet, iv, TLS_AES_IV_LENGTH);\n    }\n    \n    tls_packet_uint8(packet, context->exportable_size);\n    tls_packet_append(packet, context->exportable_keys, context->exportable_size);\n    \n    if (context->crypto.created == 2) {\n        tls_packet_uint8(packet, 0);\n#ifdef TLS_WITH_CHACHA20_POLY1305\n    } else\n    if (context->crypto.created == 3) {\n        unsigned int i;\n\n        /* ChaCha20 */\n        tls_packet_uint8(packet, 0);\n        for (i = 0; i < 16; i++)\n            tls_packet_uint32(packet, context->crypto.ctx_local.chacha_local.input[i]);\n        for (i = 0; i < 16; i++)\n            tls_packet_uint32(packet, context->crypto.ctx_remote.chacha_remote.input[i]);\n        tls_packet_append(packet, context->crypto.ctx_local.chacha_local.ks, CHACHA_BLOCKLEN);\n        tls_packet_append(packet, context->crypto.ctx_remote.chacha_remote.ks, CHACHA_BLOCKLEN);\n#endif\n    } else {\n        unsigned char mac_length = (unsigned char)_private_tls_mac_length(context);\n        tls_packet_uint8(packet, mac_length);\n        tls_packet_append(packet, context->crypto.ctx_local_mac.local_mac, mac_length);\n        tls_packet_append(packet, context->crypto.ctx_remote_mac.remote_mac, mac_length);\n    }\n    \n    if (small_version) {\n        tls_packet_uint16(packet, 0);\n    } else {\n        tls_packet_uint16(packet, context->master_key_len);\n        tls_packet_append(packet, context->master_key, context->master_key_len);\n    }\n    \n    sequence_number = htonll(context->local_sequence_number);\n    tls_packet_append(packet, (unsigned char *)&sequence_number, sizeof(uint64_t));\n    sequence_number = htonll(context->remote_sequence_number);\n    tls_packet_append(packet, (unsigned char *)&sequence_number, sizeof(uint64_t));\n    \n    tls_packet_uint32(packet, context->tls_buffer_len);\n    tls_packet_append(packet, context->tls_buffer, context->tls_buffer_len);\n    \n    tls_packet_uint32(packet, context->message_buffer_len);\n    tls_packet_append(packet, context->message_buffer, context->message_buffer_len);\n    \n    tls_packet_uint32(packet, context->application_buffer_len);\n    tls_packet_append(packet, context->application_buffer, context->application_buffer_len);\n    tls_packet_uint8(packet, context->dtls);\n    if (context->dtls) {\n        tls_packet_uint16(packet, context->dtls_epoch_local);\n        tls_packet_uint16(packet, context->dtls_epoch_remote);\n    }\n    tls_packet_update(packet);\n    size = packet->len;\n    if ((buffer) && (buf_len)) {\n        if (size > buf_len) {\n            tls_destroy_packet(packet);\n            DEBUG_PRINT0(\"EXPORT BUFFER TO SMALL\\n\");\n            return (int)buf_len - (int)size;\n        }\n        memcpy(buffer, packet->buf, size);\n    }\n    tls_destroy_packet(packet);\n    return size;\n}\n\nstruct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int buf_len) {\n    struct TLSContext *context;\n    if ((!buffer) || (buf_len < 64) || (buffer[0] != TLS_SERIALIZED_OBJECT) || (buffer[5] != 0x01)) {\n        DEBUG_PRINT0(\"CANNOT IMPORT CONTEXT BUFFER\\n\");\n        return NULL;\n    }\n    /* create a context object */\n    context = tls_create_context(0, TLS_V12);\n    if (context) {\n        unsigned char local_iv[TLS_AES_IV_LENGTH];\n        unsigned char remote_iv[TLS_AES_IV_LENGTH];\n        unsigned char server = buffer[9];\n        unsigned char iv_len = buffer[10];\n        unsigned char temp[0xFF];\n        unsigned char key_lengths;\n        unsigned char mac_length;\n        int buf_pos = 11;\n        int is_aead;\n        unsigned short length = ntohs(*(unsigned short *)&buffer[3]);\n        unsigned short master_key_len;\n        unsigned int tls_buffer_len, message_buffer_len,\n\t\tapplication_buffer_len;\n\n        context->version = ntohs(*(unsigned short *)&buffer[1]);\n        if (length != buf_len - 5) {\n            DEBUG_PRINT0(\"INVALID IMPORT BUFFER SIZE\\n\");\n            tls_destroy_context(context);\n            return NULL;\n        }\n        context->connection_status = buffer[6];\n        context->cipher = ntohs(*(unsigned short *)&buffer[7]);\n        if (server == 2) {\n            context->is_server = 1;\n            context->is_child = 1;\n        } else\n            context->is_server = server;\n        \n        if (iv_len >  TLS_AES_IV_LENGTH) {\n            DEBUG_PRINT0(\"INVALID IV LENGTH\\n\");\n            tls_destroy_context(context);\n            return NULL;\n        }\n        \n        /* get the initialization vectors */\n        memcpy(local_iv, &buffer[buf_pos], iv_len);\n        buf_pos += iv_len;\n        memcpy(remote_iv, &buffer[buf_pos], iv_len);\n        buf_pos += iv_len;\n        \n        key_lengths = buffer[buf_pos++];\n        TLS_IMPORT_CHECK_SIZE(buf_pos, key_lengths, buf_len)\n        memcpy(temp, &buffer[buf_pos], key_lengths);\n        buf_pos += key_lengths;\n#ifdef TLS_REEXPORTABLE\n        context->exportable = 1;\n        context->exportable_keys = (unsigned char *)TLS_MALLOC(key_lengths);\n        memcpy(context->exportable_keys, temp, key_lengths);\n        context->exportable_size = key_lengths;\n#else\n        context->exportable = 0;\n#endif\n        is_aead = _private_tls_is_aead(context);\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        if (is_aead == 2) {\n            /* ChaCha20 */\n            if (iv_len > TLS_CHACHA20_IV_LENGTH)\n                iv_len = TLS_CHACHA20_IV_LENGTH;\n            memcpy(context->crypto.ctx_local_mac.local_nonce, local_iv, iv_len);\n            memcpy(context->crypto.ctx_remote_mac.remote_nonce, remote_iv, iv_len);\n        } else\n#endif\n        if (is_aead) {\n#ifdef WITH_TLS_13\n            if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n                if (iv_len > TLS_13_AES_GCM_IV_LENGTH)\n                    iv_len = TLS_13_AES_GCM_IV_LENGTH;\n                memcpy(context->crypto.ctx_local_mac.local_iv, local_iv, iv_len);\n                memcpy(context->crypto.ctx_remote_mac.remote_iv, remote_iv, iv_len);\n            } else {\n#endif\n                if (iv_len > TLS_AES_GCM_IV_LENGTH)\n                    iv_len = TLS_AES_GCM_IV_LENGTH;\n                memcpy(context->crypto.ctx_local_mac.local_aead_iv, local_iv, iv_len);\n                memcpy(context->crypto.ctx_remote_mac.remote_aead_iv, remote_iv, iv_len);\n#ifdef WITH_TLS_13\n            }\n#endif\n        }\n        if (context->is_server) {\n            if (_private_tls_crypto_create(context, key_lengths / 2, temp, local_iv, temp + key_lengths / 2, remote_iv)) {\n                DEBUG_PRINT0(\"ERROR CREATING KEY CONTEXT\\n\");\n                tls_destroy_context(context);\n                return NULL;\n            }\n        } else {\n            if (_private_tls_crypto_create(context, key_lengths / 2, temp + key_lengths / 2, remote_iv, temp, local_iv)) {\n                DEBUG_PRINT0(\"ERROR CREATING KEY CONTEXT (CLIENT)\\n\");\n                tls_destroy_context(context);\n                return NULL;\n            }\n        }\n        memset(temp, 0, sizeof(temp));\n        \n        mac_length = buffer[buf_pos++];\n        if (mac_length > TLS_MAX_MAC_SIZE) {\n            DEBUG_PRINT0(\"INVALID MAC SIZE\\n\");\n            tls_destroy_context(context);\n            return NULL;\n        }\n        \n        if (mac_length) {\n            TLS_IMPORT_CHECK_SIZE(buf_pos, mac_length, buf_len)\n            memcpy(context->crypto.ctx_local_mac.local_mac, &buffer[buf_pos], mac_length);\n            buf_pos += mac_length;\n            \n            TLS_IMPORT_CHECK_SIZE(buf_pos, mac_length, buf_len)\n            memcpy(context->crypto.ctx_remote_mac.remote_mac, &buffer[buf_pos], mac_length);\n            buf_pos += mac_length;\n        } else\n#ifdef TLS_WITH_CHACHA20_POLY1305\n        if (is_aead == 2) {\n            /* ChaCha20 */\n            unsigned int i;\n            TLS_IMPORT_CHECK_SIZE(buf_pos, 128 + CHACHA_BLOCKLEN * 2, buf_len)\n            for (i = 0; i < 16; i++) {\n                context->crypto.ctx_local.chacha_local.input[i] = ntohl(*(unsigned int *)(buffer + buf_pos));\n                buf_pos += sizeof(unsigned int);\n            }\n            for (i = 0; i < 16; i++) {\n                context->crypto.ctx_remote.chacha_remote.input[i] = ntohl(*(unsigned int *)(buffer + buf_pos));\n                buf_pos += sizeof(unsigned int);\n            }\n            memcpy(context->crypto.ctx_local.chacha_local.ks, buffer + buf_pos, CHACHA_BLOCKLEN);\n            buf_pos += CHACHA_BLOCKLEN;\n            memcpy(context->crypto.ctx_remote.chacha_remote.ks, buffer + buf_pos, CHACHA_BLOCKLEN);\n            buf_pos += CHACHA_BLOCKLEN;\n        }\n#endif\n        \n        TLS_IMPORT_CHECK_SIZE(buf_pos, 2, buf_len)\n        master_key_len = ntohs(*(unsigned short *)(buffer + buf_pos));\n        buf_pos += 2;\n        if (master_key_len) {\n            TLS_IMPORT_CHECK_SIZE(buf_pos, master_key_len, buf_len)\n            context->master_key = (unsigned char *)TLS_MALLOC(master_key_len);\n            if (context->master_key) {\n                memcpy(context->master_key, &buffer[buf_pos], master_key_len);\n                context->master_key_len = master_key_len;\n            }\n            buf_pos += master_key_len;\n        }\n        \n        TLS_IMPORT_CHECK_SIZE(buf_pos, 16, buf_len)\n        \n        context->local_sequence_number = ntohll(*(uint64_t *)&buffer[buf_pos]);\n        buf_pos += 8;\n        context->remote_sequence_number = ntohll(*(uint64_t *)&buffer[buf_pos]);\n        buf_pos += 8;\n        \n        TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len)\n        tls_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]);\n        buf_pos += 4;\n        TLS_IMPORT_CHECK_SIZE(buf_pos, tls_buffer_len, buf_len)\n        if (tls_buffer_len) {\n            context->tls_buffer = (unsigned char *)TLS_MALLOC(tls_buffer_len);\n            if (context->tls_buffer) {\n                memcpy(context->tls_buffer, &buffer[buf_pos], tls_buffer_len);\n                context->tls_buffer_len = tls_buffer_len;\n            }\n            buf_pos += tls_buffer_len;\n        }\n        \n        TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len)\n        message_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]);\n        buf_pos += 4;\n        TLS_IMPORT_CHECK_SIZE(buf_pos, message_buffer_len, buf_len)\n        if (message_buffer_len) {\n            context->message_buffer = (unsigned char *)TLS_MALLOC(message_buffer_len);\n            if (context->message_buffer) {\n                memcpy(context->message_buffer, &buffer[buf_pos], message_buffer_len);\n                context->message_buffer_len = message_buffer_len;\n            }\n            buf_pos += message_buffer_len;\n        }\n        \n        TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len)\n        application_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]);\n        buf_pos += 4;\n        context->cipher_spec_set = 1;\n        TLS_IMPORT_CHECK_SIZE(buf_pos, application_buffer_len, buf_len)\n        if (application_buffer_len) {\n            context->application_buffer = (unsigned char *)TLS_MALLOC(application_buffer_len);\n            if (context->application_buffer) {\n                memcpy(context->application_buffer, &buffer[buf_pos], application_buffer_len);\n                context->application_buffer_len = application_buffer_len;\n            }\n            buf_pos += application_buffer_len;\n        }\n        TLS_IMPORT_CHECK_SIZE(buf_pos, 1, buf_len)\n        context->dtls = buffer[buf_pos];\n        buf_pos++;\n        if (context->dtls) {\n            TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len)\n            context->dtls_epoch_local = ntohs(*(unsigned short *)&buffer[buf_pos]);\n            buf_pos += 2;\n            context->dtls_epoch_remote = ntohs(*(unsigned short *)&buffer[buf_pos]);\n        }\n    }\n    return context;\n}\n\nint tls_is_broken(struct TLSContext *context) {\n    if ((!context) || (context->critical_error))\n        return 1;\n    return 0;\n}\n\nint tls_request_client_certificate(struct TLSContext *context) {\n    if ((!context) || (!context->is_server))\n        return 0;\n    \n    context->request_client_certificate = 1;\n    return 1;\n}\n\nint tls_client_verified(struct TLSContext *context) {\n    if ((!context) || (context->critical_error))\n        return 0;\n    \n    return (context->client_verified == 1);\n}\n\nconst char *tls_sni(struct TLSContext *context) {\n    if (!context)\n        return NULL;\n    return context->sni;\n}\n\nint tls_sni_set(struct TLSContext *context, const char *sni) {\n    if ((!context) || (context->is_server) || (context->critical_error) || (context->connection_status != 0))\n        return 0;\n    TLS_FREE(context->sni);\n    context->sni = NULL;\n    if (sni) {\n        size_t len = strlen(sni);\n        if (len > 0) {\n            context->sni = (char *)TLS_MALLOC(len + 1);\n            if (context->sni) {\n                context->sni[len] = 0;\n                memcpy(context->sni, sni, len);\n                return 1;\n            }\n        }\n    }\n    return 0;\n}\n\nint tls_load_root_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) {\n    unsigned int len;\n    int idx = 0;\n    \n    if (!context)\n        return TLS_GENERIC_ERROR;\n    \n    do {\n        struct TLSCertificate *cert;\n        unsigned char *data = tls_pem_decode(pem_buffer, pem_size, idx++, &len);\n\n        if ((!data) || (!len))\n            break;\n        cert = asn1_parse(NULL, data, len, 0);\n        if (cert) {\n            if ((cert->version == 2) \n#ifdef TLS_X509_V1_SUPPORT\n                || (cert->version == 0)\n#endif\n            ) {\n                if (cert->priv) {\n                    DEBUG_PRINT0(\"WARNING - parse error (private key encountered in certificate)\\n\");\n                    TLS_FREE(cert->priv);\n                    cert->priv = NULL;\n                    cert->priv_len = 0;\n                }\n                context->root_certificates = (struct TLSCertificate **)TLS_REALLOC(context->root_certificates, (context->root_count + 1) * sizeof(struct TLSCertificate *));\n                if (!context->root_certificates) {\n                    context->root_count = 0;\n                    return TLS_GENERIC_ERROR;\n                }\n                context->root_certificates[context->root_count] = cert;\n                context->root_count++;\n                DEBUG_PRINT1(\"Loaded certificate: %i\\n\", (int)context->root_count);\n            } else {\n                DEBUG_PRINT1(\"WARNING - certificate version error (v%i)\\n\", (int)cert->version);\n                tls_destroy_certificate(cert);\n            }\n        }\n        TLS_FREE(data);\n    } while (1);\n    return context->root_count;\n}\n\nint tls_default_verify(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len) {\n    int i;\n    int err;\n    \n    if (certificate_chain) {\n        for (i = 0; i < len; i++) {\n            struct TLSCertificate *certificate = certificate_chain[i];\n            /* check validity date */\n            err = tls_certificate_is_valid(certificate);\n            if (err)\n                return err;\n        }\n    }\n    /* check if chain is valid */\n    err = tls_certificate_chain_is_valid(certificate_chain, len);\n    if (err)\n        return err;\n    \n    /* check certificate subject */\n    if ((!context->is_server) && (context->sni) && (len > 0) && (certificate_chain)) {\n        err = tls_certificate_valid_subject(certificate_chain[0], context->sni);\n        if (err)\n            return err;\n    }\n    \n    err = tls_certificate_chain_is_valid_root(context, certificate_chain, len);\n    if (err)\n        return err;\n    \n    DEBUG_PRINT0(\"Certificate OK\\n\");\n    return no_error;\n}\n\n/* NB: this is not rewritten for egcs because any kernel with KTLS\n   will have access to a more recent compiler! */\n\nint tls_unmake_ktls(struct TLSContext *context, int socket) {\n#ifdef WITH_KTLS\n    struct tls12_crypto_info_aes_gcm_128 crypto_info;\n    socklen_t crypt_info_size = sizeof(crypto_info);\n    if (getsockopt(socket, SOL_TLS, TLS_TX, &crypto_info, &crypt_info_size)) {\n        DEBUG_PRINT0(\"ERROR IN getsockopt\\n\");\n        return TLS_GENERIC_ERROR;\n    }\n    memcpy(crypto_info.rec_seq, &context->local_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\n    context->local_sequence_number = ntohll(context->local_sequence_number);\n#ifdef TLS_RX\n    crypt_info_size = sizeof(crypto_info);\n    if (getsockopt(socket, SOL_TLS, TLS_RX, &crypto_info, &crypt_info_size)) {\n        DEBUG_PRINT0(\"ERROR IN getsockopt\\n\");\n        return TLS_GENERIC_ERROR;\n    }\n    memcpy(crypto_info.rec_seq, &context->remote_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\n    context->remote_sequence_number = ntohll(context->remote_sequence_number);\n#endif\n    return 0;\n#endif\n    DEBUG_PRINT0(\"TLSe COMPILED WITHOUT kTLS SUPPORT\\n\");\n    return TLS_FEATURE_NOT_SUPPORTED;\n}\n\nint tls_make_ktls(struct TLSContext *context, int socket) {\n    if ((!context) || (context->critical_error) || (context->connection_status != 0xFF) || (!context->crypto.created)) {\n        DEBUG_PRINT0(\"CANNOT SWITCH TO kTLS\\n\");\n        return TLS_GENERIC_ERROR;\n    }\n    if ((!context->exportable) || (!context->exportable_keys)) {\n        DEBUG_PRINT0(\"KEY MUST BE EXPORTABLE TO BE ABLE TO USE kTLS\\n\");\n        return TLS_GENERIC_ERROR;\n    }\n    if ((context->version != TLS_V12) && (context->version != DTLS_V12) && (context->version != TLS_V13) && (context->version != DTLS_V13)) {\n        DEBUG_PRINT0(\"kTLS IS SUPPORTED ONLY FOR TLS >= 1.2 AND DTLS >= 1.2\\n\");\n        return TLS_FEATURE_NOT_SUPPORTED;\n    }\n    switch (context->cipher) {\n        case TLS_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:\n        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:\n        case TLS_AES_128_GCM_SHA256:\n            break;\n        default:\n            DEBUG_PRINT0(\"CIPHER UNSUPPORTED: kTLS SUPPORTS ONLY AES 128 GCM CIPHERS\\n\");\n            return TLS_FEATURE_NOT_SUPPORTED;\n    }\n#ifdef WITH_KTLS\n    if (context->exportable_size < TLS_CIPHER_AES_GCM_128_KEY_SIZE * 2) {\n        DEBUG_PRINT0(\"INVALID KEY SIZE\\n\");\n        return TLS_GENERIC_ERROR;\n    }\n    int err;\n    struct tls12_crypto_info_aes_gcm_128 crypto_info;\n    crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;\n    uint64_t local_sequence_number = htonll(context->local_sequence_number);\n\n    if ((context->version == TLS_V12) || (context->version == DTLS_V12)) {\n        crypto_info.info.version = TLS_1_2_VERSION;\n        memcpy(crypto_info.iv, &local_sequence_number, TLS_CIPHER_AES_GCM_128_IV_SIZE);\n        memcpy(crypto_info.rec_seq, &local_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\n        memcpy(crypto_info.key, context->exportable_keys, TLS_CIPHER_AES_GCM_128_KEY_SIZE);\n        memcpy(crypto_info.salt, context->crypto.ctx_local_mac.local_aead_iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);\n    } else if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        crypto_info.info.version = TLS_1_3_VERSION;\n        memcpy(crypto_info.iv, context->crypto.ctx_local_mac.local_iv + 4, TLS_CIPHER_AES_GCM_128_IV_SIZE);\n        memcpy(crypto_info.rec_seq, &local_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\n        memcpy(crypto_info.key, context->exportable_keys, TLS_CIPHER_AES_GCM_128_KEY_SIZE);\n        memcpy(crypto_info.salt, context->crypto.ctx_local_mac.local_iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);\n    }\n\n    err = setsockopt(socket, SOL_TCP, TCP_ULP, \"tls\", sizeof(\"tls\"));\n    if (err)\n        return err;\n\n#ifdef TLS_RX\n    /* kernel 4.17 adds TLS_RX support */\n    struct tls12_crypto_info_aes_gcm_128 crypto_info_read;\n\n    crypto_info_read.info.cipher_type = TLS_CIPHER_AES_GCM_128;\n\n    uint64_t remote_sequence_number = htonll(context->remote_sequence_number);\n\n    if ((context->version == TLS_V12) || (context->version == DTLS_V12)) {\n        crypto_info_read.info.version = TLS_1_2_VERSION;\n        memcpy(crypto_info_read.iv, &remote_sequence_number, TLS_CIPHER_AES_GCM_128_IV_SIZE);\n        memcpy(crypto_info_read.rec_seq, &remote_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\n        memcpy(crypto_info_read.key, context->exportable_keys + TLS_CIPHER_AES_GCM_128_KEY_SIZE, TLS_CIPHER_AES_GCM_128_KEY_SIZE);\n        memcpy(crypto_info_read.salt, context->crypto.ctx_remote_mac.remote_aead_iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);\n    } else if ((context->version == TLS_V13) || (context->version == DTLS_V13)) {\n        crypto_info_read.info.version = TLS_1_3_VERSION;\n        memcpy(crypto_info_read.iv, context->crypto.ctx_remote_mac.remote_iv + 4, TLS_CIPHER_AES_GCM_128_IV_SIZE);\n        memcpy(crypto_info_read.rec_seq, &remote_sequence_number, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);\n        memcpy(crypto_info_read.key, context->exportable_keys + TLS_CIPHER_AES_GCM_128_KEY_SIZE, TLS_CIPHER_AES_GCM_128_KEY_SIZE);\n        memcpy(crypto_info_read.salt, context->crypto.ctx_remote_mac.remote_iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);\n    }\n\n    err = setsockopt(socket, SOL_TLS, TLS_RX, &crypto_info_read, sizeof(crypto_info_read));\n    if (err)\n        return err;\n#endif\n    return setsockopt(socket, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info));\n#else\n    DEBUG_PRINT0(\"TLSe COMPILED WITHOUT kTLS SUPPORT\\n\");\n    return TLS_FEATURE_NOT_SUPPORTED;\n#endif\n}\n\n#ifdef DEBUG\nvoid tls_print_certificate(const char *fname) {\n    unsigned char buf[BIG_STRING_SIZE];\n    char out_buf[BIG_STRING_SIZE];\n    int size = _private_tls_read_from_file(fname, buf, BIG_STRING_SIZE);\n    if (size > 0) {\n        int idx = 0;\n        unsigned int len;\n        do {\n            unsigned char *data;\n            struct TLSCertificate *cert;\n\n            if (buf[0] == '-')  {\n                data = tls_pem_decode(buf, size, idx++, &len);\n            } else {\n                data = buf;\n                len = size;\n            }\n            if ((!data) || (!len))\n                return;\n            cert = asn1_parse(NULL, data, len, -1);\n            if (data != buf)\n                TLS_FREE(data);\n            if (cert) {\n                fprintf(stderr, \"%s\", tls_certificate_to_string(cert, out_buf, BIG_STRING_SIZE));\n                tls_destroy_certificate(cert);\n            }\n            if (data == buf)\n                break;\n        } while (1);\n    }\n}\n#endif\n\nint tls_remote_error(struct TLSContext *context) {\n    if (!context)\n        return TLS_GENERIC_ERROR;\n\n    return context->error_code;\n}\n\n#ifdef SSL_COMPATIBLE_INTERFACE\n\nint  SSL_library_init() {\n    /* dummy function */\n    return 1;\n}\n\nvoid SSL_load_error_strings() {\n    /* dummy function */\n}\n\nvoid OpenSSL_add_all_algorithms() {\n    /* dummy function */\n}\n\nvoid OpenSSL_add_all_ciphers() {\n    /* dummy function */\n}\n\nvoid OpenSSL_add_all_digests() {\n    /* dummy function */\n}\n\nvoid EVP_cleanup() {\n    /* dummy function */\n}\n\nint _tls_ssl_private_send_pending(int client_sock, struct TLSContext *context) {\n    unsigned int out_buffer_index = 0;\n    int send_res = 0;\n    SOCKET_SEND_CALLBACK write_cb = NULL;\n    SSLUserData *ssl_data = (SSLUserData *)context->user_data;\n    unsigned int out_buffer_len = 0;\n    const unsigned char *out_buffer;\n\n    out_buffer = tls_get_write_buffer(context, &out_buffer_len);\n\n    if (ssl_data)\n        write_cb = (SOCKET_SEND_CALLBACK)ssl_data->send;\n    while ((out_buffer) && (out_buffer_len > 0)) {\n        int res;\n        if (write_cb)\n            res = write_cb(client_sock, (char *)&out_buffer[out_buffer_index], out_buffer_len, 0);\n        else\n            res = send(client_sock, (char *)&out_buffer[out_buffer_index], out_buffer_len, 0);\n        if (res <= 0) {\n            if ((!write_cb) && (res < 0)) {\n#ifdef _WIN32\n                if (WSAGetLastError() == WSAEWOULDBLOCK) {\n                    context->tls_buffer_len = out_buffer_len;\n                    memmove(context->tls_buffer, out_buffer + out_buffer_index, out_buffer_len);\n                    return res;\n                }\n#else\n                if ((errno == EAGAIN) || (errno == EINTR)) {\n                    context->tls_buffer_len = out_buffer_len;\n                    memmove(context->tls_buffer, out_buffer + out_buffer_index, out_buffer_len);\n                    return res;\n                }\n#endif\n            }\n            send_res = res;\n            break;\n        }\n        out_buffer_len -= res;\n        out_buffer_index += res;\n        send_res += res;\n    }\n    tls_buffer_clear(context);\n    return send_res;\n}\n\nstruct TLSContext *SSL_new(struct TLSContext *context) {\n    return tls_accept(context);\n}\n\nint SSLv3_server_method() {\n    return 1;\n}\n\nint SSLv3_client_method() {\n    return 0;\n}\n\nint SSL_CTX_use_certificate_file(struct TLSContext *context, const char *filename, int dummy) {\n    /* max 64k buffer */\n    unsigned char buf[BIG_STRING_SIZE];\n    int size = _private_tls_read_from_file(filename, buf, sizeof(buf));\n    if (size > 0)\n        return tls_load_certificates(context, buf, size);\n    return size;\n}\n\nint SSL_CTX_use_PrivateKey_file(struct TLSContext *context, const char *filename, int dummy) {\n    unsigned char buf[BIG_STRING_SIZE];\n    int size = _private_tls_read_from_file(filename, buf, sizeof(buf));\n    if (size > 0)\n        return tls_load_private_key(context, buf, size);\n    \n    return size;\n}\n\nint SSL_CTX_check_private_key(struct TLSContext *context) {\n    if ((!context) || (((!context->private_key) || (!context->private_key->der_bytes) || (!context->private_key->der_len))\n#ifdef TLS_ECDSA_SUPPORTED\n        && ((!context->ec_private_key) || (!context->ec_private_key->der_bytes) || (!context->ec_private_key->der_len))\n#endif\n    ))\n        return 0;\n    return 1;\n}\n\nstruct TLSContext *SSL_CTX_new(int method) {\n#ifdef WITH_TLS_13\n    return tls_create_context(method, TLS_V13);\n#else\n    return tls_create_context(method, TLS_V12);\n#endif\n}\n\nvoid SSL_free(struct TLSContext *context) {\n    if (context) {\n        TLS_FREE(context->user_data);\n        tls_destroy_context(context);\n    }\n}\n\nvoid SSL_CTX_free(struct TLSContext *context) {\n    SSL_free(context);\n}\n\nint SSL_get_error(struct TLSContext *context, int ret) {\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    return context->critical_error;\n}\n\nint SSL_set_fd(struct TLSContext *context, int socket) {\n    SSLUserData *ssl_data;\n\n    if (!context)\n        return 0;\n    ssl_data = (SSLUserData *)context->user_data;\n    if (!ssl_data) {\n        ssl_data = (SSLUserData *)TLS_MALLOC(sizeof(SSLUserData));\n        if (!ssl_data)\n            return TLS_NO_MEMORY;\n        memset(ssl_data, 0, sizeof(SSLUserData));\n        context->user_data = ssl_data;\n    }\n    ssl_data->fd = socket;\n    return 1;\n}\n\nvoid *SSL_set_userdata(struct TLSContext *context, void *data) {\n    SSLUserData *ssl_data;\n    void *old_data;\n\n    if (!context)\n        return NULL;\n    ssl_data = (SSLUserData *)context->user_data;\n    if (!ssl_data) {\n        ssl_data = (SSLUserData *)TLS_MALLOC(sizeof(SSLUserData));\n        if (!ssl_data)\n            return NULL;\n        memset(ssl_data, 0, sizeof(SSLUserData));\n        context->user_data = ssl_data;\n    }\n    old_data = ssl_data->user_data;\n    ssl_data->user_data = data;\n    return old_data;\n}\n\nvoid *SSL_userdata(struct TLSContext *context) {\n    SSLUserData *ssl_data;\n\n    if (!context)\n        return NULL;\n    ssl_data = (SSLUserData *)context->user_data;\n    if (!ssl_data)\n        return NULL;\n    \n    return ssl_data->user_data;\n}\n\nint SSL_CTX_root_ca(struct TLSContext *context, const char *pem_filename) {\n    SSLUserData *ssl_data;\n    int count = TLS_GENERIC_ERROR;\n    FILE *f;\n    size_t size;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    \n    f = fopen(pem_filename, \"rb\");\n    if (f) {\n        fseek(f, 0, SEEK_END);\n        size = (size_t)ftell(f);\n        fseek(f, 0, SEEK_SET);\n        if (size) {\n            unsigned char *buf = (unsigned char *)TLS_MALLOC(size + 1);\n            if (buf) {\n                buf[size] = 1;\n                if (fread(buf, 1, size, f) == size) {\n                    count = tls_load_root_certificates(context, buf, size);\n                    if (count > 0) {\n                        ssl_data = (SSLUserData *)context->user_data;\n                        if (!ssl_data) {\n                            ssl_data = (SSLUserData *)TLS_MALLOC(sizeof(SSLUserData));\n                            if (!ssl_data) {\n                                fclose(f);\n                                return TLS_NO_MEMORY;\n                            }\n                            memset(ssl_data, 0, sizeof(SSLUserData));\n                            context->user_data = ssl_data;\n                        }\n                        if (!ssl_data->certificate_verify)\n                            ssl_data->certificate_verify = tls_default_verify;\n                    }\n                }\n                TLS_FREE(buf);\n            }\n        }\n        fclose(f);\n    }\n    return count;\n}\n\nvoid SSL_CTX_set_verify(struct TLSContext *context, int mode, tls_validation_function verify_callback) {\n    SSLUserData *ssl_data;\n\n    if (!context)\n        return;\n    ssl_data = (SSLUserData *)context->user_data;\n    if (!ssl_data) {\n        ssl_data = (SSLUserData *)TLS_MALLOC(sizeof(SSLUserData));\n        if (!ssl_data)\n            return;\n        memset(ssl_data, 0, sizeof(SSLUserData));\n        context->user_data = ssl_data;\n    }\n    if (mode == SSL_VERIFY_NONE)\n        ssl_data->certificate_verify = NULL;\n    else\n        ssl_data->certificate_verify = verify_callback;\n}\n\nint _private_tls_safe_read(struct TLSContext *context, void *buffer, int buf_size) {\n    SSLUserData *ssl_data = (SSLUserData *)context->user_data;\n    SOCKET_RECV_CALLBACK read_cb;\n\n    if ((!ssl_data) || (ssl_data->fd < 0))\n        return TLS_GENERIC_ERROR;\n\n    read_cb = (SOCKET_RECV_CALLBACK)ssl_data->recv;\n    if (read_cb)\n        return read_cb(ssl_data->fd, (char *)buffer, buf_size, 0);\n    return recv(ssl_data->fd, (char *)buffer, buf_size, 0);\n}\n\nint SSL_accept(struct TLSContext *context) {\n    unsigned char client_message[BIG_STRING_SIZE];\n    SSLUserData *ssl_data;\n    int read_size = 0;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    ssl_data = (SSLUserData *)context->user_data;\n    if ((!ssl_data) || (ssl_data->fd < 0))\n        return TLS_GENERIC_ERROR;\n    if (tls_established(context))\n        return 1;\n    /* accept */\n    while ((read_size = _private_tls_safe_read(context, (char *)client_message, sizeof(client_message))) > 0) {\n        if (tls_consume_stream(context, client_message, read_size, ssl_data->certificate_verify) >= 0) {\n            int res = _tls_ssl_private_send_pending(ssl_data->fd, context);\n            if (res < 0)\n                return res;\n        }\n        if (tls_established(context))\n            return 1;\n    }\n    if (read_size <= 0)\n        return TLS_BROKEN_CONNECTION;\n    return 0;\n}\n\nint SSL_connect(struct TLSContext *context) {\n    SSLUserData *ssl_data;\n    int res;\n    int read_size;\n    unsigned char client_message[BIG_STRING_SIZE];\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    ssl_data = (SSLUserData *)context->user_data;\n    if ((!ssl_data) || (ssl_data->fd < 0) || (context->critical_error))\n        return TLS_GENERIC_ERROR;\n    res = tls_client_connect(context);\n    if (res < 0)\n        return res;\n    res = _tls_ssl_private_send_pending(ssl_data->fd, context);\n    if (res < 0)\n        return res;\n    \n    while ((read_size = _private_tls_safe_read(context, (char *)client_message, sizeof(client_message))) > 0) {\n        if (tls_consume_stream(context, client_message, read_size, ssl_data->certificate_verify) >= 0) {\n            res = _tls_ssl_private_send_pending(ssl_data->fd, context);\n            if (res < 0)\n                return res;\n        }\n        if (tls_established(context))\n            return 1;\n        if (context->critical_error)\n            return TLS_GENERIC_ERROR;\n    }\n    return read_size;\n}\n\nint SSL_shutdown(struct TLSContext *context) {\n    SSLUserData *ssl_data;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    ssl_data = (SSLUserData *)context->user_data;\n    if ((!ssl_data) || (ssl_data->fd < 0))\n        return TLS_GENERIC_ERROR;\n    \n    tls_close_notify(context);\n    return 0;\n}\n\nint SSL_write(struct TLSContext *context, const void *buf, unsigned int len) {\n    SSLUserData *ssl_data;\n    int written_size;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    ssl_data = (SSLUserData *)context->user_data;\n    if ((!ssl_data) || (ssl_data->fd < 0))\n        return TLS_GENERIC_ERROR;\n    \n    written_size = tls_write(context, (const unsigned char *)buf, len);\n    if (written_size > 0) {\n        int res = _tls_ssl_private_send_pending(ssl_data->fd, context);\n        if (res <= 0)\n            return res;\n    }\n    return written_size;\n}\n\nint SSL_read(struct TLSContext *context, void *buf, unsigned int len) {\n    SSLUserData *ssl_data;\n    unsigned char client_message[BIG_STRING_SIZE];\n    int read_size;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    \n    if (context->application_buffer_len)\n        return tls_read(context, (unsigned char *)buf, len);\n\n    ssl_data = (SSLUserData *)context->user_data;\n    if ((!ssl_data) || (ssl_data->fd < 0) || (context->critical_error))\n        return TLS_GENERIC_ERROR;\n    if (tls_established(context) != 1)\n        return TLS_GENERIC_ERROR;\n    \n    /* accept */\n    while ((!context->application_buffer_len) && (read_size = _private_tls_safe_read(context, (char *)client_message, sizeof(client_message))) > 0) {\n        if (tls_consume_stream(context, client_message, read_size, ssl_data->certificate_verify) > 0)\n            _tls_ssl_private_send_pending(ssl_data->fd, context);\n\n        if ((context->critical_error) && (!context->application_buffer_len))\n            return TLS_GENERIC_ERROR;\n    }\n    if ((read_size <= 0) && (!context->application_buffer_len))\n        return read_size;\n    \n    return tls_read(context, (unsigned char *)buf, len);\n}\n\nint SSL_pending(struct TLSContext *context) {\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    return context->application_buffer_len;\n}\n\nint SSL_set_io(struct TLSContext *context, void *recv_cb, void *send_cb) {\n    SSLUserData *ssl_data;\n\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    ssl_data = (SSLUserData *)context->user_data;\n    if (!ssl_data) {\n        ssl_data = (SSLUserData *)TLS_MALLOC(sizeof(SSLUserData));\n        if (!ssl_data)\n            return TLS_NO_MEMORY;\n        memset(ssl_data, 0, sizeof(SSLUserData));\n        context->user_data = ssl_data;\n    }\n    ssl_data->recv = recv_cb;\n    ssl_data->send = send_cb;\n    return 0;\n}\n#endif /* SSL_COMPATIBLE_INTERFACE */\n\n\n#ifdef TLS_SRTP\n\nstruct SRTPContext {\n    symmetric_CTR aes;\n    unsigned int salt[4];\n    unsigned char mac[TLS_SHA1_MAC_SIZE];\n    unsigned int tag_size;\n    unsigned int roc;\n    unsigned short seq;\n\n    unsigned char mode;\n    unsigned char auth_mode;\n};\n\nstruct SRTPContext *srtp_init(unsigned char mode, unsigned char auth_mode) {\n    struct SRTPContext *context = NULL;\n    tls_init();\n    switch (mode) {\n        case SRTP_NULL:\n            break;\n        case SRTP_AES_CM:\n            break;\n        default:\n            return NULL;\n    }\n\n    switch (auth_mode) {\n        case SRTP_AUTH_NULL:\n            break;\n        case SRTP_AUTH_HMAC_SHA1:\n            break;\n        default:\n            return NULL;\n    }\n    context = (struct SRTPContext *)TLS_MALLOC(sizeof(struct SRTPContext));\n    if (context) {\n        memset(context, 0, sizeof(struct SRTPContext));\n        context->mode = mode;\n        context->auth_mode = auth_mode;\n    }\n    return context;\n}\n\nstatic int _private_tls_srtp_key_derive(const void *key, int keylen, const void *salt, unsigned char label, void *out, int outlen) {\n    unsigned char iv[16];\n    void *in;\n    symmetric_CTR aes;\n\n    memcpy(iv, salt, 14);\n    iv[14] = iv[15] = 0;\n    in = TLS_MALLOC(outlen);\n    if (!in)\n        return TLS_GENERIC_ERROR;\n    memset(in, 0, outlen);\n\n    iv[7] ^= label;\n\n    if (ctr_start(find_cipher(\"aes\"), iv, (const unsigned char *)key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &aes))\n        return TLS_GENERIC_ERROR;\n\n    ctr_encrypt((unsigned char *)in, (unsigned char *)out, outlen, &aes);\n    TLS_FREE(in);\n    ctr_done(&aes);\n    return 0;\n}\n\nint srtp_key(struct SRTPContext *context, const void *key, int keylen, const void *salt, int saltlen, int tag_bits) {\n    if (!context)\n        return TLS_GENERIC_ERROR;\n    if (context->mode == SRTP_AES_CM) {\n        /* key */\n        unsigned char key_buf[16];\n        unsigned char iv[16];\n\n        if ((saltlen < 14) || (keylen < 16))\n            return TLS_GENERIC_ERROR;\n        memset(iv, 0, sizeof(iv));\n\n        if (_private_tls_srtp_key_derive(key, keylen, salt, 0, key_buf, sizeof(key_buf)))\n            return TLS_GENERIC_ERROR;\n\n        DEBUG_DUMP_HEX_LABEL(\"KEY\", key_buf, 16)\n\n        if (_private_tls_srtp_key_derive(key, keylen, salt, 1, context->mac, 20))\n            return TLS_GENERIC_ERROR;\n\n        DEBUG_DUMP_HEX_LABEL(\"AUTH\", context->mac, 20)\n\n        memset(context->salt, 0, sizeof(context->salt));\n        if (_private_tls_srtp_key_derive(key, keylen, salt, 2, context->salt, 14))\n            return TLS_GENERIC_ERROR;\n\n        DEBUG_DUMP_HEX_LABEL(\"SALT\", ((unsigned char *)context->salt), 14)\n\n        if (ctr_start(find_cipher(\"aes\"), iv, key_buf, sizeof(key_buf), 0, CTR_COUNTER_BIG_ENDIAN, &context->aes))\n            return TLS_GENERIC_ERROR;\n    }\n    if (context->auth_mode)\n        context->tag_size = tag_bits / 8;\n    return 0;\n}\n\nint srtp_inline(struct SRTPContext *context, const char *b64, int tag_bits) {\n    char out_buffer[1024];\n    int size;\n    int len;\n\n    if (!b64)\n        return TLS_GENERIC_ERROR;\n\n    len = strlen(b64);\n    if (len >= sizeof(out_buffer))\n        len = sizeof(out_buffer);\n    size = _private_b64_decode(b64, len, (unsigned char *)out_buffer);\n    if (size <= 0)\n        return TLS_GENERIC_ERROR;\n    switch (context->mode) {\n        case SRTP_AES_CM:\n            if (size < 30)\n                return TLS_BROKEN_PACKET;\n            return srtp_key(context, out_buffer, 16, out_buffer + 16, 14, tag_bits);\n    }\n    return TLS_GENERIC_ERROR;\n}\n\nint srtp_encrypt(struct SRTPContext *context, const unsigned char *pt_header, int pt_len, const unsigned char *payload, unsigned int payload_len, unsigned char *out, int *out_buffer_len) {\n    int out_len = payload_len;\n    unsigned short seq = 0;\n    unsigned int roc;\n    unsigned int roc_be;\n    unsigned int ssrc = 0;\n\n    if ((!context) || (!out) || (!out_buffer_len) || (*out_buffer_len < payload_len))\n        return TLS_GENERIC_ERROR;\n\n    roc = context->roc;\n    if ((pt_header) && (pt_len >= 12)) {\n        seq = ntohs(*((unsigned short *)&pt_header[2]));\n        ssrc = ntohl(*((unsigned long *)&pt_header[8]));\n    }\n\n    if (seq < context->seq)\n        roc++;\n\n    roc_be = htonl(roc);\n\n    if (context->mode) {\n        if (*out_buffer_len < out_len)\n            return TLS_NO_MEMORY;\n\n        unsigned int counter[4];\n        counter[0] = context->salt[0];\n        counter[1] = context->salt[1] ^ htonl (ssrc);\n        counter[2] = context->salt[2] ^ roc_be;\n        counter[3] = context->salt[3] ^ htonl (seq << 16);\n        ctr_setiv((unsigned char *)&counter, 16, &context->aes);\n        if (ctr_encrypt(payload, out, payload_len, &context->aes))\n            return TLS_GENERIC_ERROR;\n    } else {\n        memcpy(out, payload, payload_len);\n    }\n\n    *out_buffer_len = out_len;\n\n    if (context->auth_mode == SRTP_AUTH_HMAC_SHA1) {\n        unsigned char digest_out[TLS_SHA1_MAC_SIZE];\n        unsigned long dlen = TLS_SHA1_MAC_SIZE;\n        hmac_state hmac;\n        int err = hmac_init(&hmac, find_hash(\"sha1\"), context->mac, 20);\n        if (!err) {\n            if (pt_len)\n                err = hmac_process(&hmac, pt_header, pt_len);\n            if (out_len)\n                err = hmac_process(&hmac, out, payload_len);\n            err = hmac_process(&hmac, (unsigned char *)&roc_be, 4);\n            if (!err)\n                err = hmac_done(&hmac, digest_out, &dlen);\n        }\n        if (err)\n            return TLS_GENERIC_ERROR;\n        if (dlen > context->tag_size)\n            dlen = context->tag_size;\n\n        *out_buffer_len += dlen;\n        memcpy(out + out_len, digest_out, dlen);\n    }\n    context->roc = roc;\n    context->seq = seq;\n    return 0;\n}\n\nint srtp_decrypt(struct SRTPContext *context, const unsigned char *pt_header, int pt_len, const unsigned char *payload, unsigned int payload_len, unsigned char *out, int *out_buffer_len) {\n    int out_len = payload_len;\n    unsigned short seq;\n    unsigned int roc;\n    unsigned int ssrc;\n    unsigned int roc_be;\n\n    if ((!context) || (!out) || (!out_buffer_len) || (*out_buffer_len < payload_len) || (payload_len < context->tag_size) || (!pt_header) || (pt_len < 12))\n        return TLS_GENERIC_ERROR;\n\n    seq = ntohs(*((unsigned short *)&pt_header[2]));\n    roc = context->roc;\n    ssrc = ntohl(*((unsigned long *)&pt_header[8]));\n\n    if (seq < context->seq)\n        roc++;\n\n    roc_be = htonl(roc);\n    if (context->mode) {\n        unsigned int counter[4];\n        counter[0] = context->salt[0];\n        counter[1] = context->salt[1] ^ htonl (ssrc);\n        counter[2] = context->salt[2] ^ roc_be;\n        counter[3] = context->salt[3] ^ htonl (seq << 16);\n        ctr_setiv((unsigned char *)&counter, 16, &context->aes);\n\n        if (ctr_decrypt(payload, out, payload_len - context->tag_size, &context->aes))\n            return TLS_GENERIC_ERROR;\n\n        if (context->auth_mode == SRTP_AUTH_HMAC_SHA1) {\n            unsigned char digest_out[TLS_SHA1_MAC_SIZE];\n            unsigned long dlen = TLS_SHA1_MAC_SIZE;\n            hmac_state hmac;\n            int err = hmac_init(&hmac, find_hash(\"sha1\"), context->mac, 20);\n            if (!err) {\n                if (pt_len)\n                    err = hmac_process(&hmac, pt_header, pt_len);\n                if (out_len)\n                    err = hmac_process(&hmac, payload, payload_len - context->tag_size);\n                err = hmac_process(&hmac, (unsigned char *)&roc_be, 4);\n                if (!err)\n                    err = hmac_done(&hmac, digest_out, &dlen);\n            }\n            if (err)\n                return TLS_GENERIC_ERROR;\n            if (dlen > context->tag_size)\n                dlen = context->tag_size;\n\n            if (memcmp(digest_out, payload + payload_len - context->tag_size, dlen))\n                return TLS_INTEGRITY_FAILED;\n        }\n    } else {\n        memcpy(out, payload, payload_len - context->tag_size);\n    }\n    context->seq = seq;\n    context->roc = roc;\n    *out_buffer_len = payload_len - context->tag_size;\n    return 0;\n}\n\nvoid srtp_destroy(struct SRTPContext *context) {\n    if (context) {\n        if (context->mode)\n            ctr_done(&context->aes);\n        TLS_FREE(context);\n    }\n}\n\n#endif /* TLS_SRTP */\n\n#endif /* TLSE_C */\n"
  },
  {
    "path": "cryanc.h",
    "content": "#ifndef TLSE_H\n#define TLSE_H\n\n/* #define DEBUG */\n\n#define NO_SSL_COMPATIBLE_INTERFACE 1\n/* doesn't currently work */\n/* #define TLS_CURVE25519 1 */\n\n/* define TLS_LEGACY_SUPPORT to support TLS 1.1/1.0 (legacy)\n   legacy support it will use an additional 272 bytes / context */\n#ifndef NO_TLS_LEGACY_SUPPORT\n#define TLS_LEGACY_SUPPORT\n#endif\n/* SSL_* style blocking APIs */\n#ifndef NO_SSL_COMPATIBLE_INTERFACE\n#define SSL_COMPATIBLE_INTERFACE\n#endif\n/* support ChaCha20/Poly1305 */\n#ifndef NO_TLS_WITH_CHACHA20_POLY1305\n#define TLS_WITH_CHACHA20_POLY1305\n#endif\n#ifndef NO_TLS_13\n#define WITH_TLS_13\n#endif\n/* support forward secrecy (Diffie-Hellman ephemeral) */\n#ifndef NO_TLS_FORWARD_SECRECY\n#define TLS_FORWARD_SECRECY\n#endif\n/* support client-side ECDHE */\n#ifndef NO_TLS_CLIENT_ECDHE\n#define TLS_CLIENT_ECDHE\n#endif\n/* support ECDSA */\n#ifndef NO_TLS_ECDSA_SUPPORTED\n/* support ECDSA client-side */\n#define TLS_CLIENT_ECDSA\n#define TLS_ECDSA_SUPPORTED\n#endif\n\n/* TLS renegotiation is disabled by default (secured or not)\n   do not uncomment next line unless you know what you're doing! */\n/* #define TLS_ACCEPT_SECURE_RENEGOTIATION */\n\n/* basic superficial X509v1 certificate support */\n#ifndef NO_TLS_X509_V1_SUPPORT\n#define TLS_X509_V1_SUPPORT\n#endif\n\n/* disable TLS_RSA_WITH_* ciphers */\n#ifndef NO_TLS_ROBOT_MITIGATION\n#define TLS_ROBOT_MITIGATION\n#endif\n\n#define SSL_V30                 0x0300\n#define TLS_V10                 0x0301\n#define TLS_V11                 0x0302\n#define TLS_V12                 0x0303\n#define TLS_V13                 0x0304\n#define DTLS_V10                0xFEFF\n#define DTLS_V12                0xFEFD\n#define DTLS_V13                0xFEFC\n\n#define TLS_NEED_MORE_DATA       0\n#define TLS_GENERIC_ERROR       -1\n#define TLS_BROKEN_PACKET       -2\n#define TLS_NOT_UNDERSTOOD      -3\n#define TLS_NOT_SAFE            -4\n#define TLS_NO_COMMON_CIPHER    -5\n#define TLS_UNEXPECTED_MESSAGE  -6\n#define TLS_CLOSE_CONNECTION    -7\n#define TLS_COMPRESSION_NOT_SUPPORTED -8\n#define TLS_NO_MEMORY           -9\n#define TLS_NOT_VERIFIED        -10\n#define TLS_INTEGRITY_FAILED    -11\n#define TLS_ERROR_ALERT         -12\n#define TLS_BROKEN_CONNECTION   -13\n#define TLS_BAD_CERTIFICATE     -14\n#define TLS_UNSUPPORTED_CERTIFICATE -15\n#define TLS_NO_RENEGOTIATION    -16\n#define TLS_FEATURE_NOT_SUPPORTED   -17\n#define TLS_DECRYPTION_FAILED   -20\n\n#define TLS_AES_128_GCM_SHA256                0x1301\n#define TLS_AES_256_GCM_SHA384                0x1302\n#define TLS_CHACHA20_POLY1305_SHA256          0x1303\n#define TLS_AES_128_CCM_SHA256                0x1304\n#define TLS_AES_128_CCM_8_SHA256              0x1305\n\n#define TLS_RSA_WITH_AES_128_CBC_SHA          0x002F\n#define TLS_RSA_WITH_AES_256_CBC_SHA          0x0035\n#define TLS_RSA_WITH_AES_128_CBC_SHA256       0x003C\n#define TLS_RSA_WITH_AES_256_CBC_SHA256       0x003D\n#define TLS_RSA_WITH_AES_128_GCM_SHA256       0x009C\n#define TLS_RSA_WITH_AES_256_GCM_SHA384       0x009D\n\n/* forward secrecy */\n#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA      0x0033\n#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA      0x0039\n#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256   0x0067\n#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256   0x006B\n#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256   0x009E\n#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384   0x009F\n\n#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA    0xC013\n#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA    0xC014\n#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027\n#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F\n#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030\n\n#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA    0xC009\n#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA    0xC00A\n#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023\n#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024\n#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B\n#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C\n\n#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256     0xCCA8\n#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256   0xCCA9\n#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256       0xCCAA\n\n#define TLS_FALLBACK_SCSV                     0x5600\n\n#define TLS_UNSUPPORTED_ALGORITHM   0x00\n#define TLS_RSA_SIGN_RSA            0x01\n#define TLS_RSA_SIGN_MD5            0x04\n#define TLS_RSA_SIGN_SHA1           0x05\n#define TLS_RSA_SIGN_SHA256         0x0B\n#define TLS_RSA_SIGN_SHA384         0x0C\n#define TLS_RSA_SIGN_SHA512         0x0D\n#define TLS_ECDSA_SIGN_SHA256       0x0E\n\n#define TLS_EC_PUBLIC_KEY           0x11\n#define TLS_EC_prime192v1           0x12\n#define TLS_EC_prime192v2           0x13\n#define TLS_EC_prime192v3           0x14\n#define TLS_EC_prime239v1           0x15\n#define TLS_EC_prime239v2           0x16\n#define TLS_EC_prime239v3           0x17\n#define TLS_EC_prime256v1           0x18\n#define TLS_EC_secp224r1            21\n#define TLS_EC_secp256r1            23\n#define TLS_EC_secp384r1            24\n#define TLS_EC_secp521r1            25\n\n#define TLS_ALERT_WARNING           0x01\n#define TLS_ALERT_CRITICAL          0x02\n\n#ifdef TLS_ROBOT_MITIGATION\n    #define TLS_CIPHERS_SIZE(n, mitigated)         n * 2\n#else\n    #define TLS_CIPHERS_SIZE(n, mitigated)         (n + mitigated) * 2\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef enum {\n    close_notify = 0,\n    unexpected_message = 10,\n    bad_record_mac = 20,\n    decryption_failed_RESERVED = 21,\n    record_overflow = 22,\n    decompression_failure = 30,\n    handshake_failure = 40,\n    no_certificate_RESERVED = 41,\n    bad_certificate = 42,\n    unsupported_certificate = 43,\n    certificate_revoked = 44,\n    certificate_expired = 45,\n    certificate_unknown = 46,\n    illegal_parameter = 47,\n    unknown_ca = 48,\n    access_denied = 49,\n    decode_error = 50,\n    decrypt_error = 51,\n    export_restriction_RESERVED = 60,\n    protocol_version = 70,\n    insufficient_security = 71,\n    internal_error = 80,\n    inappropriate_fallback = 86,\n    user_canceled = 90,\n    no_renegotiation = 100,\n    unsupported_extension = 110,\n    no_error = 255\n} TLSAlertDescription;\n\n/* forward declarations */\nstruct TLSPacket;\nstruct TLSCertificate;\nstruct TLSContext;\nstruct ECCCurveParameters;\ntypedef struct TLSContext TLS;\ntypedef struct TLSCertificate Certificate;\n\ntypedef int (*tls_validation_function)(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len);\n\n/*\n  Global initialization. Optional, as it will be called automatically;\n  however, the initialization is not thread-safe, so if you intend to use it\n  from multiple threads, you'll need to call tls_init() once, from a single\n  thread, before using the library.\n*/\nvoid tls_init();\nunsigned char *tls_pem_decode(const unsigned char *data_in, unsigned int input_length, int cert_index, unsigned int *output_len);\nstruct TLSCertificate *tls_create_certificate();\nint tls_certificate_valid_subject(struct TLSCertificate *cert, const char *subject);\nint tls_certificate_valid_subject_name(const unsigned char *cert_subject, const char *subject);\nint tls_certificate_is_valid(struct TLSCertificate *cert);\nvoid tls_certificate_set_copy(unsigned char **member, const unsigned char *val, int len);\nvoid tls_certificate_set_copy_date(unsigned char **member, const unsigned char *val, int len);\nvoid tls_certificate_set_key(struct TLSCertificate *cert, const unsigned char *val, int len);\nvoid tls_certificate_set_priv(struct TLSCertificate *cert, const unsigned char *val, int len);\nvoid tls_certificate_set_sign_key(struct TLSCertificate *cert, const unsigned char *val, int len);\nchar *tls_certificate_to_string(struct TLSCertificate *cert, char *buffer, int len);\nvoid tls_certificate_set_exponent(struct TLSCertificate *cert, const unsigned char *val, int len);\nvoid tls_certificate_set_serial(struct TLSCertificate *cert, const unsigned char *val, int len);\nvoid tls_certificate_set_algorithm(struct TLSContext *context, unsigned int *algorithm, const unsigned char *val, int len);\nvoid tls_destroy_certificate(struct TLSCertificate *cert);\nstruct TLSPacket *tls_create_packet(struct TLSContext *context, unsigned char type, unsigned short version, int payload_size_hint);\nvoid tls_destroy_packet(struct TLSPacket *packet);\nvoid tls_packet_update(struct TLSPacket *packet);\nint tls_packet_append(struct TLSPacket *packet, const unsigned char *buf, unsigned int len);\nint tls_packet_uint8(struct TLSPacket *packet, unsigned char i);\nint tls_packet_uint16(struct TLSPacket *packet, unsigned short i);\nint tls_packet_uint32(struct TLSPacket *packet, unsigned int i);\nint tls_packet_uint24(struct TLSPacket *packet, unsigned int i);\nint tls_random(unsigned char *key, int len);\n\n/*\n  Get encrypted data to write, if any. Once you've sent all of it, call\n  tls_buffer_clear().\n*/\nconst unsigned char *tls_get_write_buffer(struct TLSContext *context, unsigned int *outlen);\n\nvoid tls_buffer_clear(struct TLSContext *context);\n\n/* Returns 1 for established, 0 for not established yet, and -1 for a critical error. */\nint tls_established(struct TLSContext *context);\n\n/* Discards any unread decrypted data not consumed by tls_read(). */\nvoid tls_read_clear(struct TLSContext *context);\n\n/*\n  Reads any unread decrypted data (see tls_consume_stream). If you don't read all of it,\n  the remainder will be left in the internal buffers for next tls_read(). Returns -1 for\n  fatal error, 0 for no more data, or otherwise the number of bytes copied into the buffer\n  (up to a maximum of the given size).\n*/\nint tls_read(struct TLSContext *context, unsigned char *buf, unsigned int size);\n\nstruct TLSContext *tls_create_context(unsigned char is_server, unsigned short version);\nconst struct ECCCurveParameters *tls_set_curve(struct TLSContext *context, const struct ECCCurveParameters *curve);\n\n/* Create a context for a given client, from a server context. Returns NULL on error. */\nstruct TLSContext *tls_accept(struct TLSContext *context);\n\nint tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, const char *g_hex_str);\nvoid tls_destroy_context(struct TLSContext *context);\nint tls_cipher_supported(struct TLSContext *context, unsigned short cipher);\nint tls_cipher_is_fs(struct TLSContext *context, unsigned short cipher);\nint tls_choose_cipher(struct TLSContext *context, const unsigned char *buf, int buf_len, int *scsv_set);\nint tls_cipher_is_ephemeral(struct TLSContext *context);\nconst char *tls_cipher_name(struct TLSContext *context);\nint tls_is_ecdsa(struct TLSContext *context);\nstruct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context);\nstruct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int method);\nstruct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrade);\nstruct TLSPacket *tls_certificate_request(struct TLSContext *context);\nstruct TLSPacket *tls_build_verify_request(struct TLSContext *context);\nint tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int buf_len, unsigned int *write_packets, unsigned int *dtls_verified);\nint tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, int buf_len, int is_client);\nint tls_parse_server_key_exchange(struct TLSContext *context, const unsigned char *buf, int buf_len);\nint tls_parse_client_key_exchange(struct TLSContext *context, const unsigned char *buf, int buf_len);\nint tls_parse_server_hello_done(struct TLSContext *context, const unsigned char *buf, int buf_len);\nint tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int buf_len, unsigned int *write_packets);\nint tls_parse_verify(struct TLSContext *context, const unsigned char *buf, int buf_len);\nint tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int buf_len, tls_validation_function certificate_verify);\nint tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_len, tls_validation_function certificate_verify);\nint tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCertificate *parent);\nint tls_certificate_chain_is_valid(struct TLSCertificate **certificates, int len);\nint tls_certificate_chain_is_valid_root(struct TLSContext *context, struct TLSCertificate **certificates, int len);\n\n/*\n  Add a certificate or a certificate chain to the given context, in PEM form.\n  Returns a negative value (TLS_GENERIC_ERROR etc.) on error, 0 if there were no\n  certificates in the buffer, or the number of loaded certificates on success.\n*/\nint tls_load_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size);\n\n/*\n  Add a private key to the given context, in PEM form. Returns a negative value\n  (TLS_GENERIC_ERROR etc.) on error, 0 if there was no private key in the\n  buffer, or 1 on success.\n*/\nint tls_load_private_key(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size);\nstruct TLSPacket *tls_build_certificate(struct TLSContext *context);\nstruct TLSPacket *tls_build_finished(struct TLSContext *context);\nstruct TLSPacket *tls_build_change_cipher_spec(struct TLSContext *context);\nstruct TLSPacket *tls_build_done(struct TLSContext *context);\nstruct TLSPacket *tls_build_message(struct TLSContext *context, const unsigned char *data, unsigned int len);\nint tls_client_connect(struct TLSContext *context);\nint tls_write(struct TLSContext *context, const unsigned char *data, unsigned int len);\nstruct TLSPacket *tls_build_alert(struct TLSContext *context, char critical, unsigned char code);\n\n/*\n  Process a given number of input bytes from a socket. If the other side just\n  presented a certificate and certificate_verify is not NULL, it will be called.\n\n  Returns 0 if there's no data ready yet, a negative value (see\n  TLS_GENERIC_ERROR etc.) for an error, or a positive value (the number of bytes\n  used from buf) if one or more complete TLS messages were received. The data\n  is copied into an internal buffer even if not all of it was consumed,\n  so you should not re-send it the next time.\n\n  Decrypted data, if any, should be read back with tls_read(). Can change the\n  status of tls_established(). If the library has anything to send back on the\n  socket (e.g. as part of the handshake), tls_get_write_buffer() will return\n  non-NULL.\n*/\nint tls_consume_stream(struct TLSContext *context, const unsigned char *buf, int buf_len, tls_validation_function certificate_verify);\nvoid tls_close_notify(struct TLSContext *context);\nvoid tls_alert(struct TLSContext *context, unsigned char critical, int code);\n\n/* Whether tls_consume_stream() has data in its buffer that is not processed yet. */\nint tls_pending(struct TLSContext *context);\n\n/*\n  Set the context as serializable or not. Must be called before negotiation.\n  Exportable contexts use a bit more memory, to be able to hold the keys.\n\n  Note that imported keys are not reexportable unless TLS_REEXPORTABLE is set.\n*/\nvoid tls_make_exportable(struct TLSContext *context, unsigned char exportable_flag);\n\nint tls_export_context(struct TLSContext *context, unsigned char *buffer, unsigned int buf_len, unsigned char small_version);\nstruct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int buf_len);\nint tls_is_broken(struct TLSContext *context);\nint tls_request_client_certificate(struct TLSContext *context);\nint tls_client_verified(struct TLSContext *context);\nconst char *tls_sni(struct TLSContext *context);\nint tls_sni_set(struct TLSContext *context, const char *sni);\nint tls_load_root_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size);\nint tls_default_verify(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len);\nvoid tls_print_certificate(const char *fname);\nint tls_add_alpn(struct TLSContext *context, const char *alpn);\nint tls_alpn_contains(struct TLSContext *context, const char *alpn, unsigned char alpn_size);\nconst char *tls_alpn(struct TLSContext *context);\n/* useful when renewing certificates for servers, without the need to restart the server */\nint tls_clear_certificates(struct TLSContext *context);\nint tls_make_ktls(struct TLSContext *context, int socket);\nint tls_unmake_ktls(struct TLSContext *context, int socket);\n/*\n  Creates a new DTLS random cookie secret to be used in HelloVerifyRequest (server-side).\n  It is recommended to call this function from time to time, to protect against some \n  DoS attacks.\n*/\nvoid dtls_reset_cookie_secret();\n\nint tls_remote_error(struct TLSContext *context);\n\n#ifdef SSL_COMPATIBLE_INTERFACE\n    #define SSL_SERVER_RSA_CERT 1\n    #define SSL_SERVER_RSA_KEY  2\n    typedef struct TLSContext SSL_CTX;\n    typedef struct TLSContext SSL;\n\n    #define SSL_FILETYPE_PEM    1\n    #define SSL_VERIFY_NONE     0\n    #define SSL_VERIFY_PEER     1\n    #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 2\n    #define SSL_VERIFY_CLIENT_ONCE  3\n\n    typedef struct {\n        int fd;\n        tls_validation_function certificate_verify;\n        void *recv;\n        void *send;\n        void *user_data;\n    } SSLUserData;\n\n    int  SSL_library_init();\n    void SSL_load_error_strings();\n    void OpenSSL_add_all_algorithms();\n    void OpenSSL_add_all_ciphers();\n    void OpenSSL_add_all_digests();\n    void EVP_cleanup();\n\n    int SSLv3_server_method();\n    int SSLv3_client_method();\n    struct TLSContext *SSL_new(struct TLSContext *context);\n    int SSL_CTX_use_certificate_file(struct TLSContext *context, const char *filename, int dummy);\n    int SSL_CTX_use_PrivateKey_file(struct TLSContext *context, const char *filename, int dummy);\n    int SSL_CTX_check_private_key(struct TLSContext *context);\n    struct TLSContext *SSL_CTX_new(int method);\n    void SSL_free(struct TLSContext *context);\n    void SSL_CTX_free(struct TLSContext *context);\n    int SSL_get_error(struct TLSContext *context, int ret);\n    int SSL_set_fd(struct TLSContext *context, int socket);\n    void *SSL_set_userdata(struct TLSContext *context, void *data);\n    void *SSL_userdata(struct TLSContext *context);\n    int SSL_CTX_root_ca(struct TLSContext *context, const char *pem_filename);\n    void SSL_CTX_set_verify(struct TLSContext *context, int mode, tls_validation_function verify_callback);\n    int SSL_accept(struct TLSContext *context);\n    int SSL_connect(struct TLSContext *context);\n    int SSL_shutdown(struct TLSContext *context);\n    int SSL_write(struct TLSContext *context, const void *buf, unsigned int len);\n    int SSL_read(struct TLSContext *context, void *buf, unsigned int len);\n    int SSL_pending(struct TLSContext *context);\n    int SSL_set_io(struct TLSContext *context, void *recv, void *send);\n#endif\n\n#ifdef TLS_SRTP\n    struct SRTPContext;\n    #define SRTP_NULL           0\n    #define SRTP_AES_CM         1\n    #define SRTP_AUTH_NULL      0\n    #define SRTP_AUTH_HMAC_SHA1 1\n\n    struct SRTPContext *srtp_init(unsigned char mode, unsigned char auth_mode);\n    int srtp_key(struct SRTPContext *context, const void *key, int keylen, const void *salt, int saltlen, int tag_bits);\n    int srtp_inline(struct SRTPContext *context, const char *b64, int tag_bits);\n    int srtp_encrypt(struct SRTPContext *context, const unsigned char *pt_header, int pt_len, const unsigned char *payload, unsigned int payload_len, unsigned char *out, int *out_buffer_len);\n    int srtp_decrypt(struct SRTPContext *context, const unsigned char *pt_header, int pt_len, const unsigned char *payload, unsigned int payload_len, unsigned char *out, int *out_buffer_len);\n    void srtp_destroy(struct SRTPContext *context);\n#endif\n\n#ifdef __cplusplus\n}  /* extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "debughello",
    "content": "#!/usr/bin/perl -s\n\nsub assert {\n\tmy $code = shift;\n\tmy $xpl = shift;\n\tif ($warn) {\n\t\teval $code || (warn(\"assertion failed: $xpl, @{[ scalar(@bytes) ]} remaining, stopped at value @{[ sprintf('%02x %02x', $bytes[0], $bytes[1]) ]}\\n$code\\n\"), return);\n\t} else {\n\t\teval $code || die(\"assertion failed: $xpl, @{[ scalar(@bytes) ]} remaining, stopped at value @{[ sprintf('%02x %02x', $bytes[0], $bytes[1]) ]}\\n$code\\n\");\n\t}\n\tprint \"pass: $xpl (@{[ scalar(@bytes) ]} remaining)\\n\";\n}\n\nsub is { my $val = shift; return scalar(grep { $_ eq $val } @_); }\n\nsub byte { my $w = shift @bytes; printf(STDOUT \"%02x \",$w); return $w; }\nsub assertbyte { &assert('&is(&byte, '.shift.')', shift); }\nsub short { my $w = (((shift @bytes) * 256) + shift @bytes);\n\tprintf(STDOUT \"%04x \", $w); return $w; }\nsub assertshort { &assert('&is(&short, '.shift.')', shift); }\nsub assertlength { &assertshort('scalar(@bytes)', 'length must be correct'); }\n\nsub groupcheck {\n\tmy $length = shift;\n\tmy $min = shift;\n\tmy $what = shift;\n\tmy $set = shift;\n\tmy $xpl = shift;\n\tmy $isbyte = shift;\n\tunless ($isbyte) {\n\t\tassert($length && !($length & 1), 'length must be non-zero and even');\n\t\t$length = $length / 2;\n\t}\n\tassert($length >= $min, \"must have at least $min elements\");\n\tprint \"processing $length $what\\n\";\n\tif ($isbyte) {\n\t\tfor(1..$length) { assertbyte($set, $xpl); }\n\t} else {\n\t\tfor(1..$length) { assertshort($set, $xpl); }\n\t}\n}\n\nundef $/;\nchomp($buf = <STDIN>);\n$buf = lc($buf);\n$buf =~ s/^[^:]+:\\s+// if ($buf =~ /:\\s/);\n1 while ($buf =~ s/[\\r\\l\\n\\s]+//g);\ndie(\"invalid hex\\n\") if ($buf =~ /[^0-9a-f]/);\n@bytes = unpack(\"C*\", pack(\"H*\", $buf));\n\nforeach(@bytes) {\n\tprintf(STDOUT \"%02x\", $_);\n}\n\nprint \"\\ntotal length: \", scalar(@bytes), \"\\n\";\n\nassertbyte('0x16', 'must be hello packet');\nassertshort('0x0303, 0x0304', 'must be TLS 1.2');\nassertlength;\nassertshort('0x0100', 'must be handshake');\nassertlength;\nassertshort('0x0303', 'must be TLS 1.2');\n\nprint \"skipping 32 bytes of client random\\n\";\nsplice(@bytes, 0, 32);\n\n$sess = &byte;\nprint \"skipping $sess bytes of session ID\\n\";\nsplice(@bytes, 0, $sess) if ($sess > 0);\n\ngroupcheck(&short, 1, 'ciphers',\n\t'0x1301, 0x1302, 0x1303, 0xc02b, 0xcca9, 0xc02f, '.\n\t'0xcca8, 0x009e, 0xccaa, 0x00ff, 0x009c, 0xc023, '.\n\t'0xc00a, 0xc009, 0xc013, 0xc014, 0xc027, 0x006b, '.\n\t'0x0067, 0x0039, 0x0033',\n'must be a supported cipher');\n\nassertshort('0x0100', 'must have no compression');\n\n# length of extensions is all bytes including itself\nif ($warnext) {\n\t$w = &short;\n\t$k = scalar(@bytes);\n\tif ($w != $k) {\n\t\tprint \"\\n\\nWARNING: expected $k bytes of extensions, got $w\\n\\n\";\n\t}\n} else { assertlength; }\n\nprint \"\\n== extensions ==\\n\";\n\nwhile(scalar(@bytes)) {\n\tprint STDOUT \"\\n\";\n\t$ext = &short;\n\t$length = &short;\n\tprintf(STDOUT \"extension 0x%04x length %d\\n\", $ext, $length);\n\n\tif ($ext == 0x0000) {\n\t\tprint \"-- SNI --\\n\";\n\t\tassertshort($length - 2, 'must be sane sublength');\n\t\tassertbyte(0, 'must have zero byte');\n\t\tprint \"bytes of hostname: \".pack(\"C*\", splice(@bytes, 0, &short)).\"\\n\";\n\t} elsif ($ext == 0x000a) {\n\t\tprint \"-- supported groups --\\n\";\n\t\tgroupcheck(&short, 1, 'groups', '0x0017,0x0018,0x0019',\n\t\t\t'must be a supported group');\n\t} elsif ($ext == 0x002b) {\n\t\tprint \"-- supported versions --\\n\";\n\t\t# XXX: 7f1c is required. we need a must-be-present checker\n\t\tgroupcheck(&byte, 2, 'versions', '0x0304,0x0303,0x7f1c',\n\t\t\t'must be a supported TLS version');\n\t} elsif ($ext == 0x0033) {\n\t\tprint \"-- keyshare --\\n\";\n\t\tassertshort($length - 2, 'must be sane sublength');\n\t\t$curve = &short;\n\t\t$curvelen = &short;\n\t\tprintf(STDOUT \"curve 0x%04x length %d\\n\", $curve, $curvelen);\n\t\tif ($curve == 0x0017) {\n\t\t\tassert($curvelen == 0x0041, 'expected length 65');\n\t\t} else {\n\t\t\tassert(0, 'must be a supported curve');\n\t\t}\n\t\tprint \"skipping $curvelen bytes of keyshare\\n\";\n\t\tsplice(@bytes, 0, $curvelen);\n\t} elsif ($ext == 0x000d) {\n\t\tprint \"-- signature algorithms --\\n\";\n\t\tgroupcheck(&short, 1, 'algorithms',\n\t\t\t'0x0403,0x0503,0x0603,'.\n\t\t\t'0x0804,0x0805,0x0806,'.\n\t\t\t'0x0401,0x0501,0x0601'.\n\t\t\t',0x0203,0x0201' # XXX\n\t\t, 'must be a supported signature algorithm');\n\t} elsif ($ext == 0x000b) {\n\t\tprint \"-- EC point formats --\\n\";\n\t\tgroupcheck(&byte, 1, 'formats', '0x00,0x01,0x02',\n\t\t\t'must be a known EC point format', 1);\n\t} elsif ($ext == 0xff01) {\n\t\tprint \"-- renegotiation info --\\n\";\n\t\tassertbyte(0, 'must have zero byte');\n\t} else {\n\t\tassert(0, 'must be a known extension');\n\t}\n}\n\nassert(!scalar(@bytes), 'must have consumed all hello bytes');\nprint \"PASS!\\n\";\n"
  }
]